@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,21 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
declare const meta: Meta;
|
|
3
|
+
export default meta;
|
|
4
|
+
type Story = StoryObj;
|
|
5
|
+
/**
|
|
6
|
+
* Tooltips work best as visual labels for icon-only controls. Each trigger
|
|
7
|
+
* must have its own accessible name via `aria-label`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const RecommendedUsage: Story;
|
|
10
|
+
/**
|
|
11
|
+
* Popups that open when hovering an info icon should use `Popover` with
|
|
12
|
+
* `openOnHover` instead of a Tooltip. This ensures the content is accessible
|
|
13
|
+
* to touch and screen reader users.
|
|
14
|
+
*/
|
|
15
|
+
export declare const InfotipWithPopover: Story;
|
|
16
|
+
/**
|
|
17
|
+
* `IconButton` has built-in tooltip support via the `label` prop,
|
|
18
|
+
* making it the easiest way to provide a tooltip for icon-only actions.
|
|
19
|
+
*/
|
|
20
|
+
export declare const IconButtonWithTooltip: Story;
|
|
21
|
+
//# sourceMappingURL=usage-guidelines.story.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-guidelines.story.d.ts","sourceRoot":"","sources":["../../../src/tooltip/stories/usage-guidelines.story.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAS5D,QAAA,MAAM,IAAI,EAAE,IAMX,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC;AAEtB;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,KA2B9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,KA0ChC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAYnC,CAAC"}
|
|
@@ -14,5 +14,9 @@ export interface PopupProps extends ComponentProps<'div'>, Pick<Tooltip.Position
|
|
|
14
14
|
* The content to be rendered inside the component.
|
|
15
15
|
*/
|
|
16
16
|
children?: ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* A parent element to render the portal into.
|
|
19
|
+
*/
|
|
20
|
+
container?: Tooltip.Portal.Props['container'];
|
|
17
21
|
}
|
|
18
22
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tooltip/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,MAAM,SAAS,GAAG,IAAI,CAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAAE,CAAC;AAE5E,MAAM,MAAM,aAAa,GAAG,IAAI,CAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,EACtB,OAAO,GAAG,UAAU,CACpB,CAAC;AAEF,MAAM,WAAW,YAAa,SAAQ,cAAc,CAAE,QAAQ,CAAE;IAC/D;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,UAChB,SAAQ,cAAc,CAAE,KAAK,CAAE,EAC9B,IAAI,CAAE,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAE;IAClE;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tooltip/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,MAAM,SAAS,GAAG,IAAI,CAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAAE,CAAC;AAE5E,MAAM,MAAM,aAAa,GAAG,IAAI,CAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,EACtB,OAAO,GAAG,UAAU,CACpB,CAAC;AAEF,MAAM,WAAW,YAAa,SAAQ,cAAc,CAAE,QAAQ,CAAE;IAC/D;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,UAChB,SAAQ,cAAc,CAAE,KAAK,CAAE,EAC9B,IAAI,CAAE,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAE;IAClE;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAE,WAAW,CAAE,CAAC;CAChD"}
|
|
@@ -3,11 +3,15 @@ type HTMLAttributesWithRef<T extends ElementType = any> = HTMLAttributes<T> & {
|
|
|
3
3
|
ref?: Ref<T> | undefined;
|
|
4
4
|
};
|
|
5
5
|
type ComponentRenderFn<Props> = (props: Props) => React.ReactElement<unknown>;
|
|
6
|
-
export type ComponentProps<E extends ElementType> = Omit<ComponentPropsWithoutRef<E>, 'className' | 'children' | 'render'> & {
|
|
6
|
+
export type ComponentProps<E extends ElementType> = Omit<ComponentPropsWithoutRef<E>, 'className' | 'children' | 'render' | 'style'> & {
|
|
7
7
|
/**
|
|
8
|
-
* CSS class name to apply to the
|
|
8
|
+
* CSS class name to apply to the element.
|
|
9
9
|
*/
|
|
10
10
|
className?: string;
|
|
11
|
+
/**
|
|
12
|
+
* CSS style to apply to the element.
|
|
13
|
+
*/
|
|
14
|
+
style?: React.CSSProperties;
|
|
11
15
|
/**
|
|
12
16
|
* Replaces the component's default HTML element using a given React
|
|
13
17
|
* element, or a function that returns a React element.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,GAAG,EACR,MAAM,OAAO,CAAC;AAEf,KAAK,qBAAqB,CAAE,CAAC,SAAS,WAAW,GAAG,GAAG,IACtD,cAAc,CAAE,CAAC,CAAE,GAAG;IAAE,GAAG,CAAC,EAAE,GAAG,CAAE,CAAC,CAAE,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtD,KAAK,iBAAiB,CAAE,KAAK,IAAK,CACjC,KAAK,EAAE,KAAK,KACR,KAAK,CAAC,YAAY,CAAE,OAAO,CAAE,CAAC;AAEnC,MAAM,MAAM,cAAc,CAAE,CAAC,SAAS,WAAW,IAAK,IAAI,CACzD,wBAAwB,CAAE,CAAC,CAAE,EAC7B,WAAW,GAAG,UAAU,GAAG,QAAQ,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,GAAG,EACR,MAAM,OAAO,CAAC;AAEf,KAAK,qBAAqB,CAAE,CAAC,SAAS,WAAW,GAAG,GAAG,IACtD,cAAc,CAAE,CAAC,CAAE,GAAG;IAAE,GAAG,CAAC,EAAE,GAAG,CAAE,CAAC,CAAE,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtD,KAAK,iBAAiB,CAAE,KAAK,IAAK,CACjC,KAAK,EAAE,KAAK,KACR,KAAK,CAAC,YAAY,CAAE,OAAO,CAAE,CAAC;AAEnC,MAAM,MAAM,cAAc,CAAE,CAAC,SAAS,WAAW,IAAK,IAAI,CACzD,wBAAwB,CAAE,CAAC,CAAE,EAC7B,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAC7C,GAAG;IACH;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAE5B;;;OAGG;IACH,MAAM,CAAC,EACJ,iBAAiB,CAAE,qBAAqB,CAAE,GAC1C,KAAK,CAAC,YAAY,CAAE,MAAM,CAAE,MAAM,EAAE,OAAO,CAAE,CAAE,CAAC;CACnD,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Popover as _Popover } from '@base-ui/react/popover';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* The `initialFocus` type shared by Base UI overlay popups (Dialog, Popover,
|
|
4
|
+
* AlertDialog, etc.). We derive it from `Popover.Popup.Props` here, but it
|
|
5
|
+
* is identical across all overlay components.
|
|
5
6
|
*/
|
|
6
|
-
type InitialFocus =
|
|
7
|
+
type InitialFocus = _Popover.Popup.Props['initialFocus'];
|
|
7
8
|
/**
|
|
8
9
|
* Returns a resolved `initialFocus` value that deprioritizes elements
|
|
9
10
|
* marked with a given data attribute (e.g. a close icon), and an internal
|
|
@@ -28,7 +29,7 @@ export declare function useDeprioritizedInitialFocus({ initialFocus, deprioritiz
|
|
|
28
29
|
initialFocus: InitialFocus;
|
|
29
30
|
deprioritizedAttribute: string;
|
|
30
31
|
}): {
|
|
31
|
-
resolvedInitialFocus: boolean | import("react").RefObject<HTMLElement | null> | ((openType: import("@base-ui/utils/useEnhancedClickHandler").InteractionType) => boolean | HTMLElement | null
|
|
32
|
+
resolvedInitialFocus: boolean | import("react").RefObject<HTMLElement | null> | ((openType: import("@base-ui/utils/useEnhancedClickHandler").InteractionType) => void | boolean | HTMLElement | null) | undefined;
|
|
32
33
|
popupRef: import("react").RefObject<HTMLDivElement>;
|
|
33
34
|
};
|
|
34
35
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-deprioritized-initial-focus.d.ts","sourceRoot":"","sources":["../../src/utils/use-deprioritized-initial-focus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"use-deprioritized-initial-focus.d.ts","sourceRoot":"","sources":["../../src/utils/use-deprioritized-initial-focus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAIlE;;;;GAIG;AACH,KAAK,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAE,cAAc,CAAE,CAAC;AAe3D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAAE,EAC7C,YAAY,EACZ,sBAAsB,GACtB,EAAE;IACF,YAAY,EAAE,YAAY,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;CAC/B;;;EAiCA"}
|
|
@@ -4,4 +4,11 @@ declare const meta: Meta<typeof VisuallyHidden>;
|
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof VisuallyHidden>;
|
|
6
6
|
export declare const Default: Story;
|
|
7
|
+
/**
|
|
8
|
+
* Use the `render` prop to change the underlying HTML element.
|
|
9
|
+
* By default, `VisuallyHidden` renders a `<div>`. Here it renders
|
|
10
|
+
* a `<label>` instead, keeping the native label–input association
|
|
11
|
+
* while hiding the label text visually.
|
|
12
|
+
*/
|
|
13
|
+
export declare const WithCustomElement: Story;
|
|
7
14
|
//# sourceMappingURL=index.story.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.story.d.ts","sourceRoot":"","sources":["../../../src/visually-hidden/stories/index.story.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.story.d.ts","sourceRoot":"","sources":["../../../src/visually-hidden/stories/index.story.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AAErC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAE,OAAO,cAAc,CAGtC,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAE,OAAO,cAAc,CAAE,CAAC;AAE/C,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAgB/B,CAAC"}
|
|
@@ -2,6 +2,40 @@ import type { VisuallyHiddenProps } from './types';
|
|
|
2
2
|
/**
|
|
3
3
|
* Visually hides content while keeping it accessible to screen readers.
|
|
4
4
|
* Useful when providing context that's only meaningful to assistive technology.
|
|
5
|
+
*
|
|
6
|
+
* Renders a `<div>` by default. Use the `render` prop to swap the
|
|
7
|
+
* underlying element while preserving the visually-hidden behavior.
|
|
8
|
+
*
|
|
9
|
+
* ## Composing with other components
|
|
10
|
+
*
|
|
11
|
+
* When composing with another component that uses the `render` prop
|
|
12
|
+
* pattern, there are two directions — and they produce different results.
|
|
13
|
+
*
|
|
14
|
+
* Most of the time you'll want `VisuallyHidden` as the **host** (outer
|
|
15
|
+
* component) and pass the other component via `render`. This keeps the
|
|
16
|
+
* other component's HTML element and semantics intact, while
|
|
17
|
+
* `VisuallyHidden` only adds its hiding styles:
|
|
18
|
+
*
|
|
19
|
+
* ```jsx
|
|
20
|
+
* // OtherComponent keeps its semantic element (e.g. <h2>).
|
|
21
|
+
* <VisuallyHidden render={ <OtherComponent /> }>
|
|
22
|
+
* Accessible text
|
|
23
|
+
* </VisuallyHidden>
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* The opposite direction is also possible, but be aware that it replaces
|
|
27
|
+
* the other component's element with VisuallyHidden's default `<div>`:
|
|
28
|
+
*
|
|
29
|
+
* ```jsx
|
|
30
|
+
* // OtherComponent's element becomes a <div>.
|
|
31
|
+
* <OtherComponent render={ <VisuallyHidden /> }>
|
|
32
|
+
* Accessible text
|
|
33
|
+
* </OtherComponent>
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* Choose based on what you need: if the other component's semantic
|
|
37
|
+
* element matters (e.g. `<label>`, `<legend>`, `<h2>`), keep
|
|
38
|
+
* `VisuallyHidden` as the host so the element is preserved.
|
|
5
39
|
*/
|
|
6
40
|
export declare const VisuallyHidden: import("react").ForwardRefExoticComponent<VisuallyHiddenProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
7
41
|
//# sourceMappingURL=visually-hidden.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visually-hidden.d.ts","sourceRoot":"","sources":["../../src/visually-hidden/visually-hidden.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGnD
|
|
1
|
+
{"version":3,"file":"visually-hidden.d.ts","sourceRoot":"","sources":["../../src/visually-hidden/visually-hidden.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,cAAc,gHAa1B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Themeable React UI components for the WordPress Design System.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -43,16 +43,16 @@
|
|
|
43
43
|
"types": "build-types",
|
|
44
44
|
"sideEffects": false,
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@base-ui/react": "^1.
|
|
47
|
-
"@wordpress/a11y": "^4.
|
|
48
|
-
"@wordpress/compose": "^7.
|
|
49
|
-
"@wordpress/element": "^6.
|
|
50
|
-
"@wordpress/i18n": "^6.
|
|
51
|
-
"@wordpress/icons": "^12.
|
|
52
|
-
"@wordpress/keycodes": "^4.
|
|
53
|
-
"@wordpress/primitives": "^4.
|
|
54
|
-
"@wordpress/private-apis": "^1.
|
|
55
|
-
"@wordpress/theme": "^0.
|
|
46
|
+
"@base-ui/react": "^1.4.0",
|
|
47
|
+
"@wordpress/a11y": "^4.44.0",
|
|
48
|
+
"@wordpress/compose": "^7.44.0",
|
|
49
|
+
"@wordpress/element": "^6.44.0",
|
|
50
|
+
"@wordpress/i18n": "^6.17.0",
|
|
51
|
+
"@wordpress/icons": "^12.2.0",
|
|
52
|
+
"@wordpress/keycodes": "^4.44.0",
|
|
53
|
+
"@wordpress/primitives": "^4.44.0",
|
|
54
|
+
"@wordpress/private-apis": "^1.44.0",
|
|
55
|
+
"@wordpress/theme": "^0.11.0",
|
|
56
56
|
"clsx": "^2.1.1",
|
|
57
57
|
"tabbable": "^6.4.0"
|
|
58
58
|
},
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"publishConfig": {
|
|
72
72
|
"access": "public"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "b862d8c84121a47bbeff882f6c87e61681ce2e0d"
|
|
75
75
|
}
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { createContext } from '@wordpress/element';
|
|
2
|
-
import type { RootProps } from './types';
|
|
3
2
|
|
|
4
|
-
type
|
|
3
|
+
type Phase = 'idle' | 'pending' | 'closing';
|
|
5
4
|
|
|
6
5
|
interface AlertDialogContextValue {
|
|
7
|
-
|
|
6
|
+
phase: Phase;
|
|
7
|
+
showSpinner: boolean;
|
|
8
|
+
errorMessage?: string;
|
|
9
|
+
confirm: () => Promise< void >;
|
|
8
10
|
}
|
|
9
11
|
|
|
12
|
+
const noop = async () => {};
|
|
13
|
+
|
|
10
14
|
const AlertDialogContext = createContext< AlertDialogContextValue >( {
|
|
11
|
-
|
|
15
|
+
phase: 'idle',
|
|
16
|
+
showSpinner: false,
|
|
17
|
+
errorMessage: undefined,
|
|
18
|
+
confirm: noop,
|
|
12
19
|
} );
|
|
13
20
|
|
|
14
21
|
export { AlertDialogContext };
|
|
22
|
+
export type { Phase };
|
|
@@ -1,56 +1,114 @@
|
|
|
1
|
+
import { AlertDialog as _AlertDialog } from '@base-ui/react/alert-dialog';
|
|
2
|
+
import clsx from 'clsx';
|
|
1
3
|
import { forwardRef, useContext } from '@wordpress/element';
|
|
2
4
|
import { __ } from '@wordpress/i18n';
|
|
5
|
+
import {
|
|
6
|
+
type ThemeProvider as ThemeProviderType,
|
|
7
|
+
privateApis as themePrivateApis,
|
|
8
|
+
} from '@wordpress/theme';
|
|
9
|
+
|
|
3
10
|
import { Button } from '../button';
|
|
4
|
-
import
|
|
11
|
+
import dialogStyles from '../dialog/style.module.css';
|
|
12
|
+
import { unlock } from '../lock-unlock';
|
|
13
|
+
import { Stack } from '../stack';
|
|
14
|
+
import { Text } from '../text';
|
|
5
15
|
import { AlertDialogContext } from './context';
|
|
6
|
-
import
|
|
16
|
+
import alertDialogStyles from './style.module.css';
|
|
7
17
|
import type { PopupProps } from './types';
|
|
8
18
|
|
|
19
|
+
const ThemeProvider: typeof ThemeProviderType =
|
|
20
|
+
unlock( themePrivateApis ).ThemeProvider;
|
|
21
|
+
|
|
9
22
|
const Popup = forwardRef< HTMLDivElement, PopupProps >(
|
|
10
23
|
function AlertDialogPopup(
|
|
11
24
|
{
|
|
25
|
+
className,
|
|
26
|
+
container,
|
|
27
|
+
intent = 'default',
|
|
12
28
|
title,
|
|
29
|
+
description,
|
|
13
30
|
children,
|
|
14
|
-
onConfirm,
|
|
15
31
|
confirmButtonText = __( 'OK' ),
|
|
16
32
|
cancelButtonText = __( 'Cancel' ),
|
|
17
|
-
|
|
33
|
+
...props
|
|
18
34
|
},
|
|
19
35
|
ref
|
|
20
36
|
) {
|
|
21
|
-
const {
|
|
37
|
+
const { phase, showSpinner, errorMessage, confirm } =
|
|
38
|
+
useContext( AlertDialogContext );
|
|
22
39
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
const confirmClassName =
|
|
41
|
+
intent === 'irreversible'
|
|
42
|
+
? alertDialogStyles[ 'irreversible-action' ]
|
|
43
|
+
: undefined;
|
|
44
|
+
|
|
45
|
+
const buttonsDisabled = phase !== 'idle' || undefined;
|
|
27
46
|
|
|
28
47
|
return (
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
</Dialog.Action>
|
|
41
|
-
<ConfirmButton
|
|
42
|
-
className={
|
|
43
|
-
intent === 'irreversible'
|
|
44
|
-
? styles[ 'irreversible-action' ]
|
|
45
|
-
: undefined
|
|
46
|
-
}
|
|
47
|
-
onClick={ onConfirm }
|
|
48
|
-
loading={ loading }
|
|
48
|
+
<_AlertDialog.Portal container={ container }>
|
|
49
|
+
<_AlertDialog.Backdrop className={ dialogStyles.backdrop } />
|
|
50
|
+
<ThemeProvider>
|
|
51
|
+
<_AlertDialog.Popup
|
|
52
|
+
ref={ ref }
|
|
53
|
+
className={ clsx(
|
|
54
|
+
dialogStyles.popup,
|
|
55
|
+
className,
|
|
56
|
+
dialogStyles[ 'is-medium' ]
|
|
57
|
+
) }
|
|
58
|
+
{ ...props }
|
|
49
59
|
>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
<Stack
|
|
61
|
+
direction="column"
|
|
62
|
+
gap="sm"
|
|
63
|
+
className={ alertDialogStyles.header }
|
|
64
|
+
>
|
|
65
|
+
<Text
|
|
66
|
+
variant="heading-xl"
|
|
67
|
+
render={ <_AlertDialog.Title /> }
|
|
68
|
+
>
|
|
69
|
+
{ title }
|
|
70
|
+
</Text>
|
|
71
|
+
{ description && (
|
|
72
|
+
<Text
|
|
73
|
+
variant="body-md"
|
|
74
|
+
render={ <_AlertDialog.Description /> }
|
|
75
|
+
>
|
|
76
|
+
{ description }
|
|
77
|
+
</Text>
|
|
78
|
+
) }
|
|
79
|
+
</Stack>
|
|
80
|
+
{ children }
|
|
81
|
+
<Stack direction="column" gap="md">
|
|
82
|
+
<div className={ dialogStyles.footer }>
|
|
83
|
+
<_AlertDialog.Close
|
|
84
|
+
render={ <Button variant="minimal" /> }
|
|
85
|
+
disabled={ buttonsDisabled }
|
|
86
|
+
>
|
|
87
|
+
{ cancelButtonText }
|
|
88
|
+
</_AlertDialog.Close>
|
|
89
|
+
<Button
|
|
90
|
+
className={ confirmClassName }
|
|
91
|
+
onClick={ confirm }
|
|
92
|
+
loading={ showSpinner || undefined }
|
|
93
|
+
disabled={ buttonsDisabled }
|
|
94
|
+
>
|
|
95
|
+
{ confirmButtonText }
|
|
96
|
+
</Button>
|
|
97
|
+
</div>
|
|
98
|
+
{ errorMessage && (
|
|
99
|
+
<Text
|
|
100
|
+
variant="body-sm"
|
|
101
|
+
className={
|
|
102
|
+
alertDialogStyles[ 'error-message' ]
|
|
103
|
+
}
|
|
104
|
+
>
|
|
105
|
+
{ errorMessage }
|
|
106
|
+
</Text>
|
|
107
|
+
) }
|
|
108
|
+
</Stack>
|
|
109
|
+
</_AlertDialog.Popup>
|
|
110
|
+
</ThemeProvider>
|
|
111
|
+
</_AlertDialog.Portal>
|
|
54
112
|
);
|
|
55
113
|
}
|
|
56
114
|
);
|
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import { AlertDialog as _AlertDialog } from '@base-ui/react/alert-dialog';
|
|
2
|
-
import {
|
|
2
|
+
import { speak } from '@wordpress/a11y';
|
|
3
|
+
import {
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from '@wordpress/element';
|
|
10
|
+
|
|
3
11
|
import { AlertDialogContext } from './context';
|
|
12
|
+
import type { Phase } from './context';
|
|
4
13
|
import type { RootProps } from './types';
|
|
5
14
|
|
|
15
|
+
function isThenable( value: unknown ): value is PromiseLike< unknown > {
|
|
16
|
+
return (
|
|
17
|
+
value !== null &&
|
|
18
|
+
value !== undefined &&
|
|
19
|
+
typeof ( value as PromiseLike< unknown > ).then === 'function'
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
6
23
|
/**
|
|
7
24
|
* A dialog that requires a user response to proceed.
|
|
8
25
|
*
|
|
@@ -11,32 +28,193 @@ import type { RootProps } from './types';
|
|
|
11
28
|
* The `AlertDialog.Trigger` is optional — the dialog can also be controlled
|
|
12
29
|
* via `open` / `onOpenChange` props.
|
|
13
30
|
*
|
|
14
|
-
* ## Use cases
|
|
15
|
-
*
|
|
16
|
-
* - **Default intent**: Standard confirmation dialog for reversible actions.
|
|
17
|
-
* - **Irreversible intent**: Confirmation dialog for irreversible actions that
|
|
18
|
-
* cannot be undone. The confirm button uses error/danger coloring.
|
|
19
|
-
*
|
|
20
31
|
* For use cases outside the standard confirm/cancel pattern, use the lower-level
|
|
21
32
|
* `Dialog` component directly.
|
|
22
33
|
*
|
|
23
|
-
* See the [Destructive Actions guidelines](
|
|
34
|
+
* See the [Destructive Actions guidelines](https://wordpress.github.io/gutenberg/?path=/docs/design-system-patterns-destructive-actions--docs)
|
|
24
35
|
* for more details on when to use each pattern.
|
|
25
36
|
*/
|
|
26
37
|
function Root( {
|
|
27
|
-
intent = 'default',
|
|
28
38
|
children,
|
|
29
|
-
open,
|
|
39
|
+
open: openProp,
|
|
30
40
|
onOpenChange,
|
|
31
41
|
defaultOpen,
|
|
42
|
+
onConfirm,
|
|
32
43
|
}: RootProps ) {
|
|
33
|
-
const
|
|
44
|
+
const [ internalOpen, setInternalOpen ] = useState( defaultOpen ?? false );
|
|
45
|
+
|
|
46
|
+
// Internal state machine for the confirm-and-close lifecycle.
|
|
47
|
+
//
|
|
48
|
+
// Phase transitions:
|
|
49
|
+
//
|
|
50
|
+
// idle ──> pending ──> closing ──> idle
|
|
51
|
+
// (confirm (success, (animation
|
|
52
|
+
// clicked) close) complete)
|
|
53
|
+
//
|
|
54
|
+
// idle ──> pending ──> idle
|
|
55
|
+
// (confirm (error, or
|
|
56
|
+
// clicked) {close:false})
|
|
57
|
+
//
|
|
58
|
+
// idle ──> closing ──> idle
|
|
59
|
+
// (cancel/ (animation
|
|
60
|
+
// escape) complete)
|
|
61
|
+
//
|
|
62
|
+
// `showSpinner` tracks whether the confirm button shows a loading
|
|
63
|
+
// indicator. It is orthogonal to `phase`:
|
|
64
|
+
//
|
|
65
|
+
// Scenario | pending | closing
|
|
66
|
+
// --------------------------+---------+---------
|
|
67
|
+
// Sync onConfirm | false | false
|
|
68
|
+
// Async onConfirm (success) | true | true
|
|
69
|
+
// Async onConfirm (error) | true | n/a (-> idle)
|
|
70
|
+
// Cancel / Escape | n/a | false
|
|
71
|
+
//
|
|
72
|
+
// Buttons are disabled whenever phase !== 'idle'.
|
|
73
|
+
// Dismiss (Escape / Cancel) is blocked during 'pending'.
|
|
74
|
+
const [ phase, setPhase ] = useState< Phase >( 'idle' );
|
|
75
|
+
const [ showSpinner, setShowSpinner ] = useState( false );
|
|
76
|
+
const [ errorMessage, setErrorMessage ] = useState< string >();
|
|
77
|
+
|
|
78
|
+
const actionsRef = useRef< _AlertDialog.Root.Actions | null >( null );
|
|
79
|
+
|
|
80
|
+
const onConfirmRef = useRef( onConfirm );
|
|
81
|
+
onConfirmRef.current = onConfirm;
|
|
82
|
+
|
|
83
|
+
// Ref keeps phase accessible synchronously from callbacks that may
|
|
84
|
+
// run between a setState call and the subsequent React re-render.
|
|
85
|
+
const phaseRef = useRef( phase );
|
|
86
|
+
phaseRef.current = phase;
|
|
87
|
+
|
|
88
|
+
// Generation counter — safety net for the edge case where the component
|
|
89
|
+
// unmounts while an async confirm is in flight. Also incremented when
|
|
90
|
+
// the dialog finishes closing, so a stale promise settling after a
|
|
91
|
+
// dismiss+reopen cycle is silently discarded.
|
|
92
|
+
const confirmIdRef = useRef( 0 );
|
|
93
|
+
|
|
94
|
+
const effectiveOpen = openProp ?? internalOpen;
|
|
95
|
+
|
|
96
|
+
// Safety net: if the consumer keeps `open={true}` after a confirm
|
|
97
|
+
// (i.e. does not react to `onOpenChange`), the phase would be stuck
|
|
98
|
+
// at 'closing'. Detect the contradiction and reset to idle.
|
|
99
|
+
useEffect( () => {
|
|
100
|
+
if ( effectiveOpen && phase === 'closing' ) {
|
|
101
|
+
phaseRef.current = 'idle';
|
|
102
|
+
setPhase( 'idle' );
|
|
103
|
+
setShowSpinner( false );
|
|
104
|
+
}
|
|
105
|
+
}, [ effectiveOpen, phase ] );
|
|
106
|
+
|
|
107
|
+
const handleOpenChange = useCallback(
|
|
108
|
+
(
|
|
109
|
+
nextOpen: boolean,
|
|
110
|
+
eventDetails: _AlertDialog.Root.ChangeEventDetails
|
|
111
|
+
) => {
|
|
112
|
+
// Block dismiss while a confirm action is pending.
|
|
113
|
+
if ( ! nextOpen && phaseRef.current === 'pending' ) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if ( ! nextOpen && phaseRef.current === 'idle' ) {
|
|
118
|
+
phaseRef.current = 'closing';
|
|
119
|
+
setPhase( 'closing' );
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
setInternalOpen( nextOpen );
|
|
123
|
+
onOpenChange?.( nextOpen, eventDetails );
|
|
124
|
+
},
|
|
125
|
+
[ onOpenChange ]
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const confirm = useCallback( async () => {
|
|
129
|
+
if ( phaseRef.current !== 'idle' ) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
phaseRef.current = 'pending';
|
|
134
|
+
setPhase( 'pending' );
|
|
135
|
+
setErrorMessage( undefined );
|
|
136
|
+
|
|
137
|
+
const id = ++confirmIdRef.current;
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const rawResult = onConfirmRef.current?.();
|
|
141
|
+
|
|
142
|
+
// Show spinner only for async handlers (Promises).
|
|
143
|
+
// Sync handlers resolve in the same tick — no spinner needed.
|
|
144
|
+
if ( isThenable( rawResult ) ) {
|
|
145
|
+
setShowSpinner( true );
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const result = await Promise.resolve( rawResult );
|
|
149
|
+
|
|
150
|
+
// Discard if the component unmounted or the dialog was
|
|
151
|
+
// dismissed and reopened while the promise was in flight.
|
|
152
|
+
if ( confirmIdRef.current !== id ) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// An error message implies the dialog should stay open.
|
|
157
|
+
if ( result?.error ) {
|
|
158
|
+
phaseRef.current = 'idle';
|
|
159
|
+
setPhase( 'idle' );
|
|
160
|
+
setShowSpinner( false );
|
|
161
|
+
setErrorMessage( result.error );
|
|
162
|
+
speak( result.error, 'assertive' );
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const shouldClose = result?.close !== false;
|
|
167
|
+
|
|
168
|
+
if ( shouldClose ) {
|
|
169
|
+
phaseRef.current = 'closing';
|
|
170
|
+
setPhase( 'closing' );
|
|
171
|
+
actionsRef.current?.close();
|
|
172
|
+
} else {
|
|
173
|
+
phaseRef.current = 'idle';
|
|
174
|
+
setPhase( 'idle' );
|
|
175
|
+
setShowSpinner( false );
|
|
176
|
+
}
|
|
177
|
+
} catch ( error ) {
|
|
178
|
+
if ( confirmIdRef.current !== id ) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
phaseRef.current = 'idle';
|
|
182
|
+
setPhase( 'idle' );
|
|
183
|
+
setShowSpinner( false );
|
|
184
|
+
// eslint-disable-next-line no-console
|
|
185
|
+
console.error( error );
|
|
186
|
+
}
|
|
187
|
+
}, [] );
|
|
188
|
+
|
|
189
|
+
const handleOpenChangeComplete = useCallback( ( open: boolean ) => {
|
|
190
|
+
if ( ! open ) {
|
|
191
|
+
// Invalidate any in-flight async so a stale promise settling
|
|
192
|
+
// after dismiss+reopen doesn't close the new session.
|
|
193
|
+
confirmIdRef.current++;
|
|
194
|
+
phaseRef.current = 'idle';
|
|
195
|
+
setPhase( 'idle' );
|
|
196
|
+
setShowSpinner( false );
|
|
197
|
+
setErrorMessage( undefined );
|
|
198
|
+
}
|
|
199
|
+
}, [] );
|
|
200
|
+
|
|
201
|
+
const contextValue = useMemo(
|
|
202
|
+
() => ( {
|
|
203
|
+
phase,
|
|
204
|
+
showSpinner,
|
|
205
|
+
errorMessage,
|
|
206
|
+
confirm,
|
|
207
|
+
} ),
|
|
208
|
+
[ phase, showSpinner, errorMessage, confirm ]
|
|
209
|
+
);
|
|
34
210
|
|
|
35
211
|
return (
|
|
36
212
|
<_AlertDialog.Root
|
|
37
|
-
open={
|
|
38
|
-
onOpenChange={ onOpenChange }
|
|
213
|
+
open={ effectiveOpen }
|
|
39
214
|
defaultOpen={ defaultOpen }
|
|
215
|
+
onOpenChange={ handleOpenChange }
|
|
216
|
+
onOpenChangeComplete={ handleOpenChangeComplete }
|
|
217
|
+
actionsRef={ actionsRef }
|
|
40
218
|
>
|
|
41
219
|
<AlertDialogContext.Provider value={ contextValue }>
|
|
42
220
|
{ children }
|