Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Site editor: obviate sidebar context #69172

Draft
wants to merge 2 commits into
base: fix/edit-site-back-button
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ import {
import { isRTL } from '@wordpress/i18n';
import { chevronRightSmall, chevronLeftSmall, Icon } from '@wordpress/icons';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { useContext } from '@wordpress/element';

/**
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
import { SidebarNavigationContext } from '../sidebar';
import { useNavStep } from '../sidebar';

const { useHistory, useLink } = unlock( routerPrivateApis );

Expand All @@ -36,16 +35,14 @@ export default function SidebarNavigationItem( {
...props
} ) {
const history = useHistory();
const { navigate } = useContext( SidebarNavigationContext );
const navStep = useNavStep( 'forward', !! uid && `[id="${ uid }"]` );
// If there is no custom click handler, create one that navigates to `params`.
function handleClick( e ) {
if ( onClick ) {
onClick( e );
navigate( 'forward' );
} else if ( to ) {
e.preventDefault();
history.navigate( to );
navigate( 'forward', `[id="${ uid }"]` );
history.navigate( to, { state: navStep } );
}
}
const linkProps = useLink( to );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { chevronRight, chevronLeft } from '@wordpress/icons';
import { store as coreStore } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { useContext } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -28,7 +27,7 @@ import {
isPreviewingTheme,
currentlyPreviewingTheme,
} from '../../utils/is-previewing-theme';
import { SidebarNavigationContext } from '../sidebar';
import { useNavStep } from '../sidebar';

const { useHistory, useLocation } = unlock( routerPrivateApis );

Expand Down Expand Up @@ -61,8 +60,8 @@ export default function SidebarNavigationScreen( {
);
const location = useLocation();
const history = useHistory();
const { navigate } = useContext( SidebarNavigationContext );
const backPath = backPathProp ?? location.state?.backPath;
const navStep = useNavStep( 'back' );
const icon = isRTL() ? chevronRight : chevronLeft;

return (
Expand All @@ -82,8 +81,9 @@ export default function SidebarNavigationScreen( {
{ ! isRoot && (
<SidebarButton
onClick={ () => {
history.navigate( backPath );
navigate( 'back' );
history.navigate( backPath, {
state: navStep,
} );
} }
icon={ icon }
label={ __( 'Back' ) }
Expand Down
87 changes: 40 additions & 47 deletions packages/edit-site/src/components/sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,24 @@ import clsx from 'clsx';
/**
* WordPress dependencies
*/
import {
createContext,
useContext,
useState,
useRef,
useLayoutEffect,
} from '@wordpress/element';
import { useState, useRef, useLayoutEffect } from '@wordpress/element';
import { focus } from '@wordpress/dom';
import { privateApis as routerPrivateApis } from '@wordpress/router';

export const SidebarNavigationContext = createContext( () => {} );
// Focus a sidebar element after a navigation. The element to focus is either
/**
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';

const { useLocation } = unlock( routerPrivateApis );

// Focus an element after a navigation. The element to focus is either
// specified by `focusSelector` (when navigating back) or it is the first
// tabbable element (usually the "Back" button).
// tabbable element in the sidebar (usually the "Back" button).
function focusSidebarElement( el, direction, focusSelector ) {
let elementToFocus;
if ( direction === 'back' && focusSelector ) {
elementToFocus = el.querySelector( focusSelector );
elementToFocus = el.ownerDocument.querySelector( focusSelector );
}
if ( direction !== null && ! elementToFocus ) {
const [ firstTabbable ] = focus.tabbable.find( el );
Expand All @@ -31,40 +32,36 @@ function focusSidebarElement( el, direction, focusSelector ) {
elementToFocus?.focus();
}

// Navigation state that is updated when navigating back or forward. Helps us
// manage the animations and also focus.
function createNavState() {
let state = {
direction: null,
focusSelector: null,
};

/**
* Helper for creating `navStep` state that’s used to manage animations and focus.
* @param {'back'|'forward'} direction
* @param {string} [focusSelector]
*/
export function useNavStep( direction, focusSelector ) {
const { navStep: priorNavStep = {} } = useLocation().state || {};
return {
get() {
return state;
},
navigate( direction, focusSelector = null ) {
state = {
direction,
focusSelector:
direction === 'forward' && focusSelector
? focusSelector
: state.focusSelector,
};
navStep: {
direction,
focusSelector:
direction === 'forward' && focusSelector
? focusSelector
: priorNavStep.focusSelector,
},
};
}

function SidebarContentWrapper( { children, shouldAnimate } ) {
const navState = useContext( SidebarNavigationContext );
const { navStep } = useLocation().state || {};
const wrapperRef = useRef();
const [ navAnimation, setNavAnimation ] = useState( null );

useLayoutEffect( () => {
const { direction, focusSelector } = navState.get();
focusSidebarElement( wrapperRef.current, direction, focusSelector );
setNavAnimation( direction );
}, [ navState ] );
if ( navStep ) {
const { direction, focusSelector } = navStep;
focusSidebarElement( wrapperRef.current, direction, focusSelector );
setNavAnimation( direction ?? null );
}
}, [ navStep ] );

const wrapperCls = clsx(
'edit-site-sidebar__screen-wrapper',
Expand Down Expand Up @@ -92,18 +89,14 @@ export default function SidebarContent( {
shouldAnimate,
children,
} ) {
const [ navState ] = useState( createNavState );

return (
<SidebarNavigationContext.Provider value={ navState }>
<div className="edit-site-sidebar__content">
<SidebarContentWrapper
shouldAnimate={ shouldAnimate }
key={ routeKey }
>
{ children }
</SidebarContentWrapper>
</div>
</SidebarNavigationContext.Provider>
<div className="edit-site-sidebar__content">
<SidebarContentWrapper
shouldAnimate={ shouldAnimate }
key={ routeKey }
>
{ children }
</SidebarContentWrapper>
</div>
);
}
12 changes: 7 additions & 5 deletions packages/edit-site/src/components/site-hub/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { __ } from '@wordpress/i18n';
import { store as coreStore } from '@wordpress/core-data';
import { decodeEntities } from '@wordpress/html-entities';
import { memo, forwardRef, useContext } from '@wordpress/element';
import { memo, forwardRef } from '@wordpress/element';
import { search } from '@wordpress/icons';
import { store as commandsStore } from '@wordpress/commands';
import { displayShortcut } from '@wordpress/keycodes';
Expand All @@ -28,8 +28,9 @@ import { privateApis as routerPrivateApis } from '@wordpress/router';
import { store as editSiteStore } from '../../store';
import SiteIcon from '../site-icon';
import { unlock } from '../../lock-unlock';
import { useNavStep } from '../sidebar';

const { useHistory } = unlock( routerPrivateApis );
import { SidebarNavigationContext } from '../sidebar';

const SiteHub = memo(
forwardRef( ( { isTransparent }, ref ) => {
Expand Down Expand Up @@ -118,7 +119,7 @@ export default SiteHub;
export const SiteHubMobile = memo(
forwardRef( ( { isTransparent }, ref ) => {
const history = useHistory();
const { navigate } = useContext( SidebarNavigationContext );
const navStep = useNavStep( 'back' );

const { dashboardLink, isBlockTheme, homeUrl, siteTitle } = useSelect(
( select ) => {
Expand Down Expand Up @@ -167,8 +168,9 @@ export const SiteHubMobile = memo(
}
: {
onClick: () => {
history.navigate( '/' );
navigate( 'back' );
history.navigate( '/', {
state: navStep,
} );
},
label: __( 'Go to Site Editor' ),
} ) }
Expand Down
Loading