@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
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { AlertDialog as _AlertDialog } from '@base-ui/react/alert-dialog';
|
|
1
2
|
import { forwardRef } from '@wordpress/element';
|
|
2
3
|
|
|
3
|
-
import * as Dialog from '../dialog';
|
|
4
4
|
import type { TriggerProps } from './types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -8,7 +8,7 @@ import type { TriggerProps } from './types';
|
|
|
8
8
|
*/
|
|
9
9
|
const Trigger = forwardRef< HTMLButtonElement, TriggerProps >(
|
|
10
10
|
function AlertDialogTrigger( props, ref ) {
|
|
11
|
-
return <
|
|
11
|
+
return <_AlertDialog.Trigger ref={ ref } { ...props } />;
|
|
12
12
|
}
|
|
13
13
|
);
|
|
14
14
|
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import type { AlertDialog as _AlertDialog } from '@base-ui/react/alert-dialog';
|
|
2
2
|
import type { ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { ComponentProps } from '../utils/types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The return type of `onConfirm`. Return `void` (or nothing) to auto-close
|
|
8
|
+
* the dialog after the confirm handler completes. Return `{ close: false }`
|
|
9
|
+
* to keep the dialog open (e.g. for validation errors).
|
|
10
|
+
*
|
|
11
|
+
* Return `{ error: '...' }` to display a built-in error message below the
|
|
12
|
+
* action buttons. When `error` is provided, the dialog stays open
|
|
13
|
+
* regardless of the `close` value.
|
|
14
|
+
*/
|
|
15
|
+
export type ConfirmResult = void | { close?: boolean; error?: string };
|
|
5
16
|
|
|
6
17
|
export interface RootProps
|
|
7
18
|
extends Pick<
|
|
@@ -14,6 +25,48 @@ export interface RootProps
|
|
|
14
25
|
*/
|
|
15
26
|
children: ReactNode;
|
|
16
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Callback fired when the user confirms the action.
|
|
30
|
+
*
|
|
31
|
+
* - Synchronous handlers: the dialog closes immediately after the
|
|
32
|
+
* handler returns.
|
|
33
|
+
* - Async handlers: the dialog enters a "pending" state (buttons
|
|
34
|
+
* disabled, spinner shown on the confirm button) until the promise
|
|
35
|
+
* settles.
|
|
36
|
+
*
|
|
37
|
+
* Return `{ close: false }` to keep the dialog open after the handler
|
|
38
|
+
* completes (e.g. for server-side validation). Return `void` or
|
|
39
|
+
* `{ close: true }` to close the dialog (the default).
|
|
40
|
+
*
|
|
41
|
+
* Return `{ error: '...' }` to show a built-in error message below
|
|
42
|
+
* the action buttons. The dialog stays open regardless of the `close`
|
|
43
|
+
* value. The error is announced to screen readers and is automatically
|
|
44
|
+
* cleared on the next confirm attempt or when the dialog reopens.
|
|
45
|
+
*
|
|
46
|
+
* If the promise rejects (or the handler throws) without returning an
|
|
47
|
+
* `error`, the dialog stays open and returns to idle without showing
|
|
48
|
+
* a visible error message. The error is logged to the console.
|
|
49
|
+
* To show a user-facing message on failure, catch the error and
|
|
50
|
+
* return `{ close: false, error: '...' }`.
|
|
51
|
+
*/
|
|
52
|
+
onConfirm?: () => ConfirmResult | Promise< ConfirmResult >;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface TriggerProps extends ComponentProps< 'button' > {
|
|
56
|
+
/**
|
|
57
|
+
* The content to be rendered inside the component.
|
|
58
|
+
*/
|
|
59
|
+
children?: ReactNode;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface PopupProps
|
|
63
|
+
extends ComponentProps< 'div' >,
|
|
64
|
+
Pick< _AlertDialog.Popup.Props, 'initialFocus' | 'finalFocus' > {
|
|
65
|
+
/**
|
|
66
|
+
* A parent element to render the portal into.
|
|
67
|
+
*/
|
|
68
|
+
container?: _AlertDialog.Portal.Props[ 'container' ];
|
|
69
|
+
|
|
17
70
|
/**
|
|
18
71
|
* The semantic intent of the dialog, which determines its styling.
|
|
19
72
|
*
|
|
@@ -28,26 +81,27 @@ export interface RootProps
|
|
|
28
81
|
* @default 'default'
|
|
29
82
|
*/
|
|
30
83
|
intent?: 'default' | 'irreversible';
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export type TriggerProps = DialogTriggerProps;
|
|
34
84
|
|
|
35
|
-
export interface PopupProps {
|
|
36
85
|
/**
|
|
37
86
|
* The title displayed in the dialog header. This serves as both the
|
|
38
|
-
* visible heading and the accessible label for the
|
|
87
|
+
* visible heading and the accessible label (`aria-labelledby`) for the
|
|
88
|
+
* dialog. Must be a plain string to ensure a predictable accessible name.
|
|
39
89
|
*/
|
|
40
90
|
title: string;
|
|
41
91
|
|
|
42
92
|
/**
|
|
43
|
-
*
|
|
93
|
+
* An optional description displayed below the title. Rendered using
|
|
94
|
+
* Base UI's `AlertDialog.Description` for proper `aria-describedby`
|
|
95
|
+
* association with the dialog. Must be a plain string to ensure a
|
|
96
|
+
* predictable accessible description.
|
|
44
97
|
*/
|
|
45
|
-
|
|
98
|
+
description?: string;
|
|
46
99
|
|
|
47
100
|
/**
|
|
48
|
-
*
|
|
101
|
+
* Optional body content displayed between the description and the
|
|
102
|
+
* action buttons. Use for supplementary details or form fields.
|
|
49
103
|
*/
|
|
50
|
-
|
|
104
|
+
children?: ReactNode;
|
|
51
105
|
|
|
52
106
|
/**
|
|
53
107
|
* Custom text for the confirm button.
|
|
@@ -62,22 +116,4 @@ export interface PopupProps {
|
|
|
62
116
|
* @default 'Cancel'
|
|
63
117
|
*/
|
|
64
118
|
cancelButtonText?: string;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Whether the confirm action is in a loading state (e.g. an async
|
|
68
|
-
* operation is in progress). When `true`, the confirm button shows a
|
|
69
|
-
* spinner and the cancel button is disabled.
|
|
70
|
-
*
|
|
71
|
-
* **Important:** Passing this prop — even as `false` — opts into
|
|
72
|
-
* manual-close mode: the confirm button will no longer auto-close the
|
|
73
|
-
* dialog. The consumer is responsible for setting `open={false}` when
|
|
74
|
-
* the operation completes. Omit the prop entirely for the default
|
|
75
|
-
* auto-close-on-confirm behavior.
|
|
76
|
-
*
|
|
77
|
-
* To implement an async confirm flow, use controlled mode
|
|
78
|
-
* (`open` / `onOpenChange`) and manage the loading state externally:
|
|
79
|
-
* prevent closing in `onOpenChange` while loading, and set
|
|
80
|
-
* `open={false}` once the operation completes.
|
|
81
|
-
*/
|
|
82
|
-
loading?: boolean;
|
|
83
119
|
}
|
package/src/badge/badge.tsx
CHANGED
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
import { useRender, mergeProps } from '@base-ui/react';
|
|
2
1
|
import clsx from 'clsx';
|
|
3
2
|
import { forwardRef } from '@wordpress/element';
|
|
4
3
|
import { type BadgeProps } from './types';
|
|
5
4
|
import styles from './style.module.css';
|
|
5
|
+
import { Text } from '../text';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* A badge component for displaying labels with semantic intent.
|
|
9
9
|
*/
|
|
10
10
|
export const Badge = forwardRef< HTMLSpanElement, BadgeProps >( function Badge(
|
|
11
|
-
{
|
|
11
|
+
{ intent = 'none', className, ...props },
|
|
12
12
|
ref
|
|
13
13
|
) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
props: mergeProps< 'span' >( props, {
|
|
19
|
-
className: clsx(
|
|
14
|
+
return (
|
|
15
|
+
<Text
|
|
16
|
+
ref={ ref }
|
|
17
|
+
className={ clsx(
|
|
20
18
|
styles.badge,
|
|
21
19
|
styles[ `is-${ intent }-intent` ],
|
|
22
20
|
className
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return element;
|
|
21
|
+
) }
|
|
22
|
+
{ ...props }
|
|
23
|
+
variant="body-sm"
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
29
26
|
} );
|
|
@@ -5,10 +5,6 @@
|
|
|
5
5
|
padding-inline: var(--wpds-dimension-padding-sm);
|
|
6
6
|
padding-block: var(--wpds-dimension-padding-xs);
|
|
7
7
|
border-radius: var(--wpds-border-radius-lg);
|
|
8
|
-
font-family: var(--wpds-font-family-body);
|
|
9
|
-
font-size: var(--wpds-font-size-sm);
|
|
10
|
-
font-weight: var(--wpds-font-weight-regular);
|
|
11
|
-
line-height: var(--wpds-font-line-height-xs);
|
|
12
8
|
}
|
|
13
9
|
|
|
14
10
|
.is-high-intent {
|
package/src/button/button.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import { type ButtonProps } from './types';
|
|
|
7
7
|
import styles from './style.module.css';
|
|
8
8
|
import resetStyles from '../utils/css/resets.module.css';
|
|
9
9
|
import focusStyles from '../utils/css/focus.module.css';
|
|
10
|
+
import defenseStyles from '../utils/css/global-css-defense.module.css';
|
|
10
11
|
|
|
11
12
|
export const Button = forwardRef< HTMLButtonElement, ButtonProps >(
|
|
12
13
|
function Button(
|
|
@@ -25,6 +26,7 @@ export const Button = forwardRef< HTMLButtonElement, ButtonProps >(
|
|
|
25
26
|
ref
|
|
26
27
|
) {
|
|
27
28
|
const mergedClassName = clsx(
|
|
29
|
+
defenseStyles.button,
|
|
28
30
|
resetStyles[ 'box-sizing' ],
|
|
29
31
|
focusStyles[ 'outset-ring--focus-except-active' ],
|
|
30
32
|
variant !== 'unstyled' && styles.button,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
--wp-ui-button-padding-inline: var(--wpds-dimension-padding-md);
|
|
21
21
|
--wp-ui-button-height: 40px;
|
|
22
22
|
--wp-ui-button-aspect-ratio: auto; /* Useful for overrides such as icon buttons */
|
|
23
|
-
--wp-ui-button-font-size: var(--wpds-font-size-md);
|
|
23
|
+
--wp-ui-button-font-size: var(--wpds-typography-font-size-md);
|
|
24
24
|
--wp-ui-button-min-width: calc(4ch + 2 * var(--wp-ui-button-padding-inline));
|
|
25
25
|
|
|
26
26
|
/* by default, borders have the same color as the background */
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
--wp-ui-button-border-color-active: var(--wp-ui-button-background-color-active);
|
|
29
29
|
--wp-ui-button-border-color-disabled: var(--wp-ui-button-background-color-disabled);
|
|
30
30
|
|
|
31
|
+
--_gcd-button-font-family: var(--wpds-typography-font-family-body);
|
|
32
|
+
--_gcd-button-font-size: var(--wp-ui-button-font-size);
|
|
33
|
+
--_gcd-button-font-weight: var(--wp-ui-button-font-weight);
|
|
34
|
+
|
|
31
35
|
/* Styles */
|
|
32
36
|
position: relative;
|
|
33
37
|
display: inline-flex;
|
|
@@ -44,10 +48,10 @@
|
|
|
44
48
|
border-radius: var(--wpds-border-radius-sm);
|
|
45
49
|
background-color: var(--wp-ui-button-background-color);
|
|
46
50
|
background-clip: padding-box;
|
|
47
|
-
font-family: var(--wpds-font-family-body);
|
|
51
|
+
font-family: var(--wpds-typography-font-family-body);
|
|
48
52
|
font-size: var(--wp-ui-button-font-size);
|
|
49
53
|
font-weight: var(--wp-ui-button-font-weight);
|
|
50
|
-
line-height: var(--wpds-
|
|
54
|
+
line-height: var(--wpds-typography-line-height-sm);
|
|
51
55
|
text-decoration: none;
|
|
52
56
|
color: var(--wp-ui-button-foreground-color);
|
|
53
57
|
cursor: var(--wpds-cursor-control);
|
|
@@ -10,10 +10,10 @@ function Text( { children }: { children: React.ReactNode } ) {
|
|
|
10
10
|
<p
|
|
11
11
|
style={ {
|
|
12
12
|
margin: 0,
|
|
13
|
-
fontFamily: 'var(--wpds-font-family-body)',
|
|
14
|
-
fontSize: 'var(--wpds-font-size-md)',
|
|
15
|
-
fontWeight: 'var(--wpds-font-weight-regular)',
|
|
16
|
-
lineHeight: 'var(--wpds-
|
|
13
|
+
fontFamily: 'var(--wpds-typography-font-family-body)',
|
|
14
|
+
fontSize: 'var(--wpds-typography-font-size-md)',
|
|
15
|
+
fontWeight: 'var(--wpds-typography-font-weight-regular)',
|
|
16
|
+
lineHeight: 'var(--wpds-typography-line-height-sm)',
|
|
17
17
|
textWrap: 'pretty',
|
|
18
18
|
color: 'var(--wpds-color-fg-content-neutral-weak)',
|
|
19
19
|
} }
|
|
@@ -116,7 +116,6 @@ export const CustomSemantics: Story = {
|
|
|
116
116
|
children: (
|
|
117
117
|
<>
|
|
118
118
|
<Card.Header>
|
|
119
|
-
{ /* eslint-disable-next-line jsx-a11y/heading-has-content -- content provided via render prop */ }
|
|
120
119
|
<Card.Title render={ <h2 /> }>Section heading</Card.Title>
|
|
121
120
|
</Card.Header>
|
|
122
121
|
<Card.Content>
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
border-radius: var(--wpds-border-radius-lg);
|
|
13
13
|
overflow: clip;
|
|
14
14
|
background-color: var(--wpds-color-bg-surface-neutral-strong);
|
|
15
|
+
color: var(--wpds-color-fg-content-neutral);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
/* Padding is applied to the individual header/content elements to enable
|
|
@@ -37,9 +38,4 @@
|
|
|
37
38
|
margin-inline: calc(-1 * var(--wp-ui-card-padding));
|
|
38
39
|
width: calc(100% + 2 * var(--wp-ui-card-padding));
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
-
.title {
|
|
42
|
-
margin: 0;
|
|
43
|
-
color: var(--wpds-color-fg-content-neutral);
|
|
44
|
-
}
|
|
45
41
|
}
|
|
@@ -82,7 +82,6 @@ describe( 'Card', () => {
|
|
|
82
82
|
render(
|
|
83
83
|
<Card.Root>
|
|
84
84
|
<Card.Header>
|
|
85
|
-
{ /* eslint-disable-next-line jsx-a11y/heading-has-content -- content provided via render prop */ }
|
|
86
85
|
<Card.Title render={ <h2 /> }>Heading</Card.Title>
|
|
87
86
|
</Card.Header>
|
|
88
87
|
</Card.Root>
|
|
@@ -92,5 +91,22 @@ describe( 'Card', () => {
|
|
|
92
91
|
screen.getByRole( 'heading', { level: 2, name: 'Heading' } )
|
|
93
92
|
).toBeVisible();
|
|
94
93
|
} );
|
|
94
|
+
|
|
95
|
+
it( 'forwards ref to custom Title render element', () => {
|
|
96
|
+
const titleRef = createRef< HTMLHeadingElement >();
|
|
97
|
+
|
|
98
|
+
render(
|
|
99
|
+
<Card.Root>
|
|
100
|
+
<Card.Header>
|
|
101
|
+
<Card.Title ref={ titleRef } render={ <h3 /> }>
|
|
102
|
+
Heading
|
|
103
|
+
</Card.Title>
|
|
104
|
+
</Card.Header>
|
|
105
|
+
</Card.Root>
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
expect( titleRef.current ).toBeInstanceOf( HTMLHeadingElement );
|
|
109
|
+
expect( titleRef.current?.tagName ).toBe( 'H3' );
|
|
110
|
+
} );
|
|
95
111
|
} );
|
|
96
112
|
} );
|
package/src/card/title.tsx
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { forwardRef } from '@wordpress/element';
|
|
2
|
-
import clsx from 'clsx';
|
|
3
2
|
import { Text } from '../text';
|
|
4
|
-
import styles from './style.module.css';
|
|
5
3
|
import type { TitleProps } from './types';
|
|
6
4
|
|
|
5
|
+
const DEFAULT_TAG = <div />;
|
|
6
|
+
|
|
7
7
|
/**
|
|
8
8
|
* The title for a card. Renders as a `<div>` by default — use the `render`
|
|
9
9
|
* prop to swap in a semantic heading element when appropriate.
|
|
10
10
|
*/
|
|
11
11
|
export const Title = forwardRef< HTMLDivElement, TitleProps >(
|
|
12
|
-
function CardTitle( {
|
|
12
|
+
function CardTitle( { render = DEFAULT_TAG, children, ...props }, ref ) {
|
|
13
13
|
return (
|
|
14
14
|
<Text
|
|
15
|
+
ref={ ref }
|
|
15
16
|
variant="heading-lg"
|
|
16
|
-
render={ render
|
|
17
|
-
|
|
17
|
+
render={ render }
|
|
18
|
+
{ ...props }
|
|
18
19
|
>
|
|
19
20
|
{ children }
|
|
20
21
|
</Text>
|
|
@@ -12,10 +12,10 @@ function Text( { children }: { children: React.ReactNode } ) {
|
|
|
12
12
|
<p
|
|
13
13
|
style={ {
|
|
14
14
|
margin: 0,
|
|
15
|
-
fontFamily: 'var(--wpds-font-family-body)',
|
|
16
|
-
fontSize: 'var(--wpds-font-size-md)',
|
|
17
|
-
fontWeight: 'var(--wpds-font-weight-regular)',
|
|
18
|
-
lineHeight: 'var(--wpds-
|
|
15
|
+
fontFamily: 'var(--wpds-typography-font-family-body)',
|
|
16
|
+
fontSize: 'var(--wpds-typography-font-size-md)',
|
|
17
|
+
fontWeight: 'var(--wpds-typography-font-weight-regular)',
|
|
18
|
+
lineHeight: 'var(--wpds-typography-line-height-sm)',
|
|
19
19
|
textWrap: 'pretty',
|
|
20
20
|
color: 'var(--wpds-color-fg-content-neutral-weak)',
|
|
21
21
|
} }
|
|
@@ -183,7 +183,7 @@ export const WithHeaderDescription: Story = {
|
|
|
183
183
|
<CollapsibleCard.HeaderDescription>
|
|
184
184
|
<span
|
|
185
185
|
style={ {
|
|
186
|
-
fontSize: 'var(--wpds-font-size-sm)',
|
|
186
|
+
fontSize: 'var(--wpds-typography-font-size-sm)',
|
|
187
187
|
color: 'var(--wpds-color-fg-content-neutral-weak)',
|
|
188
188
|
} }
|
|
189
189
|
>
|
package/src/dialog/popup.tsx
CHANGED
|
@@ -24,6 +24,7 @@ const CLOSE_ICON_ATTR = 'data-wp-ui-dialog-close-icon';
|
|
|
24
24
|
const Popup = forwardRef< HTMLDivElement, PopupProps >( function DialogPopup(
|
|
25
25
|
{
|
|
26
26
|
className,
|
|
27
|
+
container,
|
|
27
28
|
size = 'medium',
|
|
28
29
|
initialFocus,
|
|
29
30
|
finalFocus,
|
|
@@ -39,7 +40,7 @@ const Popup = forwardRef< HTMLDivElement, PopupProps >( function DialogPopup(
|
|
|
39
40
|
const mergedRef = useMergeRefs( [ ref, popupRef ] );
|
|
40
41
|
|
|
41
42
|
return (
|
|
42
|
-
<_Dialog.Portal>
|
|
43
|
+
<_Dialog.Portal container={ container }>
|
|
43
44
|
<_Dialog.Backdrop className={ styles.backdrop } />
|
|
44
45
|
<ThemeProvider>
|
|
45
46
|
<_Dialog.Popup
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
2
|
import { useId, useState } from '@wordpress/element';
|
|
3
3
|
import type { ComponentProps } from 'react';
|
|
4
|
+
import { VisuallyHidden } from '../../visually-hidden';
|
|
4
5
|
import * as Dialog from '../index';
|
|
5
6
|
|
|
6
7
|
const meta: Meta< typeof Dialog.Root > = {
|
|
@@ -161,3 +162,35 @@ export const WithCustomZIndex: Story = {
|
|
|
161
162
|
..._Default,
|
|
162
163
|
name: 'With Custom z-index',
|
|
163
164
|
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* A dialog with a visually hidden title. The title is still present in the
|
|
168
|
+
* DOM for `aria-labelledby`, but is not visible to sighted users.
|
|
169
|
+
*
|
|
170
|
+
* Use `<VisuallyHidden render={ <Dialog.Title /> }>` so that `Dialog.Title`
|
|
171
|
+
* keeps its `<h2>` element while being visually hidden.
|
|
172
|
+
*/
|
|
173
|
+
export const WithVisuallyHiddenTitle: Story = {
|
|
174
|
+
args: {
|
|
175
|
+
children: (
|
|
176
|
+
<>
|
|
177
|
+
<Dialog.Trigger>Open Dialog</Dialog.Trigger>
|
|
178
|
+
<Dialog.Popup>
|
|
179
|
+
<Dialog.Header>
|
|
180
|
+
<VisuallyHidden render={ <Dialog.Title /> }>
|
|
181
|
+
Accessible dialog heading
|
|
182
|
+
</VisuallyHidden>
|
|
183
|
+
<Dialog.CloseIcon />
|
|
184
|
+
</Dialog.Header>
|
|
185
|
+
<p>
|
|
186
|
+
This dialog has a visually hidden title. Inspect the DOM
|
|
187
|
+
or use a screen reader to verify the heading is present.
|
|
188
|
+
</p>
|
|
189
|
+
<Dialog.Footer>
|
|
190
|
+
<Dialog.Action>Got it</Dialog.Action>
|
|
191
|
+
</Dialog.Footer>
|
|
192
|
+
</Dialog.Popup>
|
|
193
|
+
</>
|
|
194
|
+
),
|
|
195
|
+
},
|
|
196
|
+
};
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
border-radius: var(--wpds-border-radius-lg);
|
|
38
38
|
box-shadow: var(--wpds-elevation-lg);
|
|
39
39
|
overflow: auto;
|
|
40
|
-
font-family: var(--wpds-font-family-body);
|
|
41
|
-
font-size: var(--wpds-font-size-md);
|
|
42
|
-
line-height: var(--wpds-
|
|
40
|
+
font-family: var(--wpds-typography-font-family-body);
|
|
41
|
+
font-size: var(--wpds-typography-font-size-md);
|
|
42
|
+
line-height: var(--wpds-typography-line-height-md);
|
|
43
43
|
color: var(--wpds-color-fg-content-neutral);
|
|
44
44
|
|
|
45
45
|
&[data-starting-style],
|
|
@@ -92,17 +92,21 @@
|
|
|
92
92
|
|
|
93
93
|
.header {
|
|
94
94
|
display: flex;
|
|
95
|
-
justify-content: space-between;
|
|
96
95
|
align-items: center;
|
|
96
|
+
gap: var(--wpds-dimension-gap-sm);
|
|
97
97
|
margin-bottom: var(--wpds-dimension-gap-lg);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
.title {
|
|
101
|
-
margin:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
margin-inline-end: auto;
|
|
102
|
+
|
|
103
|
+
/* Workaround: the GCD shorthand `margin` overrides the longhand above.
|
|
104
|
+
* Keep both so the layout survives GCD removal. */
|
|
105
|
+
--_gcd-heading-margin: 0 auto 0 0;
|
|
106
|
+
|
|
107
|
+
&:dir(rtl) {
|
|
108
|
+
--_gcd-heading-margin: 0 0 0 auto;
|
|
109
|
+
}
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
.footer {
|
|
@@ -203,10 +203,8 @@ describe( 'Dialog', () => {
|
|
|
203
203
|
<Dialog.Trigger>Open Dialog</Dialog.Trigger>
|
|
204
204
|
<Dialog.Popup>
|
|
205
205
|
<Dialog.Header>
|
|
206
|
-
{ /*
|
|
207
|
-
<Dialog.Title
|
|
208
|
-
{ /* Empty title */ }
|
|
209
|
-
</Dialog.Title>
|
|
206
|
+
{ /* Empty title */ }
|
|
207
|
+
<Dialog.Title />
|
|
210
208
|
</Dialog.Header>
|
|
211
209
|
<p>Content with empty title</p>
|
|
212
210
|
<Dialog.Footer>
|
|
@@ -423,4 +421,65 @@ describe( 'Dialog', () => {
|
|
|
423
421
|
expect( customFocus ).toHaveBeenCalled();
|
|
424
422
|
} );
|
|
425
423
|
} );
|
|
424
|
+
|
|
425
|
+
describe( 'container', () => {
|
|
426
|
+
it( 'should render inside the container when provided', async () => {
|
|
427
|
+
const user = userEvent.setup();
|
|
428
|
+
const containerRef = createRef< HTMLDivElement >();
|
|
429
|
+
|
|
430
|
+
render(
|
|
431
|
+
<div data-testid="wrapper">
|
|
432
|
+
<Dialog.Root>
|
|
433
|
+
<Dialog.Trigger>Open</Dialog.Trigger>
|
|
434
|
+
<div
|
|
435
|
+
ref={ containerRef }
|
|
436
|
+
data-testid="custom-container"
|
|
437
|
+
/>
|
|
438
|
+
<Dialog.Popup container={ containerRef }>
|
|
439
|
+
<Dialog.Header>
|
|
440
|
+
<Dialog.Title>Title</Dialog.Title>
|
|
441
|
+
</Dialog.Header>
|
|
442
|
+
Dialog content
|
|
443
|
+
</Dialog.Popup>
|
|
444
|
+
</Dialog.Root>
|
|
445
|
+
</div>
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
await user.click( screen.getByRole( 'button', { name: 'Open' } ) );
|
|
449
|
+
|
|
450
|
+
const content = await screen.findByText( 'Dialog content' );
|
|
451
|
+
expect( content ).toBeVisible();
|
|
452
|
+
|
|
453
|
+
expect( screen.getByTestId( 'custom-container' ) ).toContainElement(
|
|
454
|
+
content
|
|
455
|
+
);
|
|
456
|
+
} );
|
|
457
|
+
|
|
458
|
+
it( 'should render with a portal by default', async () => {
|
|
459
|
+
const user = userEvent.setup();
|
|
460
|
+
|
|
461
|
+
render(
|
|
462
|
+
<div data-testid="wrapper">
|
|
463
|
+
<Dialog.Root>
|
|
464
|
+
<Dialog.Trigger>Open</Dialog.Trigger>
|
|
465
|
+
<Dialog.Popup>
|
|
466
|
+
<Dialog.Header>
|
|
467
|
+
<Dialog.Title>Title</Dialog.Title>
|
|
468
|
+
</Dialog.Header>
|
|
469
|
+
Portal content
|
|
470
|
+
</Dialog.Popup>
|
|
471
|
+
</Dialog.Root>
|
|
472
|
+
</div>
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
await user.click( screen.getByRole( 'button', { name: 'Open' } ) );
|
|
476
|
+
|
|
477
|
+
const content = await screen.findByText( 'Portal content' );
|
|
478
|
+
expect( content ).toBeVisible();
|
|
479
|
+
|
|
480
|
+
expect( screen.getByTestId( 'wrapper' ) ).not.toContainElement(
|
|
481
|
+
content
|
|
482
|
+
);
|
|
483
|
+
} );
|
|
484
|
+
} );
|
|
426
485
|
} );
|
package/src/dialog/title.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Dialog as _Dialog } from '@base-ui/react/dialog';
|
|
2
|
-
import clsx from 'clsx';
|
|
3
2
|
import { useMergeRefs } from '@wordpress/compose';
|
|
4
3
|
import { forwardRef, useLayoutEffect, useRef } from '@wordpress/element';
|
|
4
|
+
import { Text } from '../text';
|
|
5
5
|
import { useDialogValidationContext } from './context';
|
|
6
6
|
import styles from './style.module.css';
|
|
7
7
|
import type { TitleProps } from './types';
|
|
@@ -11,11 +11,21 @@ import type { TitleProps } from './types';
|
|
|
11
11
|
* and serves as both the visible heading and the accessible label for
|
|
12
12
|
* the dialog.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* **Required** — every dialog must include a `Dialog.Title`, even if
|
|
15
|
+
* visually hidden. The rendered element is linked to the popup via
|
|
16
|
+
* `aria-labelledby`. Renders an `<h2>` by default.
|
|
17
|
+
*
|
|
18
|
+
* To visually hide the title while keeping it accessible, wrap it with
|
|
19
|
+
* `VisuallyHidden` using the `render` prop:
|
|
20
|
+
*
|
|
21
|
+
* ```jsx
|
|
22
|
+
* <VisuallyHidden render={ <Dialog.Title /> }>
|
|
23
|
+
* Accessible title text
|
|
24
|
+
* </VisuallyHidden>
|
|
25
|
+
* ```
|
|
16
26
|
*/
|
|
17
27
|
const Title = forwardRef< HTMLHeadingElement, TitleProps >(
|
|
18
|
-
function DialogTitle( {
|
|
28
|
+
function DialogTitle( { children, ...props }, forwardedRef ) {
|
|
19
29
|
const validationContext = useDialogValidationContext();
|
|
20
30
|
const internalRef = useRef< HTMLHeadingElement >( null );
|
|
21
31
|
const mergedRef = useMergeRefs( [ internalRef, forwardedRef ] );
|
|
@@ -26,12 +36,14 @@ const Title = forwardRef< HTMLHeadingElement, TitleProps >(
|
|
|
26
36
|
}, [ validationContext ] );
|
|
27
37
|
|
|
28
38
|
return (
|
|
29
|
-
<
|
|
39
|
+
<Text
|
|
30
40
|
ref={ mergedRef }
|
|
31
|
-
|
|
32
|
-
render={
|
|
33
|
-
{
|
|
34
|
-
|
|
41
|
+
variant="heading-xl"
|
|
42
|
+
render={ <_Dialog.Title { ...props } /> }
|
|
43
|
+
className={ styles.title }
|
|
44
|
+
>
|
|
45
|
+
{ children }
|
|
46
|
+
</Text>
|
|
35
47
|
);
|
|
36
48
|
}
|
|
37
49
|
);
|
package/src/dialog/types.ts
CHANGED
|
@@ -34,6 +34,11 @@ export interface PopupProps
|
|
|
34
34
|
*/
|
|
35
35
|
children?: ReactNode;
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* A parent element to render the portal into.
|
|
39
|
+
*/
|
|
40
|
+
container?: _Dialog.Portal.Props[ 'container' ];
|
|
41
|
+
|
|
37
42
|
/**
|
|
38
43
|
* Renders the dialog at a preset width (excluding additional padding from
|
|
39
44
|
* the viewport edges).
|
|
@@ -74,8 +79,11 @@ export interface TitleProps extends ComponentProps< 'h2' > {
|
|
|
74
79
|
/**
|
|
75
80
|
* The title content to be rendered. This serves as both the visible
|
|
76
81
|
* heading and the accessible label for the dialog.
|
|
82
|
+
*
|
|
83
|
+
* When `Dialog.Title` is passed as a render element (e.g. to
|
|
84
|
+
* `VisuallyHidden`), children can be provided by the wrapper instead.
|
|
77
85
|
*/
|
|
78
|
-
children
|
|
86
|
+
children?: ReactNode;
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
export interface CloseIconProps
|
|
@@ -4,6 +4,8 @@ import { Text } from '../text';
|
|
|
4
4
|
import type { EmptyStateDescriptionProps } from './types';
|
|
5
5
|
import styles from './style.module.css';
|
|
6
6
|
|
|
7
|
+
const DEFAULT_TAG = <p />;
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* The description text for an empty state, providing additional context and
|
|
9
11
|
* guidance on what the user should do next.
|
|
@@ -12,14 +14,16 @@ export const Description = forwardRef<
|
|
|
12
14
|
HTMLParagraphElement,
|
|
13
15
|
EmptyStateDescriptionProps
|
|
14
16
|
>( function EmptyStateDescription(
|
|
15
|
-
{ render, className, children, ...props },
|
|
17
|
+
{ render = DEFAULT_TAG, className, children, ...props },
|
|
16
18
|
ref
|
|
17
19
|
) {
|
|
18
20
|
return (
|
|
19
21
|
<Text
|
|
22
|
+
ref={ ref }
|
|
20
23
|
variant="body-md"
|
|
21
|
-
render={ render
|
|
24
|
+
render={ render }
|
|
22
25
|
className={ clsx( styles.description, className ) }
|
|
26
|
+
{ ...props }
|
|
23
27
|
>
|
|
24
28
|
{ children }
|
|
25
29
|
</Text>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
text-align: center;
|
|
9
9
|
max-width: var(--wpds-dimension-surface-width-sm);
|
|
10
10
|
gap: var(--wpds-dimension-gap-xs);
|
|
11
|
-
font-family: var(--wpds-font-family-body);
|
|
11
|
+
font-family: var(--wpds-typography-font-family-body);
|
|
12
12
|
color: var(--wpds-color-fg-content-neutral);
|
|
13
13
|
text-wrap: balance;
|
|
14
14
|
}
|