Skip to content

Commit

Permalink
Editor: Animate opening and closing editor right sidebar (#60561)
Browse files Browse the repository at this point in the history
Co-authored-by: youknowriad <[email protected]>
Co-authored-by: jameskoster <[email protected]>
Co-authored-by: jasmussen <[email protected]>
Co-authored-by: ellatrix <[email protected]>
  • Loading branch information
5 people authored Apr 11, 2024
1 parent b2015e7 commit b92efc1
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 191 deletions.
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- `ExternalLink`: Use unicode arrow instead of svg icon ([#60255](https://github.com/WordPress/gutenberg/pull/60255)).
- `ProgressBar`: Move the indicator width styles from emotion to a CSS variable ([#60388](https://github.com/WordPress/gutenberg/pull/60388)).
- `Text`: Add `text-wrap: pretty;` to improve wrapping. ([#60164](https://github.com/WordPress/gutenberg/pull/60164)).
- `Navigator`: Navigation to the active path doesn't create a new location history. ([#60561](https://github.com/WordPress/gutenberg/pull/60561))

### Bug Fix

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ function routerReducer(
action: RouterAction
): RouterState {
let { screens, locationHistory, matchedPath } = state;

switch ( action.type ) {
case 'add':
screens = addScreen( state, action.screen );
Expand All @@ -158,6 +157,13 @@ function routerReducer(
locationHistory = goBack( state );
break;
case 'goto':
if (
locationHistory.length &&
action.path ===
locationHistory[ locationHistory.length - 1 ].path
) {
break;
}
locationHistory = goTo( state, action.path, action.options );
break;
case 'gotoparent':
Expand Down
31 changes: 4 additions & 27 deletions packages/edit-post/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
privateApis as blockEditorPrivateApis,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { Button, ScrollLock } from '@wordpress/components';
import { ScrollLock } from '@wordpress/components';
import { useViewportMatch } from '@wordpress/compose';
import { PluginArea } from '@wordpress/plugins';
import { __, _x, sprintf } from '@wordpress/i18n';
Expand Down Expand Up @@ -139,8 +139,7 @@ function Layout( { initialPost } ) {
const isWideViewport = useViewportMatch( 'large' );
const isLargeViewport = useViewportMatch( 'medium' );

const { openGeneralSidebar, closeGeneralSidebar } =
useDispatch( editPostStore );
const { closeGeneralSidebar } = useDispatch( editPostStore );
const { createErrorNotice } = useDispatch( noticesStore );
const { setIsInserterOpened } = useDispatch( editorStore );
const {
Expand Down Expand Up @@ -206,11 +205,6 @@ function Layout( { initialPost } ) {

const styles = useEditorStyles();

const openSidebarPanel = () =>
openGeneralSidebar(
hasBlockSelected ? 'edit-post/block' : 'edit-post/document'
);

// Inserter and Sidebars are mutually exclusive
useEffect( () => {
if ( sidebarIsOpened && ! isHugeViewport ) {
Expand Down Expand Up @@ -313,25 +307,8 @@ function Layout( { initialPost } ) {
editorNotices={ <EditorNotices /> }
secondarySidebar={ secondarySidebar() }
sidebar={
( ( isMobileViewport && sidebarIsOpened ) ||
( ! isMobileViewport && ! isDistractionFree ) ) && (
<>
{ ! isMobileViewport && ! sidebarIsOpened && (
<div className="edit-post-layout__toggle-sidebar-panel">
<Button
variant="secondary"
className="edit-post-layout__toggle-sidebar-panel-button"
onClick={ openSidebarPanel }
aria-expanded={ false }
>
{ hasBlockSelected
? __( 'Open block settings' )
: __( 'Open document settings' ) }
</Button>
</div>
) }
<ComplementaryArea.Slot scope="core/edit-post" />
</>
! isDistractionFree && (
<ComplementaryArea.Slot scope="core/edit-post" />
)
}
notices={ <EditorSnackbars /> }
Expand Down
86 changes: 37 additions & 49 deletions packages/edit-post/src/components/sidebar/settings-sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ function onActionPerformed( actionId, items ) {
}
}

const SidebarContent = ( {
sidebarName,
keyboardShortcut,
isEditingTemplate,
} ) => {
const SidebarContent = ( { tabName, keyboardShortcut, isEditingTemplate } ) => {
const tabListRef = useRef( null );
// Because `PluginSidebarEditPost` renders a `ComplementaryArea`, we
// need to forward the `Tabs` context so it can be passed through the
Expand All @@ -86,7 +82,7 @@ const SidebarContent = ( {
// We are purposefully using a custom `data-tab-id` attribute here
// because we don't want rely on any assumptions about `Tabs`
// component internals.
( element ) => element.getAttribute( 'data-tab-id' ) === sidebarName
( element ) => element.getAttribute( 'data-tab-id' ) === tabName
);
const activeElement = selectedTabElement?.ownerDocument.activeElement;
const tabsHasFocus = tabsElements.some( ( element ) => {
Expand All @@ -99,11 +95,11 @@ const SidebarContent = ( {
) {
selectedTabElement?.focus();
}
}, [ sidebarName ] );
}, [ tabName ] );

return (
<PluginSidebarEditPost
identifier={ sidebarName }
identifier={ tabName }
header={
<Tabs.Context.Provider value={ tabsContextValue }>
<SettingsHeader ref={ tabListRef } />
Expand Down Expand Up @@ -153,41 +149,38 @@ const SidebarContent = ( {
};

const SettingsSidebar = () => {
const {
sidebarName,
isSettingsSidebarActive,
keyboardShortcut,
isEditingTemplate,
} = useSelect( ( select ) => {
// The settings sidebar is used by the edit-post/document and edit-post/block sidebars.
// sidebarName represents the sidebar that is active or that should be active when the SettingsSidebar toggle button is pressed.
// If one of the two sidebars is active the component will contain the content of that sidebar.
// When neither of the two sidebars is active we can not simply return null, because the PluginSidebarEditPost
// component, besides being used to render the sidebar, also renders the toggle button. In that case sidebarName
// should contain the sidebar that will be active when the toggle button is pressed. If a block
// is selected, that should be edit-post/block otherwise it's edit-post/document.
let sidebar = select( interfaceStore ).getActiveComplementaryArea(
editPostStore.name
);
let isSettingsSidebar = true;
if ( ! [ sidebars.document, sidebars.block ].includes( sidebar ) ) {
isSettingsSidebar = false;
if ( select( blockEditorStore ).getBlockSelectionStart() ) {
sidebar = sidebars.block;
const { tabName, keyboardShortcut, isEditingTemplate } = useSelect(
( select ) => {
const shortcut = select(
keyboardShortcutsStore
).getShortcutRepresentation( 'core/edit-post/toggle-sidebar' );

const sidebar = select( interfaceStore ).getActiveComplementaryArea(
editPostStore.name
);
const _isEditorSidebarOpened = [
sidebars.block,
sidebars.document,
].includes( sidebar );
let _tabName = sidebar;
if ( ! _isEditorSidebarOpened ) {
_tabName = !! select(
blockEditorStore
).getBlockSelectionStart()
? sidebars.block
: sidebars.document;
}
sidebar = sidebars.document;
}
const shortcut = select(
keyboardShortcutsStore
).getShortcutRepresentation( 'core/edit-post/toggle-sidebar' );
return {
sidebarName: sidebar,
isSettingsSidebarActive: isSettingsSidebar,
keyboardShortcut: shortcut,
isEditingTemplate:
select( editorStore ).getCurrentPostType() === 'wp_template',
};
}, [] );

return {
tabName: _tabName,
keyboardShortcut: shortcut,
isEditingTemplate:
select( editorStore ).getCurrentPostType() ===
'wp_template',
};
},
[]
);

const { openGeneralSidebar } = useDispatch( editPostStore );

Expand All @@ -202,17 +195,12 @@ const SettingsSidebar = () => {

return (
<Tabs
// Due to how this component is controlled (via a value from the
// `interfaceStore`), when the sidebar closes the currently selected
// tab can't be found. This causes the component to continuously reset
// the selection to `null` in an infinite loop.Proactively setting
// the selected tab to `null` avoids that.
selectedTabId={ isSettingsSidebarActive ? sidebarName : null }
selectedTabId={ tabName }
onSelect={ onTabSelect }
selectOnMove={ false }
>
<SidebarContent
sidebarName={ sidebarName }
tabName={ tabName }
keyboardShortcut={ keyboardShortcut }
isEditingTemplate={ isEditingTemplate }
/>
Expand Down
15 changes: 0 additions & 15 deletions packages/edit-post/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,3 @@ body.js.block-editor-page {
}

@include wordpress-admin-schemes();

// The edit-site package adds or removes the sidebar when it's opened or closed.
// The edit-post package, however, always has the sidebar in the canvas.
// These edit-post specific rules ensures there isn't a border on the right of
// the canvas when a sidebar is visually closed.
.interface-interface-skeleton__sidebar {
border-left: none;

.is-sidebar-opened & {
@include break-medium() {
border-left: $border-width solid $gray-200;
overflow: hidden scroll;
}
}
}
2 changes: 0 additions & 2 deletions packages/edit-site/src/components/editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,7 @@ export default function Editor( { isLoading, onClick } ) {
( shouldShowListView && <ListViewSidebar /> ) )
}
sidebar={
! isDistractionFree &&
isEditMode &&
isRightSidebarOpen &&
! isDistractionFree && (
<ComplementaryArea.Slot scope="core/edit-site" />
)
Expand Down
45 changes: 16 additions & 29 deletions packages/edit-site/src/components/sidebar-edit-mode/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ const { Slot: InspectorSlot, Fill: InspectorFill } = createSlotFill(
);
export const SidebarInspectorFill = InspectorFill;

const FillContents = ( {
sidebarName,
isEditingPage,
supportsGlobalStyles,
} ) => {
const FillContents = ( { tabName, isEditingPage, supportsGlobalStyles } ) => {
const tabListRef = useRef( null );
// Because `DefaultSidebar` renders a `ComplementaryArea`, we
// need to forward the `Tabs` context so it can be passed through the
Expand All @@ -56,7 +52,7 @@ const FillContents = ( {
// We are purposefully using a custom `data-tab-id` attribute here
// because we don't want rely on any assumptions about `Tabs`
// component internals.
( element ) => element.getAttribute( 'data-tab-id' ) === sidebarName
( element ) => element.getAttribute( 'data-tab-id' ) === tabName
);
const activeElement = selectedTabElement?.ownerDocument.activeElement;
const tabsHasFocus = tabsElements.some( ( element ) => {
Expand All @@ -69,12 +65,12 @@ const FillContents = ( {
) {
selectedTabElement?.focus();
}
}, [ sidebarName ] );
}, [ tabName ] );

return (
<>
<DefaultSidebar
identifier={ sidebarName }
identifier={ tabName }
title={ __( 'Settings' ) }
icon={ isRTL() ? drawerLeft : drawerRight }
closeLabel={ __( 'Close Settings' ) }
Expand Down Expand Up @@ -108,31 +104,34 @@ const FillContents = ( {

export function SidebarComplementaryAreaFills() {
const {
sidebar,
tabName,
isEditorSidebarOpened,
hasBlockSelection,
supportsGlobalStyles,
isEditingPage,
isEditorOpen,
} = useSelect( ( select ) => {
const _sidebar =
const sidebar =
select( interfaceStore ).getActiveComplementaryArea( STORE_NAME );

const _isEditorSidebarOpened = [
SIDEBAR_BLOCK,
SIDEBAR_TEMPLATE,
].includes( _sidebar );
const { getCanvasMode } = unlock( select( editSiteStore ) );
].includes( sidebar );
let _tabName = sidebar;
if ( ! _isEditorSidebarOpened ) {
_tabName = !! select( blockEditorStore ).getBlockSelectionStart()
? SIDEBAR_BLOCK
: SIDEBAR_TEMPLATE;
}

return {
sidebar: _sidebar,
tabName: _tabName,
isEditorSidebarOpened: _isEditorSidebarOpened,
hasBlockSelection:
!! select( blockEditorStore ).getBlockSelectionStart(),
supportsGlobalStyles:
select( coreStore ).getCurrentTheme()?.is_block_theme,
isEditingPage: select( editSiteStore ).isPage(),
isEditorOpen: getCanvasMode() === 'edit',
};
}, [] );
const { enableComplementaryArea } = useDispatch( interfaceStore );
Expand All @@ -157,11 +156,6 @@ export function SidebarComplementaryAreaFills() {
enableComplementaryArea,
] );

let sidebarName = sidebar;
if ( ! isEditorSidebarOpened ) {
sidebarName = hasBlockSelection ? SIDEBAR_BLOCK : SIDEBAR_TEMPLATE;
}

// `newSelectedTabId` could technically be falsey if no tab is selected (i.e.
// the initial render) or when we don't want a tab displayed (i.e. the
// sidebar is closed). These cases should both be covered by the `!!` check
Expand All @@ -177,19 +171,12 @@ export function SidebarComplementaryAreaFills() {

return (
<Tabs
// Due to how this component is controlled (via a value from the
// edit-site store), when the sidebar closes the currently selected
// tab can't be found. This causes the component to continuously reset
// the selection to `null` in an infinite loop. Proactively setting
// the selected tab to `null` avoids that.
selectedTabId={
isEditorOpen && isEditorSidebarOpened ? sidebarName : null
}
selectedTabId={ tabName }
onSelect={ onTabSelect }
selectOnMove={ false }
>
<FillContents
sidebarName={ sidebarName }
tabName={ tabName }
isEditingPage={ isEditingPage }
supportsGlobalStyles={ supportsGlobalStyles }
/>
Expand Down
6 changes: 1 addition & 5 deletions packages/edit-widgets/src/components/layout/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,7 @@ function Interface( { blockEditorSettings } ) {
} }
header={ <Header /> }
secondarySidebar={ hasSecondarySidebar && <SecondarySidebar /> }
sidebar={
hasSidebarEnabled && (
<ComplementaryArea.Slot scope="core/edit-widgets" />
)
}
sidebar={ <ComplementaryArea.Slot scope="core/edit-widgets" /> }
content={
<>
<WidgetAreasBlockEditorContent
Expand Down
Loading

0 comments on commit b92efc1

Please sign in to comment.