diff --git a/packages/edit-site/src/components/save-panel/index.js b/packages/edit-site/src/components/save-panel/index.js index 95ec9b9ffc8c4..1b96daea9fd69 100644 --- a/packages/edit-site/src/components/save-panel/index.js +++ b/packages/edit-site/src/components/save-panel/index.js @@ -31,7 +31,11 @@ const { EntitiesSavedStatesExtensible, NavigableRegion } = unlock( privateApis ); const { useLocation } = unlock( routerPrivateApis ); -const EntitiesSavedStatesForPreview = ( { onClose, renderDialog } ) => { +const EntitiesSavedStatesForPreview = ( { + onClose, + renderDialog, + isWithinModalDialog, +} ) => { const isDirtyProps = useEntitiesSavedStatesIsDirty(); let activateSaveLabel; if ( isDirtyProps.isDirty ) { @@ -76,22 +80,32 @@ const EntitiesSavedStatesForPreview = ( { onClose, renderDialog } ) => { saveEnabled: true, saveLabel: activateSaveLabel, renderDialog, + isWithinModalDialog, } } /> ); }; -const _EntitiesSavedStates = ( { onClose, renderDialog } ) => { +const _EntitiesSavedStates = ( { + onClose, + renderDialog, + isWithinModalDialog, +} ) => { if ( isPreviewingTheme() ) { return ( ); } return ( - + ); }; @@ -130,12 +144,10 @@ export default function SavePanel() { - <_EntitiesSavedStates onClose={ onClose } /> + <_EntitiesSavedStates onClose={ onClose } isWithinModalDialog /> ) : null; } diff --git a/packages/editor/README.md b/packages/editor/README.md index 3211e6664256d..472241efbb17d 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -402,6 +402,7 @@ _Parameters_ - _props_ `Object`: The component props. - _props.close_ `Function`: The function to close the dialog. - _props.renderDialog_ `boolean`: Whether to render the component with modal dialog behavior. +- _props.isWithinModalDialog_ `boolean`: Whether this component is rendered within a Modal component. _Returns_ diff --git a/packages/editor/src/components/entities-saved-states/entity-type-list.js b/packages/editor/src/components/entities-saved-states/entity-type-list.js index 71041dd9aebab..7cdf4c41e0f1f 100644 --- a/packages/editor/src/components/entities-saved-states/entity-type-list.js +++ b/packages/editor/src/components/entities-saved-states/entity-type-list.js @@ -94,7 +94,11 @@ export default function EntityTypeList( { } return ( - + { list.map( ( record ) => { return ( diff --git a/packages/editor/src/components/entities-saved-states/index.js b/packages/editor/src/components/entities-saved-states/index.js index 200473cccff70..abcace4155e53 100644 --- a/packages/editor/src/components/entities-saved-states/index.js +++ b/packages/editor/src/components/entities-saved-states/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + /** * WordPress dependencies */ @@ -29,18 +34,24 @@ function identity( values ) { /** * Renders the component for managing saved states of entities. * - * @param {Object} props The component props. - * @param {Function} props.close The function to close the dialog. - * @param {boolean} props.renderDialog Whether to render the component with modal dialog behavior. + * @param {Object} props The component props. + * @param {Function} props.close The function to close the dialog. + * @param {boolean} props.renderDialog Whether to render the component with modal dialog behavior. + * @param {boolean} props.isWithinModalDialog Whether this component is rendered within a Modal component. * * @return {React.ReactNode} The rendered component. */ -export default function EntitiesSavedStates( { close, renderDialog } ) { +export default function EntitiesSavedStates( { + close, + renderDialog, + isWithinModalDialog, +} ) { const isDirtyProps = useIsDirty(); return ( ); @@ -60,6 +71,7 @@ export default function EntitiesSavedStates( { close, renderDialog } ) { * @param {boolean} props.isDirty Flag indicating if there are dirty entities. * @param {Function} props.setUnselectedEntities Function to set unselected entities. * @param {Array} props.unselectedEntities Array of unselected entities. + * @param {boolean} props.isWithinModalDialog Whether this component is rendered within a Modal component. * * @return {React.ReactNode} The rendered component. */ @@ -74,6 +86,7 @@ export function EntitiesSavedStatesExtensible( { isDirty, setUnselectedEntities, unselectedEntities, + isWithinModalDialog, } ) { const saveButtonRef = useRef(); const { saveDirtyEntities } = unlock( useDispatch( editorStore ) ); @@ -109,83 +122,98 @@ export function EntitiesSavedStatesExtensible( { const [ saveDialogRef, saveDialogProps ] = useDialog( { onClose: () => dismissPanel(), } ); - const dialogLabel = useInstanceId( EntitiesSavedStatesExtensible, 'label' ); - const dialogDescription = useInstanceId( + const dialogLabelId = useInstanceId( + EntitiesSavedStatesExtensible, + 'entities-saved-states__panel-label' + ); + const dialogDescriptionId = useInstanceId( EntitiesSavedStatesExtensible, - 'description' + 'entities-saved-states__panel-description' ); const selectItemsToSaveDescription = !! dirtyEntityRecords.length ? __( 'Select the items you want to save.' ) : undefined; + const actionButtons = ( + <> + + { __( 'Cancel' ) } + + + saveDirtyEntities( { + onSave, + dirtyEntityRecords, + entitiesToSkip: unselectedEntities, + close, + } ) + } + className="editor-entities-saved-states__save-button" + > + { saveLabel } + + + ); + return (
- - - { __( 'Cancel' ) } - - - saveDirtyEntities( { - onSave, - dirtyEntityRecords, - entitiesToSkip: unselectedEntities, - close, - } ) - } - className="editor-entities-saved-states__save-button" - > - { saveLabel } - - + { ! isWithinModalDialog && ( + + { actionButtons } + + ) }
-
- +
+ { __( 'Are you ready to save?' ) } - { additionalPrompt }
-

- { isDirty - ? createInterpolateElement( - sprintf( - /* translators: %d: number of site changes waiting to be saved. */ - _n( - 'There is %d site change waiting to be saved.', - 'There are %d site changes waiting to be saved.', +

+ { additionalPrompt } +

+ { isDirty + ? createInterpolateElement( + sprintf( + /* translators: %d: number of site changes waiting to be saved. */ + _n( + 'There is %d site change waiting to be saved.', + 'There are %d site changes waiting to be saved.', + dirtyEntityRecords.length + ), dirtyEntityRecords.length ), - dirtyEntityRecords.length - ), - { strong: } - ) - : selectItemsToSaveDescription } -

+ { strong: } + ) + : selectItemsToSaveDescription } +

+
{ sortedPartitionedSavables.map( ( list ) => { @@ -198,6 +226,16 @@ export function EntitiesSavedStatesExtensible( { /> ); } ) } + + { isWithinModalDialog && ( + + { actionButtons } + + ) }
); } diff --git a/packages/editor/src/components/entities-saved-states/style.scss b/packages/editor/src/components/entities-saved-states/style.scss index e2c320678c322..4283a7ad1659d 100644 --- a/packages/editor/src/components/entities-saved-states/style.scss +++ b/packages/editor/src/components/entities-saved-states/style.scss @@ -16,14 +16,45 @@ } } -.entities-saved-states__description-heading { - font-size: $default-font-size; +.entities-saved-states__panel.is-within-modal-dialog { + .entities-saved-states__text-prompt { + padding: 0; + } + + .entities-saved-states__panel-body { + padding-left: 0; + padding-right: 0; + border: 0; + + > h2 { + margin-left: -1 * $grid-unit-20; + margin-right: -1 * $grid-unit-20; + margin-bottom: 0; + + button { + font-size: $font-size-x-small; + text-transform: uppercase; + } + } + } + + .entities-saved-states__text-prompt--header-wrapper { + display: none; + } + + .entities-saved-states__text-prompt--changes-count { + margin-top: 0; + margin-bottom: $grid-unit-30; + } + + .entities-saved-states__panel-footer { + margin-top: $grid-unit-20; + } } .entities-saved-states__changes { - color: $gray-700; - font-size: $helptext-font-size; - margin: $grid-unit-10 $grid-unit-20 0 $grid-unit-20; + font-size: $default-font-size; + margin: $grid-unit-05 $grid-unit-20 0 $grid-unit-30; list-style: disc; li {