@wordpress/ui 0.4.0 → 0.5.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 +20 -0
- package/LICENSE.md +1 -1
- package/README.md +18 -0
- package/build/badge/badge.cjs +95 -0
- package/build/badge/badge.cjs.map +7 -0
- package/build/{lock-unlock.js → badge/index.cjs} +8 -14
- package/build/badge/index.cjs.map +7 -0
- package/build/badge/types.cjs +19 -0
- package/build/badge/types.cjs.map +7 -0
- package/build/box/{box.js → box.cjs} +7 -6
- package/build/box/box.cjs.map +7 -0
- package/build/box/{index.js → index.cjs} +2 -2
- package/build/box/{types.js → types.cjs} +1 -1
- package/build/box/types.cjs.map +7 -0
- package/build/button/button.cjs +401 -0
- package/build/button/button.cjs.map +7 -0
- package/build/{utils/element.js → button/icon.cjs} +22 -20
- package/build/button/icon.cjs.map +7 -0
- package/build/button/index.cjs +39 -0
- package/build/button/index.cjs.map +7 -0
- package/build/button/types.cjs +19 -0
- package/build/button/types.cjs.map +7 -0
- package/build/form/primitives/field/control.cjs +38 -0
- package/build/form/primitives/field/control.cjs.map +7 -0
- package/build/form/primitives/field/description.cjs +92 -0
- package/build/form/primitives/field/description.cjs.map +7 -0
- package/build/form/primitives/field/details.cjs +99 -0
- package/build/form/primitives/field/details.cjs.map +7 -0
- package/build/form/primitives/field/index.cjs +46 -0
- package/build/form/primitives/field/index.cjs.map +7 -0
- package/build/form/primitives/field/item.cjs +36 -0
- package/build/form/primitives/field/item.cjs.map +7 -0
- package/build/form/primitives/field/label.cjs +98 -0
- package/build/form/primitives/field/label.cjs.map +7 -0
- package/build/form/primitives/field/root.cjs +79 -0
- package/build/form/primitives/field/root.cjs.map +7 -0
- package/build/form/primitives/field/types.cjs +19 -0
- package/build/form/primitives/field/types.cjs.map +7 -0
- package/build/form/primitives/fieldset/context.cjs +40 -0
- package/build/form/primitives/fieldset/context.cjs.map +7 -0
- package/build/form/primitives/fieldset/description.cjs +101 -0
- package/build/form/primitives/fieldset/description.cjs.map +7 -0
- package/build/form/primitives/fieldset/details.cjs +103 -0
- package/build/form/primitives/fieldset/details.cjs.map +7 -0
- package/build/form/primitives/fieldset/index.cjs +40 -0
- package/build/form/primitives/fieldset/index.cjs.map +7 -0
- package/build/form/primitives/fieldset/legend.cjs +94 -0
- package/build/form/primitives/fieldset/legend.cjs.map +7 -0
- package/build/form/primitives/fieldset/root.cjs +86 -0
- package/build/form/primitives/fieldset/root.cjs.map +7 -0
- package/build/form/primitives/fieldset/types.cjs +19 -0
- package/build/form/primitives/fieldset/types.cjs.map +7 -0
- package/build/form/primitives/index.cjs +50 -0
- package/build/form/primitives/index.cjs.map +7 -0
- package/build/form/primitives/input/index.cjs +31 -0
- package/build/form/primitives/input/index.cjs.map +7 -0
- package/build/form/primitives/input/input.cjs +148 -0
- package/build/form/primitives/input/input.cjs.map +7 -0
- package/build/form/primitives/input/types.cjs +19 -0
- package/build/form/primitives/input/types.cjs.map +7 -0
- package/build/form/primitives/input-layout/context.cjs +49 -0
- package/build/form/primitives/input-layout/context.cjs.map +7 -0
- package/build/form/primitives/input-layout/index.cjs +35 -0
- package/build/form/primitives/input-layout/index.cjs.map +7 -0
- package/build/form/primitives/input-layout/input-layout.cjs +196 -0
- package/build/form/primitives/input-layout/input-layout.cjs.map +7 -0
- package/build/form/primitives/input-layout/slot.cjs +165 -0
- package/build/form/primitives/input-layout/slot.cjs.map +7 -0
- package/build/form/primitives/input-layout/types.cjs +19 -0
- package/build/form/primitives/input-layout/types.cjs.map +7 -0
- package/build/icon/icon.cjs +46 -0
- package/build/icon/icon.cjs.map +7 -0
- package/build/{index.js → icon/index.cjs} +13 -7
- package/build/icon/index.cjs.map +7 -0
- package/build/icon/types.cjs +19 -0
- package/build/icon/types.cjs.map +7 -0
- package/build/index.cjs +37 -0
- package/build/index.cjs.map +7 -0
- package/build/stack/{index.js → index.cjs} +2 -2
- package/build/stack/index.cjs.map +7 -0
- package/build/stack/{stack.js → stack.cjs} +6 -18
- package/build/stack/stack.cjs.map +7 -0
- package/build/stack/{types.js → types.cjs} +1 -1
- package/build/stack/types.cjs.map +7 -0
- package/build/types/css-modules.d.cjs +2 -0
- package/build/types/css-modules.d.cjs.map +7 -0
- package/build/types/{react.d.js → react.d.cjs} +1 -1
- package/build/utils/{types.js → types.cjs} +1 -1
- package/build/visually-hidden/index.cjs +31 -0
- package/build/visually-hidden/index.cjs.map +7 -0
- package/build/visually-hidden/types.cjs +19 -0
- package/build/visually-hidden/types.cjs.map +7 -0
- package/build/visually-hidden/visually-hidden.cjs +69 -0
- package/build/visually-hidden/visually-hidden.cjs.map +7 -0
- package/build-module/badge/badge.mjs +70 -0
- package/build-module/badge/badge.mjs.map +7 -0
- package/build-module/badge/index.mjs +6 -0
- package/build-module/badge/index.mjs.map +7 -0
- package/build-module/badge/types.mjs +1 -0
- package/build-module/box/{box.js → box.mjs} +7 -6
- package/build-module/box/box.mjs.map +7 -0
- package/build-module/box/index.mjs +6 -0
- package/build-module/box/types.mjs +1 -0
- package/build-module/button/button.mjs +366 -0
- package/build-module/button/button.mjs.map +7 -0
- package/build-module/button/icon.mjs +22 -0
- package/build-module/button/icon.mjs.map +7 -0
- package/build-module/button/index.mjs +14 -0
- package/build-module/button/index.mjs.map +7 -0
- package/build-module/button/types.mjs +1 -0
- package/build-module/form/primitives/field/control.mjs +13 -0
- package/build-module/form/primitives/field/control.mjs.map +7 -0
- package/build-module/form/primitives/field/description.mjs +57 -0
- package/build-module/form/primitives/field/description.mjs.map +7 -0
- package/build-module/form/primitives/field/details.mjs +64 -0
- package/build-module/form/primitives/field/details.mjs.map +7 -0
- package/build-module/form/primitives/field/index.mjs +16 -0
- package/build-module/form/primitives/field/index.mjs.map +7 -0
- package/build-module/form/primitives/field/item.mjs +11 -0
- package/build-module/form/primitives/field/item.mjs.map +7 -0
- package/build-module/form/primitives/field/label.mjs +63 -0
- package/build-module/form/primitives/field/label.mjs.map +7 -0
- package/build-module/form/primitives/field/root.mjs +44 -0
- package/build-module/form/primitives/field/root.mjs.map +7 -0
- package/build-module/form/primitives/field/types.mjs +1 -0
- package/build-module/form/primitives/fieldset/context.mjs +14 -0
- package/build-module/form/primitives/fieldset/context.mjs.map +7 -0
- package/build-module/form/primitives/fieldset/description.mjs +66 -0
- package/build-module/form/primitives/fieldset/description.mjs.map +7 -0
- package/build-module/form/primitives/fieldset/details.mjs +68 -0
- package/build-module/form/primitives/fieldset/details.mjs.map +7 -0
- package/build-module/form/primitives/fieldset/index.mjs +12 -0
- package/build-module/form/primitives/fieldset/index.mjs.map +7 -0
- package/build-module/form/primitives/fieldset/legend.mjs +59 -0
- package/build-module/form/primitives/fieldset/legend.mjs.map +7 -0
- package/build-module/form/primitives/fieldset/root.mjs +51 -0
- package/build-module/form/primitives/fieldset/root.mjs.map +7 -0
- package/build-module/form/primitives/fieldset/types.mjs +1 -0
- package/build-module/form/primitives/index.mjs +12 -0
- package/build-module/form/primitives/index.mjs.map +7 -0
- package/build-module/form/primitives/input/index.mjs +6 -0
- package/build-module/form/primitives/input/index.mjs.map +7 -0
- package/build-module/form/primitives/input/input.mjs +113 -0
- package/build-module/form/primitives/input/input.mjs.map +7 -0
- package/build-module/form/primitives/input/types.mjs +1 -0
- package/build-module/form/primitives/input/types.mjs.map +7 -0
- package/build-module/form/primitives/input-layout/context.mjs +22 -0
- package/build-module/form/primitives/input-layout/context.mjs.map +7 -0
- package/build-module/form/primitives/input-layout/index.mjs +10 -0
- package/build-module/form/primitives/input-layout/index.mjs.map +7 -0
- package/build-module/form/primitives/input-layout/input-layout.mjs +161 -0
- package/build-module/form/primitives/input-layout/input-layout.mjs.map +7 -0
- package/build-module/form/primitives/input-layout/slot.mjs +130 -0
- package/build-module/form/primitives/input-layout/slot.mjs.map +7 -0
- package/build-module/form/primitives/input-layout/types.mjs +1 -0
- package/build-module/form/primitives/input-layout/types.mjs.map +7 -0
- package/build-module/icon/icon.mjs +21 -0
- package/build-module/icon/icon.mjs.map +7 -0
- package/build-module/icon/index.mjs +6 -0
- package/build-module/icon/index.mjs.map +7 -0
- package/build-module/icon/types.mjs +1 -0
- package/build-module/icon/types.mjs.map +7 -0
- package/build-module/index.mjs +9 -0
- package/build-module/index.mjs.map +7 -0
- package/build-module/stack/index.mjs +6 -0
- package/build-module/stack/index.mjs.map +7 -0
- package/build-module/stack/{stack.js → stack.mjs} +6 -8
- package/build-module/stack/stack.mjs.map +7 -0
- package/build-module/stack/types.mjs +1 -0
- package/build-module/stack/types.mjs.map +7 -0
- package/build-module/types/css-modules.d.mjs +1 -0
- package/build-module/types/css-modules.d.mjs.map +7 -0
- package/build-module/types/{react.d.js → react.d.mjs} +1 -1
- package/build-module/utils/types.mjs +1 -0
- package/build-module/utils/types.mjs.map +7 -0
- package/build-module/visually-hidden/index.mjs +6 -0
- package/build-module/visually-hidden/index.mjs.map +7 -0
- package/build-module/visually-hidden/types.mjs +1 -0
- package/build-module/visually-hidden/types.mjs.map +7 -0
- package/build-module/visually-hidden/visually-hidden.mjs +44 -0
- package/build-module/visually-hidden/visually-hidden.mjs.map +7 -0
- package/build-types/badge/badge.d.ts +7 -0
- package/build-types/badge/badge.d.ts.map +1 -0
- package/build-types/badge/index.d.ts +2 -0
- package/build-types/badge/index.d.ts.map +1 -0
- package/build-types/badge/stories/index.story.d.ts +15 -0
- package/build-types/badge/stories/index.story.d.ts.map +1 -0
- package/build-types/badge/types.d.ts +14 -0
- package/build-types/badge/types.d.ts.map +1 -0
- package/build-types/box/box.d.ts +0 -3
- package/build-types/box/box.d.ts.map +1 -1
- package/build-types/box/stories/index.story.d.ts +1 -11
- package/build-types/box/stories/index.story.d.ts.map +1 -1
- package/build-types/box/types.d.ts +8 -15
- package/build-types/box/types.d.ts.map +1 -1
- package/build-types/button/button.d.ts +3 -0
- package/build-types/button/button.d.ts.map +1 -0
- package/build-types/button/icon.d.ts +10 -0
- package/build-types/button/icon.d.ts.map +1 -0
- package/build-types/button/index.d.ts +10 -0
- package/build-types/button/index.d.ts.map +1 -0
- package/build-types/button/stories/index.story.d.ts +23 -0
- package/build-types/button/stories/index.story.d.ts.map +1 -0
- package/build-types/button/test/button.test.d.ts +2 -0
- package/build-types/button/test/button.test.d.ts.map +1 -0
- package/build-types/button/test/icon.test.d.ts +2 -0
- package/build-types/button/test/icon.test.d.ts.map +1 -0
- package/build-types/button/types.d.ts +63 -0
- package/build-types/button/types.d.ts.map +1 -0
- package/build-types/form/primitives/field/control.d.ts +6 -0
- package/build-types/form/primitives/field/control.d.ts.map +1 -0
- package/build-types/form/primitives/field/description.d.ts +9 -0
- package/build-types/form/primitives/field/description.d.ts.map +1 -0
- package/build-types/form/primitives/field/details.d.ts +21 -0
- package/build-types/form/primitives/field/details.d.ts.map +1 -0
- package/build-types/form/primitives/field/index.d.ts +8 -0
- package/build-types/form/primitives/field/index.d.ts.map +1 -0
- package/build-types/form/primitives/field/item.d.ts +3 -0
- package/build-types/form/primitives/field/item.d.ts.map +1 -0
- package/build-types/form/primitives/field/label.d.ts +11 -0
- package/build-types/form/primitives/field/label.d.ts.map +1 -0
- package/build-types/form/primitives/field/root.d.ts +15 -0
- package/build-types/form/primitives/field/root.d.ts.map +1 -0
- package/build-types/form/primitives/field/stories/index.story.d.ts +39 -0
- package/build-types/form/primitives/field/stories/index.story.d.ts.map +1 -0
- package/build-types/form/primitives/field/test/index.test.d.ts +2 -0
- package/build-types/form/primitives/field/test/index.test.d.ts.map +1 -0
- package/build-types/form/primitives/field/types.d.ts +62 -0
- package/build-types/form/primitives/field/types.d.ts.map +1 -0
- package/build-types/form/primitives/fieldset/context.d.ts +8 -0
- package/build-types/form/primitives/fieldset/context.d.ts.map +1 -0
- package/build-types/form/primitives/fieldset/description.d.ts +9 -0
- package/build-types/form/primitives/fieldset/description.d.ts.map +1 -0
- package/build-types/form/primitives/fieldset/details.d.ts +21 -0
- package/build-types/form/primitives/fieldset/details.d.ts.map +1 -0
- package/build-types/form/primitives/fieldset/index.d.ts +6 -0
- package/build-types/form/primitives/fieldset/index.d.ts.map +1 -0
- package/build-types/form/primitives/fieldset/legend.d.ts +9 -0
- package/build-types/form/primitives/fieldset/legend.d.ts.map +1 -0
- package/build-types/form/primitives/fieldset/root.d.ts +15 -0
- package/build-types/form/primitives/fieldset/root.d.ts.map +1 -0
- package/build-types/form/primitives/fieldset/stories/index.story.d.ts +18 -0
- package/build-types/form/primitives/fieldset/stories/index.story.d.ts.map +1 -0
- package/build-types/form/primitives/fieldset/test/index.test.d.ts +2 -0
- package/build-types/form/primitives/fieldset/test/index.test.d.ts.map +1 -0
- package/build-types/form/primitives/fieldset/types.d.ts +32 -0
- package/build-types/form/primitives/fieldset/types.d.ts.map +1 -0
- package/build-types/form/primitives/index.d.ts +5 -0
- package/build-types/form/primitives/index.d.ts.map +1 -0
- package/build-types/form/primitives/input/index.d.ts +2 -0
- package/build-types/form/primitives/input/index.d.ts.map +1 -0
- package/build-types/form/primitives/input/input.d.ts +10 -0
- package/build-types/form/primitives/input/input.d.ts.map +1 -0
- package/build-types/form/primitives/input/stories/index.story.d.ts +13 -0
- package/build-types/form/primitives/input/stories/index.story.d.ts.map +1 -0
- package/build-types/form/primitives/input/test/index.test.d.ts +2 -0
- package/build-types/form/primitives/input/test/index.test.d.ts.map +1 -0
- package/build-types/form/primitives/input/types.d.ts +27 -0
- package/build-types/form/primitives/input/types.d.ts.map +1 -0
- package/build-types/form/primitives/input-layout/context.d.ts +17 -0
- package/build-types/form/primitives/input-layout/context.d.ts.map +1 -0
- package/build-types/form/primitives/input-layout/index.d.ts +4 -0
- package/build-types/form/primitives/input-layout/index.d.ts.map +1 -0
- package/build-types/form/primitives/input-layout/input-layout.d.ts +7 -0
- package/build-types/form/primitives/input-layout/input-layout.d.ts.map +1 -0
- package/build-types/form/primitives/input-layout/slot.d.ts +6 -0
- package/build-types/form/primitives/input-layout/slot.d.ts.map +1 -0
- package/build-types/form/primitives/input-layout/stories/index.story.d.ts +24 -0
- package/build-types/form/primitives/input-layout/stories/index.story.d.ts.map +1 -0
- package/build-types/form/primitives/input-layout/test/index.test.d.ts +2 -0
- package/build-types/form/primitives/input-layout/test/index.test.d.ts.map +1 -0
- package/build-types/form/primitives/input-layout/types.d.ts +41 -0
- package/build-types/form/primitives/input-layout/types.d.ts.map +1 -0
- package/build-types/icon/icon.d.ts +14 -0
- package/build-types/icon/icon.d.ts.map +1 -0
- package/build-types/icon/index.d.ts +2 -0
- package/build-types/icon/index.d.ts.map +1 -0
- package/build-types/icon/stories/index.story.d.ts +11 -0
- package/build-types/icon/stories/index.story.d.ts.map +1 -0
- package/build-types/icon/test/icon.test.d.ts +2 -0
- package/build-types/icon/test/icon.test.d.ts.map +1 -0
- package/build-types/icon/types.d.ts +15 -0
- package/build-types/icon/types.d.ts.map +1 -0
- package/build-types/index.d.ts +6 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/stack/index.d.ts +0 -3
- package/build-types/stack/index.d.ts.map +1 -1
- package/build-types/stack/stack.d.ts.map +1 -1
- package/build-types/stack/stories/index.story.d.ts +1 -11
- package/build-types/stack/stories/index.story.d.ts.map +1 -1
- package/build-types/stack/types.d.ts +2 -5
- package/build-types/stack/types.d.ts.map +1 -1
- package/build-types/test/index.test.d.ts +2 -0
- package/build-types/test/index.test.d.ts.map +1 -0
- package/build-types/visually-hidden/index.d.ts +2 -0
- package/build-types/visually-hidden/index.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 -0
- package/build-types/visually-hidden/test/visually-hidden.test.d.ts +2 -0
- package/build-types/visually-hidden/test/visually-hidden.test.d.ts.map +1 -0
- package/build-types/visually-hidden/types.d.ts +8 -0
- package/build-types/visually-hidden/types.d.ts.map +1 -0
- package/build-types/visually-hidden/visually-hidden.d.ts +7 -0
- package/build-types/visually-hidden/visually-hidden.d.ts.map +1 -0
- package/package.json +26 -9
- package/src/badge/badge.tsx +88 -0
- package/src/badge/index.ts +1 -0
- package/src/badge/stories/choosing-intent.mdx +112 -0
- package/src/badge/stories/index.story.tsx +120 -0
- package/src/badge/types.ts +22 -0
- package/src/box/box.tsx +11 -23
- package/src/box/stories/index.story.tsx +3 -15
- package/src/box/types.ts +16 -59
- package/src/button/button.tsx +57 -0
- package/src/button/icon.tsx +24 -0
- package/src/button/index.ts +16 -0
- package/src/button/stories/index.story.tsx +192 -0
- package/src/button/style.module.css +232 -0
- package/src/button/test/button.test.tsx +89 -0
- package/src/button/test/icon.test.tsx +13 -0
- package/src/button/types.ts +72 -0
- package/src/form/primitives/field/control.tsx +9 -0
- package/src/form/primitives/field/description.tsx +18 -0
- package/src/form/primitives/field/details.tsx +36 -0
- package/src/form/primitives/field/index.ts +8 -0
- package/src/form/primitives/field/item.tsx +9 -0
- package/src/form/primitives/field/label.tsx +21 -0
- package/src/form/primitives/field/root.tsx +33 -0
- package/src/form/primitives/field/stories/index.story.tsx +132 -0
- package/src/form/primitives/field/test/index.test.tsx +36 -0
- package/src/form/primitives/field/types.ts +82 -0
- package/src/form/primitives/fieldset/context.tsx +13 -0
- package/src/form/primitives/fieldset/description.tsx +36 -0
- package/src/form/primitives/fieldset/details.tsx +46 -0
- package/src/form/primitives/fieldset/index.ts +6 -0
- package/src/form/primitives/fieldset/legend.tsx +17 -0
- package/src/form/primitives/fieldset/root.tsx +42 -0
- package/src/form/primitives/fieldset/stories/index.story.tsx +67 -0
- package/src/form/primitives/fieldset/style.module.css +12 -0
- package/src/form/primitives/fieldset/test/index.test.tsx +135 -0
- package/src/form/primitives/fieldset/types.ts +35 -0
- package/src/form/primitives/index.ts +4 -0
- package/src/form/primitives/input/index.ts +1 -0
- package/src/form/primitives/input/input.tsx +28 -0
- package/src/form/primitives/input/stories/index.story.tsx +40 -0
- package/src/form/primitives/input/style.module.css +34 -0
- package/src/form/primitives/input/test/index.test.tsx +13 -0
- package/src/form/primitives/input/types.ts +31 -0
- package/src/form/primitives/input-layout/context.tsx +36 -0
- package/src/form/primitives/input-layout/index.ts +6 -0
- package/src/form/primitives/input-layout/input-layout.tsx +49 -0
- package/src/form/primitives/input-layout/slot.tsx +39 -0
- package/src/form/primitives/input-layout/stories/index.story.tsx +67 -0
- package/src/form/primitives/input-layout/style.module.css +82 -0
- package/src/form/primitives/input-layout/test/index.test.tsx +23 -0
- package/src/form/primitives/input-layout/types.ts +44 -0
- package/src/icon/icon.tsx +30 -0
- package/src/icon/index.ts +1 -0
- package/src/icon/stories/index.story.tsx +47 -0
- package/src/icon/test/icon.test.tsx +13 -0
- package/src/icon/types.ts +14 -0
- package/src/index.ts +6 -0
- package/src/stack/index.ts +0 -3
- package/src/stack/stack.tsx +5 -18
- package/src/stack/stories/index.story.tsx +1 -14
- package/src/stack/test/stack.test.tsx +22 -12
- package/src/stack/types.ts +2 -6
- package/src/stories/introduction.mdx +6 -0
- package/src/test/index.test.ts +22 -0
- package/src/utils/css/field.module.css +27 -0
- package/src/utils/css/focus.module.css +31 -0
- package/src/utils/css/resets.module.css +13 -0
- package/src/visually-hidden/index.ts +1 -0
- package/src/visually-hidden/stories/index.story.tsx +22 -0
- package/src/visually-hidden/style.module.css +15 -0
- package/src/visually-hidden/test/visually-hidden.test.tsx +59 -0
- package/src/visually-hidden/types.ts +8 -0
- package/src/visually-hidden/visually-hidden.tsx +23 -0
- package/build/box/box.js.map +0 -7
- package/build/box/types.js.map +0 -7
- package/build/index.js.map +0 -7
- package/build/lock-unlock.js.map +0 -7
- package/build/stack/index.js.map +0 -7
- package/build/stack/stack.js.map +0 -7
- package/build/stack/types.js.map +0 -7
- package/build/types/css-modules.d.js +0 -2
- package/build/utils/element.js.map +0 -7
- package/build-module/box/box.js.map +0 -7
- package/build-module/box/index.js +0 -6
- package/build-module/box/types.js +0 -1
- package/build-module/index.js +0 -3
- package/build-module/index.js.map +0 -7
- package/build-module/lock-unlock.js +0 -11
- package/build-module/lock-unlock.js.map +0 -7
- package/build-module/stack/index.js +0 -6
- package/build-module/stack/index.js.map +0 -7
- package/build-module/stack/stack.js.map +0 -7
- package/build-module/stack/types.js +0 -1
- package/build-module/types/css-modules.d.js +0 -1
- package/build-module/utils/element.js +0 -20
- package/build-module/utils/element.js.map +0 -7
- package/build-module/utils/types.js +0 -1
- package/build-types/lock-unlock.d.ts +0 -2
- package/build-types/lock-unlock.d.ts.map +0 -1
- package/build-types/utils/element.d.ts +0 -25
- package/build-types/utils/element.d.ts.map +0 -1
- package/src/lock-unlock.ts +0 -10
- package/src/utils/element.ts +0 -51
- package/tsconfig.json +0 -13
- package/tsconfig.tsbuildinfo +0 -1
- /package/build/box/{index.js.map → index.cjs.map} +0 -0
- /package/build/types/{react.d.js.map → react.d.cjs.map} +0 -0
- /package/build/utils/{types.js.map → types.cjs.map} +0 -0
- /package/build-module/{box/types.js.map → badge/types.mjs.map} +0 -0
- /package/build-module/box/{index.js.map → index.mjs.map} +0 -0
- /package/build-module/{stack/types.js.map → box/types.mjs.map} +0 -0
- /package/build-module/{types/css-modules.d.js.map → button/types.mjs.map} +0 -0
- /package/build-module/{utils/types.js.map → form/primitives/field/types.mjs.map} +0 -0
- /package/{build/types/css-modules.d.js.map → build-module/form/primitives/fieldset/types.mjs.map} +0 -0
- /package/build-module/types/{react.d.js.map → react.d.mjs.map} +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { Field as _Field } from '@base-ui/react/field';
|
|
3
|
+
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import fieldStyles from '../../../utils/css/field.module.css';
|
|
5
|
+
import type { FieldLabelProps } from './types';
|
|
6
|
+
|
|
7
|
+
export const Label = forwardRef< HTMLLabelElement, FieldLabelProps >(
|
|
8
|
+
function Label( { className, variant, ...restProps }, ref ) {
|
|
9
|
+
return (
|
|
10
|
+
<_Field.Label
|
|
11
|
+
ref={ ref }
|
|
12
|
+
className={ clsx(
|
|
13
|
+
fieldStyles.label,
|
|
14
|
+
variant && fieldStyles[ `is-${ variant }` ],
|
|
15
|
+
className
|
|
16
|
+
) }
|
|
17
|
+
{ ...restProps }
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { Field as _Field } from '@base-ui/react/field';
|
|
3
|
+
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import resetStyles from '../../../utils/css/resets.module.css';
|
|
5
|
+
import type { FieldRootProps } from './types';
|
|
6
|
+
import { Stack } from '../../../stack';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_RENDER = ( props: React.ComponentProps< typeof Stack > ) => (
|
|
9
|
+
<Stack { ...props } direction="column" gap="xs" />
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A low-level component that associates an accessible label and description
|
|
14
|
+
* with a single form control element.
|
|
15
|
+
*
|
|
16
|
+
* To label a group of multiple form control elements, use the `Fieldset` component instead.
|
|
17
|
+
*
|
|
18
|
+
* Simply wrapping a control with this component does not guarantee
|
|
19
|
+
* accessible labeling. See examples for how to associate the label in different cases.
|
|
20
|
+
*/
|
|
21
|
+
export const Root = forwardRef< HTMLDivElement, FieldRootProps >( function Root(
|
|
22
|
+
{ className, render = DEFAULT_RENDER, ...restProps },
|
|
23
|
+
ref
|
|
24
|
+
) {
|
|
25
|
+
return (
|
|
26
|
+
<_Field.Root
|
|
27
|
+
ref={ ref }
|
|
28
|
+
className={ clsx( resetStyles[ 'box-sizing' ], className ) }
|
|
29
|
+
render={ render }
|
|
30
|
+
{ ...restProps }
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
} );
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { useId } from '@wordpress/element';
|
|
3
|
+
import '@wordpress/theme/design-tokens.css';
|
|
4
|
+
import { Field } from '../../../..';
|
|
5
|
+
|
|
6
|
+
const meta: Meta< typeof Field.Root > = {
|
|
7
|
+
title: 'Design System/Components/Form/Primitives/Field',
|
|
8
|
+
component: Field.Root,
|
|
9
|
+
subcomponents: {
|
|
10
|
+
Item: Field.Item,
|
|
11
|
+
Label: Field.Label,
|
|
12
|
+
Control: Field.Control,
|
|
13
|
+
Description: Field.Description,
|
|
14
|
+
Details: Field.Details,
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
export default meta;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* If your control component forwards refs, as well as the `aria-labelledby` and `aria-describedby` props
|
|
21
|
+
* to the actual underlying HTML element to be labeled,
|
|
22
|
+
* you can simply place your control in the `render` prop of `Field.Control`.
|
|
23
|
+
*/
|
|
24
|
+
export const Default: StoryObj< typeof Field.Root > = {
|
|
25
|
+
args: {
|
|
26
|
+
children: (
|
|
27
|
+
<>
|
|
28
|
+
<Field.Label>Label</Field.Label>
|
|
29
|
+
<Field.Control
|
|
30
|
+
render={ <input type="text" placeholder="Placeholder" /> }
|
|
31
|
+
/>
|
|
32
|
+
<Field.Description>
|
|
33
|
+
The accessible description.
|
|
34
|
+
</Field.Description>
|
|
35
|
+
</>
|
|
36
|
+
),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const MyNonRefForwardingControl = (
|
|
41
|
+
props: React.ComponentProps< 'input' >
|
|
42
|
+
) => {
|
|
43
|
+
return <input type="text" { ...props } />;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* If your control component does not forward refs, but does forward the `id` prop
|
|
48
|
+
* to the actual underlying HTML element to be labeled, use the `htmlFor` prop
|
|
49
|
+
* of the `Field.Label` component to associate the label with the control.
|
|
50
|
+
*
|
|
51
|
+
* This is preferred over `aria-labelledby` because it allows users to click the
|
|
52
|
+
* label to focus the control.
|
|
53
|
+
*/
|
|
54
|
+
export const UsingHtmlFor: StoryObj< typeof Field.Root > = {
|
|
55
|
+
name: 'Using htmlFor',
|
|
56
|
+
render: ( args ) => {
|
|
57
|
+
const controlId = useId();
|
|
58
|
+
const descriptionId = useId();
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<Field.Root { ...args }>
|
|
62
|
+
<Field.Label htmlFor={ controlId }>Label</Field.Label>
|
|
63
|
+
<MyNonRefForwardingControl
|
|
64
|
+
placeholder="Placeholder"
|
|
65
|
+
id={ controlId }
|
|
66
|
+
aria-describedby={ descriptionId }
|
|
67
|
+
/>
|
|
68
|
+
<Field.Description id={ descriptionId }>
|
|
69
|
+
The accessible description.
|
|
70
|
+
</Field.Description>
|
|
71
|
+
</Field.Root>
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* If your control component does not forward refs nor the `id` prop, but does
|
|
78
|
+
* forward the `aria-labelledby` prop to the actual underlying HTML element to be
|
|
79
|
+
* labeled, use the `id` prop of the `Field.Label` component to associate the
|
|
80
|
+
* label with the control.
|
|
81
|
+
*/
|
|
82
|
+
export const UsingAriaLabelledby: StoryObj< typeof Field.Root > = {
|
|
83
|
+
name: 'Using aria-labelledby',
|
|
84
|
+
render: ( args ) => {
|
|
85
|
+
const labelId = useId();
|
|
86
|
+
const descriptionId = useId();
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<Field.Root { ...args }>
|
|
90
|
+
<Field.Label id={ labelId }>Label</Field.Label>
|
|
91
|
+
<MyNonRefForwardingControl
|
|
92
|
+
placeholder="Placeholder"
|
|
93
|
+
aria-labelledby={ labelId }
|
|
94
|
+
aria-describedby={ descriptionId }
|
|
95
|
+
/>
|
|
96
|
+
<Field.Description id={ descriptionId }>
|
|
97
|
+
The accessible description.
|
|
98
|
+
</Field.Description>{ ' ' }
|
|
99
|
+
</Field.Root>
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* To add rich content (such as links) to the description, use `Field.Details`.
|
|
106
|
+
*
|
|
107
|
+
* Although this content is not associated with the field using direct semantics,
|
|
108
|
+
* it is made discoverable to screen reader users via a visually hidden description,
|
|
109
|
+
* alerting them to the presence of additional information below.
|
|
110
|
+
*
|
|
111
|
+
* If the content only includes plain text, use `Field.Description` instead,
|
|
112
|
+
* so the readout is not unnecessarily verbose for screen reader users.
|
|
113
|
+
*/
|
|
114
|
+
export const WithDetails: StoryObj< typeof Field.Root > = {
|
|
115
|
+
args: {
|
|
116
|
+
children: (
|
|
117
|
+
<>
|
|
118
|
+
<Field.Label>Label</Field.Label>
|
|
119
|
+
<Field.Control
|
|
120
|
+
render={ <input type="text" placeholder="Placeholder" /> }
|
|
121
|
+
/>
|
|
122
|
+
<Field.Details>
|
|
123
|
+
Details can include{ ' ' }
|
|
124
|
+
<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a">
|
|
125
|
+
links to more information
|
|
126
|
+
</a>{ ' ' }
|
|
127
|
+
and other semantic elements.
|
|
128
|
+
</Field.Details>
|
|
129
|
+
</>
|
|
130
|
+
),
|
|
131
|
+
},
|
|
132
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { createRef } from '@wordpress/element';
|
|
3
|
+
import * as Field from '../index';
|
|
4
|
+
|
|
5
|
+
describe( 'Field', () => {
|
|
6
|
+
it( 'forwards ref', () => {
|
|
7
|
+
const rootRef = createRef< HTMLDivElement >();
|
|
8
|
+
const itemRef = createRef< HTMLDivElement >();
|
|
9
|
+
const controlRef = createRef< HTMLInputElement >();
|
|
10
|
+
const labelRef = createRef< HTMLLabelElement >();
|
|
11
|
+
const descriptionRef = createRef< HTMLParagraphElement >();
|
|
12
|
+
const detailsRef = createRef< HTMLDivElement >();
|
|
13
|
+
|
|
14
|
+
render(
|
|
15
|
+
<Field.Root ref={ rootRef } name="test-field">
|
|
16
|
+
<Field.Item ref={ itemRef }>
|
|
17
|
+
<Field.Label ref={ labelRef }>Field Label</Field.Label>
|
|
18
|
+
<Field.Control ref={ controlRef } render={ <input /> } />
|
|
19
|
+
<Field.Description ref={ descriptionRef }>
|
|
20
|
+
Field description
|
|
21
|
+
</Field.Description>
|
|
22
|
+
<Field.Details ref={ detailsRef }>
|
|
23
|
+
Field <a href="#details">details</a>
|
|
24
|
+
</Field.Details>
|
|
25
|
+
</Field.Item>
|
|
26
|
+
</Field.Root>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
expect( rootRef.current ).toBeInstanceOf( HTMLDivElement );
|
|
30
|
+
expect( itemRef.current ).toBeInstanceOf( HTMLDivElement );
|
|
31
|
+
expect( controlRef.current ).toBeInstanceOf( HTMLInputElement );
|
|
32
|
+
expect( labelRef.current ).toBeInstanceOf( HTMLLabelElement );
|
|
33
|
+
expect( descriptionRef.current ).toBeInstanceOf( HTMLParagraphElement );
|
|
34
|
+
expect( detailsRef.current ).toBeInstanceOf( HTMLDivElement );
|
|
35
|
+
} );
|
|
36
|
+
} );
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { Field } from '@base-ui/react/field';
|
|
2
|
+
import type { ComponentProps } from '../../../utils/types';
|
|
3
|
+
|
|
4
|
+
export type FieldRootProps = Omit<
|
|
5
|
+
ComponentProps< typeof Field.Root >,
|
|
6
|
+
| 'disabled'
|
|
7
|
+
// TODO: Maybe allow these when we have validation support ready.
|
|
8
|
+
| 'dirty'
|
|
9
|
+
| 'invalid'
|
|
10
|
+
| 'touched'
|
|
11
|
+
| 'validate'
|
|
12
|
+
| 'validationDebounceTime'
|
|
13
|
+
| 'validationMode'
|
|
14
|
+
> & {
|
|
15
|
+
children?: Field.Root.Props[ 'children' ];
|
|
16
|
+
/**
|
|
17
|
+
* Whether the field is disabled.
|
|
18
|
+
*
|
|
19
|
+
* @default false
|
|
20
|
+
*/
|
|
21
|
+
disabled?: Field.Root.Props[ 'disabled' ];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type FieldItemProps = ComponentProps< typeof Field.Item > & {
|
|
25
|
+
children?: React.ReactNode;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type FieldLabelProps = ComponentProps< typeof Field.Label > & {
|
|
29
|
+
/**
|
|
30
|
+
* The label string, or the string and the element to associate it with.
|
|
31
|
+
*
|
|
32
|
+
* To keep things accessible, do not include other interactive
|
|
33
|
+
* elements such as links or buttons.
|
|
34
|
+
*/
|
|
35
|
+
children?: Field.Label.Props[ 'children' ];
|
|
36
|
+
/**
|
|
37
|
+
* The visual variant of the label.
|
|
38
|
+
*
|
|
39
|
+
* Use 'plain' for controls like checkboxes and radio buttons.
|
|
40
|
+
*
|
|
41
|
+
* @default 'default'
|
|
42
|
+
*/
|
|
43
|
+
variant?: 'default' | 'plain';
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type FieldControlProps = Omit<
|
|
47
|
+
ComponentProps< typeof Field.Control >,
|
|
48
|
+
'defaultValue'
|
|
49
|
+
> & {
|
|
50
|
+
children?: Field.Control.Props[ 'children' ];
|
|
51
|
+
/**
|
|
52
|
+
* The default value to use in uncontrolled mode.
|
|
53
|
+
*/
|
|
54
|
+
defaultValue?: Field.Control.Props[ 'defaultValue' ];
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type FieldDescriptionProps = ComponentProps<
|
|
58
|
+
typeof Field.Description
|
|
59
|
+
> & {
|
|
60
|
+
/**
|
|
61
|
+
* The accessible description, associated using `aria-describedby`.
|
|
62
|
+
*
|
|
63
|
+
* For screen reader accessibility, this should only contain plain text,
|
|
64
|
+
* and no semantics such as links.
|
|
65
|
+
*/
|
|
66
|
+
children?: string;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type FieldDetailsProps = ComponentProps< 'div' > & {
|
|
70
|
+
/**
|
|
71
|
+
* Additional information about the field, which unlike a normal description,
|
|
72
|
+
* can include links and other semantic elements.
|
|
73
|
+
*
|
|
74
|
+
* Although this content is not associated with the field using direct semantics,
|
|
75
|
+
* it is made discoverable to screen reader users via a visually hidden description,
|
|
76
|
+
* alerting them to the presence of additional information below.
|
|
77
|
+
*
|
|
78
|
+
* Do not use this component when the details content is only plain text,
|
|
79
|
+
* as it makes the readout unnecessarily verbose for screen reader users.
|
|
80
|
+
*/
|
|
81
|
+
children?: React.ReactNode;
|
|
82
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createContext, useContext } from '@wordpress/element';
|
|
2
|
+
|
|
3
|
+
type FieldsetContextType = {
|
|
4
|
+
registerDescriptionId: ( id: string ) => void;
|
|
5
|
+
unregisterDescriptionId: () => void;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const FieldsetContext = createContext< FieldsetContextType >( {
|
|
9
|
+
registerDescriptionId: () => {},
|
|
10
|
+
unregisterDescriptionId: () => {},
|
|
11
|
+
} );
|
|
12
|
+
|
|
13
|
+
export const useFieldsetContext = () => useContext( FieldsetContext );
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { mergeProps, useRender } from '@base-ui/react';
|
|
3
|
+
import { forwardRef, useEffect, useId } from '@wordpress/element';
|
|
4
|
+
import fieldStyles from '../../../utils/css/field.module.css';
|
|
5
|
+
import { useFieldsetContext } from './context';
|
|
6
|
+
import type { FieldsetDescriptionProps } from './types';
|
|
7
|
+
|
|
8
|
+
export const FieldsetDescription = forwardRef<
|
|
9
|
+
HTMLParagraphElement,
|
|
10
|
+
FieldsetDescriptionProps
|
|
11
|
+
>( function FieldsetDescription(
|
|
12
|
+
{ className, id: idProp, render, ...restProps },
|
|
13
|
+
ref
|
|
14
|
+
) {
|
|
15
|
+
const generatedId = useId();
|
|
16
|
+
const id = idProp ?? generatedId;
|
|
17
|
+
const { registerDescriptionId, unregisterDescriptionId } =
|
|
18
|
+
useFieldsetContext();
|
|
19
|
+
|
|
20
|
+
useEffect( () => {
|
|
21
|
+
registerDescriptionId( id );
|
|
22
|
+
return unregisterDescriptionId;
|
|
23
|
+
}, [ registerDescriptionId, unregisterDescriptionId, id ] );
|
|
24
|
+
|
|
25
|
+
const element = useRender( {
|
|
26
|
+
defaultTagName: 'p',
|
|
27
|
+
render,
|
|
28
|
+
ref,
|
|
29
|
+
props: mergeProps< 'p' >(
|
|
30
|
+
{ className: clsx( fieldStyles.description, className ), id },
|
|
31
|
+
restProps
|
|
32
|
+
),
|
|
33
|
+
} );
|
|
34
|
+
|
|
35
|
+
return element;
|
|
36
|
+
} );
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { forwardRef, useEffect, useId } from '@wordpress/element';
|
|
3
|
+
import { __ } from '@wordpress/i18n';
|
|
4
|
+
import fieldStyles from '../../../utils/css/field.module.css';
|
|
5
|
+
import { useFieldsetContext } from './context';
|
|
6
|
+
import { VisuallyHidden } from '../../../visually-hidden';
|
|
7
|
+
import type { FieldsetDetailsProps } from './types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A component for showing additional information about the fieldset,
|
|
11
|
+
* styled similarly to a normal `Fieldset.Description`.
|
|
12
|
+
* Unlike a normal description, it can include links and other semantic elements.
|
|
13
|
+
*
|
|
14
|
+
* Although this content is not associated with the fieldset using direct semantics,
|
|
15
|
+
* it is made discoverable to screen reader users via a visually hidden description,
|
|
16
|
+
* alerting them to the presence of additional information below.
|
|
17
|
+
*
|
|
18
|
+
* If the content only includes plain text, use `Fieldset.Description` instead,
|
|
19
|
+
* so the readout is not unnecessarily verbose for screen reader users.
|
|
20
|
+
*/
|
|
21
|
+
export const FieldsetDetails = forwardRef<
|
|
22
|
+
HTMLDivElement,
|
|
23
|
+
FieldsetDetailsProps
|
|
24
|
+
>( function FieldsetDetails( { className, ...restProps }, ref ) {
|
|
25
|
+
const id = useId();
|
|
26
|
+
const { registerDescriptionId, unregisterDescriptionId } =
|
|
27
|
+
useFieldsetContext();
|
|
28
|
+
|
|
29
|
+
useEffect( () => {
|
|
30
|
+
registerDescriptionId( id );
|
|
31
|
+
return unregisterDescriptionId;
|
|
32
|
+
}, [ registerDescriptionId, unregisterDescriptionId, id ] );
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<VisuallyHidden id={ id }>
|
|
37
|
+
{ __( 'More details follow.' ) }
|
|
38
|
+
</VisuallyHidden>
|
|
39
|
+
<div
|
|
40
|
+
ref={ ref }
|
|
41
|
+
className={ clsx( fieldStyles.description, className ) }
|
|
42
|
+
{ ...restProps }
|
|
43
|
+
/>
|
|
44
|
+
</>
|
|
45
|
+
);
|
|
46
|
+
} );
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FieldsetRoot as Root } from './root';
|
|
2
|
+
import { FieldsetLegend as Legend } from './legend';
|
|
3
|
+
import { FieldsetDescription as Description } from './description';
|
|
4
|
+
import { FieldsetDetails as Details } from './details';
|
|
5
|
+
|
|
6
|
+
export { Root, Legend, Description, Details };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { Fieldset as _Fieldset } from '@base-ui/react/fieldset';
|
|
3
|
+
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import fieldStyles from '../../../utils/css/field.module.css';
|
|
5
|
+
import type { FieldsetLegendProps } from './types';
|
|
6
|
+
|
|
7
|
+
export const FieldsetLegend = forwardRef< HTMLDivElement, FieldsetLegendProps >(
|
|
8
|
+
function FieldsetLegend( { className, ...restProps }, ref ) {
|
|
9
|
+
return (
|
|
10
|
+
<_Fieldset.Legend
|
|
11
|
+
ref={ ref }
|
|
12
|
+
className={ clsx( fieldStyles.label, className ) }
|
|
13
|
+
{ ...restProps }
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { Fieldset as _Fieldset } from '@base-ui/react/fieldset';
|
|
3
|
+
import { forwardRef, useState, useMemo } from '@wordpress/element';
|
|
4
|
+
import styles from './style.module.css';
|
|
5
|
+
import { FieldsetContext } from './context';
|
|
6
|
+
import type { FieldsetRootProps } from './types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A low-level component that associates an accessible legend and description with
|
|
10
|
+
* a group of multiple form control elements.
|
|
11
|
+
*
|
|
12
|
+
* To label a single form control element, use the `Field` component instead.
|
|
13
|
+
*/
|
|
14
|
+
export const FieldsetRoot = forwardRef<
|
|
15
|
+
HTMLFieldSetElement,
|
|
16
|
+
FieldsetRootProps
|
|
17
|
+
>( function FieldsetRoot( { className, children, ...restProps }, ref ) {
|
|
18
|
+
const [ descriptionId, setDescriptionId ] = useState< string >();
|
|
19
|
+
|
|
20
|
+
const contextValue = useMemo(
|
|
21
|
+
() => ( {
|
|
22
|
+
registerDescriptionId: ( id: string ) => setDescriptionId( id ),
|
|
23
|
+
unregisterDescriptionId: () => setDescriptionId( undefined ),
|
|
24
|
+
} ),
|
|
25
|
+
[]
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<FieldsetContext.Provider value={ contextValue }>
|
|
30
|
+
<_Fieldset.Root
|
|
31
|
+
ref={ ref }
|
|
32
|
+
className={ clsx( styles.root, className ) }
|
|
33
|
+
// Certain screen readers may not read a fieldset's description
|
|
34
|
+
// https://w3c.github.io/using-aria/#label-support
|
|
35
|
+
aria-describedby={ descriptionId }
|
|
36
|
+
{ ...restProps }
|
|
37
|
+
>
|
|
38
|
+
{ children }
|
|
39
|
+
</_Fieldset.Root>
|
|
40
|
+
</FieldsetContext.Provider>
|
|
41
|
+
);
|
|
42
|
+
} );
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Fieldset } from '../../../..';
|
|
3
|
+
|
|
4
|
+
const meta: Meta< typeof Fieldset.Root > = {
|
|
5
|
+
title: 'Design System/Components/Form/Primitives/Fieldset',
|
|
6
|
+
component: Fieldset.Root,
|
|
7
|
+
subcomponents: {
|
|
8
|
+
Legend: Fieldset.Legend,
|
|
9
|
+
Description: Fieldset.Description,
|
|
10
|
+
Details: Fieldset.Details,
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
export default meta;
|
|
14
|
+
|
|
15
|
+
type Story = StoryObj< typeof Fieldset.Root >;
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {
|
|
18
|
+
args: {
|
|
19
|
+
children: (
|
|
20
|
+
<>
|
|
21
|
+
<Fieldset.Legend>Legend</Fieldset.Legend>
|
|
22
|
+
{ [ 'Apples', 'Bananas' ].map( ( fruit ) => (
|
|
23
|
+
// eslint-disable-next-line jsx-a11y/label-has-associated-control
|
|
24
|
+
<label key={ fruit }>
|
|
25
|
+
<input type="checkbox" /> { fruit }
|
|
26
|
+
</label>
|
|
27
|
+
) ) }
|
|
28
|
+
<Fieldset.Description>
|
|
29
|
+
This is a description for the entire fieldset.
|
|
30
|
+
</Fieldset.Description>
|
|
31
|
+
</>
|
|
32
|
+
),
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* To add rich content (such as links) to the description, use `Fieldset.Details`.
|
|
38
|
+
*
|
|
39
|
+
* Although this content is not associated with the fieldset using direct semantics,
|
|
40
|
+
* it is made discoverable to screen reader users via a visually hidden description,
|
|
41
|
+
* alerting them to the presence of additional information below.
|
|
42
|
+
*
|
|
43
|
+
* If the content only includes plain text, use `Fieldset.Description` instead,
|
|
44
|
+
* so the readout is not unnecessarily verbose for screen reader users.
|
|
45
|
+
*/
|
|
46
|
+
export const WithDetails: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
children: (
|
|
49
|
+
<>
|
|
50
|
+
<Fieldset.Legend>Legend</Fieldset.Legend>
|
|
51
|
+
{ [ 'Apples', 'Bananas' ].map( ( fruit ) => (
|
|
52
|
+
// eslint-disable-next-line jsx-a11y/label-has-associated-control
|
|
53
|
+
<label key={ fruit }>
|
|
54
|
+
<input type="checkbox" /> { fruit }
|
|
55
|
+
</label>
|
|
56
|
+
) ) }
|
|
57
|
+
<Fieldset.Details>
|
|
58
|
+
Details can include{ ' ' }
|
|
59
|
+
<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a">
|
|
60
|
+
links to more information
|
|
61
|
+
</a>{ ' ' }
|
|
62
|
+
and other semantic elements.
|
|
63
|
+
</Fieldset.Details>
|
|
64
|
+
</>
|
|
65
|
+
),
|
|
66
|
+
},
|
|
67
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { createRef } from '@wordpress/element';
|
|
3
|
+
import * as Fieldset from '../';
|
|
4
|
+
|
|
5
|
+
describe( 'Fieldset', () => {
|
|
6
|
+
it( 'forwards ref', () => {
|
|
7
|
+
const rootRef = createRef< HTMLFieldSetElement >();
|
|
8
|
+
const legendRef = createRef< HTMLDivElement >();
|
|
9
|
+
const descriptionRef = createRef< HTMLParagraphElement >();
|
|
10
|
+
const detailsRef = createRef< HTMLDivElement >();
|
|
11
|
+
|
|
12
|
+
render(
|
|
13
|
+
<Fieldset.Root ref={ rootRef }>
|
|
14
|
+
<Fieldset.Legend ref={ legendRef }>
|
|
15
|
+
Fieldset Legend
|
|
16
|
+
</Fieldset.Legend>
|
|
17
|
+
<Fieldset.Description ref={ descriptionRef }>
|
|
18
|
+
Fieldset description
|
|
19
|
+
</Fieldset.Description>
|
|
20
|
+
<Fieldset.Details ref={ detailsRef }>
|
|
21
|
+
Fieldset details
|
|
22
|
+
</Fieldset.Details>
|
|
23
|
+
</Fieldset.Root>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
expect( rootRef.current ).toBeInstanceOf( HTMLFieldSetElement );
|
|
27
|
+
expect( legendRef.current ).toBeInstanceOf( HTMLDivElement );
|
|
28
|
+
expect( descriptionRef.current ).toBeInstanceOf( HTMLParagraphElement );
|
|
29
|
+
expect( detailsRef.current ).toBeInstanceOf( HTMLDivElement );
|
|
30
|
+
} );
|
|
31
|
+
|
|
32
|
+
it( 'accessibly associates description when Fieldset.Description is present', () => {
|
|
33
|
+
render(
|
|
34
|
+
<Fieldset.Root>
|
|
35
|
+
<Fieldset.Legend>Choose your options</Fieldset.Legend>
|
|
36
|
+
<Fieldset.Description>
|
|
37
|
+
Select one or more options from the list below.
|
|
38
|
+
</Fieldset.Description>
|
|
39
|
+
</Fieldset.Root>
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
expect(
|
|
43
|
+
screen.getByRole( 'group', {
|
|
44
|
+
name: 'Choose your options',
|
|
45
|
+
description: 'Select one or more options from the list below.',
|
|
46
|
+
} )
|
|
47
|
+
).toBeVisible();
|
|
48
|
+
} );
|
|
49
|
+
|
|
50
|
+
it( 'does not add aria-describedby when Fieldset.Description is not present', () => {
|
|
51
|
+
render(
|
|
52
|
+
<Fieldset.Root>
|
|
53
|
+
<Fieldset.Legend>Choose your options</Fieldset.Legend>
|
|
54
|
+
</Fieldset.Root>
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const fieldset = screen.getByRole( 'group', {
|
|
58
|
+
name: 'Choose your options',
|
|
59
|
+
} );
|
|
60
|
+
|
|
61
|
+
// Should not have aria-describedby
|
|
62
|
+
expect( fieldset ).not.toHaveAttribute( 'aria-describedby' );
|
|
63
|
+
} );
|
|
64
|
+
|
|
65
|
+
it( 'respects custom id on description', () => {
|
|
66
|
+
const customId = 'custom-description-id';
|
|
67
|
+
|
|
68
|
+
render(
|
|
69
|
+
<Fieldset.Root>
|
|
70
|
+
<Fieldset.Legend>Choose your options</Fieldset.Legend>
|
|
71
|
+
<Fieldset.Description id={ customId }>
|
|
72
|
+
Custom description with specific ID.
|
|
73
|
+
</Fieldset.Description>
|
|
74
|
+
</Fieldset.Root>
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const description = screen.getByText(
|
|
78
|
+
'Custom description with specific ID.'
|
|
79
|
+
);
|
|
80
|
+
expect( description ).toHaveAttribute( 'id', customId );
|
|
81
|
+
|
|
82
|
+
expect(
|
|
83
|
+
screen.getByRole( 'group', {
|
|
84
|
+
name: 'Choose your options',
|
|
85
|
+
description: 'Custom description with specific ID.',
|
|
86
|
+
} )
|
|
87
|
+
).toBeVisible();
|
|
88
|
+
} );
|
|
89
|
+
|
|
90
|
+
it( 'forwards className to the description element', () => {
|
|
91
|
+
render(
|
|
92
|
+
<Fieldset.Root>
|
|
93
|
+
<Fieldset.Description className="custom-class">
|
|
94
|
+
Fieldset description
|
|
95
|
+
</Fieldset.Description>
|
|
96
|
+
</Fieldset.Root>
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
expect( screen.getByText( 'Fieldset description' ) ).toHaveClass(
|
|
100
|
+
'custom-class'
|
|
101
|
+
);
|
|
102
|
+
} );
|
|
103
|
+
|
|
104
|
+
it( 'announces additional details via a visually hidden description', () => {
|
|
105
|
+
render(
|
|
106
|
+
<Fieldset.Root>
|
|
107
|
+
<Fieldset.Legend>Choose your options</Fieldset.Legend>
|
|
108
|
+
<Fieldset.Details>
|
|
109
|
+
<a href="#more-info">Learn more about these options</a>
|
|
110
|
+
</Fieldset.Details>
|
|
111
|
+
</Fieldset.Root>
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
expect(
|
|
115
|
+
screen.getByRole( 'group', {
|
|
116
|
+
name: 'Choose your options',
|
|
117
|
+
description: 'More details follow.',
|
|
118
|
+
} )
|
|
119
|
+
).toBeVisible();
|
|
120
|
+
} );
|
|
121
|
+
|
|
122
|
+
it( 'forwards className to the details element', () => {
|
|
123
|
+
render(
|
|
124
|
+
<Fieldset.Root>
|
|
125
|
+
<Fieldset.Details className="custom-class">
|
|
126
|
+
Fieldset details
|
|
127
|
+
</Fieldset.Details>
|
|
128
|
+
</Fieldset.Root>
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
expect( screen.getByText( 'Fieldset details' ) ).toHaveClass(
|
|
132
|
+
'custom-class'
|
|
133
|
+
);
|
|
134
|
+
} );
|
|
135
|
+
} );
|