@wordpress/ui 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/CONTRIBUTING.md +149 -0
- package/README.md +34 -6
- package/build/alert-dialog/context.cjs +6 -1
- package/build/alert-dialog/context.cjs.map +2 -2
- package/build/alert-dialog/popup.cjs +105 -33
- package/build/alert-dialog/popup.cjs.map +4 -4
- package/build/alert-dialog/root.cjs +106 -6
- package/build/alert-dialog/root.cjs.map +2 -2
- package/build/alert-dialog/trigger.cjs +4 -14
- package/build/alert-dialog/trigger.cjs.map +3 -3
- package/build/alert-dialog/types.cjs.map +1 -1
- package/build/badge/badge.cjs +14 -14
- package/build/badge/badge.cjs.map +2 -2
- package/build/button/button.cjs +16 -6
- package/build/button/button.cjs.map +3 -3
- package/build/card/content.cjs +4 -4
- package/build/card/content.cjs.map +2 -2
- package/build/card/full-bleed.cjs +4 -4
- package/build/card/full-bleed.cjs.map +2 -2
- package/build/card/header.cjs +4 -4
- package/build/card/header.cjs.map +2 -2
- package/build/card/root.cjs +4 -4
- package/build/card/root.cjs.map +2 -2
- package/build/card/title.cjs +5 -25
- package/build/card/title.cjs.map +4 -4
- package/build/collapsible-card/content.cjs +3 -3
- package/build/collapsible-card/content.cjs.map +1 -1
- package/build/collapsible-card/header.cjs +6 -6
- package/build/collapsible-card/header.cjs.map +2 -2
- package/build/dialog/footer.cjs +3 -3
- package/build/dialog/footer.cjs.map +2 -2
- package/build/dialog/header.cjs +3 -3
- package/build/dialog/header.cjs.map +2 -2
- package/build/dialog/popup.cjs +5 -4
- package/build/dialog/popup.cjs.map +2 -2
- package/build/dialog/title.cjs +10 -19
- package/build/dialog/title.cjs.map +3 -3
- package/build/dialog/types.cjs.map +1 -1
- package/build/empty-state/actions.cjs +3 -3
- package/build/empty-state/actions.cjs.map +2 -2
- package/build/empty-state/description.cjs +8 -5
- package/build/empty-state/description.cjs.map +2 -2
- package/build/empty-state/icon.cjs +3 -3
- package/build/empty-state/icon.cjs.map +2 -2
- package/build/empty-state/root.cjs +3 -3
- package/build/empty-state/root.cjs.map +2 -2
- package/build/empty-state/title.cjs +8 -5
- package/build/empty-state/title.cjs.map +2 -2
- package/build/empty-state/visual.cjs +3 -3
- package/build/empty-state/visual.cjs.map +2 -2
- package/build/form/primitives/field/description.cjs +17 -4
- package/build/form/primitives/field/description.cjs.map +3 -3
- package/build/form/primitives/field/details.cjs +4 -4
- package/build/form/primitives/field/details.cjs.map +2 -2
- package/build/form/primitives/field/label.cjs +8 -8
- package/build/form/primitives/field/label.cjs.map +2 -2
- package/build/form/primitives/field/root.cjs +2 -2
- package/build/form/primitives/field/root.cjs.map +2 -2
- package/build/form/primitives/fieldset/description.cjs +20 -4
- package/build/form/primitives/fieldset/description.cjs.map +3 -3
- package/build/form/primitives/fieldset/details.cjs +3 -3
- package/build/form/primitives/fieldset/details.cjs.map +2 -2
- package/build/form/primitives/fieldset/legend.cjs +8 -7
- package/build/form/primitives/fieldset/legend.cjs.map +2 -2
- package/build/form/primitives/input/input.cjs +23 -7
- package/build/form/primitives/input/input.cjs.map +3 -3
- package/build/form/primitives/input-layout/input-layout.cjs +13 -3
- package/build/form/primitives/input-layout/input-layout.cjs.map +3 -3
- package/build/form/primitives/input-layout/slot.cjs +3 -3
- package/build/form/primitives/input-layout/slot.cjs.map +2 -2
- package/build/form/primitives/select/item.cjs +3 -3
- package/build/form/primitives/select/item.cjs.map +2 -2
- package/build/form/primitives/select/popup.cjs +5 -5
- package/build/form/primitives/select/popup.cjs.map +2 -2
- package/build/form/primitives/select/trigger.cjs +6 -6
- package/build/form/primitives/select/trigger.cjs.map +2 -2
- package/build/form/primitives/select/types.cjs.map +1 -1
- package/build/form/primitives/textarea/textarea.cjs +20 -1
- package/build/form/primitives/textarea/textarea.cjs.map +3 -3
- package/build/index.cjs +3 -0
- package/build/index.cjs.map +2 -2
- package/build/link/link.cjs +16 -6
- package/build/link/link.cjs.map +3 -3
- package/build/notice/action-button.cjs +3 -3
- package/build/notice/action-button.cjs.map +2 -2
- package/build/notice/action-link.cjs +3 -3
- package/build/notice/action-link.cjs.map +2 -2
- package/build/notice/actions.cjs +3 -3
- package/build/notice/actions.cjs.map +2 -2
- package/build/notice/close-icon.cjs +3 -3
- package/build/notice/close-icon.cjs.map +2 -2
- package/build/notice/description.cjs +3 -3
- package/build/notice/description.cjs.map +2 -2
- package/build/notice/root.cjs +3 -3
- package/build/notice/root.cjs.map +2 -2
- package/build/notice/title.cjs +3 -3
- package/build/notice/title.cjs.map +2 -2
- package/build/popover/arrow.cjs +94 -0
- package/build/popover/arrow.cjs.map +7 -0
- package/build/popover/close.cjs +45 -0
- package/build/popover/close.cjs.map +7 -0
- package/build/popover/context.cjs +76 -0
- package/build/popover/context.cjs.map +7 -0
- package/build/popover/description.cjs +70 -0
- package/build/popover/description.cjs.map +7 -0
- package/build/popover/index.cjs +49 -0
- package/build/popover/index.cjs.map +7 -0
- package/build/popover/popup.cjs +138 -0
- package/build/popover/popup.cjs.map +7 -0
- package/build/popover/root.cjs +35 -0
- package/build/popover/root.cjs.map +7 -0
- package/build/popover/title.cjs +56 -0
- package/build/popover/title.cjs.map +7 -0
- package/build/popover/trigger.cjs +38 -0
- package/build/popover/trigger.cjs.map +7 -0
- package/build/popover/types.cjs +19 -0
- package/build/popover/types.cjs.map +7 -0
- package/build/tabs/list.cjs +3 -4
- package/build/tabs/list.cjs.map +2 -2
- package/build/tabs/panel.cjs +3 -3
- package/build/tabs/panel.cjs.map +2 -2
- package/build/tabs/tab.cjs +3 -3
- package/build/tabs/tab.cjs.map +2 -2
- package/build/text/text.cjs +20 -5
- package/build/text/text.cjs.map +3 -3
- package/build/tooltip/popup.cjs +5 -4
- package/build/tooltip/popup.cjs.map +2 -2
- package/build/tooltip/root.cjs.map +2 -2
- package/build/tooltip/types.cjs.map +1 -1
- package/build/utils/types.cjs.map +1 -1
- package/build/utils/use-deprioritized-initial-focus.cjs.map +2 -2
- package/build/visually-hidden/visually-hidden.cjs.map +2 -2
- package/build-module/alert-dialog/context.mjs +6 -1
- package/build-module/alert-dialog/context.mjs.map +2 -2
- package/build-module/alert-dialog/popup.mjs +107 -33
- package/build-module/alert-dialog/popup.mjs.map +4 -4
- package/build-module/alert-dialog/root.mjs +113 -7
- package/build-module/alert-dialog/root.mjs.map +2 -2
- package/build-module/alert-dialog/trigger.mjs +4 -4
- package/build-module/alert-dialog/trigger.mjs.map +3 -3
- package/build-module/badge/badge.mjs +14 -14
- package/build-module/badge/badge.mjs.map +2 -2
- package/build-module/button/button.mjs +16 -6
- package/build-module/button/button.mjs.map +3 -3
- package/build-module/card/content.mjs +4 -4
- package/build-module/card/content.mjs.map +2 -2
- package/build-module/card/full-bleed.mjs +4 -4
- package/build-module/card/full-bleed.mjs.map +2 -2
- package/build-module/card/header.mjs +4 -4
- package/build-module/card/header.mjs.map +2 -2
- package/build-module/card/root.mjs +4 -4
- package/build-module/card/root.mjs.map +2 -2
- package/build-module/card/title.mjs +5 -15
- package/build-module/card/title.mjs.map +3 -3
- package/build-module/collapsible-card/content.mjs +3 -3
- package/build-module/collapsible-card/content.mjs.map +1 -1
- package/build-module/collapsible-card/header.mjs +6 -6
- package/build-module/collapsible-card/header.mjs.map +2 -2
- package/build-module/dialog/footer.mjs +3 -3
- package/build-module/dialog/footer.mjs.map +2 -2
- package/build-module/dialog/header.mjs +3 -3
- package/build-module/dialog/header.mjs.map +2 -2
- package/build-module/dialog/popup.mjs +5 -4
- package/build-module/dialog/popup.mjs.map +2 -2
- package/build-module/dialog/title.mjs +10 -9
- package/build-module/dialog/title.mjs.map +2 -2
- package/build-module/empty-state/actions.mjs +3 -3
- package/build-module/empty-state/actions.mjs.map +2 -2
- package/build-module/empty-state/description.mjs +8 -5
- package/build-module/empty-state/description.mjs.map +2 -2
- package/build-module/empty-state/icon.mjs +3 -3
- package/build-module/empty-state/icon.mjs.map +2 -2
- package/build-module/empty-state/root.mjs +3 -3
- package/build-module/empty-state/root.mjs.map +2 -2
- package/build-module/empty-state/title.mjs +8 -5
- package/build-module/empty-state/title.mjs.map +2 -2
- package/build-module/empty-state/visual.mjs +3 -3
- package/build-module/empty-state/visual.mjs.map +2 -2
- package/build-module/form/primitives/field/description.mjs +17 -4
- package/build-module/form/primitives/field/description.mjs.map +3 -3
- package/build-module/form/primitives/field/details.mjs +4 -4
- package/build-module/form/primitives/field/details.mjs.map +2 -2
- package/build-module/form/primitives/field/label.mjs +8 -8
- package/build-module/form/primitives/field/label.mjs.map +2 -2
- package/build-module/form/primitives/field/root.mjs +2 -2
- package/build-module/form/primitives/field/root.mjs.map +2 -2
- package/build-module/form/primitives/fieldset/description.mjs +20 -4
- package/build-module/form/primitives/fieldset/description.mjs.map +3 -3
- package/build-module/form/primitives/fieldset/details.mjs +3 -3
- package/build-module/form/primitives/fieldset/details.mjs.map +2 -2
- package/build-module/form/primitives/fieldset/legend.mjs +8 -7
- package/build-module/form/primitives/fieldset/legend.mjs.map +2 -2
- package/build-module/form/primitives/input/input.mjs +23 -7
- package/build-module/form/primitives/input/input.mjs.map +3 -3
- package/build-module/form/primitives/input-layout/input-layout.mjs +13 -3
- package/build-module/form/primitives/input-layout/input-layout.mjs.map +3 -3
- package/build-module/form/primitives/input-layout/slot.mjs +3 -3
- package/build-module/form/primitives/input-layout/slot.mjs.map +2 -2
- package/build-module/form/primitives/select/item.mjs +3 -3
- package/build-module/form/primitives/select/item.mjs.map +2 -2
- package/build-module/form/primitives/select/popup.mjs +5 -5
- package/build-module/form/primitives/select/popup.mjs.map +2 -2
- package/build-module/form/primitives/select/trigger.mjs +6 -6
- package/build-module/form/primitives/select/trigger.mjs.map +2 -2
- package/build-module/form/primitives/textarea/textarea.mjs +20 -1
- package/build-module/form/primitives/textarea/textarea.mjs.map +3 -3
- package/build-module/index.mjs +2 -0
- package/build-module/index.mjs.map +2 -2
- package/build-module/link/link.mjs +16 -6
- package/build-module/link/link.mjs.map +3 -3
- package/build-module/notice/action-button.mjs +3 -3
- package/build-module/notice/action-button.mjs.map +2 -2
- package/build-module/notice/action-link.mjs +3 -3
- package/build-module/notice/action-link.mjs.map +2 -2
- package/build-module/notice/actions.mjs +3 -3
- package/build-module/notice/actions.mjs.map +2 -2
- package/build-module/notice/close-icon.mjs +3 -3
- package/build-module/notice/close-icon.mjs.map +2 -2
- package/build-module/notice/description.mjs +3 -3
- package/build-module/notice/description.mjs.map +2 -2
- package/build-module/notice/root.mjs +3 -3
- package/build-module/notice/root.mjs.map +2 -2
- package/build-module/notice/title.mjs +3 -3
- package/build-module/notice/title.mjs.map +2 -2
- package/build-module/popover/arrow.mjs +59 -0
- package/build-module/popover/arrow.mjs.map +7 -0
- package/build-module/popover/close.mjs +20 -0
- package/build-module/popover/close.mjs.map +7 -0
- package/build-module/popover/context.mjs +57 -0
- package/build-module/popover/context.mjs.map +7 -0
- package/build-module/popover/description.mjs +35 -0
- package/build-module/popover/description.mjs.map +7 -0
- package/build-module/popover/index.mjs +18 -0
- package/build-module/popover/index.mjs.map +7 -0
- package/build-module/popover/popup.mjs +105 -0
- package/build-module/popover/popup.mjs.map +7 -0
- package/build-module/popover/root.mjs +10 -0
- package/build-module/popover/root.mjs.map +7 -0
- package/build-module/popover/title.mjs +31 -0
- package/build-module/popover/title.mjs.map +7 -0
- package/build-module/popover/trigger.mjs +13 -0
- package/build-module/popover/trigger.mjs.map +7 -0
- package/build-module/popover/types.mjs +1 -0
- package/build-module/popover/types.mjs.map +7 -0
- package/build-module/tabs/list.mjs +3 -4
- package/build-module/tabs/list.mjs.map +2 -2
- package/build-module/tabs/panel.mjs +3 -3
- package/build-module/tabs/panel.mjs.map +2 -2
- package/build-module/tabs/tab.mjs +3 -3
- package/build-module/tabs/tab.mjs.map +2 -2
- package/build-module/text/text.mjs +20 -5
- package/build-module/text/text.mjs.map +3 -3
- package/build-module/tooltip/popup.mjs +5 -4
- package/build-module/tooltip/popup.mjs.map +2 -2
- package/build-module/tooltip/root.mjs.map +2 -2
- package/build-module/utils/use-deprioritized-initial-focus.mjs.map +2 -2
- package/build-module/visually-hidden/visually-hidden.mjs.map +2 -2
- package/build-types/alert-dialog/context.d.ts +6 -3
- package/build-types/alert-dialog/context.d.ts.map +1 -1
- package/build-types/alert-dialog/popup.d.ts.map +1 -1
- package/build-types/alert-dialog/root.d.ts +2 -8
- package/build-types/alert-dialog/root.d.ts.map +1 -1
- package/build-types/alert-dialog/stories/index.story.d.ts +18 -6
- package/build-types/alert-dialog/stories/index.story.d.ts.map +1 -1
- package/build-types/alert-dialog/trigger.d.ts +2 -1
- package/build-types/alert-dialog/trigger.d.ts.map +1 -1
- package/build-types/alert-dialog/types.d.ts +61 -26
- package/build-types/alert-dialog/types.d.ts.map +1 -1
- package/build-types/badge/badge.d.ts.map +1 -1
- package/build-types/button/button.d.ts.map +1 -1
- package/build-types/card/stories/index.story.d.ts.map +1 -1
- package/build-types/card/title.d.ts.map +1 -1
- package/build-types/collapsible/panel.d.ts +2 -1
- package/build-types/collapsible/panel.d.ts.map +1 -1
- package/build-types/collapsible/root.d.ts +2 -1
- package/build-types/collapsible/root.d.ts.map +1 -1
- package/build-types/collapsible/trigger.d.ts +2 -1
- package/build-types/collapsible/trigger.d.ts.map +1 -1
- package/build-types/dialog/popup.d.ts.map +1 -1
- package/build-types/dialog/stories/index.story.d.ts +8 -0
- package/build-types/dialog/stories/index.story.d.ts.map +1 -1
- package/build-types/dialog/title.d.ts +12 -2
- package/build-types/dialog/title.d.ts.map +1 -1
- package/build-types/dialog/types.d.ts +8 -1
- package/build-types/dialog/types.d.ts.map +1 -1
- package/build-types/empty-state/description.d.ts.map +1 -1
- package/build-types/empty-state/title.d.ts.map +1 -1
- package/build-types/form/primitives/field/description.d.ts +2 -1
- package/build-types/form/primitives/field/description.d.ts.map +1 -1
- package/build-types/form/primitives/field/details.d.ts +2 -1
- package/build-types/form/primitives/field/details.d.ts.map +1 -1
- package/build-types/form/primitives/field/label.d.ts +2 -1
- package/build-types/form/primitives/field/label.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/description.d.ts +2 -1
- package/build-types/form/primitives/fieldset/description.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/details.d.ts +2 -1
- package/build-types/form/primitives/fieldset/details.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/legend.d.ts +2 -1
- package/build-types/form/primitives/fieldset/legend.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/root.d.ts +2 -1
- package/build-types/form/primitives/fieldset/root.d.ts.map +1 -1
- package/build-types/form/primitives/input/input.d.ts.map +1 -1
- package/build-types/form/primitives/input-layout/input-layout.d.ts.map +1 -1
- package/build-types/form/primitives/select/item.d.ts +6 -2
- package/build-types/form/primitives/select/item.d.ts.map +1 -1
- package/build-types/form/primitives/select/popup.d.ts +11 -1
- package/build-types/form/primitives/select/popup.d.ts.map +1 -1
- package/build-types/form/primitives/select/trigger.d.ts +12 -2
- package/build-types/form/primitives/select/trigger.d.ts.map +1 -1
- package/build-types/form/primitives/select/types.d.ts +13 -3
- package/build-types/form/primitives/select/types.d.ts.map +1 -1
- package/build-types/form/primitives/textarea/textarea.d.ts.map +1 -1
- package/build-types/form/stories/shared.d.ts.map +1 -1
- package/build-types/index.d.ts +1 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/link/link.d.ts.map +1 -1
- package/build-types/popover/arrow.d.ts +10 -0
- package/build-types/popover/arrow.d.ts.map +1 -0
- package/build-types/popover/close.d.ts +11 -0
- package/build-types/popover/close.d.ts.map +1 -0
- package/build-types/popover/context.d.ts +22 -0
- package/build-types/popover/context.d.ts.map +1 -0
- package/build-types/popover/description.d.ts +10 -0
- package/build-types/popover/description.d.ts.map +1 -0
- package/build-types/popover/index.d.ts +9 -0
- package/build-types/popover/index.d.ts.map +1 -0
- package/build-types/popover/popup.d.ts +11 -0
- package/build-types/popover/popup.d.ts.map +1 -0
- package/build-types/popover/root.d.ts +37 -0
- package/build-types/popover/root.d.ts.map +1 -0
- package/build-types/popover/stories/index.story.d.ts +211 -0
- package/build-types/popover/stories/index.story.d.ts.map +1 -0
- package/build-types/popover/stories/utils.d.ts +25 -0
- package/build-types/popover/stories/utils.d.ts.map +1 -0
- package/build-types/popover/test/index.test.d.ts +2 -0
- package/build-types/popover/test/index.test.d.ts.map +1 -0
- package/build-types/popover/title.d.ts +20 -0
- package/build-types/popover/title.d.ts.map +1 -0
- package/build-types/popover/trigger.d.ts +10 -0
- package/build-types/popover/trigger.d.ts.map +1 -0
- package/build-types/popover/types.d.ts +83 -0
- package/build-types/popover/types.d.ts.map +1 -0
- package/build-types/tabs/list.d.ts +2 -1
- package/build-types/tabs/list.d.ts.map +1 -1
- package/build-types/tabs/panel.d.ts +2 -1
- package/build-types/tabs/panel.d.ts.map +1 -1
- package/build-types/tabs/root.d.ts +2 -1
- package/build-types/tabs/root.d.ts.map +1 -1
- package/build-types/tabs/tab.d.ts +2 -1
- package/build-types/tabs/tab.d.ts.map +1 -1
- package/build-types/text/stories/index.story.d.ts +4 -0
- package/build-types/text/stories/index.story.d.ts.map +1 -1
- package/build-types/text/text.d.ts.map +1 -1
- package/build-types/tooltip/popup.d.ts.map +1 -1
- package/build-types/tooltip/root.d.ts +9 -8
- package/build-types/tooltip/root.d.ts.map +1 -1
- package/build-types/tooltip/stories/usage-guidelines.story.d.ts +21 -0
- package/build-types/tooltip/stories/usage-guidelines.story.d.ts.map +1 -0
- package/build-types/tooltip/types.d.ts +4 -0
- package/build-types/tooltip/types.d.ts.map +1 -1
- package/build-types/utils/types.d.ts +6 -2
- package/build-types/utils/types.d.ts.map +1 -1
- package/build-types/utils/use-deprioritized-initial-focus.d.ts +6 -5
- package/build-types/utils/use-deprioritized-initial-focus.d.ts.map +1 -1
- package/build-types/visually-hidden/stories/index.story.d.ts +7 -0
- package/build-types/visually-hidden/stories/index.story.d.ts.map +1 -1
- package/build-types/visually-hidden/visually-hidden.d.ts +34 -0
- package/build-types/visually-hidden/visually-hidden.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/alert-dialog/context.tsx +12 -4
- package/src/alert-dialog/popup.tsx +91 -33
- package/src/alert-dialog/root.tsx +191 -13
- package/src/alert-dialog/stories/index.story.tsx +116 -65
- package/src/alert-dialog/style.module.css +11 -0
- package/src/alert-dialog/test/index.test.tsx +1319 -347
- package/src/alert-dialog/trigger.tsx +2 -2
- package/src/alert-dialog/types.ts +64 -28
- package/src/badge/badge.tsx +11 -14
- package/src/badge/style.module.css +0 -4
- package/src/button/button.tsx +2 -0
- package/src/button/style.module.css +7 -3
- package/src/card/stories/index.story.tsx +4 -5
- package/src/card/style.module.css +1 -5
- package/src/card/test/index.test.tsx +17 -1
- package/src/card/title.tsx +6 -5
- package/src/collapsible-card/stories/index.story.tsx +5 -5
- package/src/dialog/popup.tsx +2 -1
- package/src/dialog/stories/index.story.tsx +33 -0
- package/src/dialog/style.module.css +13 -9
- package/src/dialog/test/index.test.tsx +63 -4
- package/src/dialog/title.tsx +21 -9
- package/src/dialog/types.ts +9 -1
- package/src/empty-state/description.tsx +6 -2
- package/src/empty-state/style.module.css +1 -1
- package/src/empty-state/test/description.test.tsx +13 -0
- package/src/empty-state/test/title.test.tsx +13 -0
- package/src/empty-state/title.tsx +9 -3
- package/src/form/primitives/field/description.tsx +6 -1
- package/src/form/primitives/field/details.tsx +4 -2
- package/src/form/primitives/field/label.tsx +9 -5
- package/src/form/primitives/field/root.tsx +2 -2
- package/src/form/primitives/field/test/index.test.tsx +11 -0
- package/src/form/primitives/fieldset/description.tsx +9 -1
- package/src/form/primitives/fieldset/legend.tsx +9 -4
- package/src/form/primitives/fieldset/test/index.test.tsx +22 -0
- package/src/form/primitives/input/input.tsx +6 -1
- package/src/form/primitives/input/style.module.css +4 -0
- package/src/form/primitives/input-layout/input-layout.tsx +2 -0
- package/src/form/primitives/input-layout/style.module.css +3 -3
- package/src/form/primitives/select/popup.tsx +5 -2
- package/src/form/primitives/select/test/index.test.tsx +60 -1
- package/src/form/primitives/select/types.ts +14 -4
- package/src/form/primitives/textarea/textarea.tsx +10 -1
- package/src/form/stories/shared.tsx +4 -2
- package/src/index.ts +1 -0
- package/src/link/link.tsx +2 -0
- package/src/link/style.module.css +11 -1
- package/src/notice/style.module.css +5 -5
- package/src/popover/arrow.tsx +49 -0
- package/src/popover/close.tsx +24 -0
- package/src/popover/context.tsx +100 -0
- package/src/popover/description.tsx +29 -0
- package/src/popover/index.ts +9 -0
- package/src/popover/popup.tsx +106 -0
- package/src/popover/root.tsx +41 -0
- package/src/popover/stories/index.story.tsx +1315 -0
- package/src/popover/stories/utils.tsx +91 -0
- package/src/popover/style.module.css +64 -0
- package/src/popover/test/index.test.tsx +727 -0
- package/src/popover/title.tsx +47 -0
- package/src/popover/trigger.tsx +17 -0
- package/src/popover/types.ts +113 -0
- package/src/tabs/list.tsx +0 -1
- package/src/tabs/style.module.css +2 -2
- package/src/text/stories/index.story.tsx +4 -2
- package/src/text/style.module.css +62 -36
- package/src/text/test/index.test.tsx +1 -4
- package/src/text/text.tsx +8 -1
- package/src/tooltip/popup.tsx +2 -1
- package/src/tooltip/root.tsx +9 -8
- package/src/tooltip/stories/usage-guidelines.mdx +91 -0
- package/src/tooltip/stories/usage-guidelines.story.tsx +119 -0
- package/src/tooltip/style.module.css +2 -2
- package/src/tooltip/test/index.test.tsx +61 -0
- package/src/tooltip/types.ts +5 -0
- package/src/utils/css/field.module.css +12 -9
- package/src/utils/css/focus.module.css +7 -5
- package/src/utils/css/global-css-defense.module.css +117 -0
- package/src/utils/css/item-popup.module.css +2 -2
- package/src/utils/types.ts +7 -2
- package/src/utils/use-deprioritized-initial-focus.ts +5 -4
- package/src/visually-hidden/stories/index.story.tsx +25 -0
- package/src/visually-hidden/visually-hidden.tsx +34 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Popover as _Popover } from '@base-ui/react/popover';
|
|
2
|
+
import { useMergeRefs } from '@wordpress/compose';
|
|
3
|
+
import { forwardRef, useLayoutEffect, useRef } from '@wordpress/element';
|
|
4
|
+
import { Text } from '../text';
|
|
5
|
+
import { usePopoverValidationContext } from './context';
|
|
6
|
+
import type { TitleProps } from './types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Renders a heading that labels the popover for accessibility.
|
|
10
|
+
*
|
|
11
|
+
* **Required** — every popover must include a `Popover.Title`, even if
|
|
12
|
+
* visually hidden. The rendered element is linked to the popup via
|
|
13
|
+
* `aria-labelledby`. Uses the `heading-xl` text variant, matching Dialog.
|
|
14
|
+
*
|
|
15
|
+
* To visually hide the title while keeping it accessible, wrap it with
|
|
16
|
+
* `VisuallyHidden` using the `render` prop:
|
|
17
|
+
*
|
|
18
|
+
* ```jsx
|
|
19
|
+
* <VisuallyHidden render={ <Popover.Title /> }>
|
|
20
|
+
* Accessible title text
|
|
21
|
+
* </VisuallyHidden>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
const Title = forwardRef< HTMLHeadingElement, TitleProps >(
|
|
25
|
+
function PopoverTitle( { className, children, ...props }, forwardedRef ) {
|
|
26
|
+
const validationContext = usePopoverValidationContext();
|
|
27
|
+
const internalRef = useRef< HTMLHeadingElement >( null );
|
|
28
|
+
const mergedRef = useMergeRefs( [ internalRef, forwardedRef ] );
|
|
29
|
+
|
|
30
|
+
useLayoutEffect( () => {
|
|
31
|
+
validationContext?.registerTitle( internalRef.current );
|
|
32
|
+
}, [ validationContext ] );
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Text
|
|
36
|
+
ref={ mergedRef }
|
|
37
|
+
variant="heading-xl"
|
|
38
|
+
render={ <_Popover.Title { ...props } /> }
|
|
39
|
+
className={ className }
|
|
40
|
+
>
|
|
41
|
+
{ children }
|
|
42
|
+
</Text>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export { Title };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Popover as _Popover } from '@base-ui/react/popover';
|
|
2
|
+
import { forwardRef } from '@wordpress/element';
|
|
3
|
+
import type { TriggerProps } from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Renders a button that toggles the popover popup when clicked.
|
|
7
|
+
*
|
|
8
|
+
* Renders as a `<button>` by default. Also supports hover-triggered
|
|
9
|
+
* popovers via the `openOnHover`, `delay`, and `closeDelay` props.
|
|
10
|
+
*/
|
|
11
|
+
const Trigger = forwardRef< HTMLButtonElement, TriggerProps >(
|
|
12
|
+
function PopoverTrigger( props, ref ) {
|
|
13
|
+
return <_Popover.Trigger ref={ ref } { ...props } />;
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
export { Trigger };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { Popover as _Popover } from '@base-ui/react/popover';
|
|
3
|
+
import type { ComponentProps } from '../utils/types';
|
|
4
|
+
|
|
5
|
+
export interface RootProps
|
|
6
|
+
extends Pick<
|
|
7
|
+
_Popover.Root.Props,
|
|
8
|
+
'open' | 'onOpenChange' | 'defaultOpen' | 'modal'
|
|
9
|
+
> {
|
|
10
|
+
/**
|
|
11
|
+
* The popover sub-components (`Popover.Trigger`, `Popover.Popup`, etc.).
|
|
12
|
+
*/
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TriggerProps
|
|
17
|
+
extends ComponentProps< 'button' >,
|
|
18
|
+
Pick< _Popover.Trigger.Props, 'openOnHover' | 'delay' | 'closeDelay' > {
|
|
19
|
+
/**
|
|
20
|
+
* The content to be rendered inside the component.
|
|
21
|
+
*/
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `Popover.Popup` maps to two Base UI elements internally: the
|
|
27
|
+
* **Positioner** (outer, handles fixed positioning and z-index) and the
|
|
28
|
+
* **Popup** (inner, holds content and visual styles).
|
|
29
|
+
*
|
|
30
|
+
* `style` and `className` are forwarded to the **Positioner** so that
|
|
31
|
+
* z-index overrides (`--wp-ui-popover-z-index`) and Base UI CSS variables
|
|
32
|
+
* (`--available-height`, `--available-width`) work correctly. All other
|
|
33
|
+
* HTML attributes are forwarded to the inner **Popup** element.
|
|
34
|
+
*/
|
|
35
|
+
export interface PopupProps
|
|
36
|
+
extends ComponentProps< 'div' >,
|
|
37
|
+
Pick<
|
|
38
|
+
_Popover.Positioner.Props,
|
|
39
|
+
| 'align'
|
|
40
|
+
| 'alignOffset'
|
|
41
|
+
| 'anchor'
|
|
42
|
+
| 'arrowPadding'
|
|
43
|
+
| 'collisionAvoidance'
|
|
44
|
+
| 'collisionBoundary'
|
|
45
|
+
| 'collisionPadding'
|
|
46
|
+
| 'side'
|
|
47
|
+
| 'sideOffset'
|
|
48
|
+
| 'sticky'
|
|
49
|
+
>,
|
|
50
|
+
Pick< _Popover.Popup.Props, 'initialFocus' | 'finalFocus' > {
|
|
51
|
+
/**
|
|
52
|
+
* Whether to render a backdrop overlay behind the popover.
|
|
53
|
+
*
|
|
54
|
+
* Typically used with `modal` to signal that interaction with the rest
|
|
55
|
+
* of the page is blocked. The backdrop is a semi-transparent dark overlay.
|
|
56
|
+
*
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
backdrop?: boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The content to be rendered inside the component.
|
|
63
|
+
*/
|
|
64
|
+
children?: ReactNode;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A parent element to render the portal into.
|
|
68
|
+
*
|
|
69
|
+
* Useful for cross-document rendering, such as rendering a popover
|
|
70
|
+
* in a parent document when the trigger is inside an iframe.
|
|
71
|
+
*/
|
|
72
|
+
container?: _Popover.Portal.Props[ 'container' ];
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The visual style variant of the popup.
|
|
76
|
+
*
|
|
77
|
+
* - `'default'` — standard surface styling with background, padding,
|
|
78
|
+
* border radius, and shadow.
|
|
79
|
+
* - `'unstyled'` — no visual treatment; useful as a blank positioning
|
|
80
|
+
* container for fully custom content.
|
|
81
|
+
*
|
|
82
|
+
* @default 'default'
|
|
83
|
+
*/
|
|
84
|
+
variant?: 'default' | 'unstyled';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ArrowProps extends ComponentProps< 'div' > {
|
|
88
|
+
/**
|
|
89
|
+
* Custom arrow visuals to render inside the positioned container.
|
|
90
|
+
*/
|
|
91
|
+
children?: ReactNode;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface TitleProps extends ComponentProps< 'h2' > {
|
|
95
|
+
/**
|
|
96
|
+
* The title content to be rendered.
|
|
97
|
+
*/
|
|
98
|
+
children?: ReactNode;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface DescriptionProps extends ComponentProps< 'p' > {
|
|
102
|
+
/**
|
|
103
|
+
* The description content to be rendered.
|
|
104
|
+
*/
|
|
105
|
+
children?: ReactNode;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface CloseProps extends ComponentProps< 'button' > {
|
|
109
|
+
/**
|
|
110
|
+
* The content to be rendered inside the component.
|
|
111
|
+
*/
|
|
112
|
+
children?: ReactNode;
|
|
113
|
+
}
|
package/src/tabs/list.tsx
CHANGED
|
@@ -122,8 +122,8 @@
|
|
|
122
122
|
cursor: var(--wpds-cursor-control);
|
|
123
123
|
|
|
124
124
|
/* Typography */
|
|
125
|
-
font-family: var(--wpds-font-family-body);
|
|
126
|
-
font-size: var(--wpds-font-size-md);
|
|
125
|
+
font-family: var(--wpds-typography-font-family-body);
|
|
126
|
+
font-size: var(--wpds-typography-font-size-md);
|
|
127
127
|
white-space: nowrap;
|
|
128
128
|
|
|
129
129
|
/* Characters in some languages (e.g. Japanese) may have a native higher line-height. */
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable jsx-a11y/heading-has-content */
|
|
2
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
2
|
import { Text } from '../index';
|
|
4
3
|
import { Stack } from '../../stack';
|
|
@@ -18,6 +17,10 @@ export const Default: Story = {
|
|
|
18
17
|
},
|
|
19
18
|
};
|
|
20
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Important: Setting the `variant` prop to a `heading` variant will not automatically render a heading element.
|
|
22
|
+
* Use the `render` prop to render a heading element with the appropriate level.
|
|
23
|
+
*/
|
|
21
24
|
export const AllVariants: Story = {
|
|
22
25
|
render: () => (
|
|
23
26
|
<Stack
|
|
@@ -65,4 +68,3 @@ export const WithRenderProp: Story = {
|
|
|
65
68
|
</Stack>
|
|
66
69
|
),
|
|
67
70
|
};
|
|
68
|
-
/* eslint-enable jsx-a11y/heading-has-content */
|
|
@@ -1,67 +1,93 @@
|
|
|
1
1
|
@layer wp-ui-utilities, wp-ui-components, wp-ui-compositions, wp-ui-overrides;
|
|
2
2
|
|
|
3
3
|
@layer wp-ui-components {
|
|
4
|
+
.text {
|
|
5
|
+
margin: 0;
|
|
6
|
+
}
|
|
7
|
+
|
|
4
8
|
.heading-2xl {
|
|
5
|
-
font-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
font-
|
|
9
|
+
--_gcd-heading-font-size: var(--wpds-typography-font-size-2xl);
|
|
10
|
+
|
|
11
|
+
font-family: var(--wpds-typography-font-family-heading);
|
|
12
|
+
font-size: var(--wpds-typography-font-size-2xl);
|
|
13
|
+
line-height: var(--wpds-typography-line-height-2xl);
|
|
14
|
+
font-weight: var(--wpds-typography-font-weight-medium);
|
|
9
15
|
}
|
|
10
16
|
|
|
11
17
|
.heading-xl {
|
|
12
|
-
font-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
font-
|
|
18
|
+
--_gcd-heading-font-size: var(--wpds-typography-font-size-xl);
|
|
19
|
+
|
|
20
|
+
font-family: var(--wpds-typography-font-family-heading);
|
|
21
|
+
font-size: var(--wpds-typography-font-size-xl);
|
|
22
|
+
line-height: var(--wpds-typography-line-height-md);
|
|
23
|
+
font-weight: var(--wpds-typography-font-weight-medium);
|
|
16
24
|
}
|
|
17
25
|
|
|
18
26
|
.heading-lg {
|
|
19
|
-
font-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
font-
|
|
27
|
+
--_gcd-heading-font-size: var(--wpds-typography-font-size-lg);
|
|
28
|
+
|
|
29
|
+
font-family: var(--wpds-typography-font-family-heading);
|
|
30
|
+
font-size: var(--wpds-typography-font-size-lg);
|
|
31
|
+
line-height: var(--wpds-typography-line-height-sm);
|
|
32
|
+
font-weight: var(--wpds-typography-font-weight-medium);
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
.heading-md {
|
|
26
|
-
font-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
font-
|
|
36
|
+
--_gcd-heading-font-size: var(--wpds-typography-font-size-md);
|
|
37
|
+
|
|
38
|
+
font-family: var(--wpds-typography-font-family-heading);
|
|
39
|
+
font-size: var(--wpds-typography-font-size-md);
|
|
40
|
+
line-height: var(--wpds-typography-line-height-sm);
|
|
41
|
+
font-weight: var(--wpds-typography-font-weight-medium);
|
|
30
42
|
}
|
|
31
43
|
|
|
32
44
|
.heading-sm {
|
|
33
|
-
font-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
font-
|
|
45
|
+
--_gcd-heading-font-size: var(--wpds-typography-font-size-xs);
|
|
46
|
+
|
|
47
|
+
font-family: var(--wpds-typography-font-family-heading);
|
|
48
|
+
font-size: var(--wpds-typography-font-size-xs);
|
|
49
|
+
line-height: var(--wpds-typography-line-height-xs);
|
|
50
|
+
font-weight: var(--wpds-typography-font-weight-medium);
|
|
37
51
|
text-transform: uppercase;
|
|
38
52
|
}
|
|
39
53
|
|
|
40
54
|
.body-xl {
|
|
41
|
-
font-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
font-
|
|
55
|
+
--_gcd-p-font-size: var(--wpds-typography-font-size-xl);
|
|
56
|
+
--_gcd-p-line-height: var(--wpds-typography-line-height-xl);
|
|
57
|
+
|
|
58
|
+
font-family: var(--wpds-typography-font-family-body);
|
|
59
|
+
font-size: var(--wpds-typography-font-size-xl);
|
|
60
|
+
line-height: var(--wpds-typography-line-height-xl);
|
|
61
|
+
font-weight: var(--wpds-typography-font-weight-regular);
|
|
45
62
|
}
|
|
46
63
|
|
|
47
64
|
.body-lg {
|
|
48
|
-
font-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
font-
|
|
65
|
+
--_gcd-p-font-size: var(--wpds-typography-font-size-lg);
|
|
66
|
+
--_gcd-p-line-height: var(--wpds-typography-line-height-md);
|
|
67
|
+
|
|
68
|
+
font-family: var(--wpds-typography-font-family-body);
|
|
69
|
+
font-size: var(--wpds-typography-font-size-lg);
|
|
70
|
+
line-height: var(--wpds-typography-line-height-md);
|
|
71
|
+
font-weight: var(--wpds-typography-font-weight-regular);
|
|
52
72
|
}
|
|
53
73
|
|
|
54
74
|
.body-md {
|
|
55
|
-
font-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
font-
|
|
75
|
+
--_gcd-p-font-size: var(--wpds-typography-font-size-md);
|
|
76
|
+
--_gcd-p-line-height: var(--wpds-typography-line-height-sm);
|
|
77
|
+
|
|
78
|
+
font-family: var(--wpds-typography-font-family-body);
|
|
79
|
+
font-size: var(--wpds-typography-font-size-md);
|
|
80
|
+
line-height: var(--wpds-typography-line-height-sm);
|
|
81
|
+
font-weight: var(--wpds-typography-font-weight-regular);
|
|
59
82
|
}
|
|
60
83
|
|
|
61
84
|
.body-sm {
|
|
62
|
-
font-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
font-
|
|
85
|
+
--_gcd-p-font-size: var(--wpds-typography-font-size-sm);
|
|
86
|
+
--_gcd-p-line-height: var(--wpds-typography-line-height-xs);
|
|
87
|
+
|
|
88
|
+
font-family: var(--wpds-typography-font-family-body);
|
|
89
|
+
font-size: var(--wpds-typography-font-size-sm);
|
|
90
|
+
line-height: var(--wpds-typography-line-height-xs);
|
|
91
|
+
font-weight: var(--wpds-typography-font-weight-regular);
|
|
66
92
|
}
|
|
67
93
|
}
|
|
@@ -34,10 +34,7 @@ describe( 'Text', () => {
|
|
|
34
34
|
} );
|
|
35
35
|
|
|
36
36
|
it( 'supports the render prop', () => {
|
|
37
|
-
render(
|
|
38
|
-
// eslint-disable-next-line jsx-a11y/heading-has-content
|
|
39
|
-
<Text render={ <h2 /> }>Section title</Text>
|
|
40
|
-
);
|
|
37
|
+
render( <Text render={ <h2 /> }>Section title</Text> );
|
|
41
38
|
|
|
42
39
|
expect(
|
|
43
40
|
screen.getByRole( 'heading', { level: 2, name: 'Section title' } )
|
package/src/text/text.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import clsx from 'clsx';
|
|
|
3
3
|
import { forwardRef } from '@wordpress/element';
|
|
4
4
|
import { type TextProps } from './types';
|
|
5
5
|
import styles from './style.module.css';
|
|
6
|
+
import defenseStyles from '../utils/css/global-css-defense.module.css';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* A text component for rendering content with predefined typographic variants.
|
|
@@ -17,7 +18,13 @@ export const Text = forwardRef< HTMLSpanElement, TextProps >( function Text(
|
|
|
17
18
|
defaultTagName: 'span',
|
|
18
19
|
ref,
|
|
19
20
|
props: mergeProps< 'span' >( props, {
|
|
20
|
-
className: clsx(
|
|
21
|
+
className: clsx(
|
|
22
|
+
styles.text,
|
|
23
|
+
variant.startsWith( 'heading-' ) && defenseStyles.heading,
|
|
24
|
+
variant.startsWith( 'body-' ) && defenseStyles.p,
|
|
25
|
+
styles[ variant ],
|
|
26
|
+
className
|
|
27
|
+
),
|
|
21
28
|
} ),
|
|
22
29
|
} );
|
|
23
30
|
|
package/src/tooltip/popup.tsx
CHANGED
|
@@ -16,6 +16,7 @@ const ThemeProvider: typeof ThemeProviderType =
|
|
|
16
16
|
const Popup = forwardRef< HTMLDivElement, PopupProps >( function TooltipPopup(
|
|
17
17
|
{
|
|
18
18
|
align = 'center',
|
|
19
|
+
container,
|
|
19
20
|
side = 'top',
|
|
20
21
|
sideOffset = 4,
|
|
21
22
|
children,
|
|
@@ -26,7 +27,7 @@ const Popup = forwardRef< HTMLDivElement, PopupProps >( function TooltipPopup(
|
|
|
26
27
|
ref
|
|
27
28
|
) {
|
|
28
29
|
return (
|
|
29
|
-
<Tooltip.Portal>
|
|
30
|
+
<Tooltip.Portal container={ container }>
|
|
30
31
|
<Tooltip.Positioner
|
|
31
32
|
align={ align }
|
|
32
33
|
side={ side }
|
package/src/tooltip/root.tsx
CHANGED
|
@@ -2,16 +2,17 @@ import { Tooltip } from '@base-ui/react/tooltip';
|
|
|
2
2
|
import type { RootProps } from './types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* `Tooltip` is used to visually show the label of an icon button, or other such
|
|
6
|
-
* that don't have a visual text label.
|
|
5
|
+
* `Tooltip` is used to visually show the label of an icon button, or other such
|
|
6
|
+
* interactive controls that don't have a visual text label.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Tooltip popups are visual-only and not exposed to assistive technologies.
|
|
9
|
+
* The trigger's accessible name (e.g. `aria-label`) is the source of truth
|
|
10
|
+
* for screen reader users. Tooltips are not available on touch devices,
|
|
11
|
+
* and thus should not be used for infotips, descriptions, or dynamic status
|
|
12
|
+
* messages.
|
|
10
13
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* See also: [IconButton](https://wordpress.github.io/gutenberg/?path=/docs/design-system-components-iconbutton--docs)
|
|
14
|
+
* @see {@link https://wordpress.github.io/gutenberg/?path=/docs/design-system-components-tooltip-usage-guidelines--docs Usage Guidelines}
|
|
15
|
+
* @see {@link https://wordpress.github.io/gutenberg/?path=/docs/design-system-components-iconbutton--docs IconButton}
|
|
15
16
|
*/
|
|
16
17
|
function Root( props: RootProps ) {
|
|
17
18
|
return <Tooltip.Root { ...props } />;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Canvas, Meta } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as UsageGuidelinesStories from './usage-guidelines.story';
|
|
3
|
+
|
|
4
|
+
<Meta of={ UsageGuidelinesStories } />
|
|
5
|
+
|
|
6
|
+
# Tooltip usage guidelines
|
|
7
|
+
|
|
8
|
+
## Usage guidelines
|
|
9
|
+
|
|
10
|
+
- **Use tooltips as visual labels only.** Tooltips should act as
|
|
11
|
+
supplementary visual labels for sighted mouse and keyboard users.
|
|
12
|
+
Tooltip popups are not exposed to assistive technologies — the
|
|
13
|
+
trigger's accessible name (e.g. `aria-label`) is what provides the
|
|
14
|
+
label for screen reader users.
|
|
15
|
+
See [_Alternatives to tooltips_](#alternatives-to-tooltips) below for
|
|
16
|
+
more details.
|
|
17
|
+
- **Provide an accessible name for the trigger.** Tooltips are visual-only
|
|
18
|
+
elements and are not a replacement for labeling the trigger. The
|
|
19
|
+
tooltip's trigger must have an `aria-label` that matches or is a concise
|
|
20
|
+
equivalent of the tooltip's content to ensure consistency for screen
|
|
21
|
+
reader users. If the tooltip also displays a keyboard shortcut, use
|
|
22
|
+
`aria-keyshortcuts` on the trigger.
|
|
23
|
+
|
|
24
|
+
<Canvas of={ UsageGuidelinesStories.RecommendedUsage } />
|
|
25
|
+
|
|
26
|
+
`IconButton` has built-in tooltip support via the `label` prop, making it
|
|
27
|
+
the easiest way to provide a tooltip for icon-only actions.
|
|
28
|
+
|
|
29
|
+
<Canvas of={ UsageGuidelinesStories.IconButtonWithTooltip } />
|
|
30
|
+
|
|
31
|
+
## Alternatives to tooltips
|
|
32
|
+
|
|
33
|
+
Tooltips should be supplementary popups that provide non-essential clarity in
|
|
34
|
+
high-density UIs. A user should not miss critical information if they never
|
|
35
|
+
see a tooltip.
|
|
36
|
+
|
|
37
|
+
Tooltips don't work well with touch input. Unlike mouse pointers with hover
|
|
38
|
+
capability, there's no easily discoverable way to reveal a tooltip before
|
|
39
|
+
tapping its trigger on a touch device.
|
|
40
|
+
|
|
41
|
+
iOS doesn't provide a system-standard, touch-friendly tooltip affordance,
|
|
42
|
+
while Android may show a tooltip on long press. However, on the web,
|
|
43
|
+
long press is often used to trigger contextual menus in the browser, which
|
|
44
|
+
can lead to potential conflicts. For this reason, tooltips are disabled on
|
|
45
|
+
touch devices.
|
|
46
|
+
|
|
47
|
+
### Infotips
|
|
48
|
+
|
|
49
|
+
Popups that open when hovering an info icon should use
|
|
50
|
+
[Popover](?path=/docs/design-system-components-popover--docs) with the
|
|
51
|
+
`openOnHover` prop on the trigger instead of a tooltip. This way, touch
|
|
52
|
+
users and screen reader users can access the content.
|
|
53
|
+
|
|
54
|
+
To know when to reach for a popover instead of a tooltip, consider the
|
|
55
|
+
**purpose** of the trigger element: if the trigger's purpose is to open the
|
|
56
|
+
popup itself, it's a popover. If the trigger's purpose is unrelated to
|
|
57
|
+
opening the popup, it's a tooltip.
|
|
58
|
+
|
|
59
|
+
<Canvas of={ UsageGuidelinesStories.InfotipWithPopover } />
|
|
60
|
+
|
|
61
|
+
See also the [Popover Infotip story](?path=/story/design-system-components-popover--infotip).
|
|
62
|
+
|
|
63
|
+
Infotips opened on hover can be dismissed by pressing `Escape`.
|
|
64
|
+
|
|
65
|
+
### Description text
|
|
66
|
+
|
|
67
|
+
Tooltips are designed for sighted mouse and keyboard users and are not a reliable way to deliver
|
|
68
|
+
important information to touch users or assistive technologies. If the
|
|
69
|
+
description is important to understanding the element, don't hide it behind a
|
|
70
|
+
tooltip — use inline text or
|
|
71
|
+
[Popover](?path=/docs/design-system-components-popover--docs) if space is
|
|
72
|
+
limited, so the information is accessible to everyone.
|
|
73
|
+
|
|
74
|
+
Since tooltips serve sighted mouse and keyboard users, iconography should
|
|
75
|
+
clearly communicate the purpose of icon-only triggers, especially on mobile
|
|
76
|
+
where the text label may not be visible.
|
|
77
|
+
|
|
78
|
+
If the description is not critical, a tooltip can still be used to provide
|
|
79
|
+
extra clarity for sighted mouse or keyboard users.
|
|
80
|
+
|
|
81
|
+
### Contextual feedback messages
|
|
82
|
+
|
|
83
|
+
For contextual feedback after an action (e.g. "Copied!"), prefer a pattern
|
|
84
|
+
that ensures the message is announced to screen readers and supports complex
|
|
85
|
+
content, such as a
|
|
86
|
+
[Notice](?path=/docs/design-system-components-notice--docs).
|
|
87
|
+
|
|
88
|
+
## References
|
|
89
|
+
|
|
90
|
+
- [WCAG 1.4.13: Content on Hover or Focus](https://www.w3.org/WAI/WCAG21/Understanding/content-on-hover-or-focus.html) — tooltips must be dismissible (Escape), hoverable, and persistent.
|
|
91
|
+
- [WAI-ARIA APG: Tooltip pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/) — note that this component intentionally diverges from the traditional `role="tooltip"` + `aria-describedby` pattern. The trigger's `aria-label` is the source of truth for assistive technologies, and the tooltip popup is a visual-only supplement.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import {
|
|
3
|
+
formatBold,
|
|
4
|
+
formatItalic,
|
|
5
|
+
formatUnderline,
|
|
6
|
+
info,
|
|
7
|
+
} from '@wordpress/icons';
|
|
8
|
+
import { Icon, IconButton, Popover, Tooltip, VisuallyHidden } from '../..';
|
|
9
|
+
|
|
10
|
+
const meta: Meta = {
|
|
11
|
+
title: 'Design System/Components/Tooltip/Usage Guidelines',
|
|
12
|
+
parameters: {
|
|
13
|
+
controls: { disable: true },
|
|
14
|
+
},
|
|
15
|
+
tags: [ '!dev' ],
|
|
16
|
+
};
|
|
17
|
+
export default meta;
|
|
18
|
+
|
|
19
|
+
type Story = StoryObj;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Tooltips work best as visual labels for icon-only controls. Each trigger
|
|
23
|
+
* must have its own accessible name via `aria-label`.
|
|
24
|
+
*/
|
|
25
|
+
export const RecommendedUsage: Story = {
|
|
26
|
+
render: () => (
|
|
27
|
+
<Tooltip.Provider delay={ 0 }>
|
|
28
|
+
<div style={ { display: 'flex', gap: '0.25rem' } }>
|
|
29
|
+
<Tooltip.Root>
|
|
30
|
+
<Tooltip.Trigger aria-label="Bold">
|
|
31
|
+
<Icon icon={ formatBold } />
|
|
32
|
+
</Tooltip.Trigger>
|
|
33
|
+
<Tooltip.Popup>Bold</Tooltip.Popup>
|
|
34
|
+
</Tooltip.Root>
|
|
35
|
+
|
|
36
|
+
<Tooltip.Root>
|
|
37
|
+
<Tooltip.Trigger aria-label="Italic">
|
|
38
|
+
<Icon icon={ formatItalic } />
|
|
39
|
+
</Tooltip.Trigger>
|
|
40
|
+
<Tooltip.Popup>Italic</Tooltip.Popup>
|
|
41
|
+
</Tooltip.Root>
|
|
42
|
+
|
|
43
|
+
<Tooltip.Root>
|
|
44
|
+
<Tooltip.Trigger aria-label="Underline">
|
|
45
|
+
<Icon icon={ formatUnderline } />
|
|
46
|
+
</Tooltip.Trigger>
|
|
47
|
+
<Tooltip.Popup>Underline</Tooltip.Popup>
|
|
48
|
+
</Tooltip.Root>
|
|
49
|
+
</div>
|
|
50
|
+
</Tooltip.Provider>
|
|
51
|
+
),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Popups that open when hovering an info icon should use `Popover` with
|
|
56
|
+
* `openOnHover` instead of a Tooltip. This ensures the content is accessible
|
|
57
|
+
* to touch and screen reader users.
|
|
58
|
+
*/
|
|
59
|
+
export const InfotipWithPopover: Story = {
|
|
60
|
+
render: () => (
|
|
61
|
+
<div
|
|
62
|
+
style={ {
|
|
63
|
+
display: 'flex',
|
|
64
|
+
alignItems: 'center',
|
|
65
|
+
gap: 'var(--wpds-dimension-gap-xs)',
|
|
66
|
+
} }
|
|
67
|
+
>
|
|
68
|
+
<span>Label</span>
|
|
69
|
+
<Popover.Root>
|
|
70
|
+
<Popover.Trigger
|
|
71
|
+
openOnHover
|
|
72
|
+
delay={ 200 }
|
|
73
|
+
closeDelay={ 200 }
|
|
74
|
+
aria-label="More information"
|
|
75
|
+
style={ {
|
|
76
|
+
background: 'none',
|
|
77
|
+
border: 'none',
|
|
78
|
+
padding: 0,
|
|
79
|
+
cursor: 'var(--wpds-cursor-control)',
|
|
80
|
+
display: 'inline-flex',
|
|
81
|
+
alignItems: 'center',
|
|
82
|
+
borderRadius: 'var(--wpds-border-radius-sm)',
|
|
83
|
+
} }
|
|
84
|
+
>
|
|
85
|
+
<Icon icon={ info } size={ 20 } />
|
|
86
|
+
</Popover.Trigger>
|
|
87
|
+
<Popover.Popup>
|
|
88
|
+
<Popover.Arrow />
|
|
89
|
+
<VisuallyHidden render={ <Popover.Title /> }>
|
|
90
|
+
More information
|
|
91
|
+
</VisuallyHidden>
|
|
92
|
+
<Popover.Description>
|
|
93
|
+
This is additional context about the label. Unlike
|
|
94
|
+
tooltips, this content is accessible to touch and screen
|
|
95
|
+
reader users.
|
|
96
|
+
</Popover.Description>
|
|
97
|
+
</Popover.Popup>
|
|
98
|
+
</Popover.Root>
|
|
99
|
+
</div>
|
|
100
|
+
),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* `IconButton` has built-in tooltip support via the `label` prop,
|
|
105
|
+
* making it the easiest way to provide a tooltip for icon-only actions.
|
|
106
|
+
*/
|
|
107
|
+
export const IconButtonWithTooltip: Story = {
|
|
108
|
+
render: () => (
|
|
109
|
+
<div style={ { display: 'flex', gap: '0.25rem' } }>
|
|
110
|
+
<IconButton icon={ formatBold } label="Bold" size="compact" />
|
|
111
|
+
<IconButton icon={ formatItalic } label="Italic" size="compact" />
|
|
112
|
+
<IconButton
|
|
113
|
+
icon={ formatUnderline }
|
|
114
|
+
label="Underline"
|
|
115
|
+
size="compact"
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
118
|
+
),
|
|
119
|
+
};
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
var(--wpds-dimension-padding-xs)
|
|
12
12
|
var(--wpds-dimension-padding-sm);
|
|
13
13
|
border-radius: var(--wpds-border-radius-sm);
|
|
14
|
-
font-family: var(--wpds-font-family-body);
|
|
15
|
-
font-size: var(--wpds-font-size-sm);
|
|
14
|
+
font-family: var(--wpds-typography-font-family-body);
|
|
15
|
+
font-size: var(--wpds-typography-font-size-sm);
|
|
16
16
|
line-height: 1.4; /* TODO: use DS token for line height */
|
|
17
17
|
color: var(--wpds-color-fg-content-neutral);
|
|
18
18
|
box-shadow: var(--wpds-elevation-sm);
|