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

Panel: Improve scroll view handling when expanding #23327

Merged
merged 34 commits into from
Jul 14, 2020

Conversation

ItsJonQ
Copy link

@ItsJonQ ItsJonQ commented Jun 19, 2020

Screen Capture on 2020-06-19 at 14-01-50

This update adds an interaction for <PanelBody /> that scrolls the contents into view (if needed). This improves UX within the Editor's sidebar, especially for collapsed items that are nearer to the bottom.

How has this been tested?

  • Run npm run dev
  • Open the editor
  • Click on a block
  • Expand/collapse various panels in the sidebar
  • Get a sense of the feel
  • Hopefully it feels better!

Types of changes

  • Refactors PanelBody into a functional component
  • Implements Reakit/Disclosure for a11y + interaction handling of collapse/expand
  • Add element.scrollIntoView() for native (browser) scroll handling
  • Add helper util functions for effect and ref handling

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR.

@ItsJonQ ItsJonQ added [Type] Enhancement A suggestion for improvement. [Status] In Progress Tracking issues with work in progress [Package] Components /packages/components labels Jun 19, 2020
@ItsJonQ ItsJonQ self-assigned this Jun 19, 2020
@@ -59,6 +59,7 @@

.interface-interface-skeleton__sidebar > div {
height: 100%;
padding-bottom: $grid-unit-60;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds some extra padding at the bottom. Panels near won't feel so "tight"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this specific to the edit-post sidebar or all interface sidebars.
I know this selector was already here but it seems like it's too generic while added in edit-post?

Copy link
Author

@ItsJonQ ItsJonQ Jun 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose all Interface sidebars. I added it here for now, as I wasn't familiar with the Interface components, and wanted to limit scope. (Also, the CSS selector already existed)

@github-actions
Copy link

github-actions bot commented Jun 19, 2020

Size Change: +2.39 kB (0%)

Total Size: 1.14 MB

Filename Size Change
build/block-editor/index.js 115 kB -8 B (0%)
build/block-editor/style-rtl.css 10.8 kB +7 B (0%)
build/block-editor/style.css 10.8 kB +4 B (0%)
build/block-library/editor-rtl.css 7.6 kB +54 B (0%)
build/block-library/editor.css 7.59 kB +54 B (0%)
build/block-library/index.js 132 kB +1.64 kB (1%)
build/block-library/style-rtl.css 7.77 kB +13 B (0%)
build/block-library/style.css 7.77 kB +13 B (0%)
build/blocks/index.js 48.2 kB +20 B (0%)
build/components/index.js 199 kB +390 B (0%)
build/components/style-rtl.css 15.9 kB +28 B (0%)
build/components/style.css 15.8 kB +24 B (0%)
build/compose/index.js 9.67 kB +107 B (1%)
build/date/index.js 5.38 kB +3 B (0%)
build/edit-navigation/index.js 10.8 kB +1 B
build/edit-post/index.js 304 kB -1 B
build/edit-post/style-rtl.css 5.6 kB +6 B (0%)
build/edit-post/style.css 5.59 kB +6 B (0%)
build/edit-site/index.js 16.6 kB +1 B
build/edit-widgets/index.js 9.35 kB -2 B (0%)
build/editor/index.js 45.1 kB +33 B (0%)
build/format-library/index.js 7.72 kB +4 B (0%)
build/keyboard-shortcuts/index.js 2.51 kB -3 B (0%)
build/list-reusable-blocks/index.js 3.12 kB -2 B (0%)
build/media-utils/index.js 5.32 kB -4 B (0%)
build/plugins/index.js 2.56 kB -1 B
build/rich-text/index.js 13.9 kB -1 B
build/server-side-render/index.js 2.71 kB +1 B
build/token-list/index.js 1.27 kB -2 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/annotations/index.js 3.67 kB 0 B
build/api-fetch/index.js 3.39 kB 0 B
build/autop/index.js 2.82 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/index.js 7.67 kB 0 B
build/block-directory/style-rtl.css 944 B 0 B
build/block-directory/style.css 945 B 0 B
build/block-library/theme-rtl.css 728 B 0 B
build/block-library/theme.css 729 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/core-data/index.js 11.4 kB 0 B
build/data-controls/index.js 1.29 kB 0 B
build/data/index.js 8.46 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 569 B 0 B
build/dom/index.js 3.23 kB 0 B
build/edit-navigation/style-rtl.css 1.08 kB 0 B
build/edit-navigation/style.css 1.08 kB 0 B
build/edit-site/style-rtl.css 3.03 kB 0 B
build/edit-site/style.css 3.03 kB 0 B
build/edit-widgets/style-rtl.css 2.45 kB 0 B
build/edit-widgets/style.css 2.45 kB 0 B
build/editor/editor-styles-rtl.css 537 B 0 B
build/editor/editor-styles.css 539 B 0 B
build/editor/style-rtl.css 3.78 kB 0 B
build/editor/style.css 3.78 kB 0 B
build/element/index.js 4.65 kB 0 B
build/escape-html/index.js 733 B 0 B
build/format-library/style-rtl.css 547 B 0 B
build/format-library/style.css 548 B 0 B
build/hooks/index.js 2.13 kB 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.56 kB 0 B
build/is-shallow-equal/index.js 709 B 0 B
build/keycodes/index.js 1.94 kB 0 B
build/list-reusable-blocks/style-rtl.css 476 B 0 B
build/list-reusable-blocks/style.css 476 B 0 B
build/notices/index.js 1.79 kB 0 B
build/nux/index.js 3.4 kB 0 B
build/nux/style-rtl.css 671 B 0 B
build/nux/style.css 668 B 0 B
build/primitives/index.js 1.4 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/url/index.js 4.06 kB 0 B
build/viewport/index.js 1.85 kB 0 B
build/warning/index.js 1.13 kB 0 B
build/wordcount/index.js 1.17 kB 0 B

compressed-size-action

@diegohaz
Copy link
Member

I've noticed a couple of Jest test failures caused by Reakit warnings, specifically regarding ref

That's super weird! Couldn't find any problem in the implementation.

I suspect it has something to do with react-test-renderer not populating the ref object. Their docs say you can mock the node. But it's not ideal. I updated the tests to use @testing-library/react and the warnings disappeared.

Code
/**
 * External dependencies
 */
import { render } from '@testing-library/react';
import { noop } from 'lodash';

/**
 * Internal dependencies
 */
import PanelColorSettings from '../';

describe( 'PanelColorSettings', () => {
	it( 'should not render anything if there are no colors to choose', async () => {
		const { container } = render(
			<PanelColorSettings
				title="Test Title"
				colors={ [] }
				disableCustomColors={ true }
				colorSettings={ [
					{
						value: '#000',
						onChange: noop,
						label: 'border color',
					},
					{
						value: '#111',
						onChange: noop,
						label: 'background color',
					},
				] }
			/>
		);
		expect( container.innerHTML ).toBe( '' );
	} );

	it( 'should render a color panel if at least one setting supports custom colors', async () => {
		const { container } = render(
			<PanelColorSettings
				title="Test Title"
				colors={ [] }
				disableCustomColors={ true }
				colorSettings={ [
					{
						value: '#000',
						onChange: noop,
						label: 'border color',
					},
					{
						value: '#111',
						onChange: noop,
						label: 'background color',
						disableCustomColors: false,
					},
				] }
			/>
		);
		expect( container.innerHTML ).not.toBe( '' );
	} );

	it( 'should render a color panel if at least one setting specifies some colors to choose', async () => {
		const { container } = render(
			<PanelColorSettings
				title="Test Title"
				colors={ [] }
				disableCustomColors={ true }
				colorSettings={ [
					{
						value: '#000',
						onChange: noop,
						label: 'border color',
						colors: [
							{
								slug: 'red',
								name: 'Red',
								color: '#ff0000',
							},
						],
					},
					{
						value: '#111',
						onChange: noop,
						label: 'background color',
					},
				] }
			/>
		);
		expect( container.innerHTML ).not.toBe( '' );
	} );

	it( 'should not render anything if none of the setting panels has colors to choose', async () => {
		const { container } = render(
			<PanelColorSettings
				title="Test Title"
				colors={ [] }
				disableCustomColors={ false }
				colorSettings={ [
					{
						value: '#000',
						onChange: noop,
						label: 'border color',
						colors: [],
						disableCustomColors: true,
					},
					{
						value: '#111',
						onChange: noop,
						label: 'background color',
						colors: [],
						disableCustomColors: true,
					},
				] }
			/>
		);
		expect( container.innerHTML ).not.toBe( '' );
	} );
} );

@ItsJonQ
Copy link
Author

ItsJonQ commented Jun 22, 2020

@diegohaz Thank you so much for digging into this! I apologize for the extra work. I guess I was thrown off by the Reakit warnings, and focused on that (with ref) rather than the render within the tests.

Really appreciate you taking the time to help!

<3

@ItsJonQ ItsJonQ requested a review from epiqueras June 22, 2020 16:26
@ItsJonQ ItsJonQ marked this pull request as ready for review June 22, 2020 16:26
@ItsJonQ ItsJonQ removed the [Status] In Progress Tracking issues with work in progress label Jun 22, 2020
packages/components/src/utils/use-combined-refs.js Outdated Show resolved Hide resolved
* Source:
* https://github.com/reakit/reakit/blob/master/packages/reakit-utils/src/useUpdateEffect.ts
*/
export function useUpdateEffect( effect, deps ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use this technique in other parts of our code base? would it make sense to move it to compose package or is it too soon for it to be a public API?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I may have used it in my component work. I know I've had to use it many times in other projects. I chatted about it briefly with @diegohaz . It sounds like he shares the same sentiment, which is why it exists as a Reakit util I suppose :).

I'm be open to adding it to @wordpress/compose.

Side question... I'm starting to build up a collection of utils within @wordpress/components. There are more that I'd like to add/abstract. In the future, would some of these migrate to something like @wordpress/compose? Or would we create a new dedicated package for these JS/component utils?

Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think compose makes sense for React hooks. The question becomes when are we confident that we'll maintain backward compatibility forever. So it seems to me starting as internal to components and moving to compose when we think they're stable makes sense.

Now, for other kind of utils, i'd say it depends, we generally avoid generic packages like "utils" or "helpers" or things like that and prefer more dedicated packages "url", "priority-query"...

@@ -59,6 +59,7 @@

.interface-interface-skeleton__sidebar > div {
height: 100%;
padding-bottom: $grid-unit-60;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this specific to the edit-post sidebar or all interface sidebars.
I know this selector was already here but it seems like it's too generic while added in edit-post?

opened: props.initialOpen === undefined ? true : props.initialOpen,
};
this.toggle = this.toggle.bind( this );
export function PanelBody(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has an open PR here for the refactor #23065 is this based on it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! Not at all. I didn't know that https://github.com/WordPress/gutenberg/pull/23065/files existed. I refactored in order to integrate with Reakit

@ItsJonQ
Copy link
Author

ItsJonQ commented Jul 7, 2020

Update! Unfortunately, I've removed the Reakit/Disclosure integration (for now). The current tests don't seem to be happy with it (E2E and snapshots). The auto-generated IDs from Reakit is causing the snapshots to constantly trip up.

Note: I'm 💯 in favour of unique IDs + aria association. That's how it should be done.

I think we can reserve the Reakit integration for another PR 🙏

Thank you @youknowriad + @diegohaz for your time in reviewing this one!

@diegohaz
Copy link
Member

diegohaz commented Jul 7, 2020

The auto-generated IDs from Reakit is causing the snapshots to constantly trip up.

In this case you can explicitly set baseId on useDisclosureState from tests, like this:

// Passing baseId for server side rendering (which includes snapshots)
// If an id prop is passed to Toolbar, toolbar items will use it as a base for their ids
const toolbarState = useToolbarState( { loop: true, baseId: props.id } );

// id is required for server side rendering
<Toolbar
__experimentalAccessibilityLabel="Options"
id="options-toolbar"
>

I'll review the changes this week. Thanks for working on this! ❤️

Copy link
Member

@diegohaz diegohaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested this and it's working really well! Thanks for working on this!
Made a few comments on tests, but they're not mandatory.

packages/components/src/panel/test/body.js Outdated Show resolved Hide resolved
packages/components/src/panel/test/body.js Outdated Show resolved Hide resolved
@ItsJonQ
Copy link
Author

ItsJonQ commented Jul 14, 2020

Thanks for the review @diegohaz + @youknowriad !! Will merge this up

@ItsJonQ ItsJonQ merged commit bb00ad8 into master Jul 14, 2020
@ItsJonQ ItsJonQ deleted the update/panel-improve-scroll-view-handling branch July 14, 2020 19:09
@github-actions github-actions bot added this to the Gutenberg 8.6 milestone Jul 14, 2020
@afercia
Copy link
Contributor

afercia commented Jul 19, 2020

This change removed the aria-expanded attribute. Now, all the panels in the editor don't give any clue to assistive technology users whether they're collapsed or expanded.

Will create a new issue...

I do realize it was removed accidentally, this kind of things can happen to everyone. It would be great to have tools in place to avoid this kind of regressions though.

@ItsJonQ
Copy link
Author

ItsJonQ commented Jul 20, 2020

@afercia Oh! Thank you for catching this 🙏 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants