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

Implement Tabs in editor settings #55360

Merged
merged 23 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ad8819d
implement Tabs in editor settings sidebar
chad1008 Nov 1, 2023
4cb5c69
remove duplicated styles from editor sidebar
chad1008 Nov 1, 2023
ddd8d7f
incorporate initial feedback
chad1008 Nov 3, 2023
4142f5a
pass props to Tabs directly
chad1008 Nov 9, 2023
b67019b
add `closeGeneralSidebar` to `onSelect` callback
chad1008 Nov 16, 2023
b9723d7
set TabPanels to `focuasable={false}`
chad1008 Nov 16, 2023
1fbbef4
detect when sidebar is closed. pass `selectedTabId` of `null`
chad1008 Nov 16, 2023
f3fea72
improve `Tabs` `onSelect` callback
chad1008 Nov 16, 2023
a01b24c
remove `aria-label` and `data-label` props
chad1008 Nov 17, 2023
2e73939
add note explaining null selected tab when sidebar is closed
chad1008 Nov 17, 2023
ed1c930
update e2e test
chad1008 Nov 20, 2023
4d47b34
style updates
chad1008 Nov 20, 2023
1e471ee
update internal component structure to avoid rerenders
chad1008 Nov 22, 2023
9ea4a0e
remove fragment
chad1008 Nov 22, 2023
8e5ad95
prevent infinite loop when opening third party sidebar
chad1008 Nov 24, 2023
e57f8a1
update e2e tests for `Tabs` compatibility
chad1008 Nov 27, 2023
8a7b8f1
fix double top margin on tabpanels
chad1008 Nov 28, 2023
c3eb43e
update to use new tabId prop
chad1008 Dec 8, 2023
73db1df
remove import that is no longer needed after rebase
chad1008 Dec 8, 2023
7fe4d02
fix keyboard navigable blocks test
chad1008 Dec 8, 2023
4d0c547
fix visibility and tab order tests
chad1008 Dec 8, 2023
10507a2
fix footnotes tests
chad1008 Dec 8, 2023
5d20c8b
fix change detection test
chad1008 Dec 9, 2023
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 @@ -370,7 +370,11 @@ describe( 'Change detection', () => {
it( 'consecutive edits to the same attribute should mark the post as dirty after a save', async () => {
// Open the sidebar block settings.
await openDocumentSettingsSidebar();
await page.click( '.edit-post-sidebar__panel-tab[data-label="Block"]' );

const blockInspectorTab = await page.waitForXPath(
'//button[@role="tab"][contains(text(), "Block")]'
);
await blockInspectorTab.click();

// Insert a paragraph.
await clickBlockAppender();
Expand Down
15 changes: 9 additions & 6 deletions packages/e2e-tests/specs/editor/various/editor-modes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,24 @@ describe( 'Editing modes (visual/HTML)', () => {
expect( title ).toBe( 'Paragraph' );

// The Block inspector should be active.
let blockInspectorTab = await page.$(
'.edit-post-sidebar__panel-tab.is-active[data-label="Block"]'
let [ blockInspectorTab ] = await page.$x(
'//button[@role="tab"][@aria-selected="true"][contains(text(), "Block")]'
);
expect( blockInspectorTab ).not.toBeNull();

await switchEditorModeTo( 'Code' );

// The Block inspector should not be active anymore.
blockInspectorTab = await page.$(
'.edit-post-sidebar__panel-tab.is-active[data-label="Block"]'
[ blockInspectorTab ] = await page.$x(
'//button[@role="tab"][@aria-selected="true"][contains(text(), "Block")]'
);
expect( blockInspectorTab ).toBeNull();
expect( blockInspectorTab ).toBeUndefined();

// No block is selected.
await page.click( '.edit-post-sidebar__panel-tab[data-label="Block"]' );
const inactiveBlockInspectorTab = await page.waitForXPath(
'//button[@role="tab"][contains(text(), "Block")]'
);
inactiveBlockInspectorTab.click();
const noBlocksElement = await page.$(
'.block-editor-block-inspector__no-blocks'
);
Expand Down
10 changes: 7 additions & 3 deletions packages/e2e-tests/specs/editor/various/preferences.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe( 'preferences', () => {
async function getActiveSidebarTabText() {
try {
return await page.$eval(
'.edit-post-sidebar__panel-tab.is-active',
'div[aria-label="Editor settings"] [role="tab"][aria-selected="true"]',
( node ) => node.textContent
);
} catch ( error ) {
Expand All @@ -29,11 +29,15 @@ describe( 'preferences', () => {
}

it( 'remembers sidebar dismissal between sessions', async () => {
const blockTab = await page.waitForXPath(
`//button[@role="tab"][contains(text(), 'Block')]`
);

// Open by default.
expect( await getActiveSidebarTabText() ).toBe( 'Post' );

// Change to "Block" tab.
await page.click( '.edit-post-sidebar__panel-tab[aria-label="Block"]' );
await blockTab.click();
expect( await getActiveSidebarTabText() ).toBe( 'Block' );

// Regression test: Reload resets to document tab.
Expand All @@ -46,7 +50,7 @@ describe( 'preferences', () => {

// Dismiss.
await page.click(
'.edit-post-sidebar__panel-tabs [aria-label="Close Settings"]'
'div[aria-label="Editor settings"] div[role="tablist"] + button[aria-label="Close Settings"]'
chad1008 marked this conversation as resolved.
Show resolved Hide resolved
);
expect( await getActiveSidebarTabText() ).toBe( null );

Expand Down
29 changes: 16 additions & 13 deletions packages/e2e-tests/specs/editor/various/sidebar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
} from '@wordpress/e2e-test-utils';

const SIDEBAR_SELECTOR = '.edit-post-sidebar';
const ACTIVE_SIDEBAR_TAB_SELECTOR = '.edit-post-sidebar__panel-tab.is-active';
const ACTIVE_SIDEBAR_TAB_SELECTOR =
'div[aria-label="Editor settings"] [role="tab"][aria-selected="true"]';
const ACTIVE_SIDEBAR_BUTTON_TEXT = 'Post';

describe( 'Sidebar', () => {
Expand Down Expand Up @@ -99,22 +100,24 @@ describe( 'Sidebar', () => {

// Tab lands at first (presumed selected) option "Post".
await page.keyboard.press( 'Tab' );
const isActiveDocumentTab = await page.evaluate(
() =>
document.activeElement.textContent === 'Post' &&
document.activeElement.classList.contains( 'is-active' )

// The Post tab should be focused and selected.
const [ documentInspectorTab ] = await page.$x(
'//button[@role="tab"][@aria-selected="true"][contains(text(), "Post")]'
);
expect( isActiveDocumentTab ).toBe( true );
expect( documentInspectorTab ).toBeDefined();
expect( documentInspectorTab ).toHaveFocus();

// Tab into and activate "Block".
await page.keyboard.press( 'Tab' );
// Arrow key into and activate "Block".
await page.keyboard.press( 'ArrowRight' );
await page.keyboard.press( 'Space' );
const isActiveBlockTab = await page.evaluate(
() =>
document.activeElement.textContent === 'Block' &&
document.activeElement.classList.contains( 'is-active' )

// The Block tab should be focused and selected.
const [ blockInspectorTab ] = await page.$x(
'//button[@role="tab"][@aria-selected="true"][contains(text(), "Block")]'
);
expect( isActiveBlockTab ).toBe( true );
expect( blockInspectorTab ).toBeDefined();
expect( blockInspectorTab ).toHaveFocus();
} );

it( 'should be possible to programmatically remove Document Settings panels', async () => {
Expand Down
84 changes: 16 additions & 68 deletions packages/edit-post/src/components/sidebar/settings-header/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
/**
* WordPress dependencies
*/
import { Button } from '@wordpress/components';
import { __, _x, sprintf } from '@wordpress/i18n';
import { useDispatch, useSelect } from '@wordpress/data';
import { privateApis as componentsPrivateApis } from '@wordpress/components';
import { __, _x } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';

/**
* Internal dependencies
*/
import { store as editPostStore } from '../../../store';
import { unlock } from '../../../lock-unlock';
import { sidebars } from '../settings-sidebar';

const SettingsHeader = ( { sidebarName } ) => {
const { openGeneralSidebar } = useDispatch( editPostStore );
const openDocumentSettings = () =>
openGeneralSidebar( 'edit-post/document' );
const openBlockSettings = () => openGeneralSidebar( 'edit-post/block' );
const { Tabs } = unlock( componentsPrivateApis );

const SettingsHeader = () => {
const { documentLabel, isTemplateMode } = useSelect( ( select ) => {
const { getPostTypeLabel, getRenderingMode } = select( editorStore );

Expand All @@ -27,66 +25,16 @@ const SettingsHeader = ( { sidebarName } ) => {
};
}, [] );

const [ documentAriaLabel, documentActiveClass ] =
sidebarName === 'edit-post/document'
? // translators: ARIA label for the Document sidebar tab, selected. %s: Document label.
[ sprintf( __( '%s (selected)' ), documentLabel ), 'is-active' ]
: [ documentLabel, '' ];

const [ blockAriaLabel, blockActiveClass ] =
sidebarName === 'edit-post/block'
? // translators: ARIA label for the Block Settings Sidebar tab, selected.
[ __( 'Block (selected)' ), 'is-active' ]
: // translators: ARIA label for the Block Settings Sidebar tab, not selected.
[ __( 'Block' ), '' ];

const [ templateAriaLabel, templateActiveClass ] =
sidebarName === 'edit-post/document'
? [ __( 'Template (selected)' ), 'is-active' ]
: [ __( 'Template' ), '' ];

/* Use a list so screen readers will announce how many tabs there are. */
return (
<ul>
{ ! isTemplateMode && (
<li>
<Button
onClick={ openDocumentSettings }
className={ `edit-post-sidebar__panel-tab ${ documentActiveClass }` }
aria-label={ documentAriaLabel }
data-label={ documentLabel }
>
{ documentLabel }
</Button>
</li>
) }
{ isTemplateMode && (
<li>
<Button
onClick={ openDocumentSettings }
className={ `edit-post-sidebar__panel-tab ${ templateActiveClass }` }
aria-label={ templateAriaLabel }
data-label={ __( 'Template' ) }
>
{ __( 'Template' ) }
</Button>
</li>
) }
<li>
<Button
onClick={ openBlockSettings }
className={ `edit-post-sidebar__panel-tab ${ blockActiveClass }` }
aria-label={ blockAriaLabel }
// translators: Data label for the Block Settings Sidebar tab.
data-label={ __( 'Block' ) }
>
{
// translators: Text label for the Block Settings Sidebar tab.
__( 'Block' )
}
</Button>
</li>
</ul>
<Tabs.TabList>
<Tabs.Tab tabId={ sidebars.document }>
{ isTemplateMode ? __( 'Template' ) : documentLabel }
</Tabs.Tab>
<Tabs.Tab tabId={ sidebars.block }>
{ /* translators: Text label for the Block Settings Sidebar tab. */ }
{ __( 'Block' ) }
</Tabs.Tab>
</Tabs.TabList>
);
};

Expand Down

This file was deleted.

Loading
Loading