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

DateTimePicker: Replace react-dates and moment with useLilius and date-fns #43005

Merged

Conversation

noisysocks
Copy link
Member

@noisysocks noisysocks commented Aug 5, 2022

What?

Follows #41385.

Updates DatePicker to use useLilius instead of react-dates to render its calendar and removes moment as a dependency from @wordpress/components in favour of date-fns.

https://github.com/its-danny/use-lilius
https://github.com/date-fns/date-fns

Why?

Problems with react-dates

  • It contains lots of different components, most of which we do not use. We've had problems with tree shaking in the past.
  • It uses moment which is quite large and no longer actively developed.
  • It requires hacks.
    • We have to use useEffect to set an aria-label on the day button.
    • We have to do weird stuff to keep focus within the calendar when navigating between months.
    • We have to force re-render by remounting the component using key when the date is changed. (This makes the whole thing feel really slow.)
  • Limited support for using @wordpress/components components. Many of the UI elements can't be swapped out with @wordpress/components components. This results in a less consistent UI and more CSS shipped to the browser.

Considering react-calendar

I looked at using react-calendar in #41385. This is a smaller alternative to react-dates that uses date-fns.

Pros:

  • Much fewer bytes.
  • No hacks required.
  • Uses date-fns, allowing us to remove moment as a dependency.

Cons:

  • Limited support for using @wordpress/components components. Many of the UI elements can't be swapped out with @wordpress/components components. This results in a less consistent UI and more CSS shipped to the browser.

Considering useLilius

I then looked at useLilius per a suggestion by @stokesman. This is a "headless" library that uses date-fns. It offers a single hook that can be used to display a calendar and not any actual UI components.

Pros:

  • Barely any bytes.
  • No hacks required.
  • Uses date-fns, allowing us to remove moment as a dependency.
  • Headless, so we can use @wordpress/components components and Emotion for all of the UI.

Cons:

  • Doesn't implement keyboard navigation using the arrow keys.

Considering Temporal

The Temporal API is now stage 3, so I considered a completely bespoke implementation using Temporal.

Pros:

  • Much better data model. Temporal.PlainDate is perfectly suited for implementing a calendar as it does not contain time or timezone information, both of which are not relevant in the context of choosing a date from a calendar.
  • Future proof. Temporal will assumedly be a native browser API in due course.

Cons:

  • Slightly more upfront work.
  • There's literally a big yellow banner at the top of the proposal saying don't use Temporal in production.
  • Requires a heavy polyfill. No browser currently implements Temporal. What's more, Temporal is much more difficult to tree shake than date-fns because all of the functions are implemented as methods on e.g. Temporal.PlainDate.prototype. This means the polyfill we ship is quite large.

Conclusion: useLilius + date-fns

I settled on using useLilius and rolling our own implementation of keyboard navigation. This approach offers the most upfront benefit and is relatively straightforward to implement.

This approach doesn't preclude a later switch to Temporal. When the Temporal proposal is more developed and implemented by at least one widely used browser (e.g. Chrome), it will be less likely that a user needs to download a heavy polyfill. We should then be able to easily implement our own version of useLilius that uses Temporal.PlainDate. If you look at the source of useLilius you'll see that it's quite small.

How?

  • @wordpress/components: Remove moment and react-dates dependencies. Add date-fns and use-lilius.
  • DateTimePicker: Use VStack so that we can remove all CSS.
  • TimePicker: Swap moment functions for date-fns functions.
  • DatePicker
    • Use useLilius instead of react-dates.
    • Use @wordpress/components and Emotion instead of CSS.
    • Use dateI18n so that dates are correctly translated.
    • Use wp.date.getSettings() so that dates appear in the selected format.
    • Add custom implementation of keyboard navigation.

Testing Instructions

  1. Create or edit a post.
  2. Open the Publish popover in the document settings sidebar.
  3. Have at it. Things should work mostly the same as they did before. Be sure to test keyboard navigation and using screen reader.

Screenshots or screencast

Before:

before.mp4

After:

after.mp4

I don't know if it comes across on video but it feels much snappier to use because we're no longer remounting the component 🙂

