@wordpress/ui 0.9.1-next.v.202603161435.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 +76 -1
- package/CONTRIBUTING.md +180 -0
- package/README.md +34 -6
- package/build/alert-dialog/context.cjs +39 -0
- package/build/alert-dialog/context.cjs.map +7 -0
- package/build/alert-dialog/index.cjs +37 -0
- package/build/alert-dialog/index.cjs.map +7 -0
- package/build/alert-dialog/popup.cjs +165 -0
- package/build/alert-dialog/popup.cjs.map +7 -0
- package/build/alert-dialog/root.cjs +152 -0
- package/build/alert-dialog/root.cjs.map +7 -0
- package/build/alert-dialog/trigger.cjs +38 -0
- package/build/alert-dialog/trigger.cjs.map +7 -0
- package/build/alert-dialog/types.cjs +19 -0
- package/build/alert-dialog/types.cjs.map +7 -0
- package/build/badge/badge.cjs +14 -14
- package/build/badge/badge.cjs.map +2 -2
- package/build/button/button.cjs +18 -8
- 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 +6 -6
- package/build/card/root.cjs.map +2 -2
- package/build/card/title.cjs +14 -21
- package/build/card/title.cjs.map +3 -3
- package/build/collapsible-card/content.cjs +24 -3
- package/build/collapsible-card/content.cjs.map +4 -4
- package/build/collapsible-card/context.cjs +35 -0
- package/build/collapsible-card/context.cjs.map +7 -0
- package/build/collapsible-card/header-description.cjs +52 -0
- package/build/collapsible-card/header-description.cjs.map +7 -0
- package/build/collapsible-card/header.cjs +39 -18
- package/build/collapsible-card/header.cjs.map +2 -2
- package/build/collapsible-card/index.cjs +3 -0
- package/build/collapsible-card/index.cjs.map +2 -2
- package/build/collapsible-card/types.cjs.map +1 -1
- package/build/dialog/action.cjs +4 -2
- package/build/dialog/action.cjs.map +2 -2
- package/build/dialog/close-icon.cjs +2 -1
- package/build/dialog/close-icon.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 +24 -6
- 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 +66 -0
- package/build/empty-state/actions.cjs.map +7 -0
- package/build/empty-state/description.cjs +69 -0
- package/build/empty-state/description.cjs.map +7 -0
- package/build/empty-state/icon.cjs +69 -0
- package/build/empty-state/icon.cjs.map +7 -0
- package/build/empty-state/index.cjs +46 -0
- package/build/empty-state/index.cjs.map +7 -0
- package/build/empty-state/root.cjs +66 -0
- package/build/empty-state/root.cjs.map +7 -0
- package/build/empty-state/title.cjs +71 -0
- package/build/empty-state/title.cjs.map +7 -0
- package/build/empty-state/types.cjs +19 -0
- package/build/empty-state/types.cjs.map +7 -0
- package/build/empty-state/visual.cjs +66 -0
- package/build/empty-state/visual.cjs.map +7 -0
- package/build/form/index.cjs +27 -0
- package/build/form/index.cjs.map +7 -0
- package/build/form/input-control/index.cjs +31 -0
- package/build/form/input-control/index.cjs.map +7 -0
- package/build/form/input-control/input-control.cjs +50 -0
- package/build/form/input-control/input-control.cjs.map +7 -0
- package/build/form/input-control/types.cjs +19 -0
- package/build/form/input-control/types.cjs.map +7 -0
- 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 +1 -1
- 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/fieldset/root.cjs +2 -2
- package/build/form/primitives/fieldset/root.cjs.map +1 -1
- 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 +15 -5
- package/build/form/primitives/input-layout/input-layout.cjs.map +3 -3
- package/build/form/primitives/input-layout/slot.cjs +6 -5
- package/build/form/primitives/input-layout/slot.cjs.map +2 -2
- package/build/form/primitives/select/item.cjs +5 -5
- package/build/form/primitives/select/item.cjs.map +2 -2
- package/build/form/primitives/select/popup.cjs +9 -9
- 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 +23 -4
- package/build/form/primitives/textarea/textarea.cjs.map +3 -3
- package/build/form/types.cjs +19 -0
- package/build/form/types.cjs.map +7 -0
- package/build/icon-button/icon-button.cjs +2 -2
- package/build/icon-button/icon-button.cjs.map +1 -1
- package/build/index.cjs +11 -2
- package/build/index.cjs.map +2 -2
- package/build/link/link.cjs +18 -8
- 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/index.cjs.map +1 -1
- package/build/notice/root.cjs +5 -5
- 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/stack/stack.cjs +2 -2
- package/build/stack/stack.cjs.map +1 -1
- package/build/tabs/context.cjs +121 -0
- package/build/tabs/context.cjs.map +7 -0
- package/build/tabs/list.cjs +3 -4
- package/build/tabs/list.cjs.map +2 -2
- package/build/tabs/panel.cjs +5 -3
- package/build/tabs/panel.cjs.map +2 -2
- package/build/tabs/root.cjs +2 -1
- package/build/tabs/root.cjs.map +2 -2
- package/build/tabs/tab.cjs +5 -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 +7 -6
- 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 +64 -0
- package/build/utils/use-deprioritized-initial-focus.cjs.map +7 -0
- package/build/visually-hidden/visually-hidden.cjs +2 -2
- package/build/visually-hidden/visually-hidden.cjs.map +2 -2
- package/build-module/alert-dialog/context.mjs +14 -0
- package/build-module/alert-dialog/context.mjs.map +7 -0
- package/build-module/alert-dialog/index.mjs +10 -0
- package/build-module/alert-dialog/index.mjs.map +7 -0
- package/build-module/alert-dialog/popup.mjs +132 -0
- package/build-module/alert-dialog/popup.mjs.map +7 -0
- package/build-module/alert-dialog/root.mjs +133 -0
- package/build-module/alert-dialog/root.mjs.map +7 -0
- package/build-module/alert-dialog/trigger.mjs +13 -0
- package/build-module/alert-dialog/trigger.mjs.map +7 -0
- package/build-module/alert-dialog/types.mjs +1 -0
- package/build-module/alert-dialog/types.mjs.map +7 -0
- package/build-module/badge/badge.mjs +14 -14
- package/build-module/badge/badge.mjs.map +2 -2
- package/build-module/button/button.mjs +18 -8
- 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 +6 -6
- package/build-module/card/root.mjs.map +2 -2
- package/build-module/card/title.mjs +14 -21
- package/build-module/card/title.mjs.map +3 -3
- package/build-module/collapsible-card/content.mjs +24 -3
- package/build-module/collapsible-card/content.mjs.map +3 -3
- package/build-module/collapsible-card/context.mjs +10 -0
- package/build-module/collapsible-card/context.mjs.map +7 -0
- package/build-module/collapsible-card/header-description.mjs +27 -0
- package/build-module/collapsible-card/header-description.mjs.map +7 -0
- package/build-module/collapsible-card/header.mjs +40 -19
- package/build-module/collapsible-card/header.mjs.map +2 -2
- package/build-module/collapsible-card/index.mjs +2 -0
- package/build-module/collapsible-card/index.mjs.map +2 -2
- package/build-module/dialog/action.mjs +4 -2
- package/build-module/dialog/action.mjs.map +2 -2
- package/build-module/dialog/close-icon.mjs +2 -1
- package/build-module/dialog/close-icon.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 +24 -6
- 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 +31 -0
- package/build-module/empty-state/actions.mjs.map +7 -0
- package/build-module/empty-state/description.mjs +34 -0
- package/build-module/empty-state/description.mjs.map +7 -0
- package/build-module/empty-state/icon.mjs +34 -0
- package/build-module/empty-state/icon.mjs.map +7 -0
- package/build-module/empty-state/index.mjs +16 -0
- package/build-module/empty-state/index.mjs.map +7 -0
- package/build-module/empty-state/root.mjs +31 -0
- package/build-module/empty-state/root.mjs.map +7 -0
- package/build-module/empty-state/title.mjs +36 -0
- package/build-module/empty-state/title.mjs.map +7 -0
- package/build-module/empty-state/types.mjs +1 -0
- package/build-module/empty-state/types.mjs.map +7 -0
- package/build-module/empty-state/visual.mjs +31 -0
- package/build-module/empty-state/visual.mjs.map +7 -0
- package/build-module/form/index.mjs +4 -0
- package/build-module/form/index.mjs.map +7 -0
- package/build-module/form/input-control/index.mjs +6 -0
- package/build-module/form/input-control/index.mjs.map +7 -0
- package/build-module/form/input-control/input-control.mjs +25 -0
- package/build-module/form/input-control/input-control.mjs.map +7 -0
- package/build-module/form/input-control/types.mjs +1 -0
- package/build-module/form/input-control/types.mjs.map +7 -0
- 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 +1 -1
- 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/fieldset/root.mjs +2 -2
- package/build-module/form/primitives/fieldset/root.mjs.map +1 -1
- 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 +15 -5
- package/build-module/form/primitives/input-layout/input-layout.mjs.map +3 -3
- package/build-module/form/primitives/input-layout/slot.mjs +6 -5
- package/build-module/form/primitives/input-layout/slot.mjs.map +2 -2
- package/build-module/form/primitives/select/item.mjs +5 -5
- package/build-module/form/primitives/select/item.mjs.map +2 -2
- package/build-module/form/primitives/select/popup.mjs +9 -9
- 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 +23 -4
- package/build-module/form/primitives/textarea/textarea.mjs.map +3 -3
- package/build-module/form/types.mjs +1 -0
- package/build-module/form/types.mjs.map +7 -0
- package/build-module/icon-button/icon-button.mjs +2 -2
- package/build-module/icon-button/icon-button.mjs.map +1 -1
- package/build-module/index.mjs +7 -1
- package/build-module/index.mjs.map +2 -2
- package/build-module/link/link.mjs +18 -8
- 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/index.mjs.map +1 -1
- package/build-module/notice/root.mjs +5 -5
- 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/stack/stack.mjs +2 -2
- package/build-module/stack/stack.mjs.map +1 -1
- package/build-module/tabs/context.mjs +101 -0
- package/build-module/tabs/context.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 +5 -3
- package/build-module/tabs/panel.mjs.map +2 -2
- package/build-module/tabs/root.mjs +2 -1
- package/build-module/tabs/root.mjs.map +2 -2
- package/build-module/tabs/tab.mjs +5 -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 +7 -6
- 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 +39 -0
- package/build-module/utils/use-deprioritized-initial-focus.mjs.map +7 -0
- package/build-module/visually-hidden/visually-hidden.mjs +2 -2
- package/build-module/visually-hidden/visually-hidden.mjs.map +2 -2
- package/build-types/alert-dialog/context.d.ts +11 -0
- package/build-types/alert-dialog/context.d.ts.map +1 -0
- package/build-types/alert-dialog/index.d.ts +4 -0
- package/build-types/alert-dialog/index.d.ts.map +1 -0
- package/build-types/alert-dialog/popup.d.ts +4 -0
- package/build-types/alert-dialog/popup.d.ts.map +1 -0
- package/build-types/alert-dialog/root.d.ts +18 -0
- package/build-types/alert-dialog/root.d.ts.map +1 -0
- package/build-types/alert-dialog/stories/index.story.d.ts +56 -0
- package/build-types/alert-dialog/stories/index.story.d.ts.map +1 -0
- package/build-types/alert-dialog/test/index.test.d.ts +2 -0
- package/build-types/alert-dialog/test/index.test.d.ts.map +1 -0
- package/build-types/alert-dialog/trigger.d.ts +7 -0
- package/build-types/alert-dialog/trigger.d.ts.map +1 -0
- package/build-types/alert-dialog/types.d.ts +105 -0
- package/build-types/alert-dialog/types.d.ts.map +1 -0
- 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/collapsible-card/content.d.ts.map +1 -1
- package/build-types/collapsible-card/context.d.ts +4 -0
- package/build-types/collapsible-card/context.d.ts.map +1 -0
- package/build-types/collapsible-card/header-description.d.ts +15 -0
- package/build-types/collapsible-card/header-description.d.ts.map +1 -0
- package/build-types/collapsible-card/header.d.ts.map +1 -1
- package/build-types/collapsible-card/index.d.ts +2 -1
- package/build-types/collapsible-card/index.d.ts.map +1 -1
- package/build-types/collapsible-card/stories/index.story.d.ts +10 -0
- package/build-types/collapsible-card/stories/index.story.d.ts.map +1 -1
- package/build-types/collapsible-card/types.d.ts +21 -0
- package/build-types/collapsible-card/types.d.ts.map +1 -1
- package/build-types/dialog/action.d.ts.map +1 -1
- package/build-types/dialog/close-icon.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 -6
- 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 +13 -6
- package/build-types/dialog/types.d.ts.map +1 -1
- package/build-types/empty-state/actions.d.ts +7 -0
- package/build-types/empty-state/actions.d.ts.map +1 -0
- package/build-types/empty-state/description.d.ts +7 -0
- package/build-types/empty-state/description.d.ts.map +1 -0
- package/build-types/empty-state/icon.d.ts +7 -0
- package/build-types/empty-state/icon.d.ts.map +1 -0
- package/build-types/empty-state/index.d.ts +8 -0
- package/build-types/empty-state/index.d.ts.map +1 -0
- package/build-types/empty-state/root.d.ts +6 -0
- package/build-types/empty-state/root.d.ts.map +1 -0
- package/build-types/empty-state/stories/index.story.d.ts +8 -0
- package/build-types/empty-state/stories/index.story.d.ts.map +1 -0
- package/build-types/empty-state/test/actions.test.d.ts +2 -0
- package/build-types/empty-state/test/actions.test.d.ts.map +1 -0
- package/build-types/empty-state/test/description.test.d.ts +2 -0
- package/build-types/empty-state/test/description.test.d.ts.map +1 -0
- package/build-types/empty-state/test/icon.test.d.ts +2 -0
- package/build-types/empty-state/test/icon.test.d.ts.map +1 -0
- package/build-types/empty-state/test/root.test.d.ts +2 -0
- package/build-types/empty-state/test/root.test.d.ts.map +1 -0
- package/build-types/empty-state/test/title.test.d.ts +2 -0
- package/build-types/empty-state/test/title.test.d.ts.map +1 -0
- package/build-types/empty-state/test/visual.test.d.ts +2 -0
- package/build-types/empty-state/test/visual.test.d.ts.map +1 -0
- package/build-types/empty-state/title.d.ts +6 -0
- package/build-types/empty-state/title.d.ts.map +1 -0
- package/build-types/empty-state/types.d.ts +40 -0
- package/build-types/empty-state/types.d.ts.map +1 -0
- package/build-types/empty-state/visual.d.ts +7 -0
- package/build-types/empty-state/visual.d.ts.map +1 -0
- package/build-types/form/index.d.ts +3 -0
- package/build-types/form/index.d.ts.map +1 -0
- package/build-types/form/input-control/index.d.ts +2 -0
- package/build-types/form/input-control/index.d.ts.map +1 -0
- package/build-types/form/input-control/input-control.d.ts +6 -0
- package/build-types/form/input-control/input-control.d.ts.map +1 -0
- package/build-types/form/input-control/stories/index.story.d.ts +16 -0
- package/build-types/form/input-control/stories/index.story.d.ts.map +1 -0
- package/build-types/form/input-control/test/index.test.d.ts +2 -0
- package/build-types/form/input-control/test/index.test.d.ts.map +1 -0
- package/build-types/form/input-control/types.d.ts +4 -0
- package/build-types/form/input-control/types.d.ts.map +1 -0
- 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/field/stories/index.story.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/fieldset/stories/index.story.d.ts.map +1 -1
- package/build-types/form/primitives/input/input.d.ts.map +1 -1
- package/build-types/form/primitives/input/stories/index.story.d.ts +2 -0
- package/build-types/form/primitives/input/stories/index.story.d.ts.map +1 -1
- package/build-types/form/primitives/input-layout/input-layout.d.ts.map +1 -1
- package/build-types/form/primitives/input-layout/slot.d.ts.map +1 -1
- package/build-types/form/primitives/input-layout/stories/index.story.d.ts +5 -0
- package/build-types/form/primitives/input-layout/stories/index.story.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 +3 -0
- package/build-types/form/stories/shared.d.ts.map +1 -0
- package/build-types/form/types.d.ts +30 -0
- package/build-types/form/types.d.ts.map +1 -0
- package/build-types/index.d.ts +4 -1
- package/build-types/index.d.ts.map +1 -1
- package/build-types/link/link.d.ts.map +1 -1
- package/build-types/notice/index.d.ts +0 -1
- package/build-types/notice/index.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/context.d.ts +26 -0
- package/build-types/tabs/context.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 +13 -0
- package/build-types/tooltip/root.d.ts.map +1 -1
- package/build-types/tooltip/stories/index.story.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/test/use-deprioritized-initial-focus.test.d.ts +2 -0
- package/build-types/utils/test/use-deprioritized-initial-focus.test.d.ts.map +1 -0
- 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 +36 -0
- package/build-types/utils/use-deprioritized-initial-focus.d.ts.map +1 -0
- 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 +17 -16
- package/src/alert-dialog/context.tsx +22 -0
- package/src/alert-dialog/index.ts +3 -0
- package/src/alert-dialog/popup.tsx +116 -0
- package/src/alert-dialog/root.tsx +226 -0
- package/src/alert-dialog/stories/index.story.tsx +305 -0
- package/src/alert-dialog/style.module.css +21 -0
- package/src/alert-dialog/test/index.test.tsx +1509 -0
- package/src/alert-dialog/trigger.tsx +15 -0
- package/src/alert-dialog/types.ts +119 -0
- 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 +9 -3
- package/src/card/stories/index.story.tsx +4 -5
- package/src/card/style.module.css +4 -10
- package/src/card/test/index.test.tsx +17 -1
- package/src/card/title.tsx +14 -12
- package/src/collapsible-card/content.tsx +16 -3
- package/src/collapsible-card/context.ts +7 -0
- package/src/collapsible-card/header-description.tsx +43 -0
- package/src/collapsible-card/header.tsx +47 -24
- package/src/collapsible-card/index.ts +2 -1
- package/src/collapsible-card/stories/index.story.tsx +102 -4
- package/src/collapsible-card/style.module.css +34 -2
- package/src/collapsible-card/test/index.test.tsx +96 -9
- package/src/collapsible-card/types.ts +22 -0
- package/src/dialog/action.tsx +8 -2
- package/src/dialog/close-icon.tsx +1 -0
- package/src/dialog/popup.tsx +23 -3
- package/src/dialog/stories/index.story.tsx +33 -28
- package/src/dialog/style.module.css +18 -14
- package/src/dialog/test/index.test.tsx +180 -4
- package/src/dialog/title.tsx +21 -9
- package/src/dialog/types.ts +20 -6
- package/src/empty-state/actions.tsx +24 -0
- package/src/empty-state/description.tsx +31 -0
- package/src/empty-state/icon.tsx +24 -0
- package/src/empty-state/index.ts +8 -0
- package/src/empty-state/root.tsx +23 -0
- package/src/empty-state/stories/index.story.tsx +64 -0
- package/src/empty-state/style.module.css +53 -0
- package/src/empty-state/test/actions.test.tsx +18 -0
- package/src/empty-state/test/description.test.tsx +26 -0
- package/src/empty-state/test/icon.test.tsx +13 -0
- package/src/empty-state/test/root.test.tsx +13 -0
- package/src/empty-state/test/title.test.tsx +26 -0
- package/src/empty-state/test/visual.test.tsx +17 -0
- package/src/empty-state/title.tsx +29 -0
- package/src/empty-state/types.ts +45 -0
- package/src/empty-state/visual.tsx +24 -0
- package/src/form/index.ts +3 -0
- package/src/form/input-control/index.ts +1 -0
- package/src/form/input-control/input-control.tsx +33 -0
- package/src/form/input-control/stories/index.story.tsx +163 -0
- package/src/form/input-control/test/index.test.tsx +53 -0
- package/src/form/input-control/types.ts +5 -0
- 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/stories/index.story.tsx +2 -7
- 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/stories/index.story.tsx +2 -7
- 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/stories/index.story.tsx +7 -0
- 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/slot.tsx +6 -2
- package/src/form/primitives/input-layout/stories/index.story.tsx +22 -1
- 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/stories/overview.mdx +15 -0
- package/src/form/primitives/textarea/textarea.tsx +11 -2
- package/src/form/stories/shared.tsx +21 -0
- package/src/form/types.ts +34 -0
- package/src/index.ts +4 -1
- package/src/link/link.tsx +2 -0
- package/src/link/style.module.css +11 -1
- package/src/notice/index.ts +0 -2
- package/src/notice/style.module.css +6 -6
- 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/context.tsx +170 -0
- package/src/tabs/list.tsx +0 -1
- package/src/tabs/panel.tsx +3 -0
- package/src/tabs/root.tsx +6 -1
- package/src/tabs/style.module.css +3 -3
- package/src/tabs/tab.tsx +3 -0
- package/src/tabs/test/index.test.tsx +162 -0
- 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 +13 -0
- package/src/tooltip/stories/index.story.tsx +20 -15
- 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 +3 -2
- package/src/utils/css/select-trigger.module.css +1 -0
- package/src/utils/test/use-deprioritized-initial-focus.test.tsx +230 -0
- package/src/utils/types.ts +7 -2
- package/src/utils/use-deprioritized-initial-focus.ts +84 -0
- package/src/visually-hidden/stories/index.story.tsx +25 -0
- package/src/visually-hidden/visually-hidden.tsx +34 -0
|
@@ -0,0 +1,1315 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { useId, useRef, useState } from '@wordpress/element';
|
|
3
|
+
import { SlotFillProvider, Slot } from '@wordpress/components';
|
|
4
|
+
import { close, info } from '@wordpress/icons';
|
|
5
|
+
import { Popover, VisuallyHidden } from '../..';
|
|
6
|
+
import { Icon } from '../../icon';
|
|
7
|
+
import { IconButton } from '../../icon-button';
|
|
8
|
+
import { GenericIframe, useMeasure } from './utils';
|
|
9
|
+
|
|
10
|
+
const meta: Meta< typeof Popover.Root > = {
|
|
11
|
+
title: 'Design System/Components/Popover',
|
|
12
|
+
component: Popover.Root,
|
|
13
|
+
subcomponents: {
|
|
14
|
+
'Popover.Trigger': Popover.Trigger,
|
|
15
|
+
'Popover.Popup': Popover.Popup,
|
|
16
|
+
'Popover.Arrow': Popover.Arrow,
|
|
17
|
+
'Popover.Title': Popover.Title,
|
|
18
|
+
'Popover.Description': Popover.Description,
|
|
19
|
+
'Popover.Close': Popover.Close,
|
|
20
|
+
},
|
|
21
|
+
argTypes: {
|
|
22
|
+
children: { control: false },
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
export default meta;
|
|
26
|
+
|
|
27
|
+
type Story = StoryObj< typeof Popover.Root >;
|
|
28
|
+
|
|
29
|
+
export const Default: Story = {
|
|
30
|
+
argTypes: {
|
|
31
|
+
children: { control: { type: 'text' } },
|
|
32
|
+
},
|
|
33
|
+
args: {
|
|
34
|
+
children: (
|
|
35
|
+
<>
|
|
36
|
+
<Popover.Trigger>Open Popover</Popover.Trigger>
|
|
37
|
+
<Popover.Popup>
|
|
38
|
+
<Popover.Arrow />
|
|
39
|
+
<Popover.Title
|
|
40
|
+
style={ {
|
|
41
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
42
|
+
} }
|
|
43
|
+
>
|
|
44
|
+
Popover title
|
|
45
|
+
</Popover.Title>
|
|
46
|
+
<Popover.Description>
|
|
47
|
+
Popover description
|
|
48
|
+
</Popover.Description>
|
|
49
|
+
</Popover.Popup>
|
|
50
|
+
</>
|
|
51
|
+
),
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A popover without the arrow sub-component. Omit `Popover.Arrow`
|
|
57
|
+
* from the popup content when an arrow indicator is not desired.
|
|
58
|
+
*/
|
|
59
|
+
export const NoArrow: Story = {
|
|
60
|
+
args: {
|
|
61
|
+
children: (
|
|
62
|
+
<>
|
|
63
|
+
<Popover.Trigger>Open Popover</Popover.Trigger>
|
|
64
|
+
<Popover.Popup>
|
|
65
|
+
<Popover.Title
|
|
66
|
+
style={ {
|
|
67
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
68
|
+
} }
|
|
69
|
+
>
|
|
70
|
+
Popover title
|
|
71
|
+
</Popover.Title>
|
|
72
|
+
<Popover.Description>
|
|
73
|
+
Popover description
|
|
74
|
+
</Popover.Description>
|
|
75
|
+
</Popover.Popup>
|
|
76
|
+
</>
|
|
77
|
+
),
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* All combinations of `side` and `align` props on `Popover.Popup`.
|
|
83
|
+
*
|
|
84
|
+
* Each row shows a side (`top`, `right`, `bottom`, `left`), and each column
|
|
85
|
+
* shows an alignment (`start`, `center`, `end`).
|
|
86
|
+
*/
|
|
87
|
+
export const Positioning: Story = {
|
|
88
|
+
parameters: { controls: { disable: true } },
|
|
89
|
+
render: function Render() {
|
|
90
|
+
const sides = [ 'top', 'right', 'bottom', 'left' ] as const;
|
|
91
|
+
const aligns = [ 'start', 'center', 'end' ] as const;
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div
|
|
95
|
+
style={ {
|
|
96
|
+
display: 'grid',
|
|
97
|
+
gridTemplateColumns: 'repeat(3, 1fr)',
|
|
98
|
+
gap: '6rem',
|
|
99
|
+
padding: '6rem 4rem',
|
|
100
|
+
justifyItems: 'center',
|
|
101
|
+
} }
|
|
102
|
+
>
|
|
103
|
+
{ sides.flatMap( ( side ) =>
|
|
104
|
+
aligns.map( ( align ) => (
|
|
105
|
+
<Popover.Root key={ `${ side }-${ align }` } open>
|
|
106
|
+
<Popover.Trigger>
|
|
107
|
+
{ side } / { align }
|
|
108
|
+
</Popover.Trigger>
|
|
109
|
+
<Popover.Popup
|
|
110
|
+
side={ side }
|
|
111
|
+
align={ align }
|
|
112
|
+
collisionAvoidance={ {
|
|
113
|
+
side: 'none',
|
|
114
|
+
align: 'none',
|
|
115
|
+
} }
|
|
116
|
+
>
|
|
117
|
+
<VisuallyHidden render={ <Popover.Title /> }>
|
|
118
|
+
{ side } / { align }
|
|
119
|
+
</VisuallyHidden>
|
|
120
|
+
<Popover.Arrow />
|
|
121
|
+
<Popover.Description>
|
|
122
|
+
{ side } side / { align } align
|
|
123
|
+
</Popover.Description>
|
|
124
|
+
</Popover.Popup>
|
|
125
|
+
</Popover.Root>
|
|
126
|
+
) )
|
|
127
|
+
) }
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A popover with a close icon button, title, and description. The
|
|
135
|
+
* `Popover.Close` component renders a button that closes the popover when
|
|
136
|
+
* clicked. Here it wraps an `IconButton` for a properly sized, accessible
|
|
137
|
+
* close action — matching the Dialog close-icon pattern.
|
|
138
|
+
*/
|
|
139
|
+
export const WithCloseButton: Story = {
|
|
140
|
+
args: {
|
|
141
|
+
children: (
|
|
142
|
+
<>
|
|
143
|
+
<Popover.Trigger>Settings</Popover.Trigger>
|
|
144
|
+
<Popover.Popup>
|
|
145
|
+
<Popover.Arrow />
|
|
146
|
+
<div
|
|
147
|
+
style={ {
|
|
148
|
+
display: 'flex',
|
|
149
|
+
justifyContent: 'space-between',
|
|
150
|
+
alignItems: 'center',
|
|
151
|
+
marginBottom: 'var(--wpds-dimension-gap-sm)',
|
|
152
|
+
} }
|
|
153
|
+
>
|
|
154
|
+
<Popover.Title>Settings</Popover.Title>
|
|
155
|
+
<Popover.Close
|
|
156
|
+
render={
|
|
157
|
+
<IconButton
|
|
158
|
+
variant="minimal"
|
|
159
|
+
size="compact"
|
|
160
|
+
tone="neutral"
|
|
161
|
+
icon={ close }
|
|
162
|
+
label="Close"
|
|
163
|
+
/>
|
|
164
|
+
}
|
|
165
|
+
/>
|
|
166
|
+
</div>
|
|
167
|
+
<Popover.Description>
|
|
168
|
+
Configure your notification preferences and display
|
|
169
|
+
settings.
|
|
170
|
+
</Popover.Description>
|
|
171
|
+
</Popover.Popup>
|
|
172
|
+
</>
|
|
173
|
+
),
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Use the `open` and `onOpenChange` props on `Popover.Root` to control the
|
|
179
|
+
* popover's visibility programmatically.
|
|
180
|
+
*
|
|
181
|
+
* The checkbox drives the popover state externally. The popover's trigger
|
|
182
|
+
* and click-outside dismiss both sync back to the same state via
|
|
183
|
+
* `onOpenChange`, keeping everything in sync.
|
|
184
|
+
*/
|
|
185
|
+
export const Controlled: Story = {
|
|
186
|
+
argTypes: {
|
|
187
|
+
open: { control: false },
|
|
188
|
+
onOpenChange: { control: false },
|
|
189
|
+
defaultOpen: { control: false },
|
|
190
|
+
},
|
|
191
|
+
args: {
|
|
192
|
+
children: (
|
|
193
|
+
<>
|
|
194
|
+
<Popover.Trigger>Toggle Popover</Popover.Trigger>
|
|
195
|
+
<Popover.Popup>
|
|
196
|
+
<Popover.Arrow />
|
|
197
|
+
<Popover.Title
|
|
198
|
+
style={ {
|
|
199
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
200
|
+
} }
|
|
201
|
+
>
|
|
202
|
+
Controlled Popover
|
|
203
|
+
</Popover.Title>
|
|
204
|
+
<Popover.Description>
|
|
205
|
+
This popover is controlled by external state.
|
|
206
|
+
</Popover.Description>
|
|
207
|
+
</Popover.Popup>
|
|
208
|
+
</>
|
|
209
|
+
),
|
|
210
|
+
},
|
|
211
|
+
render: function Render( args ) {
|
|
212
|
+
const [ isOpen, setIsOpen ] = useState( false );
|
|
213
|
+
const checkboxId = useId();
|
|
214
|
+
const checkboxRef = useRef< HTMLInputElement >( null );
|
|
215
|
+
const labelRef = useRef< HTMLLabelElement >( null );
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<div
|
|
219
|
+
style={ {
|
|
220
|
+
display: 'flex',
|
|
221
|
+
gap: '1rem',
|
|
222
|
+
alignItems: 'center',
|
|
223
|
+
} }
|
|
224
|
+
>
|
|
225
|
+
<Popover.Root
|
|
226
|
+
{ ...args }
|
|
227
|
+
open={ isOpen }
|
|
228
|
+
onOpenChange={ ( nextOpen, eventDetails ) => {
|
|
229
|
+
if (
|
|
230
|
+
[ 'outside-press', 'focus-out' ].includes(
|
|
231
|
+
eventDetails.reason
|
|
232
|
+
) &&
|
|
233
|
+
!! eventDetails.event.target &&
|
|
234
|
+
(
|
|
235
|
+
[
|
|
236
|
+
checkboxRef.current,
|
|
237
|
+
labelRef.current,
|
|
238
|
+
].filter( Boolean ) as EventTarget[]
|
|
239
|
+
).includes( eventDetails.event.target )
|
|
240
|
+
) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
setIsOpen( nextOpen );
|
|
245
|
+
} }
|
|
246
|
+
/>
|
|
247
|
+
|
|
248
|
+
<label htmlFor={ checkboxId } ref={ labelRef }>
|
|
249
|
+
<input
|
|
250
|
+
ref={ checkboxRef }
|
|
251
|
+
id={ checkboxId }
|
|
252
|
+
type="checkbox"
|
|
253
|
+
checked={ isOpen }
|
|
254
|
+
onChange={ ( e ) => setIsOpen( e.target.checked ) }
|
|
255
|
+
/>
|
|
256
|
+
Open
|
|
257
|
+
</label>
|
|
258
|
+
</div>
|
|
259
|
+
);
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Set `modal` to `true` to trap focus inside the popover when it is open.
|
|
265
|
+
* This is useful for complex popover content that requires user interaction,
|
|
266
|
+
* such as forms. Try tabbing through the fields — focus stays inside the
|
|
267
|
+
* popover until it is dismissed.
|
|
268
|
+
*
|
|
269
|
+
* **Note:** focus trapping requires a `Popover.Close` part inside the popup
|
|
270
|
+
* so that screen readers always have an escape route. It can be visually
|
|
271
|
+
* hidden if needed.
|
|
272
|
+
*
|
|
273
|
+
* Pass `backdrop` to `Popover.Popup` to display a semi-transparent overlay
|
|
274
|
+
* beneath the popover, signalling that the page is blocked.
|
|
275
|
+
*/
|
|
276
|
+
export const Modal: Story = {
|
|
277
|
+
argTypes: { modal: { control: false } },
|
|
278
|
+
args: {
|
|
279
|
+
modal: true,
|
|
280
|
+
children: (
|
|
281
|
+
<>
|
|
282
|
+
<Popover.Trigger>Edit Settings</Popover.Trigger>
|
|
283
|
+
<Popover.Popup backdrop>
|
|
284
|
+
<Popover.Arrow />
|
|
285
|
+
<Popover.Title
|
|
286
|
+
style={ {
|
|
287
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
288
|
+
} }
|
|
289
|
+
>
|
|
290
|
+
Settings
|
|
291
|
+
</Popover.Title>
|
|
292
|
+
<form
|
|
293
|
+
style={ {
|
|
294
|
+
display: 'flex',
|
|
295
|
+
flexDirection: 'column',
|
|
296
|
+
gap: 'var(--wpds-dimension-gap-sm)',
|
|
297
|
+
marginTop: 'var(--wpds-dimension-gap-sm)',
|
|
298
|
+
} }
|
|
299
|
+
onSubmit={ ( e ) => e.preventDefault() }
|
|
300
|
+
>
|
|
301
|
+
<label
|
|
302
|
+
htmlFor="popover-test-name-id"
|
|
303
|
+
style={ {
|
|
304
|
+
display: 'flex',
|
|
305
|
+
flexDirection: 'column',
|
|
306
|
+
gap: 'var(--wpds-dimension-gap-xs)',
|
|
307
|
+
fontSize: 'inherit',
|
|
308
|
+
} }
|
|
309
|
+
>
|
|
310
|
+
Name
|
|
311
|
+
<input
|
|
312
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
313
|
+
id="popover-test-name-id"
|
|
314
|
+
type="text"
|
|
315
|
+
placeholder="Enter your name"
|
|
316
|
+
/>
|
|
317
|
+
</label>
|
|
318
|
+
<label
|
|
319
|
+
htmlFor="popover-test-email-id"
|
|
320
|
+
style={ {
|
|
321
|
+
display: 'flex',
|
|
322
|
+
flexDirection: 'column',
|
|
323
|
+
gap: 'var(--wpds-dimension-gap-xs)',
|
|
324
|
+
fontSize: 'inherit',
|
|
325
|
+
} }
|
|
326
|
+
>
|
|
327
|
+
Email
|
|
328
|
+
<input
|
|
329
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
330
|
+
id="popover-test-email-id"
|
|
331
|
+
type="email"
|
|
332
|
+
placeholder="Enter your email"
|
|
333
|
+
/>
|
|
334
|
+
</label>
|
|
335
|
+
<div
|
|
336
|
+
style={ {
|
|
337
|
+
display: 'flex',
|
|
338
|
+
justifyContent: 'flex-end',
|
|
339
|
+
gap: 'var(--wpds-dimension-gap-sm)',
|
|
340
|
+
marginTop: 'var(--wpds-dimension-gap-xs)',
|
|
341
|
+
} }
|
|
342
|
+
>
|
|
343
|
+
<Popover.Close
|
|
344
|
+
style={ {
|
|
345
|
+
all: 'unset',
|
|
346
|
+
cursor: 'pointer',
|
|
347
|
+
} }
|
|
348
|
+
>
|
|
349
|
+
Cancel
|
|
350
|
+
</Popover.Close>
|
|
351
|
+
<button type="submit">Save</button>
|
|
352
|
+
</div>
|
|
353
|
+
</form>
|
|
354
|
+
</Popover.Popup>
|
|
355
|
+
</>
|
|
356
|
+
),
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* The `variant="unstyled"` option strips all visual styling from the popup,
|
|
362
|
+
* making it a blank positioning container for fully custom content.
|
|
363
|
+
*/
|
|
364
|
+
export const Unstyled: Story = {
|
|
365
|
+
args: {
|
|
366
|
+
children: (
|
|
367
|
+
<>
|
|
368
|
+
<Popover.Trigger>Open Unstyled</Popover.Trigger>
|
|
369
|
+
<Popover.Popup variant="unstyled">
|
|
370
|
+
<Popover.Title
|
|
371
|
+
style={ {
|
|
372
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
373
|
+
} }
|
|
374
|
+
>
|
|
375
|
+
Custom Styled
|
|
376
|
+
</Popover.Title>
|
|
377
|
+
<Popover.Description>
|
|
378
|
+
This popup has no default styling — the consumer
|
|
379
|
+
controls all visual appearance.
|
|
380
|
+
</Popover.Description>
|
|
381
|
+
</Popover.Popup>
|
|
382
|
+
</>
|
|
383
|
+
),
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Overlay placement positions the popover centered on top of its trigger,
|
|
389
|
+
* effectively covering it. This is achieved by computing a negative
|
|
390
|
+
* `sideOffset` based on the measured sizes of the trigger and popup.
|
|
391
|
+
*
|
|
392
|
+
* This technique is useful when you want the popover to visually replace
|
|
393
|
+
* the trigger element in place.
|
|
394
|
+
*/
|
|
395
|
+
export const OverlayPlacement: Story = {
|
|
396
|
+
args: { defaultOpen: true },
|
|
397
|
+
argTypes: { defaultOpen: { control: false } },
|
|
398
|
+
render: function Render( { children: _children, ...args } ) {
|
|
399
|
+
const [ popupRef, popupSize ] = useMeasure< HTMLDivElement >();
|
|
400
|
+
const [ triggerRef, triggerSize ] = useMeasure< HTMLButtonElement >();
|
|
401
|
+
|
|
402
|
+
return (
|
|
403
|
+
<div style={ { padding: '4rem', textAlign: 'center' } }>
|
|
404
|
+
<Popover.Root { ...args }>
|
|
405
|
+
<Popover.Trigger ref={ triggerRef }>
|
|
406
|
+
Trigger (covered by popover)
|
|
407
|
+
</Popover.Trigger>
|
|
408
|
+
<Popover.Popup
|
|
409
|
+
ref={ popupRef }
|
|
410
|
+
side="bottom"
|
|
411
|
+
align="center"
|
|
412
|
+
sideOffset={
|
|
413
|
+
-1 *
|
|
414
|
+
( popupSize.height / 2 + triggerSize.height / 2 )
|
|
415
|
+
}
|
|
416
|
+
collisionAvoidance={ {
|
|
417
|
+
side: 'none',
|
|
418
|
+
align: 'none',
|
|
419
|
+
} }
|
|
420
|
+
>
|
|
421
|
+
<Popover.Title
|
|
422
|
+
style={ {
|
|
423
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
424
|
+
} }
|
|
425
|
+
>
|
|
426
|
+
Overlay
|
|
427
|
+
</Popover.Title>
|
|
428
|
+
<Popover.Description>
|
|
429
|
+
This popover is centered over its trigger using a
|
|
430
|
+
negative sideOffset.
|
|
431
|
+
<br />
|
|
432
|
+
The trigger is currently hidden under the popover.
|
|
433
|
+
<br />
|
|
434
|
+
Try resizing the browser — collision avoidance is
|
|
435
|
+
disabled so the popover stays overlaid.
|
|
436
|
+
</Popover.Description>
|
|
437
|
+
</Popover.Popup>
|
|
438
|
+
</Popover.Root>
|
|
439
|
+
</div>
|
|
440
|
+
);
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* To render the popup inline (without a portal), create a local ref to a
|
|
446
|
+
* `<span>` with `display: contents` and pass it as the `container` prop.
|
|
447
|
+
* The popup will render inside the span rather than being portaled to
|
|
448
|
+
* `document.body`, while retaining all positioning behavior.
|
|
449
|
+
*
|
|
450
|
+
* **Note:** `backdrop` will not cover the full viewport in this mode.
|
|
451
|
+
*/
|
|
452
|
+
export const Inline: Story = {
|
|
453
|
+
parameters: { controls: { disable: true } },
|
|
454
|
+
render: function Render() {
|
|
455
|
+
const inlineContainerRef = useRef< HTMLSpanElement >( null );
|
|
456
|
+
|
|
457
|
+
return (
|
|
458
|
+
<div data-testid="inline-wrapper">
|
|
459
|
+
<Popover.Root>
|
|
460
|
+
<Popover.Trigger>Open Inline</Popover.Trigger>
|
|
461
|
+
<span
|
|
462
|
+
ref={ inlineContainerRef }
|
|
463
|
+
style={ { display: 'contents' } }
|
|
464
|
+
/>
|
|
465
|
+
<Popover.Popup container={ inlineContainerRef }>
|
|
466
|
+
<Popover.Arrow />
|
|
467
|
+
<Popover.Title
|
|
468
|
+
style={ {
|
|
469
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
470
|
+
} }
|
|
471
|
+
>
|
|
472
|
+
Inline Popover
|
|
473
|
+
</Popover.Title>
|
|
474
|
+
<Popover.Description>
|
|
475
|
+
This popup is rendered in place — no portal is used.
|
|
476
|
+
Inspect the DOM to see it lives inside its parent.
|
|
477
|
+
</Popover.Description>
|
|
478
|
+
</Popover.Popup>
|
|
479
|
+
</Popover.Root>
|
|
480
|
+
</div>
|
|
481
|
+
);
|
|
482
|
+
},
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Use the `collisionAvoidance` prop to control how the popover behaves when
|
|
487
|
+
* it collides with the edges of its collision boundary.
|
|
488
|
+
*
|
|
489
|
+
* Because the popup renders via a portal (outside the scrollable container),
|
|
490
|
+
* the container must be passed as `collisionBoundary` so Floating UI treats
|
|
491
|
+
* it as the clipping edge.
|
|
492
|
+
*
|
|
493
|
+
* - `side: 'flip'` flips to the opposite side (default).
|
|
494
|
+
* - `side: 'none'` disables collision handling.
|
|
495
|
+
*
|
|
496
|
+
* Scroll the container to see collision avoidance in action.
|
|
497
|
+
*/
|
|
498
|
+
export const CollisionAvoidance: Story = {
|
|
499
|
+
parameters: { controls: { disable: true } },
|
|
500
|
+
render: function Render() {
|
|
501
|
+
const [ boundary, setBoundary ] = useState< HTMLElement | null >(
|
|
502
|
+
null
|
|
503
|
+
);
|
|
504
|
+
|
|
505
|
+
return (
|
|
506
|
+
<div
|
|
507
|
+
ref={ setBoundary }
|
|
508
|
+
style={ {
|
|
509
|
+
height: 300,
|
|
510
|
+
overflow: 'auto',
|
|
511
|
+
border: '1px solid #ccc',
|
|
512
|
+
padding: '200px 2rem',
|
|
513
|
+
} }
|
|
514
|
+
>
|
|
515
|
+
<div
|
|
516
|
+
style={ {
|
|
517
|
+
display: 'flex',
|
|
518
|
+
gap: '2rem',
|
|
519
|
+
justifyContent: 'center',
|
|
520
|
+
} }
|
|
521
|
+
>
|
|
522
|
+
<Popover.Root defaultOpen>
|
|
523
|
+
<Popover.Trigger>Flip (default)</Popover.Trigger>
|
|
524
|
+
<Popover.Popup
|
|
525
|
+
side="top"
|
|
526
|
+
collisionBoundary={ boundary ?? undefined }
|
|
527
|
+
>
|
|
528
|
+
<Popover.Title
|
|
529
|
+
style={ {
|
|
530
|
+
marginBottom:
|
|
531
|
+
'var(--wpds-dimension-gap-xs)',
|
|
532
|
+
} }
|
|
533
|
+
>
|
|
534
|
+
Flip
|
|
535
|
+
</Popover.Title>
|
|
536
|
+
<Popover.Description>
|
|
537
|
+
Flips to bottom when clipped
|
|
538
|
+
</Popover.Description>
|
|
539
|
+
</Popover.Popup>
|
|
540
|
+
</Popover.Root>
|
|
541
|
+
|
|
542
|
+
<Popover.Root defaultOpen>
|
|
543
|
+
<Popover.Trigger>No collision</Popover.Trigger>
|
|
544
|
+
<Popover.Popup
|
|
545
|
+
side="top"
|
|
546
|
+
collisionBoundary={ boundary ?? undefined }
|
|
547
|
+
collisionAvoidance={ {
|
|
548
|
+
side: 'none',
|
|
549
|
+
align: 'none',
|
|
550
|
+
} }
|
|
551
|
+
>
|
|
552
|
+
<Popover.Title
|
|
553
|
+
style={ {
|
|
554
|
+
marginBottom:
|
|
555
|
+
'var(--wpds-dimension-gap-xs)',
|
|
556
|
+
} }
|
|
557
|
+
>
|
|
558
|
+
None
|
|
559
|
+
</Popover.Title>
|
|
560
|
+
<Popover.Description>
|
|
561
|
+
Stays on top even when clipped
|
|
562
|
+
</Popover.Description>
|
|
563
|
+
</Popover.Popup>
|
|
564
|
+
</Popover.Root>
|
|
565
|
+
</div>
|
|
566
|
+
<div style={ { height: 600 } } />
|
|
567
|
+
</div>
|
|
568
|
+
);
|
|
569
|
+
},
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* When the popover's trigger lives inside an iframe but the popover should
|
|
574
|
+
* render in the parent document, pass a parent-document element to the
|
|
575
|
+
* `container` prop on `Popover.Popup`.
|
|
576
|
+
*
|
|
577
|
+
* This technique is used in Gutenberg where the block editor canvas is an
|
|
578
|
+
* iframe but toolbars and menus must appear outside it.
|
|
579
|
+
*
|
|
580
|
+
* Scroll inside the iframe to verify that the popover tracks the trigger
|
|
581
|
+
* position across document boundaries.
|
|
582
|
+
*/
|
|
583
|
+
export const CrossIframe: Story = {
|
|
584
|
+
args: { defaultOpen: true },
|
|
585
|
+
argTypes: { defaultOpen: { control: false } },
|
|
586
|
+
render: function Render( { children: _children, ...args } ) {
|
|
587
|
+
const portalContainerRef = useRef< HTMLDivElement >( null );
|
|
588
|
+
const [ iframeBoundary, setIframeBoundary ] =
|
|
589
|
+
useState< HTMLIFrameElement | null >( null );
|
|
590
|
+
|
|
591
|
+
return (
|
|
592
|
+
<div>
|
|
593
|
+
<div ref={ portalContainerRef } />
|
|
594
|
+
<GenericIframe
|
|
595
|
+
ref={ setIframeBoundary }
|
|
596
|
+
style={ {
|
|
597
|
+
width: '100%',
|
|
598
|
+
height: 400,
|
|
599
|
+
border: 0,
|
|
600
|
+
outline: '1px solid purple',
|
|
601
|
+
} }
|
|
602
|
+
>
|
|
603
|
+
<div
|
|
604
|
+
style={ {
|
|
605
|
+
height: '200vh',
|
|
606
|
+
paddingTop: '10vh',
|
|
607
|
+
} }
|
|
608
|
+
>
|
|
609
|
+
<div
|
|
610
|
+
style={ {
|
|
611
|
+
maxWidth: 200,
|
|
612
|
+
marginTop: 100,
|
|
613
|
+
marginInline: 'auto',
|
|
614
|
+
} }
|
|
615
|
+
>
|
|
616
|
+
<Popover.Root { ...args }>
|
|
617
|
+
<Popover.Trigger
|
|
618
|
+
style={ {
|
|
619
|
+
padding: 8,
|
|
620
|
+
background: 'salmon',
|
|
621
|
+
} }
|
|
622
|
+
>
|
|
623
|
+
Popover's anchor (inside iframe)
|
|
624
|
+
</Popover.Trigger>
|
|
625
|
+
<Popover.Popup
|
|
626
|
+
container={
|
|
627
|
+
portalContainerRef as React.RefObject< HTMLElement >
|
|
628
|
+
}
|
|
629
|
+
collisionBoundary={
|
|
630
|
+
iframeBoundary ?? undefined
|
|
631
|
+
}
|
|
632
|
+
>
|
|
633
|
+
<Popover.Arrow />
|
|
634
|
+
<Popover.Title
|
|
635
|
+
style={ {
|
|
636
|
+
marginBottom:
|
|
637
|
+
'var(--wpds-dimension-gap-xs)',
|
|
638
|
+
} }
|
|
639
|
+
>
|
|
640
|
+
Cross-Iframe Popover
|
|
641
|
+
</Popover.Title>
|
|
642
|
+
<Popover.Description>
|
|
643
|
+
This popup is rendered in the parent
|
|
644
|
+
document, not inside the iframe. Scroll
|
|
645
|
+
the iframe to see the popover track the
|
|
646
|
+
trigger.
|
|
647
|
+
</Popover.Description>
|
|
648
|
+
</Popover.Popup>
|
|
649
|
+
</Popover.Root>
|
|
650
|
+
</div>
|
|
651
|
+
</div>
|
|
652
|
+
</GenericIframe>
|
|
653
|
+
</div>
|
|
654
|
+
);
|
|
655
|
+
},
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Same cross-iframe scenario, but using `SlotFillProvider` and `Slot` from
|
|
660
|
+
* `@wordpress/components` as the render target.
|
|
661
|
+
*
|
|
662
|
+
* The `Slot` renders a `div` in the parent document, and its forwarded ref
|
|
663
|
+
* is passed to `Popover.Popup`'s `container` prop so the popup portals into
|
|
664
|
+
* the slot element. This mirrors the legacy Popover's `WithSlotOutsideIframe`
|
|
665
|
+
* pattern.
|
|
666
|
+
*/
|
|
667
|
+
export const CrossIframeWithSlotFill: Story = {
|
|
668
|
+
name: 'Cross-Iframe (SlotFill)',
|
|
669
|
+
args: { defaultOpen: true },
|
|
670
|
+
argTypes: { defaultOpen: { control: false } },
|
|
671
|
+
render: function Render( { children: _children, ...args } ) {
|
|
672
|
+
const slotRef = useRef< HTMLDivElement >( null );
|
|
673
|
+
const [ iframeBoundary, setIframeBoundary ] =
|
|
674
|
+
useState< HTMLIFrameElement | null >( null );
|
|
675
|
+
|
|
676
|
+
return (
|
|
677
|
+
<SlotFillProvider>
|
|
678
|
+
<Slot
|
|
679
|
+
name="popover-container"
|
|
680
|
+
bubblesVirtually
|
|
681
|
+
ref={ slotRef }
|
|
682
|
+
/>
|
|
683
|
+
<GenericIframe
|
|
684
|
+
ref={ setIframeBoundary }
|
|
685
|
+
style={ {
|
|
686
|
+
width: '100%',
|
|
687
|
+
height: 400,
|
|
688
|
+
border: 0,
|
|
689
|
+
outline: '1px solid purple',
|
|
690
|
+
} }
|
|
691
|
+
>
|
|
692
|
+
<div
|
|
693
|
+
style={ {
|
|
694
|
+
height: '200vh',
|
|
695
|
+
paddingTop: '10vh',
|
|
696
|
+
} }
|
|
697
|
+
>
|
|
698
|
+
<div
|
|
699
|
+
style={ {
|
|
700
|
+
maxWidth: 200,
|
|
701
|
+
marginTop: 100,
|
|
702
|
+
marginInline: 'auto',
|
|
703
|
+
} }
|
|
704
|
+
>
|
|
705
|
+
<Popover.Root { ...args }>
|
|
706
|
+
<Popover.Trigger
|
|
707
|
+
style={ {
|
|
708
|
+
padding: 8,
|
|
709
|
+
background: 'salmon',
|
|
710
|
+
} }
|
|
711
|
+
>
|
|
712
|
+
Popover's anchor (inside iframe)
|
|
713
|
+
</Popover.Trigger>
|
|
714
|
+
<Popover.Popup
|
|
715
|
+
container={
|
|
716
|
+
slotRef as React.RefObject< HTMLElement >
|
|
717
|
+
}
|
|
718
|
+
collisionBoundary={
|
|
719
|
+
iframeBoundary ?? undefined
|
|
720
|
+
}
|
|
721
|
+
>
|
|
722
|
+
<Popover.Arrow />
|
|
723
|
+
<Popover.Title
|
|
724
|
+
style={ {
|
|
725
|
+
marginBottom:
|
|
726
|
+
'var(--wpds-dimension-gap-xs)',
|
|
727
|
+
} }
|
|
728
|
+
>
|
|
729
|
+
Cross-Iframe (SlotFill)
|
|
730
|
+
</Popover.Title>
|
|
731
|
+
<Popover.Description>
|
|
732
|
+
This popup renders in the parent
|
|
733
|
+
document via a `Slot` from
|
|
734
|
+
`@wordpress/components`.
|
|
735
|
+
</Popover.Description>
|
|
736
|
+
</Popover.Popup>
|
|
737
|
+
</Popover.Root>
|
|
738
|
+
</div>
|
|
739
|
+
</div>
|
|
740
|
+
</GenericIframe>
|
|
741
|
+
</SlotFillProvider>
|
|
742
|
+
);
|
|
743
|
+
},
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Popovers in Gutenberg are managed with explicit z-index values, which can
|
|
748
|
+
* create situations where a popover renders below another popover, when you
|
|
749
|
+
* want it to be rendered above.
|
|
750
|
+
*
|
|
751
|
+
* The `--wp-ui-popover-z-index` CSS variable, available on the
|
|
752
|
+
* `Popover.Popup` component, is an escape hatch that can be used to override
|
|
753
|
+
* the z-index of a given popover on a case-by-case basis.
|
|
754
|
+
*/
|
|
755
|
+
export const WithCustomZIndex: Story = {
|
|
756
|
+
name: 'With Custom z-index',
|
|
757
|
+
args: {
|
|
758
|
+
children: (
|
|
759
|
+
<>
|
|
760
|
+
<Popover.Trigger>Open Popover</Popover.Trigger>
|
|
761
|
+
<Popover.Popup style={ { '--wp-ui-popover-z-index': '9999' } }>
|
|
762
|
+
<Popover.Arrow />
|
|
763
|
+
<Popover.Title
|
|
764
|
+
style={ {
|
|
765
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
766
|
+
} }
|
|
767
|
+
>
|
|
768
|
+
Custom z-index
|
|
769
|
+
</Popover.Title>
|
|
770
|
+
<Popover.Description>
|
|
771
|
+
This popover's positioner has z-index: 9999 via the
|
|
772
|
+
`--wp-ui-popover-z-index` CSS custom property.
|
|
773
|
+
</Popover.Description>
|
|
774
|
+
</Popover.Popup>
|
|
775
|
+
</>
|
|
776
|
+
),
|
|
777
|
+
},
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Use the `anchor` prop on `Popover.Popup` to position the popover against an
|
|
782
|
+
* arbitrary element instead of the built-in trigger. Base UI accepts four
|
|
783
|
+
* anchor types:
|
|
784
|
+
*
|
|
785
|
+
* 1. **Element** — a direct DOM element reference.
|
|
786
|
+
* 2. **VirtualElement** — an object with a `getBoundingClientRect()` method.
|
|
787
|
+
* 3. **RefObject** — a `React.RefObject` pointing to an element.
|
|
788
|
+
* 4. **Callback** — a function returning an Element or VirtualElement.
|
|
789
|
+
*
|
|
790
|
+
* This is the most-used pattern in Gutenberg: block popovers anchor to
|
|
791
|
+
* selected block elements, the link popover anchors to the text selection, and
|
|
792
|
+
* data views anchor to right-click positions.
|
|
793
|
+
*/
|
|
794
|
+
export const Anchor: Story = {
|
|
795
|
+
parameters: { controls: { disable: true } },
|
|
796
|
+
render: function Render() {
|
|
797
|
+
const [ elementAnchor, setElementAnchor ] =
|
|
798
|
+
useState< HTMLElement | null >( null );
|
|
799
|
+
const refAnchor = useRef< HTMLDivElement >( null );
|
|
800
|
+
const virtualAnchorLabel = useRef< HTMLDivElement >( null );
|
|
801
|
+
const callbackTarget = useRef< HTMLDivElement >( null );
|
|
802
|
+
|
|
803
|
+
const virtualAnchor = {
|
|
804
|
+
getBoundingClientRect: () =>
|
|
805
|
+
virtualAnchorLabel.current?.getBoundingClientRect() ??
|
|
806
|
+
new DOMRect(),
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
const anchorBoxStyle = {
|
|
810
|
+
padding: '8px 12px',
|
|
811
|
+
border: '2px dashed currentcolor',
|
|
812
|
+
borderRadius: 4,
|
|
813
|
+
fontSize: 12,
|
|
814
|
+
textAlign: 'center' as const,
|
|
815
|
+
};
|
|
816
|
+
|
|
817
|
+
const popupProps = {
|
|
818
|
+
collisionAvoidance: {
|
|
819
|
+
side: 'none' as const,
|
|
820
|
+
align: 'none' as const,
|
|
821
|
+
},
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
return (
|
|
825
|
+
<div
|
|
826
|
+
style={ {
|
|
827
|
+
display: 'grid',
|
|
828
|
+
gridTemplateColumns: '1fr 1fr',
|
|
829
|
+
gap: '4rem',
|
|
830
|
+
padding: '4rem 2rem',
|
|
831
|
+
} }
|
|
832
|
+
>
|
|
833
|
+
{ /* 1. Element anchor */ }
|
|
834
|
+
<div>
|
|
835
|
+
<div ref={ setElementAnchor } style={ anchorBoxStyle }>
|
|
836
|
+
Element anchor
|
|
837
|
+
</div>
|
|
838
|
+
<Popover.Root open>
|
|
839
|
+
<Popover.Popup
|
|
840
|
+
anchor={ elementAnchor ?? undefined }
|
|
841
|
+
{ ...popupProps }
|
|
842
|
+
>
|
|
843
|
+
<VisuallyHidden render={ <Popover.Title /> }>
|
|
844
|
+
Element anchor
|
|
845
|
+
</VisuallyHidden>
|
|
846
|
+
<Popover.Arrow />
|
|
847
|
+
<Popover.Description>
|
|
848
|
+
Anchored to a DOM element
|
|
849
|
+
</Popover.Description>
|
|
850
|
+
</Popover.Popup>
|
|
851
|
+
</Popover.Root>
|
|
852
|
+
</div>
|
|
853
|
+
|
|
854
|
+
{ /* 2. VirtualElement anchor */ }
|
|
855
|
+
<div>
|
|
856
|
+
<div ref={ virtualAnchorLabel } style={ anchorBoxStyle }>
|
|
857
|
+
VirtualElement anchor
|
|
858
|
+
</div>
|
|
859
|
+
<Popover.Root open>
|
|
860
|
+
<Popover.Popup
|
|
861
|
+
anchor={ virtualAnchor }
|
|
862
|
+
{ ...popupProps }
|
|
863
|
+
>
|
|
864
|
+
<VisuallyHidden render={ <Popover.Title /> }>
|
|
865
|
+
Virtual anchor
|
|
866
|
+
</VisuallyHidden>
|
|
867
|
+
<Popover.Arrow />
|
|
868
|
+
<Popover.Description>
|
|
869
|
+
Anchored to a virtual element
|
|
870
|
+
</Popover.Description>
|
|
871
|
+
</Popover.Popup>
|
|
872
|
+
</Popover.Root>
|
|
873
|
+
</div>
|
|
874
|
+
|
|
875
|
+
{ /* 3. RefObject anchor */ }
|
|
876
|
+
<div>
|
|
877
|
+
<div ref={ refAnchor } style={ anchorBoxStyle }>
|
|
878
|
+
RefObject anchor
|
|
879
|
+
</div>
|
|
880
|
+
<Popover.Root open>
|
|
881
|
+
<Popover.Popup anchor={ refAnchor } { ...popupProps }>
|
|
882
|
+
<VisuallyHidden render={ <Popover.Title /> }>
|
|
883
|
+
Ref anchor
|
|
884
|
+
</VisuallyHidden>
|
|
885
|
+
<Popover.Arrow />
|
|
886
|
+
<Popover.Description>
|
|
887
|
+
Anchored via useRef
|
|
888
|
+
</Popover.Description>
|
|
889
|
+
</Popover.Popup>
|
|
890
|
+
</Popover.Root>
|
|
891
|
+
</div>
|
|
892
|
+
|
|
893
|
+
{ /* 4. Callback anchor */ }
|
|
894
|
+
<div>
|
|
895
|
+
<div ref={ callbackTarget } style={ anchorBoxStyle }>
|
|
896
|
+
Callback anchor
|
|
897
|
+
</div>
|
|
898
|
+
<Popover.Root open>
|
|
899
|
+
<Popover.Popup
|
|
900
|
+
anchor={ () => callbackTarget.current }
|
|
901
|
+
{ ...popupProps }
|
|
902
|
+
>
|
|
903
|
+
<VisuallyHidden render={ <Popover.Title /> }>
|
|
904
|
+
Callback anchor
|
|
905
|
+
</VisuallyHidden>
|
|
906
|
+
<Popover.Arrow />
|
|
907
|
+
<Popover.Description>
|
|
908
|
+
Anchored via callback function
|
|
909
|
+
</Popover.Description>
|
|
910
|
+
</Popover.Popup>
|
|
911
|
+
</Popover.Root>
|
|
912
|
+
</div>
|
|
913
|
+
</div>
|
|
914
|
+
);
|
|
915
|
+
},
|
|
916
|
+
};
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Use `variant="unstyled"` and custom inline styles to replicate a toolbar-like
|
|
920
|
+
* appearance: high-contrast border, no shadow, and a smaller border radius.
|
|
921
|
+
*
|
|
922
|
+
* A first-class `variant="toolbar"` may be added in the future if this pattern
|
|
923
|
+
* becomes widespread.
|
|
924
|
+
*/
|
|
925
|
+
export const ToolbarVariant: Story = {
|
|
926
|
+
args: {
|
|
927
|
+
children: (
|
|
928
|
+
<>
|
|
929
|
+
<Popover.Trigger>Open Toolbar</Popover.Trigger>
|
|
930
|
+
<Popover.Popup
|
|
931
|
+
variant="unstyled"
|
|
932
|
+
style={ {
|
|
933
|
+
display: 'flex',
|
|
934
|
+
gap: 'var(--wpds-dimension-gap-xs)',
|
|
935
|
+
padding: '4px 8px',
|
|
936
|
+
border: '1px solid #1e1e1e',
|
|
937
|
+
borderRadius: 2,
|
|
938
|
+
background: '#fff',
|
|
939
|
+
fontSize: 13,
|
|
940
|
+
} }
|
|
941
|
+
>
|
|
942
|
+
<VisuallyHidden render={ <Popover.Title /> }>
|
|
943
|
+
Formatting
|
|
944
|
+
</VisuallyHidden>
|
|
945
|
+
<button type="button">B</button>
|
|
946
|
+
<button type="button">I</button>
|
|
947
|
+
<button type="button">U</button>
|
|
948
|
+
<button type="button">Link</button>
|
|
949
|
+
</Popover.Popup>
|
|
950
|
+
</>
|
|
951
|
+
),
|
|
952
|
+
},
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* Base UI's Positioner exposes `--available-height` and
|
|
957
|
+
* `--available-width` CSS variables representing the space
|
|
958
|
+
* between the anchor and the viewport edge. Apply them as `max-height` /
|
|
959
|
+
* `max-width` via the `style` prop (which targets the positioner) to
|
|
960
|
+
* constrain the popup size. Then add `overflow: auto` on an inner wrapper
|
|
961
|
+
* so scrolling happens inside the popup content area — this replaces the
|
|
962
|
+
* legacy Popover's `resize` prop.
|
|
963
|
+
*
|
|
964
|
+
* Open the popover and resize or scroll the container to see the popup shrink
|
|
965
|
+
* to fit.
|
|
966
|
+
*/
|
|
967
|
+
export const ViewportConstrainedSize: Story = {
|
|
968
|
+
name: 'Viewport-Constrained Size',
|
|
969
|
+
args: { defaultOpen: true },
|
|
970
|
+
argTypes: { defaultOpen: { control: false } },
|
|
971
|
+
render: function Render( { children: _children, ...args } ) {
|
|
972
|
+
return (
|
|
973
|
+
<div
|
|
974
|
+
style={ {
|
|
975
|
+
height: 250,
|
|
976
|
+
overflow: 'auto',
|
|
977
|
+
border: '1px solid #ccc',
|
|
978
|
+
padding: '60px 2rem',
|
|
979
|
+
} }
|
|
980
|
+
>
|
|
981
|
+
<Popover.Root { ...args }>
|
|
982
|
+
<Popover.Trigger>Show Content</Popover.Trigger>
|
|
983
|
+
<Popover.Popup
|
|
984
|
+
side="bottom"
|
|
985
|
+
style={ {
|
|
986
|
+
maxHeight: 'var(--available-height, 300px)',
|
|
987
|
+
maxWidth: 'var(--available-width, 300px)',
|
|
988
|
+
} }
|
|
989
|
+
>
|
|
990
|
+
<div style={ { overflow: 'auto', height: '100%' } }>
|
|
991
|
+
<Popover.Title
|
|
992
|
+
style={ {
|
|
993
|
+
marginBottom:
|
|
994
|
+
'var(--wpds-dimension-gap-xs)',
|
|
995
|
+
} }
|
|
996
|
+
>
|
|
997
|
+
Constrained
|
|
998
|
+
</Popover.Title>
|
|
999
|
+
<Popover.Description>
|
|
1000
|
+
This popup constrains its size using the
|
|
1001
|
+
`--available-height` and `--available-width` CSS
|
|
1002
|
+
variables exposed by the positioner.
|
|
1003
|
+
</Popover.Description>
|
|
1004
|
+
<div style={ { height: 400 } }>
|
|
1005
|
+
<p>
|
|
1006
|
+
Scroll inside this popup — its max-height is
|
|
1007
|
+
capped to the available viewport space.
|
|
1008
|
+
</p>
|
|
1009
|
+
</div>
|
|
1010
|
+
</div>
|
|
1011
|
+
</Popover.Popup>
|
|
1012
|
+
</Popover.Root>
|
|
1013
|
+
<div style={ { height: 600 } } />
|
|
1014
|
+
</div>
|
|
1015
|
+
);
|
|
1016
|
+
},
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* The `onOpenChange` callback on `Popover.Root` receives an `eventDetails`
|
|
1021
|
+
* object with a `reason` field that describes why the popover is
|
|
1022
|
+
* opening/closing. This replaces the legacy Popover's separate `onClose` and
|
|
1023
|
+
* `onFocusOutside` callbacks:
|
|
1024
|
+
*
|
|
1025
|
+
* - `reason === 'escape-key'` — user pressed Escape (was `onClose`)
|
|
1026
|
+
* - `reason === 'outside-press'` — user clicked outside (was `onClose`)
|
|
1027
|
+
* - `reason === 'focus-out'` — focus moved outside (was `onFocusOutside`)
|
|
1028
|
+
*
|
|
1029
|
+
* Open the popover, then dismiss it in different ways to see the logged reason.
|
|
1030
|
+
*/
|
|
1031
|
+
export const OnOpenChangeDetails: Story = {
|
|
1032
|
+
name: 'onOpenChange Details',
|
|
1033
|
+
parameters: { controls: { disable: true } },
|
|
1034
|
+
render: function Render() {
|
|
1035
|
+
const [ log, setLog ] = useState< string[] >( [] );
|
|
1036
|
+
|
|
1037
|
+
return (
|
|
1038
|
+
<div style={ { display: 'flex', gap: '2rem' } }>
|
|
1039
|
+
<Popover.Root
|
|
1040
|
+
onOpenChange={ ( nextOpen, eventDetails ) => {
|
|
1041
|
+
setLog( ( prev ) => [
|
|
1042
|
+
...prev.slice( -9 ),
|
|
1043
|
+
`open=${ nextOpen } reason=${ eventDetails.reason }`,
|
|
1044
|
+
] );
|
|
1045
|
+
} }
|
|
1046
|
+
>
|
|
1047
|
+
<Popover.Trigger>Toggle</Popover.Trigger>
|
|
1048
|
+
<Popover.Popup>
|
|
1049
|
+
<Popover.Arrow />
|
|
1050
|
+
<Popover.Title
|
|
1051
|
+
style={ {
|
|
1052
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
1053
|
+
} }
|
|
1054
|
+
>
|
|
1055
|
+
Event Log
|
|
1056
|
+
</Popover.Title>
|
|
1057
|
+
<Popover.Description>
|
|
1058
|
+
Dismiss this popover via Escape, click-outside, or
|
|
1059
|
+
moving focus away.
|
|
1060
|
+
</Popover.Description>
|
|
1061
|
+
</Popover.Popup>
|
|
1062
|
+
</Popover.Root>
|
|
1063
|
+
|
|
1064
|
+
<pre
|
|
1065
|
+
style={ {
|
|
1066
|
+
flex: 1,
|
|
1067
|
+
padding: 8,
|
|
1068
|
+
fontSize: 12,
|
|
1069
|
+
lineHeight: 1.5,
|
|
1070
|
+
background: '#f5f5f5',
|
|
1071
|
+
borderRadius: 4,
|
|
1072
|
+
minHeight: 100,
|
|
1073
|
+
margin: 0,
|
|
1074
|
+
} }
|
|
1075
|
+
>
|
|
1076
|
+
{ log.length
|
|
1077
|
+
? log.join( '\n' )
|
|
1078
|
+
: 'Interact with the popover to see events…' }
|
|
1079
|
+
</pre>
|
|
1080
|
+
</div>
|
|
1081
|
+
);
|
|
1082
|
+
},
|
|
1083
|
+
};
|
|
1084
|
+
|
|
1085
|
+
/**
|
|
1086
|
+
* Pass a ref to `initialFocus` on `Popover.Popup` to focus a specific element
|
|
1087
|
+
* when the popover opens. This replaces the legacy Popover's `focusOnMount`
|
|
1088
|
+
* prop.
|
|
1089
|
+
*
|
|
1090
|
+
* In this example, the Email field receives focus instead of the first
|
|
1091
|
+
* focusable element (Name).
|
|
1092
|
+
*/
|
|
1093
|
+
export const InitialFocus: Story = {
|
|
1094
|
+
parameters: { controls: { disable: true } },
|
|
1095
|
+
render: function Render() {
|
|
1096
|
+
const emailRef = useRef< HTMLInputElement >( null );
|
|
1097
|
+
const nameId = useId();
|
|
1098
|
+
const emailId = useId();
|
|
1099
|
+
|
|
1100
|
+
return (
|
|
1101
|
+
<Popover.Root>
|
|
1102
|
+
<Popover.Trigger>Open Form</Popover.Trigger>
|
|
1103
|
+
<Popover.Popup initialFocus={ emailRef }>
|
|
1104
|
+
<Popover.Arrow />
|
|
1105
|
+
<Popover.Title
|
|
1106
|
+
style={ {
|
|
1107
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
1108
|
+
} }
|
|
1109
|
+
>
|
|
1110
|
+
Contact
|
|
1111
|
+
</Popover.Title>
|
|
1112
|
+
<form
|
|
1113
|
+
style={ {
|
|
1114
|
+
display: 'flex',
|
|
1115
|
+
flexDirection: 'column',
|
|
1116
|
+
gap: 'var(--wpds-dimension-gap-sm)',
|
|
1117
|
+
} }
|
|
1118
|
+
onSubmit={ ( e ) => e.preventDefault() }
|
|
1119
|
+
>
|
|
1120
|
+
<label
|
|
1121
|
+
htmlFor={ nameId }
|
|
1122
|
+
style={ {
|
|
1123
|
+
display: 'flex',
|
|
1124
|
+
flexDirection: 'column',
|
|
1125
|
+
gap: 'var(--wpds-dimension-gap-xs)',
|
|
1126
|
+
fontSize: 'inherit',
|
|
1127
|
+
} }
|
|
1128
|
+
>
|
|
1129
|
+
Name
|
|
1130
|
+
</label>
|
|
1131
|
+
<input
|
|
1132
|
+
id={ nameId }
|
|
1133
|
+
type="text"
|
|
1134
|
+
placeholder="Enter name"
|
|
1135
|
+
/>
|
|
1136
|
+
<label
|
|
1137
|
+
htmlFor={ emailId }
|
|
1138
|
+
style={ {
|
|
1139
|
+
display: 'flex',
|
|
1140
|
+
flexDirection: 'column',
|
|
1141
|
+
gap: 'var(--wpds-dimension-gap-xs)',
|
|
1142
|
+
fontSize: 'inherit',
|
|
1143
|
+
} }
|
|
1144
|
+
>
|
|
1145
|
+
Email (auto-focused)
|
|
1146
|
+
</label>
|
|
1147
|
+
<input
|
|
1148
|
+
id={ emailId }
|
|
1149
|
+
ref={ emailRef }
|
|
1150
|
+
type="email"
|
|
1151
|
+
placeholder="Enter email"
|
|
1152
|
+
/>
|
|
1153
|
+
</form>
|
|
1154
|
+
</Popover.Popup>
|
|
1155
|
+
</Popover.Root>
|
|
1156
|
+
);
|
|
1157
|
+
},
|
|
1158
|
+
};
|
|
1159
|
+
|
|
1160
|
+
/**
|
|
1161
|
+
* Set `modal="trap-focus"` on `Popover.Root` to trap keyboard focus inside the
|
|
1162
|
+
* popover without making it fully modal. Unlike `modal={true}`, this mode:
|
|
1163
|
+
*
|
|
1164
|
+
* - Traps Tab/Shift+Tab cycling within the popover
|
|
1165
|
+
* - Does **not** lock page scroll
|
|
1166
|
+
* - Does **not** block pointer interaction outside
|
|
1167
|
+
*
|
|
1168
|
+
* A `Popover.Close` part must be rendered inside the popup so that screen
|
|
1169
|
+
* readers can escape. It can be visually hidden if not needed visually.
|
|
1170
|
+
*
|
|
1171
|
+
* This replaces the legacy Popover's `constrainTabbing` prop. Try tabbing
|
|
1172
|
+
* through the fields — focus stays inside — then click the button outside
|
|
1173
|
+
* to verify that pointer interaction still works.
|
|
1174
|
+
*/
|
|
1175
|
+
export const TrapFocus: Story = {
|
|
1176
|
+
argTypes: { modal: { control: false } },
|
|
1177
|
+
args: {
|
|
1178
|
+
modal: 'trap-focus' as const,
|
|
1179
|
+
},
|
|
1180
|
+
render: function Render( args ) {
|
|
1181
|
+
return (
|
|
1182
|
+
<div style={ { display: 'flex', gap: '2rem' } }>
|
|
1183
|
+
<Popover.Root { ...args }>
|
|
1184
|
+
<Popover.Trigger>Open</Popover.Trigger>
|
|
1185
|
+
<Popover.Popup>
|
|
1186
|
+
<Popover.Arrow />
|
|
1187
|
+
<Popover.Title
|
|
1188
|
+
style={ {
|
|
1189
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
1190
|
+
} }
|
|
1191
|
+
>
|
|
1192
|
+
Trap Focus
|
|
1193
|
+
</Popover.Title>
|
|
1194
|
+
<Popover.Description>
|
|
1195
|
+
Tab cycles within this popover, but clicking outside
|
|
1196
|
+
still works.
|
|
1197
|
+
</Popover.Description>
|
|
1198
|
+
<div
|
|
1199
|
+
style={ {
|
|
1200
|
+
display: 'flex',
|
|
1201
|
+
gap: 'var(--wpds-dimension-gap-sm)',
|
|
1202
|
+
marginTop: 'var(--wpds-dimension-gap-sm)',
|
|
1203
|
+
} }
|
|
1204
|
+
>
|
|
1205
|
+
<input placeholder="Field A" />
|
|
1206
|
+
<input placeholder="Field B" />
|
|
1207
|
+
<Popover.Close>Close</Popover.Close>
|
|
1208
|
+
</div>
|
|
1209
|
+
</Popover.Popup>
|
|
1210
|
+
</Popover.Root>
|
|
1211
|
+
|
|
1212
|
+
<button
|
|
1213
|
+
type="button"
|
|
1214
|
+
onClick={ () =>
|
|
1215
|
+
// eslint-disable-next-line no-alert
|
|
1216
|
+
window.alert( 'Outside button clicked!' )
|
|
1217
|
+
}
|
|
1218
|
+
>
|
|
1219
|
+
Outside button
|
|
1220
|
+
</button>
|
|
1221
|
+
</div>
|
|
1222
|
+
);
|
|
1223
|
+
},
|
|
1224
|
+
};
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* Set `openOnHover` on `Popover.Trigger` to open the popover when the trigger
|
|
1228
|
+
* is hovered. The `delay` and `closeDelay` props control the timing (in ms).
|
|
1229
|
+
*
|
|
1230
|
+
* This is a capability the legacy Popover does not have natively — consumers
|
|
1231
|
+
* would need to wire up `mouseenter`/`mouseleave` handlers manually.
|
|
1232
|
+
*/
|
|
1233
|
+
export const HoverTrigger: Story = {
|
|
1234
|
+
parameters: { controls: { disable: true } },
|
|
1235
|
+
render: function Render( args ) {
|
|
1236
|
+
return (
|
|
1237
|
+
<Popover.Root { ...args }>
|
|
1238
|
+
<Popover.Trigger openOnHover delay={ 200 } closeDelay={ 150 }>
|
|
1239
|
+
Hover me
|
|
1240
|
+
</Popover.Trigger>
|
|
1241
|
+
<Popover.Popup>
|
|
1242
|
+
<Popover.Arrow />
|
|
1243
|
+
<Popover.Title
|
|
1244
|
+
style={ {
|
|
1245
|
+
marginBottom: 'var(--wpds-dimension-gap-xs)',
|
|
1246
|
+
} }
|
|
1247
|
+
>
|
|
1248
|
+
Hover Popover
|
|
1249
|
+
</Popover.Title>
|
|
1250
|
+
<Popover.Description>
|
|
1251
|
+
This popover opens on hover with a 200ms delay and
|
|
1252
|
+
closes 150ms after the pointer leaves.
|
|
1253
|
+
</Popover.Description>
|
|
1254
|
+
</Popover.Popup>
|
|
1255
|
+
</Popover.Root>
|
|
1256
|
+
);
|
|
1257
|
+
},
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* Popups that open when hovering an info icon should use Popover with the
|
|
1262
|
+
* `openOnHover` prop on the trigger instead of a tooltip. This way, touch
|
|
1263
|
+
* users and screen reader users can access the content.
|
|
1264
|
+
*
|
|
1265
|
+
* To know when to reach for a popover instead of a tooltip, consider the
|
|
1266
|
+
* purpose of the trigger element: If the trigger's purpose is to open the
|
|
1267
|
+
* popup itself, it's a popover. If the trigger's purpose is unrelated to
|
|
1268
|
+
* opening the popup, it's a tooltip.
|
|
1269
|
+
*/
|
|
1270
|
+
export const Infotip: Story = {
|
|
1271
|
+
parameters: { controls: { disable: true } },
|
|
1272
|
+
render: function Render( args ) {
|
|
1273
|
+
return (
|
|
1274
|
+
<div
|
|
1275
|
+
style={ {
|
|
1276
|
+
display: 'flex',
|
|
1277
|
+
alignItems: 'center',
|
|
1278
|
+
gap: 'var(--wpds-dimension-gap-xs)',
|
|
1279
|
+
} }
|
|
1280
|
+
>
|
|
1281
|
+
<span>Label</span>
|
|
1282
|
+
<Popover.Root { ...args }>
|
|
1283
|
+
<Popover.Trigger
|
|
1284
|
+
openOnHover
|
|
1285
|
+
delay={ 200 }
|
|
1286
|
+
closeDelay={ 200 }
|
|
1287
|
+
aria-label="More information"
|
|
1288
|
+
style={ {
|
|
1289
|
+
background: 'none',
|
|
1290
|
+
border: 'none',
|
|
1291
|
+
padding: 0,
|
|
1292
|
+
cursor: 'var(--wpds-cursor-control)',
|
|
1293
|
+
display: 'inline-flex',
|
|
1294
|
+
alignItems: 'center',
|
|
1295
|
+
borderRadius: 'var(--wpds-border-radius-sm)',
|
|
1296
|
+
} }
|
|
1297
|
+
>
|
|
1298
|
+
<Icon icon={ info } size={ 20 } />
|
|
1299
|
+
</Popover.Trigger>
|
|
1300
|
+
<Popover.Popup>
|
|
1301
|
+
<Popover.Arrow />
|
|
1302
|
+
<VisuallyHidden render={ <Popover.Title /> }>
|
|
1303
|
+
More information
|
|
1304
|
+
</VisuallyHidden>
|
|
1305
|
+
<Popover.Description>
|
|
1306
|
+
This is additional context about the label. Unlike
|
|
1307
|
+
tooltips, this content is accessible to touch and
|
|
1308
|
+
screen reader users.
|
|
1309
|
+
</Popover.Description>
|
|
1310
|
+
</Popover.Popup>
|
|
1311
|
+
</Popover.Root>
|
|
1312
|
+
</div>
|
|
1313
|
+
);
|
|
1314
|
+
},
|
|
1315
|
+
};
|