diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss index 50af0938bccdb..4c9448d8712df 100644 --- a/packages/base-styles/_mixins.scss +++ b/packages/base-styles/_mixins.scss @@ -550,3 +550,36 @@ } /* stylelint-enable function-comma-space-after */ } + +@mixin custom-scrollbars-on-hover() { + visibility: hidden; + + $handle-color: #757575; + $track-color: #1e1e1e; + + // WebKit + &::-webkit-scrollbar { + width: 12px; + height: 12px; + } + &::-webkit-scrollbar-track { + background-color: $track-color; + } + &::-webkit-scrollbar-thumb { + background-color: $handle-color; + border-radius: 8px; + border: 3px solid transparent; + background-clip: padding-box; + } + + // Firefox 109+ and Chrome 111+ + scrollbar-color: $handle-color $track-color; // Syntax, "dark", "light", or "#handle-color #track-color" + scrollbar-width: thin; + scrollbar-gutter: stable; + + &:hover, + &:focus, + & > * { + visibility: visible; + } +} diff --git a/packages/e2e-tests/specs/experiments/blocks/post-comments-form.test.js b/packages/e2e-tests/specs/experiments/blocks/post-comments-form.test.js index 4253c38a3da04..5c36049468427 100644 --- a/packages/e2e-tests/specs/experiments/blocks/post-comments-form.test.js +++ b/packages/e2e-tests/specs/experiments/blocks/post-comments-form.test.js @@ -27,9 +27,10 @@ describe( 'Post Comments Form', () => { '.edit-site-sidebar-navigation-item', { text: /templates/i } ); - await expect( page ).toClick( '.components-heading > a', { - text: /singular/i, - } ); + await expect( page ).toClick( + '.edit-site-sidebar-navigation-item', + { text: /singular/i } + ); await enterEditMode(); // Insert post comments form diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss index f8b788704b936..746dcb4ef76fe 100644 --- a/packages/edit-site/src/components/layout/style.scss +++ b/packages/edit-site/src/components/layout/style.scss @@ -45,7 +45,9 @@ .edit-site-layout__sidebar { grid-area: sidebar; z-index: 1; - padding-top: $grid-unit-80; + overflow-y: auto; + max-height: calc(100vh - #{$header-height}); + @include custom-scrollbars-on-hover; // This is only necessary for the exit animation .edit-site-layout.is-full-canvas & { diff --git a/packages/edit-site/src/components/sidebar-navigation-item/index.js b/packages/edit-site/src/components/sidebar-navigation-item/index.js index a39ecfe7734bf..fb5cfdf1b32f8 100644 --- a/packages/edit-site/src/components/sidebar-navigation-item/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-item/index.js @@ -9,13 +9,14 @@ import classnames from 'classnames'; import { __experimentalItem as Item, __experimentalHStack as HStack, - FlexItem, + FlexBlock, } from '@wordpress/components'; -import { Icon } from '@wordpress/icons'; +import { chevronRight, Icon } from '@wordpress/icons'; export default function SidebarNavigationItem( { className, icon, + withChevron = false, children, ...props } ) { @@ -34,7 +35,14 @@ export default function SidebarNavigationItem( { icon={ icon } size={ 24 } /> - { children } + { children } + { withChevron && ( + + ) } ) } { ! icon && children } diff --git a/packages/edit-site/src/components/sidebar-navigation-item/style.scss b/packages/edit-site/src/components/sidebar-navigation-item/style.scss index 61885c0132fa2..7d77e2cb8b76d 100644 --- a/packages/edit-site/src/components/sidebar-navigation-item/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-item/style.scss @@ -1,9 +1,17 @@ .edit-site-sidebar-navigation-item.components-item { color: $gray-600; + border-width: $border-width-tab; &:hover, - &:focus, + &:focus { + color: $white; + background: $gray-800; + border-width: $border-width-tab; + } + &[aria-current] { color: $white; + background: var(--wp-admin-theme-color); + border-width: $border-width-tab; } } diff --git a/packages/edit-site/src/components/sidebar-navigation-root/index.js b/packages/edit-site/src/components/sidebar-navigation-root/index.js deleted file mode 100644 index 96c3a9324c0cf..0000000000000 --- a/packages/edit-site/src/components/sidebar-navigation-root/index.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * WordPress dependencies - */ -import { - __experimentalItemGroup as ItemGroup, - __experimentalVStack as VStack, - __experimentalHStack as HStack, - Button, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { layout, symbolFilled } from '@wordpress/icons'; -import { useDispatch } from '@wordpress/data'; -import { useViewportMatch } from '@wordpress/compose'; - -/** - * Internal dependencies - */ -import SidebarNavigationTitle from '../sidebar-navigation-title'; -import { useLink } from '../routes/link'; -import SidebarNavigationItem from '../sidebar-navigation-item'; -import { useLocation } from '../routes'; -import { store as editSiteStore } from '../../store'; -import getIsListPage from '../../utils/get-is-list-page'; - -export default function SidebarNavigationRoot() { - const { params } = useLocation(); - const isListPage = getIsListPage( params ); - const isEditorPage = ! isListPage; - const templatesLink = useLink( { - postType: 'wp_template', - postId: undefined, - } ); - const templatePartsLink = useLink( { - postType: 'wp_template_part', - postId: undefined, - } ); - const { __unstableSetCanvasMode } = useDispatch( editSiteStore ); - const isMobileViewport = useViewportMatch( 'medium', '<' ); - const isTemplatesPage = - params.postType === 'wp_template' && ! params.postId; - const isTemplatePartsPage = - params.postType === 'wp_template_part' && ! params.postId; - - return ( - - -
{ __( 'Design' ) }
- { ! isMobileViewport && isEditorPage && ( - - ) } - - } - /> - -
- ); -} diff --git a/packages/edit-site/src/components/sidebar-navigation-root/style.scss b/packages/edit-site/src/components/sidebar-navigation-root/style.scss deleted file mode 100644 index 7d2efc6efeb29..0000000000000 --- a/packages/edit-site/src/components/sidebar-navigation-root/style.scss +++ /dev/null @@ -1,3 +0,0 @@ -.edit-site-sidebar-navigation-root { - margin: 0 $button-size; -} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js new file mode 100644 index 0000000000000..9a7b4479c972b --- /dev/null +++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js @@ -0,0 +1,72 @@ +/** + * WordPress dependencies + */ +import { + __experimentalItemGroup as ItemGroup, + __experimentalHStack as HStack, + __experimentalNavigatorButton as NavigatorButton, + Button, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { layout, symbolFilled } from '@wordpress/icons'; +import { useDispatch } from '@wordpress/data'; +import { useViewportMatch } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import SidebarNavigationItem from '../sidebar-navigation-item'; +import { useLocation } from '../routes'; +import { store as editSiteStore } from '../../store'; +import getIsListPage from '../../utils/get-is-list-page'; + +export default function SidebarNavigationScreenMain() { + const { params } = useLocation(); + const isListPage = getIsListPage( params ); + const isEditorPage = ! isListPage; + const { __unstableSetCanvasMode } = useDispatch( editSiteStore ); + const isMobileViewport = useViewportMatch( 'medium', '<' ); + + return ( + +
{ __( 'Design' ) }
+ { ! isMobileViewport && isEditorPage && ( + + ) } + + } + content={ + + + { __( 'Templates' ) } + + + { __( 'Template Parts' ) } + + + } + /> + ); +} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-templates/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-templates/index.js new file mode 100644 index 0000000000000..f807c2bacd62a --- /dev/null +++ b/packages/edit-site/src/components/sidebar-navigation-screen-templates/index.js @@ -0,0 +1,167 @@ +/** + * WordPress dependencies + */ +import { + __experimentalItemGroup as ItemGroup, + __experimentalHStack as HStack, + Button, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { useEntityRecords } from '@wordpress/core-data'; +import { decodeEntities } from '@wordpress/html-entities'; +import { useViewportMatch } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import SidebarNavigationScreen from '../sidebar-navigation-screen'; +import { useLink } from '../routes/link'; +import SidebarNavigationItem from '../sidebar-navigation-item'; +import { useLocation } from '../routes'; +import { store as editSiteStore } from '../../store'; +import getIsListPage from '../../utils/get-is-list-page'; + +function omit( object, keys ) { + return Object.fromEntries( + Object.entries( object ).filter( ( [ key ] ) => ! keys.includes( key ) ) + ); +} + +const Item = ( { item } ) => { + const linkInfo = useLink( item.params ); + const props = item.params + ? { ...omit( item, 'params' ), ...linkInfo } + : item; + return ; +}; + +const config = { + wp_template: { + path: '/templates', + labels: { + title: __( 'Templates' ), + loading: __( 'Loading templates' ), + notFound: __( 'No templates found' ), + manage: __( 'Manage all templates' ), + }, + }, + wp_template_part: { + path: '/template-parts', + labels: { + title: __( 'Template parts' ), + loading: __( 'Loading template parts' ), + notFound: __( 'No template parts found' ), + manage: __( 'Manage all template parts' ), + }, + }, +}; + +export default function SidebarNavigationScreenTemplates( { + postType = 'wp_template', +} ) { + const { params } = useLocation(); + const { __unstableSetCanvasMode } = useDispatch( editSiteStore ); + const isMobileViewport = useViewportMatch( 'medium', '<' ); + const isListPage = getIsListPage( params ); + const isEditorPage = ! isListPage; + + // Ideally the URL params would be enough. + // Loading the editor should ideally redirect to the home page + // instead of fetching the edited entity here. + const { editedPostId, editedPostType } = useSelect( ( select ) => { + const { getEditedPostType, getEditedPostId } = select( editSiteStore ); + return { + editedPostId: getEditedPostId(), + editedPostType: getEditedPostType(), + }; + }, [] ); + + const { records: templates, isResolving: isLoading } = useEntityRecords( + 'postType', + postType, + { + per_page: -1, + } + ); + + let items = []; + if ( isLoading ) { + items = [ + { + children: config[ postType ].labels.loading, + }, + ]; + } else if ( ! templates && ! isLoading ) { + items = [ + { + children: config[ postType ].labels.notFound, + }, + ]; + } else { + items = templates?.map( ( template ) => ( { + params: { + postType, + postId: template.id, + }, + children: decodeEntities( + template.title?.rendered || template.slug + ), + 'aria-current': + ( params.postType === postType && + params.postId === template.id ) || + // This is a special case for the home page. + ( editedPostId === template.id && + editedPostType === postType && + !! params.postId ) + ? 'page' + : undefined, + } ) ); + } + + return ( + +
{ config[ postType ].labels.title }
+ { ! isMobileViewport && isEditorPage && ( + + ) } + + } + content={ + <> + + { items.map( ( item, index ) => ( + + ) ) } + + + + + } + /> + ); +} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-templates/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-templates/style.scss new file mode 100644 index 0000000000000..432774f903e46 --- /dev/null +++ b/packages/edit-site/src/components/sidebar-navigation-screen-templates/style.scss @@ -0,0 +1,4 @@ +.edit-site-sidebar-navigation-screen-templates__see-all { + /* Overrides the margin that comes from the Item component */ + margin-top: $grid-unit-20 !important; +} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/index.js b/packages/edit-site/src/components/sidebar-navigation-screen/index.js new file mode 100644 index 0000000000000..7edca14681007 --- /dev/null +++ b/packages/edit-site/src/components/sidebar-navigation-screen/index.js @@ -0,0 +1,55 @@ +/** + * WordPress dependencies + */ +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, + __experimentalNavigatorBackButton as NavigatorBackButton, + __experimentalNavigatorScreen as NavigatorScreen, +} from '@wordpress/components'; +import { isRTL, __, sprintf } from '@wordpress/i18n'; +import { chevronRight, chevronLeft } from '@wordpress/icons'; + +export default function SidebarNavigationScreen( { + path, + parentTitle, + title, + content, +} ) { + return ( + + + + { parentTitle ? ( + + ) : ( +
+ ) } + +
+ { title } +
+ + + + + + ); +} diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss new file mode 100644 index 0000000000000..e3044e95bbdd0 --- /dev/null +++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss @@ -0,0 +1,39 @@ +.edit-site-sidebar-navigation-screen { + display: flex; + flex-direction: column; + overflow-x: unset !important; + position: relative; +} + +.edit-site-sidebar-navigation-screen__content { + margin: 0 $button-size; + flex-grow: 1; + overflow-y: auto; +} + +.edit-site-sidebar-navigation-screen__title-icon { + position: sticky; + top: 0; + background: $gray-900; + padding-top: $grid-unit-80; + box-shadow: 0 $grid-unit-10 $grid-unit-20 $gray-900; + margin-bottom: $grid-unit-10; + padding-bottom: $grid-unit-10; +} + +.edit-site-sidebar-navigation-screen__title { + font-size: calc(1.56 * 13px); + font-weight: 600; +} + +.edit-site-sidebar-navigation-screen__back { + color: $gray-200; + + &:hover { + color: $white; + } +} + +.edit-site-sidebar-navigation-screen__icon-placeholder { + width: $button-size; +} diff --git a/packages/edit-site/src/components/sidebar-navigation-title/index.js b/packages/edit-site/src/components/sidebar-navigation-title/index.js deleted file mode 100644 index c233b06544ffe..0000000000000 --- a/packages/edit-site/src/components/sidebar-navigation-title/index.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * WordPress dependencies - */ -import { - __experimentalHStack as HStack, - __experimentalNavigatorBackButton as NavigatorBackButton, -} from '@wordpress/components'; -import { isRTL, __, sprintf } from '@wordpress/i18n'; -import { chevronRight, chevronLeft } from '@wordpress/icons'; - -export default function SidebarNavigationTitle( { parentTitle, title } ) { - return ( - - { parentTitle ? ( - - ) : ( -
- ) } -
{ title }
- - ); -} diff --git a/packages/edit-site/src/components/sidebar-navigation-title/style.scss b/packages/edit-site/src/components/sidebar-navigation-title/style.scss deleted file mode 100644 index 0ac287fec2cdf..0000000000000 --- a/packages/edit-site/src/components/sidebar-navigation-title/style.scss +++ /dev/null @@ -1,16 +0,0 @@ -.edit-site-sidebar-navigation-title { - font-size: calc(1.56 * 13px); - font-weight: 600; -} - -.edit-site-sidebar-navigation-title__back { - color: $gray-200; - - &:hover { - color: $white; - } -} - -.edit-site-sidebar-navigation-title__icon-placeholder { - width: $button-size; -} diff --git a/packages/edit-site/src/components/sidebar/index.js b/packages/edit-site/src/components/sidebar/index.js index 578f13813305b..154fa9c0a17b4 100644 --- a/packages/edit-site/src/components/sidebar/index.js +++ b/packages/edit-site/src/components/sidebar/index.js @@ -1,19 +1,23 @@ /** * WordPress dependencies */ -import { __experimentalVStack as VStack } from '@wordpress/components'; +import { __experimentalNavigatorProvider as NavigatorProvider } from '@wordpress/components'; /** * Internal dependencies */ -import SidebarNavigationRoot from '../sidebar-navigation-root'; +import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; +import SidebarNavigationScreenTemplates from '../sidebar-navigation-screen-templates'; export function Sidebar() { return ( - -
- -
-
+ + + + + ); } diff --git a/packages/edit-site/src/components/sidebar/style.scss b/packages/edit-site/src/components/sidebar/style.scss index 3fbdfbafbe06f..456a5bf9dc9de 100644 --- a/packages/edit-site/src/components/sidebar/style.scss +++ b/packages/edit-site/src/components/sidebar/style.scss @@ -1,4 +1,8 @@ -.edit-site-sidebar__content { +.edit-site-sidebar__content.edit-site-sidebar__content { + overflow-x: unset; +} + +.edit-site-sidebar__content > div { // This matches the logo padding - padding: $grid-unit-15; + padding: 0 $grid-unit-15; } diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index efc6187a39a6b..b06ed6bde9ae0 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -20,8 +20,8 @@ @import "./components/layout/style.scss"; @import "./components/sidebar/style.scss"; @import "./components/sidebar-navigation-item/style.scss"; -@import "./components/sidebar-navigation-root/style.scss"; -@import "./components/sidebar-navigation-title/style.scss"; +@import "./components/sidebar-navigation-screen/style.scss"; +@import "./components/sidebar-navigation-screen-templates/style.scss"; @import "./components/site-icon/style.scss"; html #wpadminbar {