@noisysocks noisysocks added [Type] Enhancement A suggestion for improvement. [Feature] Document Settings Document settings experience [Type] Code Quality Issues or PRs that relate to code quality [Package] Components /packages/components labels Aug 5, 2022
@noisysocks noisysocks requested a review from ciampo August 5, 2022 02:21
@noisysocks noisysocks added the [Type] Performance Related to performance efforts label Aug 5, 2022
Copy link
Contributor

@talldan talldan left a comment

Choose a reason for hiding this comment

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

Looks great, it's so nice to be getting rid of that keepFocusInside hack. 🎉

packages/components/package.json Show resolved Hide resolved
Comment on lines 262 to 279
useEffect( () => {
if ( ref.current && isFocusable && isFocusAllowed ) {
ref.current.focus();
}
}, [ isFocusable ] );
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess the alternative is to set focus in the onKeyDown event handler directly. Is that something you considered? It'd mean there's no need for isFocusAllowed.

I guess you might have to use a data attribute or something to find the appropriate Day element in the DOM that way, and the event handler would probably need to be bound to the parent month.

It works nicely as it is, so no need to change it, just curious.

Should isFocusAllowed be in the deps?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm glad you're here! This keyboard stuff took me a day to get right and the whole time I was thinking of you and your struggles with RovingTabIndex 😂

I guess the alternative is to set focus in the onKeyDown event handler directly. Is that something you considered? It'd mean there's no need for isFocusAllowed.

Yeah, I did think about it, but it makes it difficult to implement the nice behaviour where if you arrow past the beginning/end of the grid it automatically switches to the previous/next month. You have to wait until the new month renders before calling focus() since otherwise the element won't exist in the DOM yet. You get this for free when using this state approach since React will call useEffect() after rendering the new state.

Should isFocusAllowed be in the deps?

If we did this then we'd be calling focus() on an element that already has focus. I suppose it doesn't actually matter... idk, I like that the intention here is explicit which is that we only want to focus the element when isFocusable changes to true 😀

Copy link
Contributor

Choose a reason for hiding this comment

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

Might be worth adding a comment to the code to explain why it's missing from the deps. It's something a well meaning dev would change.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, I tried to explain it all using some comments, although it feels like I just wrote the word "focus" a dozen times in a row 😅

packages/components/src/date-time/date/index.tsx Outdated Show resolved Hide resolved
className="components-datetime__date__day" // Unused, for backwards compatibility.
disabled={ isInvalid }
tabIndex={ isFocusable ? 0 : -1 }
aria-label={ getDayLabel( day, isSelected, numEvents ) }
Copy link
Contributor

Choose a reason for hiding this comment

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

getDayLabel looks like a candidate for useMemo.

Copy link
Member Author

@noisysocks noisysocks Aug 5, 2022

Choose a reason for hiding this comment

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

Agreed with you but then I ended up having to remove the push stuff from getDayLabel because it didn't really work in RTL languages. This means getDayLabel is now a simple if and therefore I think not necessary to memoize.

