Make it possible to resize the page editor’s side panels (#9276)

Co-authored-by: Thibaud Colas <thibaudcolas@gmail.com>
pull/9659/head
sag᠎e 2022-11-17 15:53:15 +00:00 zatwierdzone przez GitHub
rodzic 119f288a3c
commit dd0d2c4b88
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
6 zmienionych plików z 151 dodań i 9 usunięć

Wyświetl plik

@ -9,6 +9,7 @@ Changelog
* Ensure that the `rebuild_references_index` command can run without console output if called with `--verbosity 0` (Omerzahid Ali, Aman Pandey)
* Add full support for secondary buttons with icons in the Wagtail design system - `button bicolor button--icon button-secondary` including the `button-small` variant (Seremba Patrick)
* Add `purge_embeds` management command to delete all the cached embed objects in the database (Aman Pandey)
* Make it possible to resize the page editors side panels (Sage Abdullah)
* Fix: Make sure workflow timeline icons are visible in high-contrast mode (Loveth Omokaro)
* Fix: Ensure authentication forms (login, password reset) have a visible border in Windows high-contrast mode (Loveth Omokaro)
* Fix: Ensure visual consistency between buttons and links as buttons in Windows high-contrast mode (Albina Starykova)

Wyświetl plik

@ -6,6 +6,14 @@
@apply w-overflow-y-hidden sm:w-overflow-y-auto;
}
.side-panel-resizing {
@apply w-select-none w-cursor-ew-resize;
.form-side {
@apply w-transition;
}
}
.form-side {
@apply w-absolute
w-right-0
@ -15,18 +23,16 @@
md:w-w-1/3
w-transform
w-translate-x-full
w-px-5
xl:w-px-10
w-py-4
w-bg-white
w-box-border
w-transition
w-transition-all
motion-reduce:w-transition-none
w-duration-300
w-border-l
w-border-grey-100
w-overflow-y-auto
w-scrollbar-thin
w-min-w-full
md:w-min-w-[22.875rem]
w-max-w-full
sm:w-max-w-[22.5rem]
md:w-max-w-[35.937rem]
lg:w-max-w-[31.25rem]
@ -41,6 +47,10 @@
@apply w-transition-none;
}
&--preview {
@apply sm:w-max-w-[70vw];
}
&__close-button {
@apply w-text-primary w-absolute w-left-3 w-top-3 hover:w-text-primary-200 w-bg-white w-p-3 w-hidden w-transition;
@ -49,12 +59,45 @@
}
}
&__resize-grip-container {
@apply w-absolute w-place-items-center w-hidden md:w-flex w-z-10 w-left-[-21.5px];
height: calc(100% - theme('spacing.8'));
}
&__resize-grip {
@apply w-text-primary hover:w-text-primary-200 w-border w-border-transparent w-rounded w-bg-white w-p-3 w-hidden w-touch-pinch-zoom w-cursor-ew-resize;
.form-side--open & {
@apply w-flex;
}
&:focus-within:has(:focus-visible) {
@include focus-outline;
}
@supports not selector(:focus-visible) {
&:focus-within {
/* Fallback for browsers without :focus-visible support */
@include focus-outline;
}
}
.icon {
@apply w-w-4 w-h-4;
}
}
&__width-input {
@apply w-w-0 w-h-0 w-opacity-0 w-absolute w-pointer-events-none;
}
&--open .form-side__close-button,
&--open .form-side__panel {
@apply w-block;
}
&__panel {
@apply w-hidden w-h-full;
@apply w-px-5 xl:w-px-10 w-py-4 w-w-full w-h-full w-overflow-y-auto w-scrollbar-thin w-hidden;
}
}

Wyświetl plik

