Skip to content

Commit b200d6d

Browse files
ramonjdandrewserongfcoveramt-hamanojordesign
authored
Media Editor: refactor the panel layout (#81840)
Co-authored-by: ramonjd <ramonopoly@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org> Co-authored-by: fcoveram <fcoveram@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: jordesign <jordesign@git.wordpress.org>
1 parent 6340786 commit b200d6d

14 files changed

Lines changed: 475 additions & 454 deletions

File tree

‎package-lock.json‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/base-styles/_z-index.scss‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ $z-layers: (
9393
".editor-post-template__swap-template-modal": 1000001,
9494
".editor-post-template__create-template-modal": 1000001,
9595
".editor-sync-connection-error-modal": 1000001,
96-
".media-editor-modal__footer": 1000001,
9796
".components-snackbar-list.media-editor-modal__snackbar": 1000001,
9897

9998
// Show media replace flow and similar popovers beneath the media modal when its open.

‎packages/media-editor/CHANGELOG.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66

77
### Enhancements
88

9-
- Add a `scope` prop to `MediaEditor` so each frame can keep its own persisted details-sidebar visibility ([#81559](https://github.com/WordPress/gutenberg/pull/81559)).
9+
- `MediaEditor`: replace `ComplementaryArea` and `InterfaceSkeleton` with a layout the media editor owns, and widen the settings panel so its controls and fields are not so cramped ([#81840](https://github.com/WordPress/gutenberg/pull/81840)).
10+
- `MediaEditor.ImageControls` is removed, and `renderFrame` drops `hasCanvas`. Both were added in the same unreleased cycle: the transform controls belong to the Crop panel, and `HistoryActions` already renders nothing when a panel covers the canvas, so a frame gating on it repeated that check from the outside. The `scope` prop is removed too: it named an `@wordpress/interface` scope that persisted the panel's open state, which went with `ComplementaryArea` ([#81840](https://github.com/WordPress/gutenberg/pull/81840)).
1011
- Expose the header, history (reset/undo/redo), save (cancel/save) and image control clusters as `MediaEditor` sub-components, so each frame imports and arranges them to suit its own chrome. `renderFrame` now passes data only: `footerActions` is gone, `footerLayout` is now `layout`, and `isImage` is new. `showCloseButton` moves from `MediaEditor` to `MediaEditor.HeaderActions` ([#81563](https://github.com/WordPress/gutenberg/pull/81563)).
1112

1213
### Bug Fixes
1314

15+
- `MediaEditor`: make the Details fields reachable below the `small` breakpoint. `ComplementaryArea` closed the sidebar on small viewports and offered no way to re-open it, so the fields could not be edited on a phone at all ([#81840](https://github.com/WordPress/gutenberg/pull/81840)).
1416
- Keep the Details sidebar from clipping focus outlines, with balanced horizontal padding ([#81703](https://github.com/WordPress/gutenberg/pull/81703)).
1517
- Keep initial focus on the modal dialog frame instead of moving it to the crop area once the image loads ([#81541](https://github.com/WordPress/gutenberg/pull/81541)).
1618

‎packages/media-editor/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
],
4545
"dependencies": {
4646
"@wordpress/a11y": "file:../a11y",
47+
"@wordpress/admin-ui": "file:../admin-ui",
4748
"@wordpress/api-fetch": "file:../api-fetch",
4849
"@wordpress/base-styles": "file:../base-styles",
4950
"@wordpress/components": "file:../components",
@@ -55,7 +56,6 @@
5556
"@wordpress/element": "file:../element",
5657
"@wordpress/i18n": "file:../i18n",
5758
"@wordpress/icons": "file:../icons",
58-
"@wordpress/interface": "file:../interface",
5959
"@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts",
6060
"@wordpress/keycodes": "file:../keycodes",
6161
"@wordpress/notices": "file:../notices",

‎packages/media-editor/src/components/media-editor-crop-panel/index.tsx‎

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,21 @@ export interface MediaEditorCropPanelProps {
1616
onAspectRatioChange: ( value: string ) => void;
1717
/** Aspect-ratio presets to display in the selector. */
1818
aspectRatioOptions: AspectRatioPreset[];
19-
/**
20-
* When `true`, render the rotate/flip/zoom image controls at the top of
21-
* the panel. Used on wide viewports where the footer no longer carries
22-
* them.
23-
*/
24-
showTransformControls?: boolean;
2519
}
2620

2721
/**
28-
* Sidebar panel for crop controls. Renders the aspect-ratio selector, plus the
29-
* rotate/flip and zoom controls on wide viewports (these move to the footer
30-
* toolbar when the sidebar collapses).
22+
* Sidebar panel for crop controls: rotate, flip and zoom above the
23+
* aspect-ratio selector. Rendered where the panel docks; below that the
24+
* transform controls sit under the canvas instead, placed by the editor.
3125
* @param props
3226
* @param props.aspectRatioValue
3327
* @param props.onAspectRatioChange
3428
* @param props.aspectRatioOptions
35-
* @param props.showTransformControls
3629
*/
3730
export default function MediaEditorCropPanel( {
3831
aspectRatioValue,
3932
onAspectRatioChange,
4033
aspectRatioOptions,
41-
showTransformControls = false,
4234
}: MediaEditorCropPanelProps ) {
4335
return (
4436
// Tag the whole panel as a crop-control region so the modal's
@@ -52,7 +44,7 @@ export default function MediaEditorCropPanel( {
5244
<VisuallyHidden render={ <h2 /> }>
5345
{ __( 'Crop options' ) }
5446
</VisuallyHidden>
55-
{ showTransformControls && <MediaEditorImageControls withLabels /> }
47+
<MediaEditorImageControls withLabels />
5648
<SelectControl
5749
label={ __( 'Aspect ratio' ) }
5850
value={ aspectRatioValue }

‎packages/media-editor/src/components/media-editor-crop-panel/test/index.tsx‎

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,9 @@ describe( 'MediaEditorCropPanel', () => {
4444
).toBe( '0' );
4545
} );
4646

47-
it( 'omits the image controls by default', () => {
47+
it( 'renders rotate, flip and zoom controls', () => {
4848
setupCropPanel();
4949

50-
expect( screen.queryByText( 'Rotate' ) ).not.toBeInTheDocument();
51-
expect( screen.queryByText( 'Flip' ) ).not.toBeInTheDocument();
52-
expect( screen.queryByText( 'Zoom' ) ).not.toBeInTheDocument();
53-
} );
54-
55-
it( 'renders rotate, flip and zoom controls when showTransformControls is set', () => {
56-
setupCropPanel( { showTransformControls: true } );
57-
5850
expect( screen.getByText( 'Rotate' ) ).toBeInTheDocument();
5951
expect( screen.getByText( 'Flip' ) ).toBeInTheDocument();
6052
expect( screen.getByText( 'Zoom' ) ).toBeInTheDocument();
@@ -67,7 +59,7 @@ describe( 'MediaEditorCropPanel', () => {
6759
} );
6860

6961
it( 'renders the image controls above the aspect-ratio selector', () => {
70-
setupCropPanel( { showTransformControls: true } );
62+
setupCropPanel();
7163

7264
const rotate = screen.getByText( 'Rotate' );
7365
const aspectRatio = screen.getByLabelText( 'Aspect ratio' );

‎packages/media-editor/src/components/media-editor-modal/index.tsx‎

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,21 @@ interface MediaEditorModalProps {
2626
aspectRatioPresets?: AspectRatioPreset[];
2727
}
2828

29-
interface ModalFooterProps {
30-
layout: 'wide' | 'narrow';
31-
}
32-
3329
/**
34-
* The modal's footer chrome. The fine-rotation ruler always lives under the
35-
* canvas (in `media-editor__content`), never here, so it stays constrained to
36-
* the canvas column at every viewport. One JSX tree per layout; DOM order
37-
* matches visual order.
30+
* The modal's footer chrome. The fine-rotation ruler and the image controls
31+
* both live under the canvas (in `media-editor__content`), never here, so the
32+
* footer has one layout at every width: History on the left, Cancel/Save on
33+
* the right.
3834
*/
39-
function ModalFooter( { layout }: ModalFooterProps ) {
35+
function ModalFooter() {
4036
return (
4137
<div
42-
className={ `media-editor-modal__footer is-${ layout }` }
38+
className="media-editor-modal__footer"
4339
role="region"
4440
aria-label={ __( 'Editor actions' ) }
4541
>
46-
{ layout === 'wide' ? (
47-
// Sidebar is a column: the image controls live in the Crop
48-
// panel, so the footer is just History + Cancel/Save.
49-
<>
50-
<MediaEditor.HistoryActions />
51-
<MediaEditor.SaveActions />
52-
</>
53-
) : (
54-
// Sidebar collapsed: the image controls drop into the footer.
55-
<>
56-
<MediaEditor.ImageControls />
57-
<div className="media-editor-modal__footer-row">
58-
<MediaEditor.HistoryActions />
59-
<MediaEditor.SaveActions />
60-
</div>
61-
</>
62-
) }
42+
<MediaEditor.HistoryActions />
43+
<MediaEditor.SaveActions />
6344
</div>
6445
);
6546
}
@@ -144,7 +125,6 @@ export function MediaEditorModal( {
144125
} }
145126
renderFrame={ ( {
146127
children,
147-
layout,
148128
onRequestClose,
149129
onKeyDown,
150130
shouldCloseOnClickOutside,
@@ -166,7 +146,7 @@ export function MediaEditorModal( {
166146
}
167147
>
168148
{ children }
169-
<ModalFooter layout={ layout } />
149+
<ModalFooter />
170150
</Modal>
171151
</ShortcutProvider>
172152
) }

‎packages/media-editor/src/components/media-editor-modal/style.scss‎

Lines changed: 8 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -21,61 +21,20 @@
2121
min-height: 0;
2222
}
2323

24-
// Footer chrome — two layouts driven by `is-wide` / `is-narrow` modifier
25-
// classes set from the media editor at the sidebar-collapse breakpoint.
26-
// Wide is a single flex row (History | Cancel/Save); narrow stacks via
27-
// `flex-direction: column` (image controls above the History |
28-
// Cancel/Save row). Each layout has its own JSX tree (not `order`
29-
// reshuffling, which the project's stylelint rule treats as an a11y red
30-
// flag), so DOM order always matches visual order.
24+
// Footer chrome. The image controls live under the canvas at every viewport,
25+
// so the footer has a single layout at every width: History on the left,
26+
// Cancel/Save on the right.
3127
.media-editor-modal.components-modal__frame .media-editor-modal__footer {
3228
flex-shrink: 0;
3329
display: flex;
34-
gap: $grid-unit-20;
35-
// Borderless: sections are demarcated by the inset canvas panel and
36-
// spacing, not divider lines. 16px top / 32px sides / 24px bottom.
37-
padding: $grid-unit-20 $grid-unit-40 $grid-unit-30;
38-
background: $white;
39-
// Above the `.interface-interface-skeleton__sidebar` which has a z-index of 100000.
40-
z-index: z-index(".media-editor-modal__footer");
41-
42-
&.is-wide {
43-
flex-direction: row;
44-
align-items: center;
45-
46-
// Panel mode: the footer holds only History (left) and
47-
// Cancel/Save (right). `margin-left: auto` pins the actions to the
48-
// right edge whether or not History renders (e.g. non-image
49-
// attachments show only `SaveActions`).
50-
.media-editor__save-actions {
51-
margin-left: auto;
52-
}
53-
}
54-
55-
&.is-narrow {
56-
flex-direction: column;
57-
}
58-
59-
// Narrow only: image controls sit on their own row, centered.
60-
&.is-narrow > .media-editor-image-controls {
61-
align-self: center;
62-
}
63-
}
64-
65-
// Secondary row used by medium (History + Image controls + Cancel/Save) and
66-
// narrow (History + Cancel/Save). `margin-left: auto` on the image controls
67-
// cluster and on Cancel/Save splits any free space — History gets the
68-
// left edge, Cancel/Save the right edge, and the image controls (when
69-
// present, i.e. medium only) approximately centers. Exact centering only
70-
// holds when History and Cancel/Save have matching widths; in practice
71-
// they're close enough that the offset is imperceptible.
72-
.media-editor-modal__footer-row {
73-
display: flex;
74-
flex-wrap: wrap;
30+
flex-direction: row;
7531
align-items: center;
7632
gap: $grid-unit-20;
33+
padding: $grid-unit-30;
34+
background: $white;
7735

78-
.media-editor-image-controls,
36+
// `margin-left: auto` pins the actions to the right edge whether or not
37+
// History renders (e.g. non-image attachments show only `SaveActions`).
7938
.media-editor__save-actions {
8039
margin-left: auto;
8140
}

0 commit comments

Comments
 (0)