(Could also React.memo the whole of Day if we wanted to. Idk. Probably it's premature optimisation...)

…e-fns

Updates DateTimePicker, TimePicker and DatePicker to use date-fns and
useLilius instead of react-dates and moment. Both libraries result in
less minified bytes sent to the client. useLilius also has other
advantages: less component remounting, can use dateI18n to localise
labels, can use @wordpress/components components, can use Emotion
instead of SCSS.
@noisysocks noisysocks force-pushed the update/replace-moment-and-react-dates-from-wp-components branch from d30f194 to 1951ead Compare August 5, 2022 06:29
@github-actions
Copy link

github-actions bot commented Aug 5, 2022

Size Change: -38.7 kB (-3%)

Total Size: 1.24 MB

Filename Size Change
build/components/index.min.js 198 kB -33.7 kB (-15%) 👏
build/components/style-rtl.css 11.6 kB -2.48 kB (-18%) 👏
build/components/style.css 11.6 kB -2.47 kB (-18%) 👏
build/compose/index.min.js 12 kB -1 B (0%)
build/date/index.min.js 32 kB +5 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 982 B
build/annotations/index.min.js 2.76 kB
build/api-fetch/index.min.js 2.26 kB
build/autop/index.min.js 2.14 kB
build/blob/index.min.js 475 B
build/block-directory/index.min.js 7.02 kB
build/block-directory/style-rtl.css 990 B
build/block-directory/style.css 991 B
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
build/block-editor/index.min.js 159 kB
build/block-editor/style-rtl.css 15.1 kB
build/block-editor/style.css 15.1 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 65 B
build/block-library/blocks/archives/style.css 65 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 103 B
build/block-library/blocks/audio/style.css 103 B
build/block-library/blocks/audio/theme-rtl.css 110 B
build/block-library/blocks/audio/theme.css 110 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 59 B
build/block-library/blocks/avatar/style.css 59 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 441 B
build/block-library/blocks/button/editor.css 441 B
build/block-library/blocks/button/style-rtl.css 539 B
build/block-library/blocks/button/style.css 539 B
build/block-library/blocks/buttons/editor-rtl.css 292 B
build/block-library/blocks/buttons/editor.css 292 B
build/block-library/blocks/buttons/style-rtl.css 275 B
build/block-library/blocks/buttons/style.css 275 B
build/block-library/blocks/calendar/style-rtl.css 207 B
build/block-library/blocks/calendar/style.css 207 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 79 B
build/block-library/blocks/categories/style.css 79 B
build/block-library/blocks/code/style-rtl.css 103 B
build/block-library/blocks/code/style.css 103 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 406 B
build/block-library/blocks/columns/style.css 406 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 187 B
build/block-library/blocks/comment-template/style.css 185 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 834 B
build/block-library/blocks/comments/editor.css 832 B
build/block-library/blocks/comments/style-rtl.css 632 B
build/block-library/blocks/comments/style.css 630 B
build/block-library/blocks/cover/editor-rtl.css 615 B
build/block-library/blocks/cover/editor.css 616 B
build/block-library/blocks/cover/style-rtl.css 1.55 kB
build/block-library/blocks/cover/style.css 1.55 kB
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 110 B
build/block-library/blocks/embed/theme.css 110 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 253 B
build/block-library/blocks/file/style.css 254 B
build/block-library/blocks/file/view.min.js 346 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 948 B
build/block-library/blocks/gallery/editor.css 950 B
build/block-library/blocks/gallery/style-rtl.css 1.53 kB
build/block-library/blocks/gallery/style.css 1.53 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 412 B
build/block-library/blocks/group/editor.css 412 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 327 B
build/block-library/blocks/html/editor.css 329 B
build/block-library/blocks/image/editor-rtl.css 736 B
build/block-library/blocks/image/editor.css 737 B
build/block-library/blocks/image/style-rtl.css 627 B
build/block-library/blocks/image/style.css 630 B
build/block-library/blocks/image/theme-rtl.css 110 B
build/block-library/blocks/image/theme.css 110 B
build/block-library/blocks/latest-comments/style-rtl.css 284 B
build/block-library/blocks/latest-comments/style.css 284 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 463 B
build/block-library/blocks/latest-posts/style.css 462 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 493 B
build/block-library/blocks/media-text/style.css 490 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 705 B
build/block-library/blocks/navigation-link/editor.css 703 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 296 B
build/block-library/blocks/navigation-submenu/editor.css 295 B
build/block-library/blocks/navigation-submenu/view.min.js 423 B
build/block-library/blocks/navigation/editor-rtl.css 2.03 kB
build/block-library/blocks/navigation/editor.css 2.04 kB
build/block-library/blocks/navigation/style-rtl.css 1.98 kB
build/block-library/blocks/navigation/style.css 1.97 kB
build/block-library/blocks/navigation/view-modal.min.js 2.78 kB
build/block-library/blocks/navigation/view.min.js 443 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 363 B
build/block-library/blocks/page-list/editor.css 363 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B
build/block-library/blocks/paragraph/editor.css 157 B
build/block-library/blocks/paragraph/style-rtl.css 260 B
build/block-library/blocks/paragraph/style.css 260 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 493 B
build/block-library/blocks/post-comments-form/style.css 493 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 377 B
build/block-library/blocks/post-featured-image/editor.css 377 B
build/block-library/blocks/post-featured-image/style-rtl.css 153 B
build/block-library/blocks/post-featured-image/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 282 B
build/block-library/blocks/post-template/style.css 282 B
build/block-library/blocks/post-terms/style-rtl.css 73 B
build/block-library/blocks/post-terms/style.css 73 B
build/block-library/blocks/post-title/style-rtl.css 80 B
build/block-library/blocks/post-title/style.css 80 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 198 B
build/block-library/blocks/pullquote/editor.css 198 B
build/block-library/blocks/pullquote/style-rtl.css 370 B
build/block-library/blocks/pullquote/style.css 370 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 282 B
build/block-library/blocks/query-pagination/style.css 278 B
build/block-library/blocks/query/editor-rtl.css 439 B
build/block-library/blocks/query/editor.css 439 B
build/block-library/blocks/quote/style-rtl.css 213 B
build/block-library/blocks/quote/style.css 213 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 396 B
build/block-library/blocks/search/style.css 393 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 233 B
build/block-library/blocks/separator/style.css 233 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 464 B
build/block-library/blocks/shortcode/editor.css 464 B
build/block-library/blocks/site-logo/editor-rtl.css 455 B
build/block-library/blocks/site-logo/editor.css 455 B
build/block-library/blocks/site-logo/style-rtl.css 192 B
build/block-library/blocks/site-logo/style.css 192 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 84 B
build/block-library/blocks/site-title/editor.css 84 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.39 kB
build/block-library/blocks/social-links/style.css 1.38 kB
build/block-library/blocks/spacer/editor-rtl.css 322 B
build/block-library/blocks/spacer/editor.css 322 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 494 B
build/block-library/blocks/table/editor.css 494 B
build/block-library/blocks/table/style-rtl.css 611 B
build/block-library/blocks/table/style.css 609 B
build/block-library/blocks/table/theme-rtl.css 175 B
build/block-library/blocks/table/theme.css 175 B
build/block-library/blocks/tag-cloud/style-rtl.css 239 B
build/block-library/blocks/tag-cloud/style.css 239 B
build/block-library/blocks/template-part/editor-rtl.css 235 B
build/block-library/blocks/template-part/editor.css 235 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 561 B
build/block-library/blocks/video/editor.css 563 B
build/block-library/blocks/video/style-rtl.css 159 B
build/block-library/blocks/video/style.css 159 B
build/block-library/blocks/video/theme-rtl.css 110 B
build/block-library/blocks/video/theme.css 110 B
build/block-library/common-rtl.css 1.01 kB
build/block-library/common.css 1 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 10.8 kB
build/block-library/editor.css 10.8 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 185 kB
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/style-rtl.css 11.9 kB
build/block-library/style.css 11.9 kB
build/block-library/theme-rtl.css 695 B
build/block-library/theme.css 700 B
build/block-serialization-default-parser/index.min.js 1.11 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 49.4 kB
build/core-data/index.min.js 15.4 kB
build/customize-widgets/index.min.js 11.3 kB
build/customize-widgets/style-rtl.css 1.4 kB
build/customize-widgets/style.css 1.4 kB
build/data-controls/index.min.js 653 B
build/data/index.min.js 8.03 kB
build/deprecated/index.min.js 507 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.69 kB
build/edit-navigation/index.min.js 16 kB
build/edit-navigation/style-rtl.css 4.02 kB
build/edit-navigation/style.css 4.03 kB
build/edit-post/classic-rtl.css 546 B
build/edit-post/classic.css 547 B
build/edit-post/index.min.js 30.5 kB
build/edit-post/style-rtl.css 6.94 kB
build/edit-post/style.css 6.94 kB
build/edit-site/index.min.js 57.1 kB
build/edit-site/style-rtl.css 8.23 kB
build/edit-site/style.css 8.22 kB
build/edit-widgets/index.min.js 16.5 kB
build/edit-widgets/style-rtl.css 4.35 kB
build/edit-widgets/style.css 4.35 kB
build/editor/index.min.js 41.4 kB
build/editor/style-rtl.css 3.66 kB
build/editor/style.css 3.65 kB
build/element/index.min.js 4.68 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 6.75 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.64 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.77 kB
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.78 kB
build/keycodes/index.min.js 1.79 kB
build/list-reusable-blocks/index.min.js 1.74 kB
build/list-reusable-blocks/style-rtl.css 835 B
build/list-reusable-blocks/style.css 835 B
build/media-utils/index.min.js 2.93 kB
build/notices/index.min.js 953 B
build/nux/index.min.js 2.05 kB
build/nux/style-rtl.css 732 B
build/nux/style.css 728 B
build/plugins/index.min.js 1.94 kB
build/preferences-persistence/index.min.js 2.22 kB
build/preferences/index.min.js 1.3 kB
build/primitives/index.min.js 933 B
build/priority-queue/index.min.js 612 B
build/react-i18n/index.min.js 696 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.74 kB
build/reusable-blocks/index.min.js 2.21 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 11.2 kB
build/server-side-render/index.min.js 1.61 kB
build/shortcode/index.min.js 1.53 kB
build/token-list/index.min.js 644 B
build/url/index.min.js 3.61 kB
build/vendors/react-dom.min.js 38.5 kB
build/vendors/react.min.js 4.34 kB
build/viewport/index.min.js 1.08 kB
build/warning/index.min.js 268 B
build/widgets/index.min.js 7.19 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

Comment on lines +106 to +107
role="application"
aria-label={ __( 'Calendar' ) }
Copy link
Member Author

@noisysocks noisysocks Aug 5, 2022

Choose a reason for hiding this comment

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

I copied this from the previous implementation but I'm not sure if role=application is the right thing to do. Maybe someone who knows what they're doing can answer cc. @talldan @tellthemachines

@ramonjd
Copy link
Member

ramonjd commented Aug 11, 2022

I've been testing this using keyboard and mouse interactions in LTR and RTL langs and it's working great!

  • date selector from calendar and input fields works as expected
  • custom start of the week setting appears as expected
  • publish date updates with my changes

🎉

Copy link
Contributor

@talldan talldan left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for tackling this difficult task!

@noisysocks noisysocks merged commit c1f96c2 into trunk Aug 16, 2022
@noisysocks noisysocks deleted the update/replace-moment-and-react-dates-from-wp-components branch August 16, 2022 03:45
@github-actions github-actions bot added this to the Gutenberg 14.0 milestone Aug 16, 2022
Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

Hey @noisysocks thank you for working on this!

Even though this PR has already been merged, I went ahead and gave it a good look.

Apart from my inline comments, here's some additional feedback:

  • we should add box-sizing reset styles to the root element of each component (DatePicker, TimePicker, DateTimePicker)

  • When the calendar is focused, pressing arrow keys scrolls the page (we should preventDefault or stopPropagation)

  • The "calendar help" text was not updated to remove support for page up / page down / home / end keys (unless we didn't mean to remove support for those keys)

  • The font size "day of the week" text (i.e "Wed", "Thu") should be set in a way that doesn't change when the wordpress Global Styles are added or removed (you can use the switch in Storybook to toggle them on/off)

  • Could we look into replacing userEvent.setup( { delay: null } ) with const user = userEvent.setup( { advanceTimers: jest.advanceTimersByTime } ) ?

A couple of additional thoughts:

  • The component's chosen timezone seem to be tightly coupled with the WordPress editor's settings — we should work on a way to decouple this, and maybe have the desired timezone offset as a prop?
  • It would be great if the @wordpress/componentspackage didn't import any date library at all (i.e.date-fns), and instead used @wordpress/date` as its date utility library
  • Of course, we should look into migrating @wordpress/date away from moment too, but that's a whole different story

(cc'ing @sgomes since he was involved in previous conversations where we evaluated Temporal).

@@ -47,7 +43,7 @@ describe( 'DatePicker', () => {
);

await user.click(
screen.getByRole( 'button', { name: 'Friday, May 20, 2022' } )
screen.getByRole( 'button', { name: 'May 20, 2022' } )
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason why we changed the button's accessible name (removing the week-day name) in this refactor, instead of making the new implementation match the old one?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes! Using the format string in wp.date.__experimentalGetSettings().formats.date instead of a hardcoded format string ensures that the ARIA label respects the site's Date Format setting:

Screen Shot 2022-08-23 at 10 07 00

It also ensures that the format string is internationalised because the format string obtained from wp-date has been passed through __:

https://github.com/WordPress/wordpress-develop/blob/85ae9dd89b4c91f61a3517f7c41813f53cde87fd/src/wp-includes/script-loader.php#L412

This is important as not all languages use {Day}, {Month} {Day}, {Year}.

Worth noting that prior to this PR these labels weren't working anyway. The labels contained format string tokens:

Screen Shot 2022-08-23 at 10 00 10

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good, thank you for the context!

"Are you free on Thursday F, j?"

Comment on lines +116 to +121
day: format( date, 'dd' ),
month: format( date, 'MM' ),
year: format( date, 'yyyy' ),
minutes: format( date, 'mm' ),
hours: format( date, is12Hour ? 'hh' : 'HH' ),
am: format( date, 'a' ),
Copy link
Contributor

Choose a reason for hiding this comment

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

Could these also be moved to the constants file?

Copy link
Member Author

Choose a reason for hiding this comment

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

The format strings? I think it's nice having them near to where they're used as the reader has to jump around less.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, although I thought that would be more coherent with having the TIMEZONELESS_FORMAT as a variable in a separate file.

Copy link
Member Author

Choose a reason for hiding this comment

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

The difference there is that TIMEZONELESS_FORMAT is used by two components (TimePicker and DatePicker) so makes sense to have it in a separate file where both can get at it.

};

const momentDate = getMomentDate( currentDate );
}, [ isFocusable ] );
Copy link
Contributor

Choose a reason for hiding this comment

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

We should add a eslint-disable inline comment for the missing isFocusAllowed dep here — see #41166 (cc @chad1008 )

Comment on lines +305 to +310
const { formats } = __experimentalGetSettings();
const localizedDate = dateI18n(
formats.date,
date,
-date.getTimezoneOffset()
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Previously we were not relying on @wordpress/date:

  • could we use date-fns for formatting the date instead ?
  • alternatively, should we aim at using @wordpress/date more instead of date-fns?

Ultimately, I'm trying to understand if we get to "one source" of date utils, instead of using both third party libraries AND internal libraries.

Copy link
Member Author

Choose a reason for hiding this comment

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

We could use format from date-fns but we would need to set up internationalisation which is a little tricky to do in a way that doesn't increase the size of the build. We'd have to pass the locale to the component which I'm not a huge fan of because it makes it difficult to switch DatePicker away from date-fns in the future.

https://date-fns.org/v2.16.1/docs/I18n

dateI8n from @wordpress/date already handles localisation and is configured properly by WordPress which is why I'm using it here.

My view on @wordpress/date is that it is complimentary to a date util library (e.g. date-fns) and should only provide:

  • A store for the WordPress site's date settings including format preference and timezone.
  • A function similar to wp_date in PHP.

Everything else should be deprecated from @wordpress/date in favour of date-fns. Right now I believe that's just the isInTheFuture function.

Copy link
Contributor

Choose a reason for hiding this comment

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

Gotcha. Not something that needs to be addressed urgently, but I'll see if I can open an issue on next steps for @wordpress/date (which should include what we discussed in this comment too)

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks!

packages/date/src/index.js Show resolved Hide resolved
@noisysocks
Copy link
Member Author

Thanks so much @ciampo! I've opened #43495 to address your notes.

  • The component's chosen timezone seem to be tightly coupled with the WordPress editor's settings — we should work on a way to decouple this, and maybe have the desired timezone offset as a prop?

DatePicker doesn't actually use the WordPress editor timezone because we are explicitly passing a timezone each time we call dateI18n.

We are relying on the date format that you get from wp.date.__experimentalGetSettings().formats.date, though. I'll have a play with some options here—maybe injecting formatI18n as a prop would be a good idea.

  • It would be great if the @wordpress/componentspackage didn't import any date library at all (i.e.date-fns), and instead used @wordpress/date` as its date utility library

I wrote my thoughts on this in #43005 (comment). In short I think both packages are complimentary.

  • Of course, we should look into migrating @wordpress/date away from moment too, but that's a whole different story

Yes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Document Settings Document settings experience [Package] Components /packages/components [Type] Code Quality Issues or PRs that relate to code quality [Type] Enhancement A suggestion for improvement. [Type] Performance Related to performance efforts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants