@mich8060/unified-design-system 0.1.10
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/LICENSE +21 -0
- package/README.lib.md +103 -0
- package/README.md +265 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +103 -0
- package/dist/package.json +49 -0
- package/dist/styles.css +20544 -0
- package/dist/uds-components.es.js +67031 -0
- package/dist/uds-components.es.js.map +1 -0
- package/dist/uds-components.umd.js +67048 -0
- package/dist/uds-components.umd.js.map +1 -0
- package/package.json +158 -0
- package/src/styles/_typography.scss +932 -0
- package/src/styles/_utilities.scss +3738 -0
- package/src/styles/_variables.scss +620 -0
- package/src/styles/prism-custom.css +204 -0
- package/src/styles/prism-custom.scss +205 -0
- package/src/styles/tokens.css +1463 -0
- package/src/styles/tokens.scss +1116 -0
- package/src/ui/Accordion/Accordion.ai.md +69 -0
- package/src/ui/Accordion/Accordion.scss +87 -0
- package/src/ui/Accordion/Accordion.spec.ts +25 -0
- package/src/ui/Accordion/Accordion.stories.tsx +46 -0
- package/src/ui/Accordion/Accordion.test.tsx +54 -0
- package/src/ui/Accordion/Accordion.tsx +73 -0
- package/src/ui/Accordion/Accordion.types.ts +15 -0
- package/src/ui/Accordion/index.js +1 -0
- package/src/ui/ActionMenu/ActionMenu.ai.md +106 -0
- package/src/ui/ActionMenu/ActionMenu.jsx +437 -0
- package/src/ui/ActionMenu/ActionMenu.scss +252 -0
- package/src/ui/ActionMenu/ActionMenu.spec.ts +12 -0
- package/src/ui/ActionMenu/ActionMenu.stories.jsx +14 -0
- package/src/ui/ActionMenu/ActionMenu.stories.tsx +124 -0
- package/src/ui/ActionMenu/ActionMenu.test.tsx +1 -0
- package/src/ui/ActionMenu/ActionMenu.tsx +6 -0
- package/src/ui/ActionMenu/ActionMenu.types.ts +3 -0
- package/src/ui/ActionMenu/index.js +1 -0
- package/src/ui/Avatar/Avatar.ai.md +54 -0
- package/src/ui/Avatar/Avatar.jsx +49 -0
- package/src/ui/Avatar/Avatar.scss +87 -0
- package/src/ui/Avatar/Avatar.spec.ts +12 -0
- package/src/ui/Avatar/Avatar.stories.jsx +14 -0
- package/src/ui/Avatar/Avatar.stories.tsx +14 -0
- package/src/ui/Avatar/Avatar.test.tsx +1 -0
- package/src/ui/Avatar/Avatar.tsx +6 -0
- package/src/ui/Avatar/Avatar.types.ts +3 -0
- package/src/ui/Avatar/index.js +1 -0
- package/src/ui/Badge/Badge.ai.md +37 -0
- package/src/ui/Badge/Badge.jsx +64 -0
- package/src/ui/Badge/Badge.scss +84 -0
- package/src/ui/Badge/Badge.spec.ts +12 -0
- package/src/ui/Badge/Badge.stories.jsx +14 -0
- package/src/ui/Badge/Badge.stories.tsx +14 -0
- package/src/ui/Badge/Badge.test.tsx +1 -0
- package/src/ui/Badge/Badge.tsx +6 -0
- package/src/ui/Badge/Badge.types.ts +3 -0
- package/src/ui/Badge/index.js +1 -0
- package/src/ui/Branding/Branding.ai.md +81 -0
- package/src/ui/Branding/Branding.jsx +127 -0
- package/src/ui/Branding/Branding.scss +57 -0
- package/src/ui/Branding/Branding.spec.ts +12 -0
- package/src/ui/Branding/Branding.stories.jsx +14 -0
- package/src/ui/Branding/Branding.stories.tsx +14 -0
- package/src/ui/Branding/Branding.test.tsx +1 -0
- package/src/ui/Branding/Branding.tsx +6 -0
- package/src/ui/Branding/Branding.types.ts +3 -0
- package/src/ui/Branding/index.js +1 -0
- package/src/ui/Breadcrumb/Breadcrumb.ai.md +50 -0
- package/src/ui/Breadcrumb/Breadcrumb.jsx +167 -0
- package/src/ui/Breadcrumb/Breadcrumb.scss +46 -0
- package/src/ui/Breadcrumb/Breadcrumb.spec.ts +12 -0
- package/src/ui/Breadcrumb/Breadcrumb.stories.jsx +26 -0
- package/src/ui/Breadcrumb/Breadcrumb.stories.tsx +14 -0
- package/src/ui/Breadcrumb/Breadcrumb.test.tsx +1 -0
- package/src/ui/Breadcrumb/Breadcrumb.tsx +6 -0
- package/src/ui/Breadcrumb/Breadcrumb.types.ts +3 -0
- package/src/ui/Breadcrumb/index.js +2 -0
- package/src/ui/Button/Button.ai.md +122 -0
- package/src/ui/Button/Button.figma.tsx +49 -0
- package/src/ui/Button/Button.scss +188 -0
- package/src/ui/Button/Button.spec.ts +52 -0
- package/src/ui/Button/Button.stories.tsx +199 -0
- package/src/ui/Button/Button.test.tsx +85 -0
- package/src/ui/Button/Button.tsx +131 -0
- package/src/ui/Button/Button.types.ts +32 -0
- package/src/ui/Button/index.js +1 -0
- package/src/ui/Calendar/Calendar.ai.md +151 -0
- package/src/ui/Calendar/Calendar.jsx +504 -0
- package/src/ui/Calendar/Calendar.scss +451 -0
- package/src/ui/Calendar/Calendar.spec.ts +12 -0
- package/src/ui/Calendar/Calendar.stories.jsx +14 -0
- package/src/ui/Calendar/Calendar.stories.tsx +14 -0
- package/src/ui/Calendar/Calendar.test.tsx +1 -0
- package/src/ui/Calendar/Calendar.tsx +6 -0
- package/src/ui/Calendar/Calendar.types.ts +3 -0
- package/src/ui/Calendar/index.js +1 -0
- package/src/ui/Card/Card.ai.md +41 -0
- package/src/ui/Card/Card.jsx +25 -0
- package/src/ui/Card/Card.scss +47 -0
- package/src/ui/Card/Card.spec.ts +12 -0
- package/src/ui/Card/Card.stories.jsx +28 -0
- package/src/ui/Card/Card.stories.tsx +14 -0
- package/src/ui/Card/Card.test.tsx +1 -0
- package/src/ui/Card/Card.tsx +6 -0
- package/src/ui/Card/Card.types.ts +3 -0
- package/src/ui/Card/index.js +1 -0
- package/src/ui/Checkbox/Checkbox.ai.md +50 -0
- package/src/ui/Checkbox/Checkbox.jsx +73 -0
- package/src/ui/Checkbox/Checkbox.scss +115 -0
- package/src/ui/Checkbox/Checkbox.spec.ts +12 -0
- package/src/ui/Checkbox/Checkbox.stories.jsx +14 -0
- package/src/ui/Checkbox/Checkbox.stories.tsx +14 -0
- package/src/ui/Checkbox/Checkbox.test.tsx +1 -0
- package/src/ui/Checkbox/Checkbox.tsx +6 -0
- package/src/ui/Checkbox/Checkbox.types.ts +3 -0
- package/src/ui/Checkbox/index.js +1 -0
- package/src/ui/Chip/Chip.ai.md +43 -0
- package/src/ui/Chip/Chip.jsx +102 -0
- package/src/ui/Chip/Chip.scss +118 -0
- package/src/ui/Chip/Chip.spec.ts +12 -0
- package/src/ui/Chip/Chip.stories.jsx +14 -0
- package/src/ui/Chip/Chip.stories.tsx +14 -0
- package/src/ui/Chip/Chip.test.tsx +1 -0
- package/src/ui/Chip/Chip.tsx +6 -0
- package/src/ui/Chip/Chip.types.ts +3 -0
- package/src/ui/Chip/index.js +1 -0
- package/src/ui/Datepicker/Datepicker.ai.md +45 -0
- package/src/ui/Datepicker/Datepicker.jsx +330 -0
- package/src/ui/Datepicker/Datepicker.scss +206 -0
- package/src/ui/Datepicker/Datepicker.spec.ts +12 -0
- package/src/ui/Datepicker/Datepicker.stories.jsx +14 -0
- package/src/ui/Datepicker/Datepicker.stories.tsx +14 -0
- package/src/ui/Datepicker/Datepicker.test.tsx +1 -0
- package/src/ui/Datepicker/Datepicker.tsx +6 -0
- package/src/ui/Datepicker/Datepicker.types.ts +3 -0
- package/src/ui/Datepicker/index.js +2 -0
- package/src/ui/Divider/Divider.ai.md +34 -0
- package/src/ui/Divider/Divider.jsx +89 -0
- package/src/ui/Divider/Divider.scss +116 -0
- package/src/ui/Divider/Divider.spec.ts +12 -0
- package/src/ui/Divider/Divider.stories.jsx +14 -0
- package/src/ui/Divider/Divider.stories.tsx +14 -0
- package/src/ui/Divider/Divider.test.tsx +1 -0
- package/src/ui/Divider/Divider.tsx +6 -0
- package/src/ui/Divider/Divider.types.ts +3 -0
- package/src/ui/Divider/index.js +1 -0
- package/src/ui/DotStatus/DotStatus.ai.md +36 -0
- package/src/ui/DotStatus/DotStatus.jsx +64 -0
- package/src/ui/DotStatus/DotStatus.scss +87 -0
- package/src/ui/DotStatus/DotStatus.spec.ts +12 -0
- package/src/ui/DotStatus/DotStatus.stories.jsx +14 -0
- package/src/ui/DotStatus/DotStatus.stories.tsx +14 -0
- package/src/ui/DotStatus/DotStatus.test.tsx +1 -0
- package/src/ui/DotStatus/DotStatus.tsx +6 -0
- package/src/ui/DotStatus/DotStatus.types.ts +3 -0
- package/src/ui/DotStatus/index.js +1 -0
- package/src/ui/Dropdown/Dropdown.ai.md +118 -0
- package/src/ui/Dropdown/Dropdown.scss +129 -0
- package/src/ui/Dropdown/Dropdown.spec.ts +54 -0
- package/src/ui/Dropdown/Dropdown.stories.tsx +59 -0
- package/src/ui/Dropdown/Dropdown.test.tsx +37 -0
- package/src/ui/Dropdown/Dropdown.tsx +119 -0
- package/src/ui/Dropdown/Dropdown.types.ts +25 -0
- package/src/ui/Dropdown/index.js +1 -0
- package/src/ui/EventCard/EventCard.ai.md +101 -0
- package/src/ui/EventCard/EventCard.jsx +92 -0
- package/src/ui/EventCard/EventCard.scss +186 -0
- package/src/ui/EventCard/EventCard.spec.ts +12 -0
- package/src/ui/EventCard/EventCard.stories.jsx +14 -0
- package/src/ui/EventCard/EventCard.stories.tsx +14 -0
- package/src/ui/EventCard/EventCard.test.tsx +1 -0
- package/src/ui/EventCard/EventCard.tsx +6 -0
- package/src/ui/EventCard/EventCard.types.ts +3 -0
- package/src/ui/EventCard/index.js +1 -0
- package/src/ui/Field/Field.ai.md +69 -0
- package/src/ui/Field/Field.jsx +89 -0
- package/src/ui/Field/Field.scss +76 -0
- package/src/ui/Field/Field.spec.ts +12 -0
- package/src/ui/Field/Field.stories.jsx +14 -0
- package/src/ui/Field/Field.stories.tsx +14 -0
- package/src/ui/Field/Field.test.tsx +1 -0
- package/src/ui/Field/Field.tsx +6 -0
- package/src/ui/Field/Field.types.ts +3 -0
- package/src/ui/Field/index.js +1 -0
- package/src/ui/FileUpload/FileUpload.ai.md +38 -0
- package/src/ui/FileUpload/FileUpload.figma.tsx +28 -0
- package/src/ui/FileUpload/FileUpload.jsx +153 -0
- package/src/ui/FileUpload/FileUpload.scss +78 -0
- package/src/ui/FileUpload/FileUpload.spec.ts +12 -0
- package/src/ui/FileUpload/FileUpload.stories.jsx +14 -0
- package/src/ui/FileUpload/FileUpload.stories.tsx +14 -0
- package/src/ui/FileUpload/FileUpload.test.tsx +1 -0
- package/src/ui/FileUpload/FileUpload.tsx +6 -0
- package/src/ui/FileUpload/FileUpload.types.ts +3 -0
- package/src/ui/FileUpload/index.js +2 -0
- package/src/ui/Flex/Flex.ai.md +130 -0
- package/src/ui/Flex/Flex.jsx +53 -0
- package/src/ui/Flex/Flex.scss +119 -0
- package/src/ui/Flex/Flex.spec.ts +12 -0
- package/src/ui/Flex/Flex.stories.jsx +14 -0
- package/src/ui/Flex/Flex.stories.tsx +14 -0
- package/src/ui/Flex/Flex.test.tsx +1 -0
- package/src/ui/Flex/Flex.tsx +6 -0
- package/src/ui/Flex/Flex.types.ts +3 -0
- package/src/ui/Flex/index.js +1 -0
- package/src/ui/Icon/Icon.ai.md +46 -0
- package/src/ui/Icon/Icon.figma.tsx +22 -0
- package/src/ui/Icon/Icon.jsx +47 -0
- package/src/ui/Icon/Icon.scss +1 -0
- package/src/ui/Icon/Icon.spec.ts +12 -0
- package/src/ui/Icon/Icon.stories.jsx +14 -0
- package/src/ui/Icon/Icon.stories.tsx +14 -0
- package/src/ui/Icon/Icon.test.tsx +1 -0
- package/src/ui/Icon/Icon.tsx +6 -0
- package/src/ui/Icon/Icon.types.ts +3 -0
- package/src/ui/Icon/index.js +1 -0
- package/src/ui/ImageAspect/ImageAspect.ai.md +37 -0
- package/src/ui/ImageAspect/ImageAspect.jsx +56 -0
- package/src/ui/ImageAspect/ImageAspect.scss +62 -0
- package/src/ui/ImageAspect/ImageAspect.spec.ts +12 -0
- package/src/ui/ImageAspect/ImageAspect.stories.jsx +14 -0
- package/src/ui/ImageAspect/ImageAspect.stories.tsx +14 -0
- package/src/ui/ImageAspect/ImageAspect.test.tsx +1 -0
- package/src/ui/ImageAspect/ImageAspect.tsx +6 -0
- package/src/ui/ImageAspect/ImageAspect.types.ts +3 -0
- package/src/ui/ImageAspect/index.js +1 -0
- package/src/ui/Input/Input.ai.md +89 -0
- package/src/ui/Input/Input.figma.tsx +35 -0
- package/src/ui/Input/Input.scss +126 -0
- package/src/ui/Input/Input.spec.ts +54 -0
- package/src/ui/Input/Input.stories.tsx +72 -0
- package/src/ui/Input/Input.test.tsx +70 -0
- package/src/ui/Input/Input.tsx +91 -0
- package/src/ui/Input/Input.types.ts +22 -0
- package/src/ui/Input/index.js +2 -0
- package/src/ui/Key/Key.ai.md +31 -0
- package/src/ui/Key/Key.jsx +37 -0
- package/src/ui/Key/Key.scss +31 -0
- package/src/ui/Key/Key.spec.ts +12 -0
- package/src/ui/Key/Key.stories.jsx +14 -0
- package/src/ui/Key/Key.stories.tsx +14 -0
- package/src/ui/Key/Key.test.tsx +1 -0
- package/src/ui/Key/Key.tsx +6 -0
- package/src/ui/Key/Key.types.ts +3 -0
- package/src/ui/Key/index.js +1 -0
- package/src/ui/Menu/Menu.jsx +232 -0
- package/src/ui/Menu/Menu.scss +370 -0
- package/src/ui/Menu/Menu.spec.ts +12 -0
- package/src/ui/Menu/Menu.stories.jsx +41 -0
- package/src/ui/Menu/Menu.stories.tsx +14 -0
- package/src/ui/Menu/Menu.test.tsx +1 -0
- package/src/ui/Menu/Menu.tsx +6 -0
- package/src/ui/Menu/Menu.types.ts +3 -0
- package/src/ui/Menu/index.js +1 -0
- package/src/ui/MicroCalendar/MicroCalendar.ai.md +35 -0
- package/src/ui/MicroCalendar/MicroCalendar.jsx +393 -0
- package/src/ui/MicroCalendar/MicroCalendar.scss +289 -0
- package/src/ui/MicroCalendar/MicroCalendar.spec.ts +12 -0
- package/src/ui/MicroCalendar/MicroCalendar.stories.jsx +14 -0
- package/src/ui/MicroCalendar/MicroCalendar.stories.tsx +14 -0
- package/src/ui/MicroCalendar/MicroCalendar.test.tsx +1 -0
- package/src/ui/MicroCalendar/MicroCalendar.tsx +6 -0
- package/src/ui/MicroCalendar/MicroCalendar.types.ts +3 -0
- package/src/ui/MicroCalendar/index.js +1 -0
- package/src/ui/Modal/Modal.ai.md +150 -0
- package/src/ui/Modal/Modal.jsx +173 -0
- package/src/ui/Modal/Modal.scss +179 -0
- package/src/ui/Modal/Modal.spec.ts +12 -0
- package/src/ui/Modal/Modal.stories.jsx +14 -0
- package/src/ui/Modal/Modal.stories.tsx +14 -0
- package/src/ui/Modal/Modal.test.tsx +1 -0
- package/src/ui/Modal/Modal.tsx +6 -0
- package/src/ui/Modal/Modal.types.ts +3 -0
- package/src/ui/Modal/index.js +1 -0
- package/src/ui/Pagination/Pagination.ai.md +30 -0
- package/src/ui/Pagination/Pagination.jsx +237 -0
- package/src/ui/Pagination/Pagination.scss +182 -0
- package/src/ui/Pagination/Pagination.spec.ts +12 -0
- package/src/ui/Pagination/Pagination.stories.jsx +14 -0
- package/src/ui/Pagination/Pagination.stories.tsx +14 -0
- package/src/ui/Pagination/Pagination.test.tsx +1 -0
- package/src/ui/Pagination/Pagination.tsx +6 -0
- package/src/ui/Pagination/Pagination.types.ts +3 -0
- package/src/ui/Pagination/index.js +1 -0
- package/src/ui/PillToggle/PillToggle.ai.md +44 -0
- package/src/ui/PillToggle/PillToggle.jsx +56 -0
- package/src/ui/PillToggle/PillToggle.scss +84 -0
- package/src/ui/PillToggle/PillToggle.spec.ts +12 -0
- package/src/ui/PillToggle/PillToggle.stories.jsx +14 -0
- package/src/ui/PillToggle/PillToggle.stories.tsx +14 -0
- package/src/ui/PillToggle/PillToggle.test.tsx +1 -0
- package/src/ui/PillToggle/PillToggle.tsx +6 -0
- package/src/ui/PillToggle/PillToggle.types.ts +3 -0
- package/src/ui/PillToggle/index.js +1 -0
- package/src/ui/Playground/Playground.ai.md +96 -0
- package/src/ui/Playground/Playground.jsx +524 -0
- package/src/ui/Playground/Playground.scss +310 -0
- package/src/ui/Playground/Playground.spec.ts +12 -0
- package/src/ui/Playground/Playground.stories.jsx +14 -0
- package/src/ui/Playground/Playground.stories.tsx +14 -0
- package/src/ui/Playground/Playground.test.tsx +1 -0
- package/src/ui/Playground/Playground.tsx +6 -0
- package/src/ui/Playground/Playground.types.ts +3 -0
- package/src/ui/Playground/index.js +2 -0
- package/src/ui/ProgressCircle/ProgressCircle.ai.md +36 -0
- package/src/ui/ProgressCircle/ProgressCircle.jsx +147 -0
- package/src/ui/ProgressCircle/ProgressCircle.scss +143 -0
- package/src/ui/ProgressCircle/ProgressCircle.spec.ts +12 -0
- package/src/ui/ProgressCircle/ProgressCircle.stories.jsx +14 -0
- package/src/ui/ProgressCircle/ProgressCircle.stories.tsx +14 -0
- package/src/ui/ProgressCircle/ProgressCircle.test.tsx +1 -0
- package/src/ui/ProgressCircle/ProgressCircle.tsx +6 -0
- package/src/ui/ProgressCircle/ProgressCircle.types.ts +3 -0
- package/src/ui/ProgressCircle/index.js +1 -0
- package/src/ui/ProgressIndicator/ProgressIndicator.ai.md +27 -0
- package/src/ui/ProgressIndicator/ProgressIndicator.jsx +92 -0
- package/src/ui/ProgressIndicator/ProgressIndicator.scss +133 -0
- package/src/ui/ProgressIndicator/ProgressIndicator.spec.ts +12 -0
- package/src/ui/ProgressIndicator/ProgressIndicator.stories.jsx +14 -0
- package/src/ui/ProgressIndicator/ProgressIndicator.stories.tsx +14 -0
- package/src/ui/ProgressIndicator/ProgressIndicator.test.tsx +1 -0
- package/src/ui/ProgressIndicator/ProgressIndicator.tsx +6 -0
- package/src/ui/ProgressIndicator/ProgressIndicator.types.ts +3 -0
- package/src/ui/ProgressIndicator/index.js +1 -0
- package/src/ui/Radio/Radio.ai.md +53 -0
- package/src/ui/Radio/Radio.jsx +57 -0
- package/src/ui/Radio/Radio.scss +89 -0
- package/src/ui/Radio/Radio.spec.ts +12 -0
- package/src/ui/Radio/Radio.stories.jsx +14 -0
- package/src/ui/Radio/Radio.stories.tsx +14 -0
- package/src/ui/Radio/Radio.test.tsx +1 -0
- package/src/ui/Radio/Radio.tsx +6 -0
- package/src/ui/Radio/Radio.types.ts +3 -0
- package/src/ui/Radio/index.js +1 -0
- package/src/ui/Slider/Slider.ai.md +33 -0
- package/src/ui/Slider/Slider.jsx +283 -0
- package/src/ui/Slider/Slider.scss +156 -0
- package/src/ui/Slider/Slider.spec.ts +12 -0
- package/src/ui/Slider/Slider.stories.jsx +14 -0
- package/src/ui/Slider/Slider.stories.tsx +14 -0
- package/src/ui/Slider/Slider.test.tsx +1 -0
- package/src/ui/Slider/Slider.tsx +6 -0
- package/src/ui/Slider/Slider.types.ts +3 -0
- package/src/ui/Slider/index.js +1 -0
- package/src/ui/Status/Status.ai.md +36 -0
- package/src/ui/Status/Status.jsx +66 -0
- package/src/ui/Status/Status.scss +90 -0
- package/src/ui/Status/Status.spec.ts +12 -0
- package/src/ui/Status/Status.stories.jsx +14 -0
- package/src/ui/Status/Status.stories.tsx +14 -0
- package/src/ui/Status/Status.test.tsx +1 -0
- package/src/ui/Status/Status.tsx +6 -0
- package/src/ui/Status/Status.types.ts +3 -0
- package/src/ui/Status/index.js +1 -0
- package/src/ui/Steps/Steps.ai.md +56 -0
- package/src/ui/Steps/Steps.jsx +201 -0
- package/src/ui/Steps/Steps.scss +240 -0
- package/src/ui/Steps/Steps.spec.ts +12 -0
- package/src/ui/Steps/Steps.stories.jsx +14 -0
- package/src/ui/Steps/Steps.stories.tsx +14 -0
- package/src/ui/Steps/Steps.test.tsx +1 -0
- package/src/ui/Steps/Steps.tsx +6 -0
- package/src/ui/Steps/Steps.types.ts +3 -0
- package/src/ui/Steps/index.js +1 -0
- package/src/ui/Table/Table.ai.md +108 -0
- package/src/ui/Table/Table.jsx +143 -0
- package/src/ui/Table/Table.scss +90 -0
- package/src/ui/Table/Table.spec.ts +12 -0
- package/src/ui/Table/Table.stories.jsx +14 -0
- package/src/ui/Table/Table.stories.tsx +14 -0
- package/src/ui/Table/Table.test.tsx +1 -0
- package/src/ui/Table/Table.tsx +6 -0
- package/src/ui/Table/Table.types.ts +3 -0
- package/src/ui/Table/index.js +1 -0
- package/src/ui/Tabs/TabItem.jsx +80 -0
- package/src/ui/Tabs/Tabs.ai.md +52 -0
- package/src/ui/Tabs/Tabs.figma.tsx +30 -0
- package/src/ui/Tabs/Tabs.jsx +318 -0
- package/src/ui/Tabs/Tabs.scss +164 -0
- package/src/ui/Tabs/Tabs.spec.ts +12 -0
- package/src/ui/Tabs/Tabs.stories.jsx +18 -0
- package/src/ui/Tabs/Tabs.stories.tsx +14 -0
- package/src/ui/Tabs/Tabs.test.tsx +1 -0
- package/src/ui/Tabs/Tabs.tsx +6 -0
- package/src/ui/Tabs/Tabs.types.ts +3 -0
- package/src/ui/Tabs/index.js +3 -0
- package/src/ui/Tag/Tag.ai.md +59 -0
- package/src/ui/Tag/Tag.figma.tsx +29 -0
- package/src/ui/Tag/Tag.jsx +93 -0
- package/src/ui/Tag/Tag.scss +258 -0
- package/src/ui/Tag/Tag.spec.ts +12 -0
- package/src/ui/Tag/Tag.stories.jsx +14 -0
- package/src/ui/Tag/Tag.stories.tsx +14 -0
- package/src/ui/Tag/Tag.test.tsx +1 -0
- package/src/ui/Tag/Tag.tsx +6 -0
- package/src/ui/Tag/Tag.types.ts +3 -0
- package/src/ui/Tag/index.js +2 -0
- package/src/ui/Textarea/Textarea.ai.md +40 -0
- package/src/ui/Textarea/Textarea.figma.tsx +35 -0
- package/src/ui/Textarea/Textarea.jsx +68 -0
- package/src/ui/Textarea/Textarea.scss +71 -0
- package/src/ui/Textarea/Textarea.spec.ts +12 -0
- package/src/ui/Textarea/Textarea.stories.jsx +14 -0
- package/src/ui/Textarea/Textarea.stories.tsx +14 -0
- package/src/ui/Textarea/Textarea.test.tsx +1 -0
- package/src/ui/Textarea/Textarea.tsx +6 -0
- package/src/ui/Textarea/Textarea.types.ts +3 -0
- package/src/ui/Textarea/index.js +2 -0
- package/src/ui/Toast/Toast.ai.md +47 -0
- package/src/ui/Toast/Toast.jsx +75 -0
- package/src/ui/Toast/Toast.scss +132 -0
- package/src/ui/Toast/Toast.spec.ts +12 -0
- package/src/ui/Toast/Toast.stories.jsx +14 -0
- package/src/ui/Toast/Toast.stories.tsx +14 -0
- package/src/ui/Toast/Toast.test.tsx +1 -0
- package/src/ui/Toast/Toast.tsx +6 -0
- package/src/ui/Toast/Toast.types.ts +3 -0
- package/src/ui/Toast/index.js +2 -0
- package/src/ui/Toggle/Toggle.ai.md +37 -0
- package/src/ui/Toggle/Toggle.jsx +73 -0
- package/src/ui/Toggle/Toggle.scss +139 -0
- package/src/ui/Toggle/Toggle.spec.ts +12 -0
- package/src/ui/Toggle/Toggle.stories.jsx +14 -0
- package/src/ui/Toggle/Toggle.stories.tsx +14 -0
- package/src/ui/Toggle/Toggle.test.tsx +1 -0
- package/src/ui/Toggle/Toggle.tsx +6 -0
- package/src/ui/Toggle/Toggle.types.ts +3 -0
- package/src/ui/Toggle/index.js +1 -0
- package/src/ui/Tooltip/Tooltip.ai.md +33 -0
- package/src/ui/Tooltip/Tooltip.figma.tsx +24 -0
- package/src/ui/Tooltip/Tooltip.jsx +125 -0
- package/src/ui/Tooltip/Tooltip.scss +80 -0
- package/src/ui/Tooltip/Tooltip.spec.ts +12 -0
- package/src/ui/Tooltip/Tooltip.stories.jsx +14 -0
- package/src/ui/Tooltip/Tooltip.stories.tsx +14 -0
- package/src/ui/Tooltip/Tooltip.test.tsx +1 -0
- package/src/ui/Tooltip/Tooltip.tsx +6 -0
- package/src/ui/Tooltip/Tooltip.types.ts +3 -0
- package/src/ui/Tooltip/index.js +2 -0
- package/src/ui/UDS/UDS.jsx +52 -0
- package/src/ui/UDS/UDS.scss +49 -0
- package/src/ui/UDS/UDS.spec.ts +12 -0
- package/src/ui/UDS/UDS.stories.jsx +22 -0
- package/src/ui/UDS/UDS.stories.tsx +14 -0
- package/src/ui/UDS/UDS.test.tsx +1 -0
- package/src/ui/UDS/UDS.tsx +6 -0
- package/src/ui/UDS/UDS.types.ts +3 -0
- package/src/ui/UDS/index.js +1 -0
- package/src/ui/_spec/createMetaFromSpec.ts +35 -0
- package/src/ui/_spec/createStoryArgsFromSpec.ts +8 -0
- package/src/ui/_spec/generated/spec-props-reference.md +55 -0
- package/src/ui/_spec/specStorySync.test.ts +73 -0
- package/src/ui/_spec/types.ts +21 -0
- package/src/ui/index.js +66 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
3
|
+
Primary action trigger component supporting multiple visual styles, sizes, and icon layouts.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
- Triggering actions (submit, save, delete, navigate)
|
|
7
|
+
- Primary CTA buttons, secondary actions, destructive confirmations
|
|
8
|
+
- Icon-only actions in toolbars or compact UIs
|
|
9
|
+
|
|
10
|
+
## Props
|
|
11
|
+
|
|
12
|
+
| Prop | Type | Default | Values | Description |
|
|
13
|
+
|------|------|---------|--------|-------------|
|
|
14
|
+
| `label` | `string` | — | Any text | Button text label |
|
|
15
|
+
| `appearance` | `string` | `"primary"` | `"primary"`, `"soft"`, `"outline"`, `"text"`, `"ghost"`, `"disabled"`, `"destructive"` | Visual style variant |
|
|
16
|
+
| `layout` | `string` | `"label-only"` | `"label-only"`, `"icon-left"`, `"icon-right"`, `"icon-only"`, `"only"` | Content arrangement |
|
|
17
|
+
| `size` | `string` | `"default"` | `"large"`, `"default"`, `"small"`, `"xsmall"` | Button size |
|
|
18
|
+
| `icon` | `string` or `ReactNode` | — | Phosphor icon name (e.g., `"ArrowRight"`, `"Plus"`, `"Trash"`) or JSX | Icon to display |
|
|
19
|
+
| `iconSize` | `number` | — | Any number | Override icon size in px |
|
|
20
|
+
| `className` | `string` | `""` | Any CSS class | Additional CSS classes |
|
|
21
|
+
| `tracking` | `string` or `object` | — | `"event-name"` or `{ event, category, ... }` | Fires a `uds:track` CustomEvent on click with a structured payload |
|
|
22
|
+
| `onClick` | `function` | — | — | Click handler |
|
|
23
|
+
| `disabled` | `boolean` | `false` | — | Disables the button |
|
|
24
|
+
| `aria-label` | `string` | — | — | Accessible label (auto-generated for icon-only) |
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### Basic buttons
|
|
29
|
+
```jsx
|
|
30
|
+
<Button label="Save" />
|
|
31
|
+
<Button label="Cancel" appearance="outline" />
|
|
32
|
+
<Button label="Delete" appearance="destructive" />
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### With icons
|
|
36
|
+
```jsx
|
|
37
|
+
<Button label="Add Item" icon="Plus" layout="icon-left" />
|
|
38
|
+
<Button label="Next" icon="ArrowRight" layout="icon-right" />
|
|
39
|
+
<Button icon="Trash" layout="icon-only" aria-label="Delete item" />
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Size variants
|
|
43
|
+
```jsx
|
|
44
|
+
<Button label="Large" size="large" />
|
|
45
|
+
<Button label="Default" />
|
|
46
|
+
<Button label="Small" size="small" />
|
|
47
|
+
<Button label="XSmall" size="xsmall" />
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### All appearances
|
|
51
|
+
```jsx
|
|
52
|
+
<Button label="Primary" appearance="primary" />
|
|
53
|
+
<Button label="Soft" appearance="soft" />
|
|
54
|
+
<Button label="Outline" appearance="outline" />
|
|
55
|
+
<Button label="Text" appearance="text" />
|
|
56
|
+
<Button label="Ghost" appearance="ghost" />
|
|
57
|
+
<Button label="Destructive" appearance="destructive" />
|
|
58
|
+
<Button label="Disabled" appearance="disabled" />
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Action bar pattern
|
|
62
|
+
```jsx
|
|
63
|
+
<Flex gap="8" justifyContent="flex-end">
|
|
64
|
+
<Button label="Cancel" appearance="outline" onClick={onCancel} />
|
|
65
|
+
<Button label="Save Changes" icon="FloppyDisk" layout="icon-left" onClick={onSave} />
|
|
66
|
+
</Flex>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Toolbar with icon-only buttons
|
|
70
|
+
```jsx
|
|
71
|
+
<Flex gap="4">
|
|
72
|
+
<Button icon="TextB" layout="icon-only" appearance="ghost" aria-label="Bold" />
|
|
73
|
+
<Button icon="TextItalic" layout="icon-only" appearance="ghost" aria-label="Italic" />
|
|
74
|
+
<Button icon="TextUnderline" layout="icon-only" appearance="ghost" aria-label="Underline" />
|
|
75
|
+
</Flex>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Data tracking
|
|
79
|
+
```jsx
|
|
80
|
+
// Simple string event name
|
|
81
|
+
<Button label="Sign Up" tracking="signup-cta" onClick={handleSignUp} />
|
|
82
|
+
|
|
83
|
+
// Rich payload — all fields are merged into the CustomEvent detail
|
|
84
|
+
<Button
|
|
85
|
+
label="Add to Cart"
|
|
86
|
+
icon="ShoppingCart"
|
|
87
|
+
layout="icon-left"
|
|
88
|
+
tracking={{ event: "add_to_cart", category: "ecommerce", productId: "widget-123" }}
|
|
89
|
+
onClick={handleAddToCart}
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
// Subscribe in your app root
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
const handler = (e) => analytics.track(e.detail.event ?? e.detail.action, e.detail);
|
|
95
|
+
window.addEventListener("uds:track", handler);
|
|
96
|
+
return () => window.removeEventListener("uds:track", handler);
|
|
97
|
+
}, []);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Composition
|
|
101
|
+
|
|
102
|
+
- **In forms**: Place at the bottom of form sections, typically paired with a cancel button
|
|
103
|
+
- **In `Card`**: Use in card footer for card-level actions
|
|
104
|
+
- **In `UDS.PageHeader`**: Pass as `actions` prop for page-level actions
|
|
105
|
+
- **In `Table` rows**: Use `size="xsmall"` or `"small"` with `appearance="ghost"` for inline row actions
|
|
106
|
+
- **In `UDS.Modal` footer**: Primary + secondary action buttons
|
|
107
|
+
|
|
108
|
+
## Do's and Don'ts
|
|
109
|
+
|
|
110
|
+
✅ **Do**: Use `appearance="destructive"` for delete/remove actions
|
|
111
|
+
✅ **Do**: Always provide `aria-label` for icon-only buttons
|
|
112
|
+
✅ **Do**: Use `icon` prop with a Phosphor icon name string (e.g., `icon="Plus"`)
|
|
113
|
+
✅ **Do**: Use `layout="icon-left"` for action buttons with context (e.g., "Add User")
|
|
114
|
+
|
|
115
|
+
❌ **Don't**: Use `appearance="disabled"` for conditional disabling — use the `disabled` prop instead
|
|
116
|
+
❌ **Don't**: Use `appearance="primary"` for every button — reserve for the main page action
|
|
117
|
+
❌ **Don't**: Nest interactive elements inside Button
|
|
118
|
+
|
|
119
|
+
## Accessibility
|
|
120
|
+
- Icon-only buttons automatically get `aria-label` from the `label` prop or icon name
|
|
121
|
+
- Disabled buttons use native `disabled` attribute
|
|
122
|
+
- Renders as `<button type="button">` by default
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import Button from "./Button"
|
|
3
|
+
import figma from "@figma/code-connect"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* -- This file was auto-generated by Code Connect --
|
|
7
|
+
* `props` includes a mapping from Figma properties and variants to
|
|
8
|
+
* suggested values. You should update this to match the props of your
|
|
9
|
+
* code component, and update the `example` function to return the
|
|
10
|
+
* code example you'd like to see in Figma
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
figma.connect(
|
|
14
|
+
Button,
|
|
15
|
+
"https://www.figma.com/file/LkIyThUA0oVNsDEAyOF7ER/Design-System--Components?node-id=19%3A360",
|
|
16
|
+
{
|
|
17
|
+
props: {
|
|
18
|
+
label: figma.string("Label"),
|
|
19
|
+
appearance: figma.enum("Appearance", {
|
|
20
|
+
Primary: "primary",
|
|
21
|
+
Soft: "soft",
|
|
22
|
+
Disabled: "disabled",
|
|
23
|
+
Outline: "outline",
|
|
24
|
+
"Ghost+": "ghost-",
|
|
25
|
+
Destructive: "destructive",
|
|
26
|
+
Ghost: "ghost",
|
|
27
|
+
}),
|
|
28
|
+
layout: figma.enum("Layout", {
|
|
29
|
+
"Label Only": "label-only",
|
|
30
|
+
"Icon Right": "icon-right",
|
|
31
|
+
"Icon Left": "icon-left",
|
|
32
|
+
"Icon Only": "icon-only",
|
|
33
|
+
}),
|
|
34
|
+
state: figma.enum("State", {
|
|
35
|
+
Default: "default",
|
|
36
|
+
Focus: "focus",
|
|
37
|
+
Hover: "hover",
|
|
38
|
+
}),
|
|
39
|
+
size: figma.enum("Size", {
|
|
40
|
+
XSmall: "xsmall",
|
|
41
|
+
Large: "large",
|
|
42
|
+
Default: "default",
|
|
43
|
+
Small: "small",
|
|
44
|
+
}),
|
|
45
|
+
onDark: figma.boolean("On Dark"),
|
|
46
|
+
},
|
|
47
|
+
example: (props) => <Button />,
|
|
48
|
+
},
|
|
49
|
+
)
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
@use "../../styles/typography" as *;
|
|
2
|
+
|
|
3
|
+
.uds-button {
|
|
4
|
+
all: unset;
|
|
5
|
+
@include uds-body-16-semibold;
|
|
6
|
+
align-items: center;
|
|
7
|
+
background: var(--uds-button-surface-primary-default);
|
|
8
|
+
border: var(--uds-border-width-1) solid var(--uds-button-border-primary-default);
|
|
9
|
+
border-radius: var(--uds-radius-4);
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
color: var(--uds-button-text-default);
|
|
12
|
+
cursor: pointer;
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
gap: var(--uds-gap-4);
|
|
16
|
+
height: fit-content;
|
|
17
|
+
padding-inline: var(--uds-spacing-16);
|
|
18
|
+
padding-block: var(--uds-spacing-10);
|
|
19
|
+
text-transform: capitalize;
|
|
20
|
+
width: fit-content;
|
|
21
|
+
transition: all var(--uds-animation-duration-200) var(--uds-animation-ease-standard);
|
|
22
|
+
|
|
23
|
+
&:hover:not(:disabled) {
|
|
24
|
+
background: var(--uds-button-surface-primary-hover);
|
|
25
|
+
border-color: var(--uds-button-border-primary-hover);
|
|
26
|
+
color: var(--uds-button-text-default);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&__icon {
|
|
30
|
+
display: inline-flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
line-height: 0;
|
|
34
|
+
|
|
35
|
+
svg {
|
|
36
|
+
width: 20px;
|
|
37
|
+
height: 20px;
|
|
38
|
+
flex-shrink: 0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&__label {
|
|
43
|
+
display: inline-block;
|
|
44
|
+
padding: 0 var(--uds-spacing-4);
|
|
45
|
+
white-space: nowrap;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&:focus-visible {
|
|
49
|
+
outline: solid var(--uds-focus-ring-width) var(--uds-focus-ring-border);
|
|
50
|
+
outline-offset: var(--uds-focus-ring-offset);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
&.large {
|
|
54
|
+
@include uds-body-20-semibold;
|
|
55
|
+
padding: var(--uds-spacing-12) var(--uds-spacing-18);
|
|
56
|
+
|
|
57
|
+
.uds-button__icon svg {
|
|
58
|
+
width: 24px;
|
|
59
|
+
height: 24px;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&.small {
|
|
64
|
+
@include uds-body-14-semibold;
|
|
65
|
+
padding: var(--uds-spacing-8) var(--uds-spacing-12);
|
|
66
|
+
|
|
67
|
+
.uds-button__icon svg {
|
|
68
|
+
width: 16px;
|
|
69
|
+
height: 16px;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&.xsmall {
|
|
74
|
+
@include uds-body-12-semibold;
|
|
75
|
+
padding: var(--uds-spacing-8) var(--uds-spacing-10);
|
|
76
|
+
|
|
77
|
+
.uds-button__icon svg {
|
|
78
|
+
width: 16px;
|
|
79
|
+
height: 16px;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
&.icon {
|
|
84
|
+
&-only {
|
|
85
|
+
padding: var(--uds-spacing-12);
|
|
86
|
+
|
|
87
|
+
&.large {
|
|
88
|
+
padding: var(--uds-spacing-14);
|
|
89
|
+
|
|
90
|
+
.uds-button__icon svg {
|
|
91
|
+
width: 24px;
|
|
92
|
+
height: 24px;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
&.small {
|
|
97
|
+
padding: var(--uds-spacing-10);
|
|
98
|
+
|
|
99
|
+
.uds-button__icon svg {
|
|
100
|
+
width: 16px;
|
|
101
|
+
height: 16px;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
&.xsmall {
|
|
106
|
+
padding: var(--uds-spacing-8);
|
|
107
|
+
|
|
108
|
+
.uds-button__icon svg {
|
|
109
|
+
width: 16px;
|
|
110
|
+
height: 16px;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
&.soft {
|
|
117
|
+
background: var(--uds-button-surface-secondary-default);
|
|
118
|
+
border-color: var(--uds-button-border-secondary-default);
|
|
119
|
+
color: var(--uds-button-text-secondary);
|
|
120
|
+
|
|
121
|
+
&:hover:not(:disabled) {
|
|
122
|
+
background: var(--uds-button-surface-secondary-hover);
|
|
123
|
+
border-color: var(--uds-button-border-secondary-hover);
|
|
124
|
+
color: var(--uds-button-text-secondary);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
&.outline {
|
|
129
|
+
background: var(--uds-color-transparent);
|
|
130
|
+
border: solid 1px var(--uds-border-primary);
|
|
131
|
+
color: var(--uds-text-primary);
|
|
132
|
+
|
|
133
|
+
&:hover:not(:disabled) {
|
|
134
|
+
background: var(--uds-color-transparent);
|
|
135
|
+
border-color: var(--uds-border-brand-primary);
|
|
136
|
+
color: var(--uds-text-primary);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
&.text {
|
|
141
|
+
background: var(--uds-surface-transparent);
|
|
142
|
+
color: var(--uds-text-primary);
|
|
143
|
+
border-color: var(--uds-border-transparent);
|
|
144
|
+
|
|
145
|
+
&:hover:not(:disabled) {
|
|
146
|
+
background: var(--uds-surface-transparent);
|
|
147
|
+
color: var(--uds-text-brand-primary);
|
|
148
|
+
border-color: var(--uds-border-transparent);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
&.ghost {
|
|
153
|
+
background: var(--uds-surface-transparent);
|
|
154
|
+
color: var(--uds-text-brand-primary);
|
|
155
|
+
border-color: var(--uds-border-transparent);
|
|
156
|
+
|
|
157
|
+
&:hover:not(:disabled) {
|
|
158
|
+
background: var(--uds-surface-transparent);
|
|
159
|
+
color: var(--uds-text-brand-primary);
|
|
160
|
+
border-color: var(--uds-border-transparent);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
&.destructive {
|
|
165
|
+
background: var(--uds-button-surface-primary-destructive);
|
|
166
|
+
color: var(--uds-button-text-default);
|
|
167
|
+
border-color: var(--uds-button-border-primary-destructive);
|
|
168
|
+
|
|
169
|
+
&:hover:not(:disabled) {
|
|
170
|
+
background: var(--uds-button-surface-primary-destructive);
|
|
171
|
+
color: var(--uds-button-text-default);
|
|
172
|
+
border-color: var(--uds-button-border-primary-destructive);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
&.disabled {
|
|
177
|
+
background: var(--uds-button-surface-primary-disabled);
|
|
178
|
+
color: var(--uds-button-text-disabled);
|
|
179
|
+
cursor: not-allowed;
|
|
180
|
+
border-color: var(--uds-button-border-primary-disabled);
|
|
181
|
+
box-shadow: none;
|
|
182
|
+
pointer-events: none;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
&:disabled {
|
|
186
|
+
cursor: not-allowed;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export const BUTTON_LAYOUTS = [
|
|
2
|
+
"label-only",
|
|
3
|
+
"icon-left",
|
|
4
|
+
"icon-right",
|
|
5
|
+
"icon-only",
|
|
6
|
+
"only",
|
|
7
|
+
] as const;
|
|
8
|
+
|
|
9
|
+
export const BUTTON_APPEARANCES = [
|
|
10
|
+
"primary",
|
|
11
|
+
"soft",
|
|
12
|
+
"outline",
|
|
13
|
+
"text",
|
|
14
|
+
"ghost",
|
|
15
|
+
"disabled",
|
|
16
|
+
"destructive",
|
|
17
|
+
] as const;
|
|
18
|
+
|
|
19
|
+
export const BUTTON_SIZES = ["large", "default", "small", "xsmall"] as const;
|
|
20
|
+
|
|
21
|
+
export const BUTTON_DEFAULTS = {
|
|
22
|
+
appearance: "primary",
|
|
23
|
+
layout: "label-only",
|
|
24
|
+
size: "default",
|
|
25
|
+
} as const;
|
|
26
|
+
|
|
27
|
+
export const BUTTON_CLASS_MAP = {
|
|
28
|
+
layout: {
|
|
29
|
+
"label-only": "label-only",
|
|
30
|
+
"icon-left": "icon-left",
|
|
31
|
+
"icon-right": "icon-right",
|
|
32
|
+
"icon-only": "icon-only",
|
|
33
|
+
only: "only",
|
|
34
|
+
} as const,
|
|
35
|
+
appearance: {
|
|
36
|
+
primary: "primary",
|
|
37
|
+
soft: "soft",
|
|
38
|
+
outline: "outline",
|
|
39
|
+
text: "text",
|
|
40
|
+
ghost: "ghost",
|
|
41
|
+
disabled: "disabled",
|
|
42
|
+
destructive: "destructive",
|
|
43
|
+
} as const,
|
|
44
|
+
size: {
|
|
45
|
+
large: "large",
|
|
46
|
+
default: "default",
|
|
47
|
+
small: "small",
|
|
48
|
+
xsmall: "xsmall",
|
|
49
|
+
} as const,
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
52
|
+
export const BUTTON_BASE_CLASS = "uds-button";
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import Button from "./Button";
|
|
2
|
+
import { createStoryArgsFromSpec } from "../_spec/createStoryArgsFromSpec";
|
|
3
|
+
import {
|
|
4
|
+
BUTTON_APPEARANCES,
|
|
5
|
+
BUTTON_DEFAULTS,
|
|
6
|
+
BUTTON_LAYOUTS,
|
|
7
|
+
BUTTON_SIZES,
|
|
8
|
+
} from "./Button.spec";
|
|
9
|
+
import type { StorySpec } from "../_spec/types";
|
|
10
|
+
|
|
11
|
+
type ButtonStoryArgs = {
|
|
12
|
+
label: string;
|
|
13
|
+
icon?: string;
|
|
14
|
+
appearance: (typeof BUTTON_APPEARANCES)[number];
|
|
15
|
+
layout: (typeof BUTTON_LAYOUTS)[number];
|
|
16
|
+
size: (typeof BUTTON_SIZES)[number];
|
|
17
|
+
iconSize?: number;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
tracking?: string | Record<string, unknown>;
|
|
20
|
+
"aria-label"?: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const BUTTON_DEFAULT_ARGS: ButtonStoryArgs = {
|
|
24
|
+
label: "Button",
|
|
25
|
+
icon: "Plus",
|
|
26
|
+
appearance: BUTTON_DEFAULTS.appearance,
|
|
27
|
+
layout: BUTTON_DEFAULTS.layout,
|
|
28
|
+
size: BUTTON_DEFAULTS.size,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const BUTTON_STORY_SPEC = {
|
|
32
|
+
defaults: BUTTON_DEFAULT_ARGS,
|
|
33
|
+
options: {
|
|
34
|
+
appearance: BUTTON_APPEARANCES,
|
|
35
|
+
layout: BUTTON_LAYOUTS,
|
|
36
|
+
size: BUTTON_SIZES,
|
|
37
|
+
},
|
|
38
|
+
stories: {
|
|
39
|
+
primary: { label: "Primary", appearance: "primary" },
|
|
40
|
+
soft: { label: "Soft", appearance: "soft" },
|
|
41
|
+
outline: { label: "Outline", appearance: "outline" },
|
|
42
|
+
text: { label: "Text", appearance: "text" },
|
|
43
|
+
ghost: { label: "Ghost", appearance: "ghost" },
|
|
44
|
+
destructive: { label: "Destructive", appearance: "destructive" },
|
|
45
|
+
disabled: { label: "Disabled", appearance: "disabled", disabled: true },
|
|
46
|
+
large: { label: "Large", size: "large" },
|
|
47
|
+
small: { label: "Small", size: "small" },
|
|
48
|
+
xsmall: { label: "XSmall", size: "xsmall" },
|
|
49
|
+
iconLeft: { label: "Add Item", icon: "Plus", layout: "icon-left" },
|
|
50
|
+
iconRight: { label: "Next", icon: "ArrowRight", layout: "icon-right" },
|
|
51
|
+
iconOnly: { icon: "Trash", layout: "icon-only", label: "", "aria-label": "Delete item" },
|
|
52
|
+
customIconSize: {
|
|
53
|
+
label: "Download",
|
|
54
|
+
icon: "DownloadSimple",
|
|
55
|
+
layout: "icon-left",
|
|
56
|
+
iconSize: 24,
|
|
57
|
+
},
|
|
58
|
+
trackingString: {
|
|
59
|
+
label: "Sign Up",
|
|
60
|
+
tracking: "signup-cta",
|
|
61
|
+
},
|
|
62
|
+
trackingObject: {
|
|
63
|
+
label: "Add to Cart",
|
|
64
|
+
icon: "ShoppingCart",
|
|
65
|
+
layout: "icon-left",
|
|
66
|
+
tracking: {
|
|
67
|
+
event: "add_to_cart",
|
|
68
|
+
category: "ecommerce",
|
|
69
|
+
productId: "widget-123",
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
} as const,
|
|
73
|
+
} satisfies StorySpec<ButtonStoryArgs>;
|
|
74
|
+
|
|
75
|
+
const fromSpec = createStoryArgsFromSpec<ButtonStoryArgs>(
|
|
76
|
+
BUTTON_STORY_SPEC.defaults,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
export default {
|
|
80
|
+
title: "Components/Button",
|
|
81
|
+
component: Button,
|
|
82
|
+
tags: ["autodocs"],
|
|
83
|
+
args: BUTTON_STORY_SPEC.defaults,
|
|
84
|
+
argTypes: {
|
|
85
|
+
label: {
|
|
86
|
+
control: "text",
|
|
87
|
+
description: "Button text label",
|
|
88
|
+
},
|
|
89
|
+
tracking: {
|
|
90
|
+
control: "object",
|
|
91
|
+
description:
|
|
92
|
+
'Analytics payload — string or object. Fires a "uds:track" CustomEvent on click.',
|
|
93
|
+
},
|
|
94
|
+
icon: {
|
|
95
|
+
control: "text",
|
|
96
|
+
description: "Phosphor icon name (e.g. ArrowRight, Plus, Trash)",
|
|
97
|
+
},
|
|
98
|
+
iconSize: {
|
|
99
|
+
control: "number",
|
|
100
|
+
description: "Override icon size in px",
|
|
101
|
+
},
|
|
102
|
+
disabled: {
|
|
103
|
+
control: "boolean",
|
|
104
|
+
description: "Disables the button",
|
|
105
|
+
},
|
|
106
|
+
onClick: {
|
|
107
|
+
action: "clicked",
|
|
108
|
+
description: "Click handler",
|
|
109
|
+
},
|
|
110
|
+
appearance: {
|
|
111
|
+
control: "select",
|
|
112
|
+
options: [...BUTTON_APPEARANCES],
|
|
113
|
+
description: "Visual style variant",
|
|
114
|
+
},
|
|
115
|
+
layout: {
|
|
116
|
+
control: "select",
|
|
117
|
+
options: [...BUTTON_LAYOUTS],
|
|
118
|
+
description: "Content arrangement",
|
|
119
|
+
},
|
|
120
|
+
size: {
|
|
121
|
+
control: "select",
|
|
122
|
+
options: [...BUTTON_SIZES],
|
|
123
|
+
description: "Button size",
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
parameters: {
|
|
127
|
+
layout: "centered",
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const Default = {
|
|
132
|
+
args: fromSpec({}),
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const Primary = {
|
|
136
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.primary),
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const Soft = {
|
|
140
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.soft),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export const Outline = {
|
|
144
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.outline),
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export const Text = {
|
|
148
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.text),
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export const Ghost = {
|
|
152
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.ghost),
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export const Destructive = {
|
|
156
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.destructive),
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export const Disabled = {
|
|
160
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.disabled),
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export const Large = {
|
|
164
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.large),
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export const Small = {
|
|
168
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.small),
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export const XSmall = {
|
|
172
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.xsmall),
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export const IconLeft = {
|
|
176
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.iconLeft),
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export const IconRight = {
|
|
180
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.iconRight),
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const IconOnly = {
|
|
184
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.iconOnly),
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export const CustomIconSize = {
|
|
188
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.customIconSize),
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const TrackingString = {
|
|
192
|
+
name: "Tracking (string)",
|
|
193
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.trackingString),
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export const TrackingObject = {
|
|
197
|
+
name: "Tracking (object)",
|
|
198
|
+
args: fromSpec(BUTTON_STORY_SPEC.stories.trackingObject),
|
|
199
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { describe, test, jest } from "@jest/globals";
|
|
2
|
+
import { render, screen, fireEvent } from "@testing-library/react";
|
|
3
|
+
import Button from "./Button";
|
|
4
|
+
import {
|
|
5
|
+
BUTTON_APPEARANCES,
|
|
6
|
+
BUTTON_DEFAULTS,
|
|
7
|
+
BUTTON_LAYOUTS,
|
|
8
|
+
BUTTON_SIZES,
|
|
9
|
+
} from "./Button.spec";
|
|
10
|
+
|
|
11
|
+
describe("Button spec sync", () => {
|
|
12
|
+
test("renders with spec defaults", () => {
|
|
13
|
+
render(<Button label="Default" />);
|
|
14
|
+
const button = screen.getByRole("button", { name: "Default" });
|
|
15
|
+
expect(button).toHaveClass("uds-button");
|
|
16
|
+
expect(button).not.toHaveClass(BUTTON_DEFAULTS.appearance);
|
|
17
|
+
expect(button).not.toHaveClass(BUTTON_DEFAULTS.layout);
|
|
18
|
+
expect(button).not.toHaveClass(BUTTON_DEFAULTS.size);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("supports all appearance options from spec", () => {
|
|
22
|
+
BUTTON_APPEARANCES.forEach((appearance) => {
|
|
23
|
+
const { unmount } = render(<Button label={appearance} appearance={appearance} />);
|
|
24
|
+
const button = screen.getByRole("button", { name: appearance });
|
|
25
|
+
if (appearance === BUTTON_DEFAULTS.appearance) {
|
|
26
|
+
expect(button).not.toHaveClass(appearance);
|
|
27
|
+
} else {
|
|
28
|
+
expect(button).toHaveClass(appearance);
|
|
29
|
+
}
|
|
30
|
+
unmount();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("supports all size options from spec", () => {
|
|
35
|
+
BUTTON_SIZES.forEach((size) => {
|
|
36
|
+
const { unmount } = render(<Button label={size} size={size} />);
|
|
37
|
+
const button = screen.getByRole("button", { name: size });
|
|
38
|
+
if (size === BUTTON_DEFAULTS.size) {
|
|
39
|
+
expect(button).not.toHaveClass(size);
|
|
40
|
+
} else {
|
|
41
|
+
expect(button).toHaveClass(size);
|
|
42
|
+
}
|
|
43
|
+
unmount();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("supports all layout options from spec", () => {
|
|
48
|
+
BUTTON_LAYOUTS.forEach((layout) => {
|
|
49
|
+
const isIconOnly = layout === "icon-only" || layout === "only";
|
|
50
|
+
const baseProps = {
|
|
51
|
+
icon: "Plus",
|
|
52
|
+
layout,
|
|
53
|
+
} as const;
|
|
54
|
+
const props = isIconOnly
|
|
55
|
+
? { ...baseProps, "aria-label": "icon-action" }
|
|
56
|
+
: { ...baseProps, label: layout };
|
|
57
|
+
|
|
58
|
+
const { unmount } = render(
|
|
59
|
+
<Button {...props} />,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const button = screen.getByRole("button", {
|
|
63
|
+
name: isIconOnly ? "icon-action" : layout,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
if (layout === BUTTON_DEFAULTS.layout) {
|
|
67
|
+
expect(button).not.toHaveClass(layout);
|
|
68
|
+
} else {
|
|
69
|
+
expect(button).toHaveClass(layout);
|
|
70
|
+
}
|
|
71
|
+
unmount();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("tracks click event when tracking prop is provided", () => {
|
|
76
|
+
const onTrack = jest.fn();
|
|
77
|
+
window.addEventListener("uds:track", onTrack as EventListener);
|
|
78
|
+
|
|
79
|
+
render(<Button label="Track me" tracking="cta-click" />);
|
|
80
|
+
fireEvent.click(screen.getByRole("button", { name: "Track me" }));
|
|
81
|
+
|
|
82
|
+
expect(onTrack).toHaveBeenCalled();
|
|
83
|
+
window.removeEventListener("uds:track", onTrack as EventListener);
|
|
84
|
+
});
|
|
85
|
+
});
|