@wordpress/ui 0.8.0 → 0.9.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 +27 -0
- package/README.md +106 -0
- package/build/badge/badge.cjs +3 -3
- package/build/badge/badge.cjs.map +2 -2
- package/build/button/button.cjs +7 -7
- package/build/button/button.cjs.map +2 -2
- package/build/card/content.cjs +54 -0
- package/build/card/content.cjs.map +7 -0
- package/build/card/full-bleed.cjs +57 -0
- package/build/card/full-bleed.cjs.map +7 -0
- package/build/card/header.cjs +54 -0
- package/build/card/header.cjs.map +7 -0
- package/build/card/index.cjs +43 -0
- package/build/card/index.cjs.map +7 -0
- package/build/card/root.cjs +73 -0
- package/build/card/root.cjs.map +7 -0
- package/build/card/title.cjs +55 -0
- package/build/card/title.cjs.map +7 -0
- package/build/card/types.cjs +19 -0
- package/build/card/types.cjs.map +7 -0
- package/build/collapsible/index.cjs +37 -0
- package/build/collapsible/index.cjs.map +7 -0
- package/build/collapsible/panel.cjs +38 -0
- package/build/collapsible/panel.cjs.map +7 -0
- package/build/collapsible/root.cjs +38 -0
- package/build/collapsible/root.cjs.map +7 -0
- package/build/collapsible/trigger.cjs +38 -0
- package/build/collapsible/trigger.cjs.map +7 -0
- package/build/collapsible/types.cjs +19 -0
- package/build/collapsible/types.cjs.map +7 -0
- package/build/collapsible-card/content.cjs +77 -0
- package/build/collapsible-card/content.cjs.map +7 -0
- package/build/collapsible-card/header.cjs +102 -0
- package/build/collapsible-card/header.cjs.map +7 -0
- package/build/collapsible-card/index.cjs +37 -0
- package/build/collapsible-card/index.cjs.map +7 -0
- package/build/collapsible-card/root.cjs +56 -0
- package/build/collapsible-card/root.cjs.map +7 -0
- package/build/collapsible-card/types.cjs +19 -0
- package/build/collapsible-card/types.cjs.map +7 -0
- 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 +3 -3
- package/build/dialog/popup.cjs.map +2 -2
- package/build/dialog/title.cjs +3 -3
- package/build/dialog/title.cjs.map +2 -2
- package/build/dialog/types.cjs.map +1 -1
- package/build/form/primitives/field/label.cjs +6 -1
- package/build/form/primitives/field/label.cjs.map +2 -2
- package/build/form/primitives/field/types.cjs.map +1 -1
- package/build/form/primitives/fieldset/legend.cjs +5 -1
- package/build/form/primitives/fieldset/legend.cjs.map +2 -2
- package/build/form/primitives/fieldset/types.cjs.map +1 -1
- package/build/form/primitives/input/input.cjs +4 -4
- package/build/form/primitives/input/input.cjs.map +2 -2
- package/build/form/primitives/input-layout/slot.cjs +3 -2
- 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 +3 -3
- package/build/form/primitives/select/popup.cjs.map +2 -2
- package/build/form/primitives/select/trigger.cjs +7 -7
- package/build/form/primitives/select/trigger.cjs.map +2 -2
- package/build/index.cjs +13 -0
- package/build/index.cjs.map +2 -2
- package/build/link/index.cjs +31 -0
- package/build/link/index.cjs.map +7 -0
- package/build/link/link.cjs +125 -0
- package/build/link/link.cjs.map +7 -0
- package/build/link/types.cjs +19 -0
- package/build/link/types.cjs.map +7 -0
- package/build/notice/action-button.cjs +3 -3
- package/build/notice/action-button.cjs.map +2 -2
- package/build/notice/action-link.cjs +17 -18
- 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 +26 -15
- package/build/notice/description.cjs.map +3 -3
- package/build/notice/root.cjs +3 -3
- package/build/notice/root.cjs.map +2 -2
- package/build/notice/title.cjs +26 -12
- package/build/notice/title.cjs.map +3 -3
- package/build/notice/types.cjs.map +1 -1
- package/build/tabs/list.cjs +3 -3
- 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/index.cjs +31 -0
- package/build/text/index.cjs.map +7 -0
- package/build/text/text.cjs +65 -0
- package/build/text/text.cjs.map +7 -0
- package/build/text/types.cjs +19 -0
- package/build/text/types.cjs.map +7 -0
- package/build/tooltip/popup.cjs +1 -1
- package/build/tooltip/popup.cjs.map +1 -1
- package/build/visually-hidden/visually-hidden.cjs +3 -3
- package/build/visually-hidden/visually-hidden.cjs.map +2 -2
- package/build-module/badge/badge.mjs +3 -3
- package/build-module/badge/badge.mjs.map +2 -2
- package/build-module/button/button.mjs +7 -7
- package/build-module/button/button.mjs.map +2 -2
- package/build-module/card/content.mjs +29 -0
- package/build-module/card/content.mjs.map +7 -0
- package/build-module/card/full-bleed.mjs +32 -0
- package/build-module/card/full-bleed.mjs.map +7 -0
- package/build-module/card/header.mjs +29 -0
- package/build-module/card/header.mjs.map +7 -0
- package/build-module/card/index.mjs +14 -0
- package/build-module/card/index.mjs.map +7 -0
- package/build-module/card/root.mjs +38 -0
- package/build-module/card/root.mjs.map +7 -0
- package/build-module/card/title.mjs +30 -0
- package/build-module/card/title.mjs.map +7 -0
- package/build-module/card/types.mjs +1 -0
- package/build-module/card/types.mjs.map +7 -0
- package/build-module/collapsible/index.mjs +10 -0
- package/build-module/collapsible/index.mjs.map +7 -0
- package/build-module/collapsible/panel.mjs +13 -0
- package/build-module/collapsible/panel.mjs.map +7 -0
- package/build-module/collapsible/root.mjs +13 -0
- package/build-module/collapsible/root.mjs.map +7 -0
- package/build-module/collapsible/trigger.mjs +13 -0
- package/build-module/collapsible/trigger.mjs.map +7 -0
- package/build-module/collapsible/types.mjs +1 -0
- package/build-module/collapsible/types.mjs.map +7 -0
- package/build-module/collapsible-card/content.mjs +42 -0
- package/build-module/collapsible-card/content.mjs.map +7 -0
- package/build-module/collapsible-card/header.mjs +67 -0
- package/build-module/collapsible-card/header.mjs.map +7 -0
- package/build-module/collapsible-card/index.mjs +10 -0
- package/build-module/collapsible-card/index.mjs.map +7 -0
- package/build-module/collapsible-card/root.mjs +21 -0
- package/build-module/collapsible-card/root.mjs.map +7 -0
- package/build-module/collapsible-card/types.mjs +1 -0
- package/build-module/collapsible-card/types.mjs.map +7 -0
- 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 +3 -3
- package/build-module/dialog/popup.mjs.map +2 -2
- package/build-module/dialog/title.mjs +3 -3
- package/build-module/dialog/title.mjs.map +2 -2
- package/build-module/form/primitives/field/label.mjs +6 -1
- package/build-module/form/primitives/field/label.mjs.map +2 -2
- package/build-module/form/primitives/fieldset/legend.mjs +5 -1
- package/build-module/form/primitives/fieldset/legend.mjs.map +2 -2
- package/build-module/form/primitives/input/input.mjs +4 -4
- package/build-module/form/primitives/input/input.mjs.map +2 -2
- package/build-module/form/primitives/input-layout/slot.mjs +3 -2
- 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 +3 -3
- package/build-module/form/primitives/select/popup.mjs.map +2 -2
- package/build-module/form/primitives/select/trigger.mjs +7 -7
- package/build-module/form/primitives/select/trigger.mjs.map +2 -2
- package/build-module/index.mjs +8 -0
- package/build-module/index.mjs.map +2 -2
- package/build-module/link/index.mjs +6 -0
- package/build-module/link/index.mjs.map +7 -0
- package/build-module/link/link.mjs +90 -0
- package/build-module/link/link.mjs.map +7 -0
- package/build-module/link/types.mjs +1 -0
- package/build-module/link/types.mjs.map +7 -0
- 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 +17 -18
- 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 +16 -15
- 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 +16 -12
- package/build-module/notice/title.mjs.map +2 -2
- package/build-module/tabs/list.mjs +3 -3
- 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/index.mjs +6 -0
- package/build-module/text/index.mjs.map +7 -0
- package/build-module/text/text.mjs +30 -0
- package/build-module/text/text.mjs.map +7 -0
- package/build-module/text/types.mjs +1 -0
- package/build-module/text/types.mjs.map +7 -0
- package/build-module/tooltip/popup.mjs +1 -1
- package/build-module/tooltip/popup.mjs.map +1 -1
- package/build-module/visually-hidden/visually-hidden.mjs +3 -3
- package/build-module/visually-hidden/visually-hidden.mjs.map +2 -2
- package/build-types/card/content.d.ts +6 -0
- package/build-types/card/content.d.ts.map +1 -0
- package/build-types/card/full-bleed.d.ts +9 -0
- package/build-types/card/full-bleed.d.ts.map +1 -0
- package/build-types/card/header.d.ts +7 -0
- package/build-types/card/header.d.ts.map +1 -0
- package/build-types/card/index.d.ts +7 -0
- package/build-types/card/index.d.ts.map +1 -0
- package/build-types/card/root.d.ts +23 -0
- package/build-types/card/root.d.ts.map +1 -0
- package/build-types/card/stories/index.story.d.ts +22 -0
- package/build-types/card/stories/index.story.d.ts.map +1 -0
- package/build-types/card/test/index.test.d.ts +2 -0
- package/build-types/card/test/index.test.d.ts.map +1 -0
- package/build-types/card/title.d.ts +7 -0
- package/build-types/card/title.d.ts.map +1 -0
- package/build-types/card/types.d.ts +34 -0
- package/build-types/card/types.d.ts.map +1 -0
- package/build-types/collapsible/index.d.ts +5 -0
- package/build-types/collapsible/index.d.ts.map +1 -0
- package/build-types/collapsible/panel.d.ts +16 -0
- package/build-types/collapsible/panel.d.ts.map +1 -0
- package/build-types/collapsible/root.d.ts +15 -0
- package/build-types/collapsible/root.d.ts.map +1 -0
- package/build-types/collapsible/stories/index.story.d.ts +18 -0
- package/build-types/collapsible/stories/index.story.d.ts.map +1 -0
- package/build-types/collapsible/test/index.test.d.ts +2 -0
- package/build-types/collapsible/test/index.test.d.ts.map +1 -0
- package/build-types/collapsible/trigger.d.ts +15 -0
- package/build-types/collapsible/trigger.d.ts.map +1 -0
- package/build-types/collapsible/types.d.ts +22 -0
- package/build-types/collapsible/types.d.ts.map +1 -0
- package/build-types/collapsible-card/content.d.ts +7 -0
- package/build-types/collapsible-card/content.d.ts.map +1 -0
- package/build-types/collapsible-card/header.d.ts +12 -0
- package/build-types/collapsible-card/header.d.ts.map +1 -0
- package/build-types/collapsible-card/index.d.ts +5 -0
- package/build-types/collapsible-card/index.d.ts.map +1 -0
- package/build-types/collapsible-card/root.d.ts +24 -0
- package/build-types/collapsible-card/root.d.ts.map +1 -0
- package/build-types/collapsible-card/stories/index.story.d.ts +28 -0
- package/build-types/collapsible-card/stories/index.story.d.ts.map +1 -0
- package/build-types/collapsible-card/test/index.test.d.ts +2 -0
- package/build-types/collapsible-card/test/index.test.d.ts.map +1 -0
- package/build-types/collapsible-card/types.d.ts +52 -0
- package/build-types/collapsible-card/types.d.ts.map +1 -0
- package/build-types/dialog/types.d.ts +3 -3
- package/build-types/form/primitives/field/label.d.ts +1 -0
- package/build-types/form/primitives/field/label.d.ts.map +1 -1
- package/build-types/form/primitives/field/stories/index.story.d.ts +5 -0
- package/build-types/form/primitives/field/stories/index.story.d.ts.map +1 -1
- package/build-types/form/primitives/field/types.d.ts +7 -0
- package/build-types/form/primitives/field/types.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/legend.d.ts +1 -0
- package/build-types/form/primitives/fieldset/legend.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/stories/index.story.d.ts +5 -0
- package/build-types/form/primitives/fieldset/stories/index.story.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/types.d.ts +7 -0
- package/build-types/form/primitives/fieldset/types.d.ts.map +1 -1
- package/build-types/form/primitives/input-layout/slot.d.ts.map +1 -1
- package/build-types/index.d.ts +5 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/link/index.d.ts +2 -0
- package/build-types/link/index.d.ts.map +1 -0
- package/build-types/link/link.d.ts +7 -0
- package/build-types/link/link.d.ts.map +1 -0
- package/build-types/link/stories/index.story.d.ts +18 -0
- package/build-types/link/stories/index.story.d.ts.map +1 -0
- package/build-types/link/test/index.test.d.ts +2 -0
- package/build-types/link/test/index.test.d.ts.map +1 -0
- package/build-types/link/types.d.ts +33 -0
- package/build-types/link/types.d.ts.map +1 -0
- package/build-types/notice/action-link.d.ts +0 -2
- package/build-types/notice/action-link.d.ts.map +1 -1
- package/build-types/notice/description.d.ts +1 -1
- package/build-types/notice/description.d.ts.map +1 -1
- package/build-types/notice/title.d.ts.map +1 -1
- package/build-types/notice/types.d.ts +3 -2
- package/build-types/notice/types.d.ts.map +1 -1
- package/build-types/text/index.d.ts +2 -0
- package/build-types/text/index.d.ts.map +1 -0
- package/build-types/text/stories/index.story.d.ts +9 -0
- package/build-types/text/stories/index.story.d.ts.map +1 -0
- package/build-types/text/test/index.test.d.ts +2 -0
- package/build-types/text/test/index.test.d.ts.map +1 -0
- package/build-types/text/text.d.ts +7 -0
- package/build-types/text/text.d.ts.map +1 -0
- package/build-types/text/types.d.ts +15 -0
- package/build-types/text/types.d.ts.map +1 -0
- package/package.json +14 -14
- package/src/badge/style.module.css +5 -2
- package/src/button/style.module.css +2 -0
- package/src/card/content.tsx +20 -0
- package/src/card/full-bleed.tsx +26 -0
- package/src/card/header.tsx +21 -0
- package/src/card/index.ts +7 -0
- package/src/card/root.tsx +42 -0
- package/src/card/stories/index.story.tsx +128 -0
- package/src/card/style.module.css +48 -0
- package/src/card/test/index.test.tsx +96 -0
- package/src/card/title.tsx +22 -0
- package/src/card/types.ts +38 -0
- package/src/collapsible/index.ts +5 -0
- package/src/collapsible/panel.tsx +16 -0
- package/src/collapsible/root.tsx +15 -0
- package/src/collapsible/stories/index.story.tsx +108 -0
- package/src/collapsible/test/index.test.tsx +228 -0
- package/src/collapsible/trigger.tsx +15 -0
- package/src/collapsible/types.ts +24 -0
- package/src/collapsible-card/content.tsx +33 -0
- package/src/collapsible-card/header.tsx +53 -0
- package/src/collapsible-card/index.ts +5 -0
- package/src/collapsible-card/root.tsx +37 -0
- package/src/collapsible-card/stories/index.story.tsx +207 -0
- package/src/collapsible-card/style.module.css +78 -0
- package/src/collapsible-card/test/index.test.tsx +181 -0
- package/src/collapsible-card/types.ts +54 -0
- package/src/dialog/style.module.css +5 -5
- package/src/dialog/types.ts +3 -3
- package/src/form/primitives/field/label.tsx +9 -1
- package/src/form/primitives/field/stories/index.story.tsx +17 -0
- package/src/form/primitives/field/test/index.test.tsx +13 -0
- package/src/form/primitives/field/types.ts +7 -0
- package/src/form/primitives/fieldset/legend.tsx +8 -1
- package/src/form/primitives/fieldset/stories/index.story.tsx +20 -0
- package/src/form/primitives/fieldset/test/index.test.tsx +14 -0
- package/src/form/primitives/fieldset/types.ts +7 -0
- package/src/form/primitives/input-layout/slot.tsx +6 -2
- package/src/index.ts +5 -0
- package/src/link/index.ts +1 -0
- package/src/link/link.tsx +73 -0
- package/src/link/stories/index.story.tsx +92 -0
- package/src/link/style.module.css +68 -0
- package/src/link/test/index.test.tsx +93 -0
- package/src/link/types.ts +36 -0
- package/src/notice/action-link.tsx +12 -18
- package/src/notice/description.tsx +12 -14
- package/src/notice/style.module.css +9 -22
- package/src/notice/test/index.test.tsx +2 -2
- package/src/notice/title.tsx +11 -10
- package/src/notice/types.ts +3 -2
- package/src/tabs/style.module.css +1 -1
- package/src/text/index.ts +1 -0
- package/src/text/stories/index.story.tsx +68 -0
- package/src/text/style.module.css +67 -0
- package/src/text/test/index.test.tsx +46 -0
- package/src/text/text.tsx +25 -0
- package/src/text/types.ts +25 -0
- package/src/tooltip/popup.tsx +1 -1
- package/src/utils/css/focus.module.css +4 -2
- package/src/utils/css/item-popup.module.css +1 -0
- package/src/utils/css/select-trigger.module.css +1 -0
- package/src/visually-hidden/style.module.css +1 -0
- package/AGENTS.md +0 -9
- package/CLAUDE.md +0 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { userEvent } from '@testing-library/user-event';
|
|
3
|
+
import { createRef, useState } from '@wordpress/element';
|
|
4
|
+
import * as Collapsible from '../index';
|
|
5
|
+
|
|
6
|
+
function UncontrolledCollapsible( {
|
|
7
|
+
defaultOpen,
|
|
8
|
+
disabled,
|
|
9
|
+
}: {
|
|
10
|
+
defaultOpen?: boolean;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
} ) {
|
|
13
|
+
return (
|
|
14
|
+
<Collapsible.Root defaultOpen={ defaultOpen } disabled={ disabled }>
|
|
15
|
+
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
16
|
+
<Collapsible.Panel>Panel content</Collapsible.Panel>
|
|
17
|
+
</Collapsible.Root>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function ControlledCollapsible( {
|
|
22
|
+
onOpenChange,
|
|
23
|
+
}: {
|
|
24
|
+
onOpenChange?: ( open: boolean ) => void;
|
|
25
|
+
} ) {
|
|
26
|
+
const [ open, setOpen ] = useState( false );
|
|
27
|
+
return (
|
|
28
|
+
<Collapsible.Root
|
|
29
|
+
open={ open }
|
|
30
|
+
onOpenChange={ ( nextOpen ) => {
|
|
31
|
+
setOpen( nextOpen );
|
|
32
|
+
onOpenChange?.( nextOpen );
|
|
33
|
+
} }
|
|
34
|
+
>
|
|
35
|
+
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
36
|
+
<Collapsible.Panel>Controlled panel</Collapsible.Panel>
|
|
37
|
+
</Collapsible.Root>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe( 'Collapsible', () => {
|
|
42
|
+
describe( 'ref forwarding', () => {
|
|
43
|
+
it( 'forwards ref on Root', () => {
|
|
44
|
+
const ref = createRef< HTMLDivElement >();
|
|
45
|
+
render(
|
|
46
|
+
<Collapsible.Root ref={ ref }>
|
|
47
|
+
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
48
|
+
<Collapsible.Panel>Content</Collapsible.Panel>
|
|
49
|
+
</Collapsible.Root>
|
|
50
|
+
);
|
|
51
|
+
expect( ref.current ).toBeInstanceOf( HTMLDivElement );
|
|
52
|
+
} );
|
|
53
|
+
|
|
54
|
+
it( 'forwards ref on Trigger', () => {
|
|
55
|
+
const ref = createRef< HTMLButtonElement >();
|
|
56
|
+
render(
|
|
57
|
+
<Collapsible.Root>
|
|
58
|
+
<Collapsible.Trigger ref={ ref }>
|
|
59
|
+
Toggle
|
|
60
|
+
</Collapsible.Trigger>
|
|
61
|
+
<Collapsible.Panel>Content</Collapsible.Panel>
|
|
62
|
+
</Collapsible.Root>
|
|
63
|
+
);
|
|
64
|
+
expect( ref.current ).toBeInstanceOf( HTMLButtonElement );
|
|
65
|
+
} );
|
|
66
|
+
|
|
67
|
+
it( 'forwards ref on Panel', () => {
|
|
68
|
+
const ref = createRef< HTMLDivElement >();
|
|
69
|
+
render(
|
|
70
|
+
<Collapsible.Root defaultOpen>
|
|
71
|
+
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
72
|
+
<Collapsible.Panel ref={ ref }>Content</Collapsible.Panel>
|
|
73
|
+
</Collapsible.Root>
|
|
74
|
+
);
|
|
75
|
+
expect( ref.current ).toBeInstanceOf( HTMLDivElement );
|
|
76
|
+
} );
|
|
77
|
+
} );
|
|
78
|
+
|
|
79
|
+
describe( 'uncontrolled', () => {
|
|
80
|
+
it( 'is collapsed by default', () => {
|
|
81
|
+
render( <UncontrolledCollapsible /> );
|
|
82
|
+
expect(
|
|
83
|
+
screen.queryByText( 'Panel content' )
|
|
84
|
+
).not.toBeInTheDocument();
|
|
85
|
+
} );
|
|
86
|
+
|
|
87
|
+
it( 'shows panel when defaultOpen is true', () => {
|
|
88
|
+
render( <UncontrolledCollapsible defaultOpen /> );
|
|
89
|
+
expect( screen.getByText( 'Panel content' ) ).toBeVisible();
|
|
90
|
+
} );
|
|
91
|
+
|
|
92
|
+
it( 'toggles panel on trigger click', async () => {
|
|
93
|
+
const user = userEvent.setup();
|
|
94
|
+
render( <UncontrolledCollapsible /> );
|
|
95
|
+
|
|
96
|
+
expect(
|
|
97
|
+
screen.queryByText( 'Panel content' )
|
|
98
|
+
).not.toBeInTheDocument();
|
|
99
|
+
|
|
100
|
+
await user.click(
|
|
101
|
+
screen.getByRole( 'button', { name: 'Toggle' } )
|
|
102
|
+
);
|
|
103
|
+
expect( screen.getByText( 'Panel content' ) ).toBeVisible();
|
|
104
|
+
|
|
105
|
+
await user.click(
|
|
106
|
+
screen.getByRole( 'button', { name: 'Toggle' } )
|
|
107
|
+
);
|
|
108
|
+
expect(
|
|
109
|
+
screen.queryByText( 'Panel content' )
|
|
110
|
+
).not.toBeInTheDocument();
|
|
111
|
+
} );
|
|
112
|
+
} );
|
|
113
|
+
|
|
114
|
+
describe( 'controlled', () => {
|
|
115
|
+
it( 'calls onOpenChange when toggled', async () => {
|
|
116
|
+
const onOpenChange = jest.fn();
|
|
117
|
+
const user = userEvent.setup();
|
|
118
|
+
|
|
119
|
+
render( <ControlledCollapsible onOpenChange={ onOpenChange } /> );
|
|
120
|
+
|
|
121
|
+
await user.click(
|
|
122
|
+
screen.getByRole( 'button', { name: 'Toggle' } )
|
|
123
|
+
);
|
|
124
|
+
expect( onOpenChange ).toHaveBeenCalledWith( true );
|
|
125
|
+
|
|
126
|
+
await user.click(
|
|
127
|
+
screen.getByRole( 'button', { name: 'Toggle' } )
|
|
128
|
+
);
|
|
129
|
+
expect( onOpenChange ).toHaveBeenCalledWith( false );
|
|
130
|
+
} );
|
|
131
|
+
} );
|
|
132
|
+
|
|
133
|
+
describe( 'disabled', () => {
|
|
134
|
+
it( 'does not toggle when disabled', async () => {
|
|
135
|
+
const user = userEvent.setup();
|
|
136
|
+
render( <UncontrolledCollapsible defaultOpen disabled /> );
|
|
137
|
+
|
|
138
|
+
expect( screen.getByText( 'Panel content' ) ).toBeVisible();
|
|
139
|
+
|
|
140
|
+
await user.click(
|
|
141
|
+
screen.getByRole( 'button', { name: 'Toggle' } )
|
|
142
|
+
);
|
|
143
|
+
expect( screen.getByText( 'Panel content' ) ).toBeVisible();
|
|
144
|
+
} );
|
|
145
|
+
} );
|
|
146
|
+
|
|
147
|
+
describe( 'render prop', () => {
|
|
148
|
+
it( 'supports render prop on Root', () => {
|
|
149
|
+
const ref = createRef< HTMLDivElement >();
|
|
150
|
+
render(
|
|
151
|
+
<Collapsible.Root ref={ ref } render={ <section /> }>
|
|
152
|
+
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
153
|
+
<Collapsible.Panel>Content</Collapsible.Panel>
|
|
154
|
+
</Collapsible.Root>
|
|
155
|
+
);
|
|
156
|
+
expect( ref.current?.tagName ).toBe( 'SECTION' );
|
|
157
|
+
} );
|
|
158
|
+
|
|
159
|
+
it( 'supports render prop on Trigger', () => {
|
|
160
|
+
render(
|
|
161
|
+
<Collapsible.Root>
|
|
162
|
+
<Collapsible.Trigger
|
|
163
|
+
nativeButton={ false }
|
|
164
|
+
render={ <div /> }
|
|
165
|
+
>
|
|
166
|
+
Toggle
|
|
167
|
+
</Collapsible.Trigger>
|
|
168
|
+
<Collapsible.Panel>Content</Collapsible.Panel>
|
|
169
|
+
</Collapsible.Root>
|
|
170
|
+
);
|
|
171
|
+
const trigger = screen.getByRole( 'button', { name: 'Toggle' } );
|
|
172
|
+
expect( trigger.tagName ).toBe( 'DIV' );
|
|
173
|
+
} );
|
|
174
|
+
|
|
175
|
+
it( 'supports render prop on Panel', () => {
|
|
176
|
+
const ref = createRef< HTMLDivElement >();
|
|
177
|
+
render(
|
|
178
|
+
<Collapsible.Root defaultOpen>
|
|
179
|
+
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
180
|
+
<Collapsible.Panel ref={ ref } render={ <section /> }>
|
|
181
|
+
Content
|
|
182
|
+
</Collapsible.Panel>
|
|
183
|
+
</Collapsible.Root>
|
|
184
|
+
);
|
|
185
|
+
expect( ref.current?.tagName ).toBe( 'SECTION' );
|
|
186
|
+
} );
|
|
187
|
+
} );
|
|
188
|
+
|
|
189
|
+
describe( 'custom className', () => {
|
|
190
|
+
it( 'applies className to Root', () => {
|
|
191
|
+
const ref = createRef< HTMLDivElement >();
|
|
192
|
+
render(
|
|
193
|
+
<Collapsible.Root ref={ ref } className="custom-root">
|
|
194
|
+
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
195
|
+
<Collapsible.Panel>Content</Collapsible.Panel>
|
|
196
|
+
</Collapsible.Root>
|
|
197
|
+
);
|
|
198
|
+
expect( ref.current ).toHaveClass( 'custom-root' );
|
|
199
|
+
} );
|
|
200
|
+
|
|
201
|
+
it( 'applies className to Trigger', () => {
|
|
202
|
+
render(
|
|
203
|
+
<Collapsible.Root>
|
|
204
|
+
<Collapsible.Trigger className="custom-trigger">
|
|
205
|
+
Toggle
|
|
206
|
+
</Collapsible.Trigger>
|
|
207
|
+
<Collapsible.Panel>Content</Collapsible.Panel>
|
|
208
|
+
</Collapsible.Root>
|
|
209
|
+
);
|
|
210
|
+
expect(
|
|
211
|
+
screen.getByRole( 'button', { name: 'Toggle' } )
|
|
212
|
+
).toHaveClass( 'custom-trigger' );
|
|
213
|
+
} );
|
|
214
|
+
|
|
215
|
+
it( 'applies className to Panel', () => {
|
|
216
|
+
const ref = createRef< HTMLDivElement >();
|
|
217
|
+
render(
|
|
218
|
+
<Collapsible.Root defaultOpen>
|
|
219
|
+
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
220
|
+
<Collapsible.Panel ref={ ref } className="custom-panel">
|
|
221
|
+
Content
|
|
222
|
+
</Collapsible.Panel>
|
|
223
|
+
</Collapsible.Root>
|
|
224
|
+
);
|
|
225
|
+
expect( ref.current ).toHaveClass( 'custom-panel' );
|
|
226
|
+
} );
|
|
227
|
+
} );
|
|
228
|
+
} );
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Collapsible as _Collapsible } from '@base-ui/react/collapsible';
|
|
2
|
+
import { forwardRef } from '@wordpress/element';
|
|
3
|
+
import type { TriggerProps } from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A button that opens and closes the collapsible panel.
|
|
7
|
+
*
|
|
8
|
+
* `Collapsible` is a collection of React components that combine to render
|
|
9
|
+
* a collapsible panel controlled by a button.
|
|
10
|
+
*/
|
|
11
|
+
export const Trigger = forwardRef< HTMLButtonElement, TriggerProps >(
|
|
12
|
+
function CollapsibleTrigger( props, forwardedRef ) {
|
|
13
|
+
return <_Collapsible.Trigger ref={ forwardedRef } { ...props } />;
|
|
14
|
+
}
|
|
15
|
+
);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { Collapsible as _Collapsible } from '@base-ui/react/collapsible';
|
|
3
|
+
import type { ComponentProps } from '../utils/types';
|
|
4
|
+
|
|
5
|
+
export type RootProps = ComponentProps< typeof _Collapsible.Root > & {
|
|
6
|
+
/**
|
|
7
|
+
* The content to be rendered inside the component.
|
|
8
|
+
*/
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type TriggerProps = ComponentProps< typeof _Collapsible.Trigger > & {
|
|
13
|
+
/**
|
|
14
|
+
* The content to be rendered inside the component.
|
|
15
|
+
*/
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type PanelProps = ComponentProps< typeof _Collapsible.Panel > & {
|
|
20
|
+
/**
|
|
21
|
+
* The content to be rendered inside the component.
|
|
22
|
+
*/
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { forwardRef } from '@wordpress/element';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import * as Card from '../card';
|
|
4
|
+
import * as Collapsible from '../collapsible';
|
|
5
|
+
import styles from './style.module.css';
|
|
6
|
+
import type { ContentProps } from './types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The collapsible content area of the card. Hidden when collapsed,
|
|
10
|
+
* visible when expanded.
|
|
11
|
+
*/
|
|
12
|
+
export const Content = forwardRef< HTMLDivElement, ContentProps >(
|
|
13
|
+
function CollapsibleCardContent(
|
|
14
|
+
{ className, render, children, hiddenUntilFound = true, ...restProps },
|
|
15
|
+
ref
|
|
16
|
+
) {
|
|
17
|
+
return (
|
|
18
|
+
<Collapsible.Panel
|
|
19
|
+
ref={ ref }
|
|
20
|
+
className={ clsx( styles.content, className ) }
|
|
21
|
+
hiddenUntilFound={ hiddenUntilFound }
|
|
22
|
+
{ ...restProps }
|
|
23
|
+
>
|
|
24
|
+
<Card.Content
|
|
25
|
+
className={ styles[ 'content-inner' ] }
|
|
26
|
+
render={ render }
|
|
27
|
+
>
|
|
28
|
+
{ children }
|
|
29
|
+
</Card.Content>
|
|
30
|
+
</Collapsible.Panel>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { forwardRef } from '@wordpress/element';
|
|
3
|
+
import { chevronDown } from '@wordpress/icons';
|
|
4
|
+
import * as Card from '../card';
|
|
5
|
+
import * as Collapsible from '../collapsible';
|
|
6
|
+
import { Icon } from '../icon';
|
|
7
|
+
import styles from './style.module.css';
|
|
8
|
+
import focusStyles from '../utils/css/focus.module.css';
|
|
9
|
+
import type { HeaderProps } from './types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The header of a collapsible card. Always visible, and acts as the
|
|
13
|
+
* toggle trigger — clicking anywhere on it expands or collapses the
|
|
14
|
+
* card's content.
|
|
15
|
+
*
|
|
16
|
+
* Avoid placing interactive elements (buttons, links, inputs) inside the
|
|
17
|
+
* header, since the entire area is clickable and their events will bubble
|
|
18
|
+
* to trigger the collapse toggle.
|
|
19
|
+
*/
|
|
20
|
+
export const Header = forwardRef< HTMLDivElement, HeaderProps >(
|
|
21
|
+
function CollapsibleCardHeader(
|
|
22
|
+
{ children, className, render, ...restProps },
|
|
23
|
+
ref
|
|
24
|
+
) {
|
|
25
|
+
return (
|
|
26
|
+
<Collapsible.Trigger
|
|
27
|
+
className={ clsx( styles.header, className ) }
|
|
28
|
+
render={
|
|
29
|
+
<Card.Header
|
|
30
|
+
ref={ ref }
|
|
31
|
+
render={ render }
|
|
32
|
+
{ ...restProps }
|
|
33
|
+
/>
|
|
34
|
+
}
|
|
35
|
+
nativeButton={ false }
|
|
36
|
+
>
|
|
37
|
+
<div className={ styles[ 'header-content' ] }>{ children }</div>
|
|
38
|
+
<div className={ styles[ 'header-trigger-wrapper' ] }>
|
|
39
|
+
<Icon
|
|
40
|
+
icon={ chevronDown }
|
|
41
|
+
className={ clsx(
|
|
42
|
+
styles[ 'header-trigger' ],
|
|
43
|
+
// While the interactive trigger element is the whole header,
|
|
44
|
+
// the focus ring will be displayed only on the icon to visually
|
|
45
|
+
// emulate it being the button.
|
|
46
|
+
focusStyles[ 'outset-ring--focus-parent-visible' ]
|
|
47
|
+
) }
|
|
48
|
+
/>
|
|
49
|
+
</div>
|
|
50
|
+
</Collapsible.Trigger>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { forwardRef } from '@wordpress/element';
|
|
2
|
+
import * as Card from '../card';
|
|
3
|
+
import * as Collapsible from '../collapsible';
|
|
4
|
+
import type { RootProps } from './types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A card that can be expanded and collapsed. When collapsed, only the
|
|
8
|
+
* header is visible.
|
|
9
|
+
*
|
|
10
|
+
* ```jsx
|
|
11
|
+
* import { CollapsibleCard, Card } from '@wordpress/ui';
|
|
12
|
+
*
|
|
13
|
+
* function MyComponent() {
|
|
14
|
+
* return (
|
|
15
|
+
* <CollapsibleCard.Root defaultOpen>
|
|
16
|
+
* <CollapsibleCard.Header>
|
|
17
|
+
* <Card.Title>Heading</Card.Title>
|
|
18
|
+
* </CollapsibleCard.Header>
|
|
19
|
+
* <CollapsibleCard.Content>
|
|
20
|
+
* <p>Collapsible content here.</p>
|
|
21
|
+
* </CollapsibleCard.Content>
|
|
22
|
+
* </CollapsibleCard.Root>
|
|
23
|
+
* );
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export const Root = forwardRef< HTMLDivElement, RootProps >(
|
|
28
|
+
function CollapsibleCardRoot( { render, ...restProps }, ref ) {
|
|
29
|
+
return (
|
|
30
|
+
<Collapsible.Root
|
|
31
|
+
ref={ ref }
|
|
32
|
+
render={ <Card.Root render={ render } /> }
|
|
33
|
+
{ ...restProps }
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
);
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import * as Card from '../../card';
|
|
3
|
+
import * as CollapsibleCard from '../index';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Temporary text component for story examples. This will be replaced by an
|
|
7
|
+
* official DS `<Text />` component once it's available.
|
|
8
|
+
*/
|
|
9
|
+
function Text( { children }: { children: React.ReactNode } ) {
|
|
10
|
+
return (
|
|
11
|
+
<p
|
|
12
|
+
style={ {
|
|
13
|
+
margin: 0,
|
|
14
|
+
fontFamily: 'var(--wpds-font-family-body)',
|
|
15
|
+
fontSize: 'var(--wpds-font-size-md)',
|
|
16
|
+
fontWeight: 'var(--wpds-font-weight-regular)',
|
|
17
|
+
lineHeight: 'var(--wpds-font-line-height-sm)',
|
|
18
|
+
textWrap: 'pretty',
|
|
19
|
+
color: 'var(--wpds-color-fg-content-neutral-weak)',
|
|
20
|
+
} }
|
|
21
|
+
>
|
|
22
|
+
{ children }
|
|
23
|
+
</p>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const meta: Meta< typeof CollapsibleCard.Root > = {
|
|
28
|
+
title: 'Design System/Components/CollapsibleCard',
|
|
29
|
+
component: CollapsibleCard.Root,
|
|
30
|
+
subcomponents: {
|
|
31
|
+
'CollapsibleCard.Header': CollapsibleCard.Header,
|
|
32
|
+
'CollapsibleCard.Content': CollapsibleCard.Content,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
export default meta;
|
|
36
|
+
|
|
37
|
+
type Story = StoryObj< typeof CollapsibleCard.Root >;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A collapsible card that is open by default.
|
|
41
|
+
*/
|
|
42
|
+
export const Default: Story = {
|
|
43
|
+
args: {
|
|
44
|
+
children: (
|
|
45
|
+
<>
|
|
46
|
+
<CollapsibleCard.Header>
|
|
47
|
+
<Card.Title>
|
|
48
|
+
Collapsible card (closed by default)
|
|
49
|
+
</Card.Title>
|
|
50
|
+
</CollapsibleCard.Header>
|
|
51
|
+
<CollapsibleCard.Content>
|
|
52
|
+
<Text>
|
|
53
|
+
This is the collapsible content area. It can contain any
|
|
54
|
+
elements, just like a regular Card.Content.
|
|
55
|
+
</Text>
|
|
56
|
+
<Text>
|
|
57
|
+
When collapsed, only the header and chevron are visible.
|
|
58
|
+
</Text>
|
|
59
|
+
</CollapsibleCard.Content>
|
|
60
|
+
</>
|
|
61
|
+
),
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* A collapsible card that starts collapsed.
|
|
67
|
+
*/
|
|
68
|
+
export const InitiallyOpened: Story = {
|
|
69
|
+
// `defaultOpen` (uncontrolled) and `open` (controlled) should not be
|
|
70
|
+
// used together — disable the `open` control to avoid confusion.
|
|
71
|
+
argTypes: { open: { control: false } },
|
|
72
|
+
args: {
|
|
73
|
+
...Default.args,
|
|
74
|
+
defaultOpen: true,
|
|
75
|
+
children: (
|
|
76
|
+
<>
|
|
77
|
+
<CollapsibleCard.Header>
|
|
78
|
+
<Card.Title>Collapsed by default</Card.Title>
|
|
79
|
+
</CollapsibleCard.Header>
|
|
80
|
+
<CollapsibleCard.Content>
|
|
81
|
+
<Text>This content was hidden until you expanded it.</Text>
|
|
82
|
+
</CollapsibleCard.Content>
|
|
83
|
+
</>
|
|
84
|
+
),
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* A disabled collapsible card cannot be toggled by the user.
|
|
90
|
+
*/
|
|
91
|
+
export const Disabled: Story = {
|
|
92
|
+
args: {
|
|
93
|
+
...Default.args,
|
|
94
|
+
disabled: true,
|
|
95
|
+
children: (
|
|
96
|
+
<>
|
|
97
|
+
<CollapsibleCard.Header>
|
|
98
|
+
<Card.Title>Disabled card</Card.Title>
|
|
99
|
+
</CollapsibleCard.Header>
|
|
100
|
+
<CollapsibleCard.Content>
|
|
101
|
+
<Text>The header is not interactive when disabled.</Text>
|
|
102
|
+
</CollapsibleCard.Content>
|
|
103
|
+
</>
|
|
104
|
+
),
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Multiple collapsible cards stacked vertically, simulating a typical
|
|
110
|
+
* settings-panel or FAQ-style layout.
|
|
111
|
+
*/
|
|
112
|
+
export const Stacked: Story = {
|
|
113
|
+
parameters: { controls: { disable: true } },
|
|
114
|
+
render: () => (
|
|
115
|
+
<div
|
|
116
|
+
style={ {
|
|
117
|
+
display: 'flex',
|
|
118
|
+
flexDirection: 'column',
|
|
119
|
+
gap: 'var(--wpds-dimension-gap-lg)',
|
|
120
|
+
} }
|
|
121
|
+
>
|
|
122
|
+
{ [
|
|
123
|
+
'General',
|
|
124
|
+
'Advanced',
|
|
125
|
+
'Accessibility',
|
|
126
|
+
'Performance',
|
|
127
|
+
'Privacy',
|
|
128
|
+
'Notifications',
|
|
129
|
+
].map( ( title ) => (
|
|
130
|
+
<CollapsibleCard.Root key={ title }>
|
|
131
|
+
<CollapsibleCard.Header>
|
|
132
|
+
<Card.Title>{ title }</Card.Title>
|
|
133
|
+
</CollapsibleCard.Header>
|
|
134
|
+
<CollapsibleCard.Content>
|
|
135
|
+
<Text>
|
|
136
|
+
Configure all { title.toLowerCase() } settings for
|
|
137
|
+
your site. Changes here affect how your site behaves
|
|
138
|
+
across all pages and posts.
|
|
139
|
+
</Text>
|
|
140
|
+
<Text>
|
|
141
|
+
Review each option carefully before saving. Some
|
|
142
|
+
changes may require a page reload to take effect.
|
|
143
|
+
Hover over individual options for more details about
|
|
144
|
+
what they control.
|
|
145
|
+
</Text>
|
|
146
|
+
<Text>
|
|
147
|
+
If you're unsure about a setting, you can
|
|
148
|
+
always reset to defaults using the button at the
|
|
149
|
+
bottom of this section. Your previous configuration
|
|
150
|
+
will be saved as a backup.
|
|
151
|
+
</Text>
|
|
152
|
+
</CollapsibleCard.Content>
|
|
153
|
+
</CollapsibleCard.Root>
|
|
154
|
+
) ) }
|
|
155
|
+
</div>
|
|
156
|
+
),
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Visual comparison: a `CollapsibleCard` (open) next to a regular `Card`
|
|
161
|
+
* to verify identical spacing and layout.
|
|
162
|
+
*/
|
|
163
|
+
export const ComparedToCard: Story = {
|
|
164
|
+
// `defaultOpen` (uncontrolled) and `open` (controlled) should not be
|
|
165
|
+
// used together — disable the `open` control to avoid confusion.
|
|
166
|
+
argTypes: { open: { control: false } },
|
|
167
|
+
args: {
|
|
168
|
+
...Default.args,
|
|
169
|
+
defaultOpen: true,
|
|
170
|
+
},
|
|
171
|
+
render: ( { open, defaultOpen, onOpenChange, disabled, ...restArgs } ) => (
|
|
172
|
+
<div
|
|
173
|
+
style={ {
|
|
174
|
+
display: 'flex',
|
|
175
|
+
flexDirection: 'column',
|
|
176
|
+
gap: 'var( --wpds-dimension-gap-lg )',
|
|
177
|
+
} }
|
|
178
|
+
>
|
|
179
|
+
<CollapsibleCard.Root
|
|
180
|
+
open={ open }
|
|
181
|
+
defaultOpen={ defaultOpen }
|
|
182
|
+
onOpenChange={ onOpenChange }
|
|
183
|
+
disabled={ disabled }
|
|
184
|
+
{ ...restArgs }
|
|
185
|
+
>
|
|
186
|
+
<CollapsibleCard.Header>
|
|
187
|
+
<Card.Title>CollapsibleCard (open)</Card.Title>
|
|
188
|
+
</CollapsibleCard.Header>
|
|
189
|
+
<CollapsibleCard.Content>
|
|
190
|
+
<Text>
|
|
191
|
+
Content should align with the regular card below.
|
|
192
|
+
</Text>
|
|
193
|
+
</CollapsibleCard.Content>
|
|
194
|
+
</CollapsibleCard.Root>
|
|
195
|
+
<Card.Root { ...restArgs }>
|
|
196
|
+
<Card.Header>
|
|
197
|
+
<Card.Title>Regular Card</Card.Title>
|
|
198
|
+
</Card.Header>
|
|
199
|
+
<Card.Content>
|
|
200
|
+
<Text>
|
|
201
|
+
Content should align with the collapsible card above.
|
|
202
|
+
</Text>
|
|
203
|
+
</Card.Content>
|
|
204
|
+
</Card.Root>
|
|
205
|
+
</div>
|
|
206
|
+
),
|
|
207
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
@layer wp-ui-utilities, wp-ui-components, wp-ui-compositions, wp-ui-overrides;
|
|
2
|
+
|
|
3
|
+
@layer wp-ui-components {
|
|
4
|
+
.header-content {
|
|
5
|
+
flex: 1;
|
|
6
|
+
min-width: 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.header-trigger-wrapper {
|
|
10
|
+
flex-shrink: 0;
|
|
11
|
+
align-self: center;
|
|
12
|
+
/* Prevent the trigger from making the header taller than its content,
|
|
13
|
+
preserving the same metrics between `Card` and `CollapsibleCard`. */
|
|
14
|
+
max-height: 0;
|
|
15
|
+
overflow: visible;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.header-trigger {
|
|
19
|
+
/* Offset by half the button's own height so it visually centers
|
|
20
|
+
at the wrapper's midpoint (which `align-self: center` places at
|
|
21
|
+
the vertical center of the header). */
|
|
22
|
+
translate: 0 -50%;
|
|
23
|
+
|
|
24
|
+
/* For an outline that looks like `IconButton`'s */
|
|
25
|
+
border-radius: var(--wpds-border-radius-sm);
|
|
26
|
+
|
|
27
|
+
@media not (prefers-reduced-motion) {
|
|
28
|
+
transition: rotate 0.15s ease-out;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.header[data-panel-open] .header-trigger {
|
|
33
|
+
rotate: 180deg;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Simulate disabled button styles */
|
|
37
|
+
.header[data-disabled] .header-trigger {
|
|
38
|
+
color: var(--wpds-color-fg-interactive-neutral-disabled);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.content {
|
|
42
|
+
height: var(--collapsible-panel-height);
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
margin-block-start: var(--wp-ui-card-header-content-margin);
|
|
45
|
+
|
|
46
|
+
&[hidden]:not([hidden="until-found"]) {
|
|
47
|
+
display: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&[data-starting-style],
|
|
51
|
+
&[data-ending-style] {
|
|
52
|
+
height: 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@media not (prefers-reduced-motion) {
|
|
56
|
+
transition: all 150ms ease-out;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@layer wp-ui-compositions {
|
|
63
|
+
.content-inner {
|
|
64
|
+
padding-block-start: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.header {
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-direction: row;
|
|
70
|
+
align-items: stretch;
|
|
71
|
+
gap: var(--wpds-dimension-gap-sm);
|
|
72
|
+
outline: none;
|
|
73
|
+
|
|
74
|
+
&:not([data-disabled]) {
|
|
75
|
+
cursor: var(--wpds-cursor-control);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|