@ -19,6 +19,7 @@
}
&__wrapper {
position: relative;
width: calc(var(--preview-iframe-width) * var(--preview-width-ratio));
height: 100%;
margin-inline-start: auto;

Wyświetl plik

@ -1,3 +1,5 @@
import { ngettext } from '../utils/gettext';
export default function initSidePanel() {
const sidePanelWrapper = document.querySelector('[data-form-side]');
@ -7,6 +9,20 @@ export default function initSidePanel() {
// For now, we do not want to persist the side panel state in the explorer
const inExplorer = 'formSideExplorer' in sidePanelWrapper.dataset;
const resizeGrip = document.querySelector('[data-form-side-resize-grip]');
const widthInput = document.querySelector('[data-form-side-width-input]');
const getSidePanelWidthStyles = () => {
const sidePanelStyles = getComputedStyle(sidePanelWrapper);
const minWidth = parseFloat(sidePanelStyles.minWidth);
const maxWidth = parseFloat(sidePanelStyles.maxWidth);
const width = parseFloat(sidePanelStyles.width);
const range = maxWidth - minWidth;
const percentage = ((width - minWidth) / range) * 100;
return { minWidth, maxWidth, width, range, percentage };
};
const setPanel = (panelName) => {
const body = document.querySelector('body');
const selectedPanel = document.querySelector(
@ -36,17 +52,20 @@ export default function initSidePanel() {
}
document.querySelectorAll('[data-side-panel]').forEach((panel) => {
if (panel.dataset.sidePanel === panelName) {
const name = panel.dataset.sidePanel;
if (name === panelName) {
if (panel.hidden) {
// eslint-disable-next-line no-param-reassign
panel.hidden = false;
panel.dispatchEvent(new CustomEvent('show'));
sidePanelWrapper.classList.add(`form-side--${name}`);
body.classList.add('side-panel-open');
}
} else if (!panel.hidden) {
// eslint-disable-next-line no-param-reassign
panel.hidden = true;
panel.dispatchEvent(new CustomEvent('hide'));
sidePanelWrapper.classList.remove(`form-side--${name}`);
if (panelName === '') {
body.classList.remove('side-panel-open');
@ -69,6 +88,15 @@ export default function initSidePanel() {
} catch (e) {
// Proceed without saving the last-open panel.
}
// Update width input percentage as each panel may have its own maxWidth
// (e.g. the preview panel), use timeout to wait until the resize
// transition has finished
setTimeout(() => {
const { percentage } = getSidePanelWidthStyles();
// Invert the percentage to make the slider work in the opposite direction
widthInput.value = 100 - percentage;
}, 500);
}
};
@ -99,6 +127,65 @@ export default function initSidePanel() {
});
}
const setSidePanelWidth = (targetWidth) => {
const { minWidth, maxWidth, range, width } = getSidePanelWidthStyles();
const newWidth =
parseInt(Math.max(minWidth, Math.min(targetWidth, maxWidth)), 10) ||
width;
const valueText = ngettext('{num} pixel', '{num} pixels', newWidth).replace(
'{num}',
newWidth,
);
sidePanelWrapper.style.width = `${newWidth}px`;
widthInput.value = 100 - ((newWidth - minWidth) / range) * 100;
widthInput.setAttribute('aria-valuetext', valueText);
// Save the new width to localStorage unless we're in the explorer
if (inExplorer) return;
try {
localStorage.setItem('wagtail:side-panel-width', newWidth);
} catch (e) {
// Proceed without saving the side panel width.
}
};
let startPos;
let startWidth;
const onPointerMove = (e) => {
if (!e.screenX || !startPos || !startWidth) return;
const delta = startPos - e.screenX;
setSidePanelWidth(startWidth + delta);
};
resizeGrip.addEventListener('pointerdown', (e) => {
// Remember the starting position and width of the side panel, so we can
// calculate the new width based on the position change during the drag and
// not resize the panel when it has gone past the minimum/maximum width.
startPos = e.screenX;
startWidth = getSidePanelWidthStyles().width;
document.body.classList.add('side-panel-resizing');
resizeGrip.setPointerCapture(e.pointerId);
resizeGrip.addEventListener('pointermove', onPointerMove);
});
resizeGrip.addEventListener('pointerup', (e) => {
resizeGrip.removeEventListener('pointermove', onPointerMove);
resizeGrip.releasePointerCapture(e.pointerId);
document.body.classList.remove('side-panel-resizing');
});
// Handle resizing with keyboard using a hidden range input.
widthInput.addEventListener('change', (event) => {
const { minWidth, range } = getSidePanelWidthStyles();
const inputPercentage = 100 - parseInt(event.target.value, 10);
const newWidth = minWidth + (range * inputPercentage) / 100;
setSidePanelWidth(newWidth);
});
// Open the last opened panel if not in explorer,
// use timeout to allow comments to load first
setTimeout(() => {
@ -107,8 +194,9 @@ export default function initSidePanel() {
if (!inExplorer && sidePanelOpen) {
setPanel(sidePanelOpen);
}
setSidePanelWidth(localStorage.getItem('wagtail:side-panel-width'));
} catch (e) {
// Proceed without remembering the last-open panel.
// Proceed without remembering the last-open panel and the panel width.
}
// Skip the animation on initial load only,

Wyświetl plik

@ -19,6 +19,7 @@ depth: 1
* Ensure that the `rebuild_references_index` command can run without console output if called with `--verbosity 0` (Omerzahid Ali, Aman Pandey)
* Add full support for secondary buttons with icons in the Wagtail design system - `button bicolor button--icon button-secondary` including the `button-small` variant (Seremba Patrick)
* Add [`purge_embeds`](purge_embeds) management command to delete all the cached embed objects in the database (Aman Pandey)
* Make it possible to resize the page editors side panels (Sage Abdullah)
### Bug fixes

Wyświetl plik

@ -5,6 +5,14 @@
{% icon name="expand-right" %}
</button>
<div class="form-side__resize-grip-container">
<label class="form-side__resize-grip" data-form-side-resize-grip>
<input type="range" step="10" class="form-side__width-input" name="wagtail-side-panel-width" data-form-side-width-input />
<span class="w-sr-only">{% trans 'Side panel width' %}</span>
{% icon name="grip" %}
</label>
</div>
{% for panel in side_panels %}
<div class="form-side__panel" data-side-panel="{{ panel.name }}" hidden>
<h2 id="side-panel-{{ panel.name }}-title" class="w-sr-only">{{ panel.title }}</h2>