@byline/ui 6.8.0 → 6.10.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.
Files changed (51) hide show
  1. package/README.md +43 -5
  2. package/package.json +16 -7
  3. package/src/components/accordion/accordion.stories.tsx +121 -0
  4. package/src/components/animation/fade-in-lift.stories.tsx +80 -0
  5. package/src/components/avatar/avatar.stories.tsx +39 -0
  6. package/src/components/badge/badge.stories.tsx +41 -0
  7. package/src/components/button/button-group.stories.tsx +44 -0
  8. package/src/components/button/button-intents.stories.tsx +97 -0
  9. package/src/components/button/button-overrides.stories.tsx +59 -0
  10. package/src/components/button/button-test.stories.tsx +59 -0
  11. package/src/components/button/button-variants.stories.tsx +57 -0
  12. package/src/components/button/combo-buttons.stories.tsx +82 -0
  13. package/src/components/button/control-buttons.stories.tsx +60 -0
  14. package/src/components/button/copy-button.stories.tsx +50 -0
  15. package/src/components/button/icon-button.stories.tsx +140 -0
  16. package/src/components/card/card.stories.tsx +60 -0
  17. package/src/components/chips/chip.stories.tsx +120 -0
  18. package/src/components/container/container.stories.tsx +35 -0
  19. package/src/components/dropdown/dropdown.stories.tsx +108 -0
  20. package/src/components/hamburger/hamburger.stories.tsx +33 -0
  21. package/src/components/inputs/autocomplete.stories.tsx +189 -0
  22. package/src/components/inputs/calendar.stories.tsx +141 -0
  23. package/src/components/inputs/checkbox-group.stories.tsx +43 -0
  24. package/src/components/inputs/checkbox.stories.tsx +284 -0
  25. package/src/components/inputs/input.stories.tsx +189 -0
  26. package/src/components/inputs/radio-group.stories.tsx +73 -0
  27. package/src/components/inputs/select.stories.tsx +70 -0
  28. package/src/components/inputs/text-area.stories.tsx +45 -0
  29. package/src/components/notifications/alert.stories.tsx +75 -0
  30. package/src/components/notifications/toast.stories.tsx +40 -0
  31. package/src/components/pager/pagination.stories.tsx +189 -0
  32. package/src/components/scroll-area/scroll-area.stories.tsx +33 -0
  33. package/src/components/shimmer/shimmer.stories.tsx +24 -0
  34. package/src/components/table/table.stories.tsx +94 -0
  35. package/src/components/tabs/tabs.stories.tsx +47 -0
  36. package/src/components/tooltip/tooltip.stories.tsx +56 -0
  37. package/src/icons/icons.stories.tsx +67 -0
  38. package/src/icons/index.stories.tsx +24 -0
  39. package/src/loaders/loaders.stories.tsx +188 -0
  40. package/src/styles/base/colors.stories.tsx +671 -0
  41. package/src/styles/theme/theme.stories.tsx +40 -0
  42. package/src/styles/typography/article.stories.tsx +39 -0
  43. package/src/styles/typography/code.stories.tsx +73 -0
  44. package/src/styles/typography/default.stories.tsx +49 -0
  45. package/src/styles/typography/lists.stories.tsx +48 -0
  46. package/src/styles/typography/quote.stories.tsx +38 -0
  47. package/src/widgets/datepicker/datepicker.stories.tsx +42 -0
  48. package/src/widgets/drawer/drawer.stories.tsx +281 -0
  49. package/src/widgets/modal/modal.stories.tsx +63 -0
  50. package/src/widgets/search/search.stories.tsx +18 -0
  51. package/src/widgets/timeline/timeline.stories.tsx +50 -0
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @byline/ui
2
2
 
3
- Shared UI package for Byline CMS — the field-rendering primitives, form
4
- context and patch-emitting field widgets, the `BylineFieldServicesProvider`
5
- context, and other shared components consumed by the admin UI.
3
+ Framework-independent React primitives for Byline CMS, including buttons,
4
+ inputs, overlays, icons, and drag-and-drop components. CMS field widgets and
5
+ document-editor forms belong to `@byline/admin`.
6
6
 
7
7
  This package is part of [Byline CMS](https://github.com/Byline-CMS/bylinecms.dev)
8
8
  — a developer-friendly, open-source headless CMS with versioning, editorial
@@ -22,8 +22,46 @@ change originates**: a change made here is ported upstream, a change made
22
22
  upstream is ported here. Either copy may be edited directly; neither is the sole
23
23
  source of truth.
24
24
 
25
- Byline-specific code (`admin/`, `dnd/`, `fields/`, `forms/`, `services/`, and
26
- `react.ts`) lives only in this package and has no upstream counterpart.
25
+ Byline's `dnd/` components and `react.ts` entry point have no upstream counterpart.
26
+
27
+ ## Storybook
28
+
29
+ Storybook lets you inspect and interact with the UI primitives without starting
30
+ the CMS or a database. The stories are ported from the sibling UI kit and live
31
+ beside their components in `src/**/*.stories.tsx`.
32
+
33
+ After installing the workspace dependencies, run from the repository root:
34
+
35
+ ```sh
36
+ pnpm storybook
37
+ ```
38
+
39
+ Open <http://localhost:6007>. The preview includes the UI kit's reset, theme,
40
+ typography, local fonts, drawer provider, and toast provider. Use the toolbar
41
+ to switch between light and dark themes. The accessibility panel runs checks
42
+ against the selected story; documentation pages and controls are also available.
43
+
44
+ Build a static site with:
45
+
46
+ ```sh
47
+ pnpm build-storybook
48
+ ```
49
+
50
+ The output is `packages/ui/storybook-static/`, which is ignored by Git.
51
+ Both commands also work with `pnpm --filter @byline/ui` before the command name.
52
+ Port 6007 matches the sibling kit; stop its server before starting this one, or
53
+ run `pnpm --filter @byline/ui storybook --port 6008` to use a different port.
54
+
55
+ Configuration lives in `.storybook/main.ts` and `.storybook/preview.tsx`.
56
+ Static preview assets live in `public/`, with font licences beside the fonts.
57
+ The preview applies `.byline-ui` to the iframe body so portalled overlays inherit
58
+ the same scoped styles as the stories. Story layout uses inline styles and does
59
+ not require the web application's Tailwind configuration.
60
+
61
+ When adding a story, import components from their local source modules and
62
+ Storybook types from `@storybook/react-vite`. The package's `typecheck` command
63
+ checks stories and configuration; the library build excludes story modules.
64
+ Run the static build and inspect changed stories in the browser before merging.
27
65
 
28
66
  ## License
29
67
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "private": false,
4
4
  "type": "module",
5
5
  "license": "MPL-2.0",
6
- "version": "6.8.0",
6
+ "version": "6.10.0",
7
7
  "engines": {
8
8
  "node": ">=22.22.2"
9
9
  },
@@ -55,7 +55,7 @@
55
55
  "@dnd-kit/sortable": "^10.0.0",
56
56
  "clsx": "^2.1.1",
57
57
  "date-fns": "^4.4.0",
58
- "motion": "^14.2.0",
58
+ "motion": "^14.5.0",
59
59
  "react-day-picker": "^10.0.2",
60
60
  "zod": "^4.6.7"
61
61
  },
@@ -64,22 +64,29 @@
64
64
  "react-dom": "^19.0.0"
65
65
  },
66
66
  "devDependencies": {
67
- "@biomejs/biome": "2.5.15",
67
+ "@biomejs/biome": "2.6.2",
68
68
  "@rsbuild/plugin-react": "^2.1.1",
69
69
  "@rslib/core": "^1.0.3",
70
+ "@storybook/addon-a11y": "^10.6.3",
71
+ "@storybook/addon-docs": "^10.6.3",
72
+ "@storybook/addon-links": "^10.6.3",
73
+ "@storybook/addon-themes": "^10.6.3",
74
+ "@storybook/react-vite": "^10.6.3",
70
75
  "@types/node": "^26.6.5",
71
76
  "@types/react": "19.3.0",
72
77
  "@types/react-dom": "19.3.0",
73
78
  "@vitejs/plugin-react": "^6.1.2",
74
- "chokidar": "^5.0.0",
79
+ "chokidar": "^6.0.0",
75
80
  "lightningcss-cli": "^1.33.0",
76
81
  "npm-run-all": "^4.1.5",
82
+ "prism-react-renderer": "^2.4.1",
77
83
  "react": "^19.3.1",
78
84
  "react-dom": "^19.3.1",
85
+ "storybook": "^10.6.3",
79
86
  "typescript": "^7.0.2",
80
87
  "typescript-plugin-css-modules": "^5.2.0",
81
- "vite": "^8.3.4",
82
- "vitest": "^5.0.4"
88
+ "vite": "^8.3.5",
89
+ "vitest": "^5.0.5"
83
90
  },
84
91
  "publishConfig": {
85
92
  "access": "public",
@@ -96,7 +103,9 @@
96
103
  "build:code": "rslib build",
97
104
  "build:css": "lightningcss --bundle ./src/styles/reset.css ./src/styles/styles.css ./src/styles/typography.css --output-dir ./dist/styles",
98
105
  "typecheck": "tsc --noEmit",
99
- "clean": "node scripts/clean.js node_modules dist build types .turbo",
106
+ "storybook": "storybook dev -p 6007 --no-open",
107
+ "build-storybook": "storybook build",
108
+ "clean": "node scripts/clean.js node_modules dist build types .turbo storybook-static",
100
109
  "lint": "biome check --write --unsafe --diagnostic-level=error",
101
110
  "skip:test": "vitest"
102
111
  }
@@ -0,0 +1,121 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+
3
+ import { ChevronDownIcon } from '../../icons/chevron-down-icon.js'
4
+ import { Accordion as AccordionComponent } from './accordion.js'
5
+
6
+ const meta: Meta = {
7
+ /* 👇 The title prop is optional.
8
+ * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
9
+ * to learn how to generate automatic titles
10
+ */
11
+ title: 'Components',
12
+ component: AccordionComponent.Root,
13
+ }
14
+
15
+ export default meta
16
+
17
+ type Story = StoryObj<typeof AccordionComponent.Root>
18
+
19
+ /**
20
+ * NOTE: Accordions are very much context specific in terms of styling
21
+ * and so we apply very little styling to the default accordion component.
22
+ * Below is an example of a custom (albeit basic) styled accordion for demo
23
+ * purposes.
24
+ */
25
+ export const Accordion: Story = {
26
+ args: {
27
+ defaultValue: ['item-1'],
28
+ className: 'accordion-root',
29
+ },
30
+ render: (args) => (
31
+ <div style={{ maxWidth: '600px', margin: '2rem auto' }}>
32
+ <style>
33
+ {`
34
+ .accordion-root {
35
+ border: 1px solid var(--gray-100);
36
+ border-radius: 6px;
37
+ padding: 12px 6px;
38
+ width: 300px;
39
+ background-color: white;
40
+ box-shadow: var(--shadow-md);
41
+ }
42
+
43
+ .accordion-header {
44
+ border-radius: 6px;
45
+ padding: 12px;
46
+ }
47
+
48
+ .accordion-header:hover {
49
+ background-color: var(--gray-25);
50
+ }
51
+
52
+ .accordion-chevron {
53
+ transition: transform 300ms cubic-bezier(0.87, 0, 0.13, 1);
54
+ }
55
+
56
+ .accordion-trigger[data-panel-open] ~ .accordion-chevron {
57
+ transform: rotate(180deg);
58
+ }
59
+
60
+ .accordion-panel {
61
+ padding: 0 12px;
62
+ }
63
+
64
+ .dark .accordion-root {
65
+ border: 1px solid var(--gray-600);
66
+ background-color: var(--canvas-700);
67
+ }
68
+
69
+ .dark .accordion-header:hover {
70
+ background-color: var(--canvas-600);
71
+ }
72
+
73
+
74
+ `}
75
+ </style>
76
+ <AccordionComponent.Root {...args}>
77
+ <nav>
78
+ <AccordionComponent.Item value="item-1" className="accordion-item">
79
+ <AccordionComponent.Header className="accordion-header">
80
+ <AccordionComponent.Trigger className="accordion-trigger">
81
+ Is it accessible?
82
+ </AccordionComponent.Trigger>
83
+ <ChevronDownIcon className="accordion-chevron" />
84
+ </AccordionComponent.Header>
85
+ <AccordionComponent.Panel className="accordion-panel">
86
+ <p>Yes. It adheres to the WAI-ARIA design pattern.</p>
87
+ </AccordionComponent.Panel>
88
+ </AccordionComponent.Item>
89
+
90
+ <AccordionComponent.Item value="item-2">
91
+ <AccordionComponent.Header className="accordion-header">
92
+ <AccordionComponent.Trigger className="accordion-trigger">
93
+ Is it unstyled?
94
+ </AccordionComponent.Trigger>
95
+ <ChevronDownIcon className="accordion-chevron" />
96
+ </AccordionComponent.Header>
97
+ <AccordionComponent.Panel className="accordion-panel">
98
+ <ul>
99
+ <li>Submenu Item One</li>
100
+ <li>Submenu Item Two</li>
101
+ <li>Submenu Item Three</li>
102
+ </ul>
103
+ </AccordionComponent.Panel>
104
+ </AccordionComponent.Item>
105
+
106
+ <AccordionComponent.Item value="item-3">
107
+ <AccordionComponent.Header className="accordion-header">
108
+ <AccordionComponent.Trigger className="accordion-trigger">
109
+ Can it be animated?
110
+ </AccordionComponent.Trigger>
111
+ <ChevronDownIcon className="accordion-chevron" />
112
+ </AccordionComponent.Header>
113
+ <AccordionComponent.Panel className="accordion-panel">
114
+ <p> Yes! You can animate the Accordion with CSS or JavaScript.</p>
115
+ </AccordionComponent.Panel>
116
+ </AccordionComponent.Item>
117
+ </nav>
118
+ </AccordionComponent.Root>
119
+ </div>
120
+ ),
121
+ }
@@ -0,0 +1,80 @@
1
+ import type React from 'react'
2
+
3
+ import type { Meta, StoryObj } from '@storybook/react-vite'
4
+
5
+ import { Section } from '../section/section.js'
6
+ import { FadeInLift } from './fade-in-lift.js'
7
+
8
+ const meta: Meta<typeof FadeInLift> = {
9
+ /* 👇 The title prop is optional.
10
+ * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
11
+ * to learn how to generate automatic titles
12
+ */
13
+ title: 'Animation/FadeInLift',
14
+ component: FadeInLift,
15
+ }
16
+
17
+ export default meta
18
+
19
+ type Story = StoryObj<typeof FadeInLift>
20
+
21
+ const DivDemo = (): React.JSX.Element => {
22
+ return (
23
+ <div style={{ marginLeft: '4rem', marginBottom: '4rem' }}>
24
+ <Section style={{ height: '100vh' }}>
25
+ <FadeInLift
26
+ as="div"
27
+ duration={1}
28
+ delay={0.5}
29
+ style={{
30
+ width: '400px',
31
+ height: '400px',
32
+ display: 'flex',
33
+ alignItems: 'center',
34
+ justifyContent: 'center',
35
+ backgroundColor: 'var(--primary-500)',
36
+ }}
37
+ >
38
+ <p style={{ color: 'black' }}>Fade me in 1!</p>
39
+ </FadeInLift>
40
+ </Section>
41
+ <Section style={{ height: '100vh' }}>
42
+ <FadeInLift
43
+ as="span"
44
+ duration={1}
45
+ delay={0.2}
46
+ style={{
47
+ width: '400px',
48
+ height: '400px',
49
+ display: 'flex',
50
+ alignItems: 'center',
51
+ justifyContent: 'center',
52
+ backgroundColor: 'var(--secondary-500)',
53
+ }}
54
+ >
55
+ <p style={{ color: 'black' }}>Fade me in 2!</p>
56
+ </FadeInLift>
57
+ </Section>
58
+ <Section style={{ height: '100vh' }}>
59
+ <FadeInLift
60
+ duration={1}
61
+ delay={0.2}
62
+ style={{
63
+ width: '400px',
64
+ height: '400px',
65
+ display: 'flex',
66
+ alignItems: 'center',
67
+ justifyContent: 'center',
68
+ backgroundColor: 'var(--yellow-500)',
69
+ }}
70
+ >
71
+ <p style={{ color: 'black' }}>Fade me in 3!</p>
72
+ </FadeInLift>
73
+ </Section>
74
+ </div>
75
+ )
76
+ }
77
+
78
+ export const Default: Story = {
79
+ render: () => <DivDemo />,
80
+ }
@@ -0,0 +1,39 @@
1
+ import type React from 'react'
2
+
3
+ import type { Meta } from '@storybook/react-vite'
4
+
5
+ import { Avatar as AvatarComponent } from './avatar.js'
6
+
7
+ const meta: Meta = {
8
+ /* 👇 The title prop is optional.
9
+ * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
10
+ * to learn how to generate automatic titles
11
+ */
12
+ title: 'Components',
13
+ component: AvatarComponent,
14
+ }
15
+
16
+ export default meta
17
+
18
+ export const Avatar = (): React.JSX.Element => (
19
+ <div
20
+ style={{
21
+ maxWidth: '300px',
22
+ margin: '2rem auto',
23
+ display: 'flex',
24
+ gap: '24px',
25
+ alignItems: 'center',
26
+ justifyContent: 'center',
27
+ }}
28
+ >
29
+ <div style={{ height: '28px', width: '28px' }}>
30
+ <AvatarComponent initials="AB" />
31
+ </div>
32
+ <div style={{ height: '34px', width: '34px' }}>
33
+ <AvatarComponent initials="AB" />
34
+ </div>
35
+ <div style={{ height: '40px', width: '40px' }}>
36
+ <AvatarComponent initials="AB" />
37
+ </div>
38
+ </div>
39
+ )
@@ -0,0 +1,41 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+
3
+ import { capitalize } from '../../utils/capitalize.js'
4
+ import { intent } from '../@types/shared.js'
5
+ import { Badge } from './badge.js'
6
+
7
+ type Story = StoryObj<typeof Badge>
8
+
9
+ const AllIntents = (): React.JSX.Element => {
10
+ return (
11
+ <div style={{ maxWidth: '800px', margin: '2rem auto' }}>
12
+ {intent.map((i) => {
13
+ return (
14
+ <div
15
+ key={i}
16
+ style={{
17
+ marginBottom: '12px',
18
+ }}
19
+ >
20
+ <Badge key={`${i}`} intent={i}>{`${capitalize(i)}`}</Badge>
21
+ </div>
22
+ )
23
+ })}
24
+ </div>
25
+ )
26
+ }
27
+
28
+ export const Intents: Story = {
29
+ render: () => <AllIntents />,
30
+ }
31
+
32
+ const meta: Meta<typeof Badge> = {
33
+ /* 👇 The title prop is optional.
34
+ * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
35
+ * to learn how to generate automatic titles
36
+ */
37
+ title: 'Components/Badge',
38
+ component: Badge,
39
+ }
40
+
41
+ export default meta
@@ -0,0 +1,44 @@
1
+ import type React from 'react'
2
+ import { useState } from 'react'
3
+
4
+ import type { Meta, StoryObj } from '@storybook/react-vite'
5
+
6
+ import { ButtonGroup as ButtonGroupComponent, ButtonGroupItem } from './button-group.js'
7
+
8
+ const meta: Meta<typeof ButtonGroupComponent> = {
9
+ /* 👇 The title prop is optional.
10
+ * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
11
+ * to learn how to generate automatic titles
12
+ */
13
+ title: 'Components/Button',
14
+ component: ButtonGroupComponent,
15
+ }
16
+
17
+ export default meta
18
+
19
+ type Story = StoryObj<typeof ButtonGroupComponent>
20
+
21
+ const ButtonGroupDemo = (): React.JSX.Element => {
22
+ const [value, setValue] = useState<string | string[]>('one')
23
+ const handleOnValueChange = (value: string | string[]) => {
24
+ setValue(value)
25
+ }
26
+ return (
27
+ <div style={{ maxWidth: '600px', margin: '2rem auto' }}>
28
+ <ButtonGroupComponent
29
+ type="single"
30
+ expandToFit={true}
31
+ value={value as string}
32
+ onValueChange={handleOnValueChange}
33
+ >
34
+ <ButtonGroupItem value="one">One</ButtonGroupItem>
35
+ <ButtonGroupItem value="two">Two</ButtonGroupItem>
36
+ <ButtonGroupItem value="three">Three</ButtonGroupItem>
37
+ </ButtonGroupComponent>
38
+ </div>
39
+ )
40
+ }
41
+
42
+ export const ButtonGroup: Story = {
43
+ render: () => <ButtonGroupDemo />,
44
+ }
@@ -0,0 +1,97 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+
3
+ import { capitalize } from '../../utils/capitalize.js'
4
+ import { intent } from '../@types/shared.js'
5
+ import { variant } from './@types/button.js'
6
+ import { Button } from './button.js'
7
+
8
+ type Story = StoryObj<typeof Button>
9
+
10
+ const AllIntents = (): React.JSX.Element => {
11
+ return (
12
+ <>
13
+ <div
14
+ style={{
15
+ maxWidth: '1100px',
16
+ margin: '2rem auto',
17
+ padding: '2rem',
18
+ borderRadius: '6px',
19
+ backgroundColor: 'var(--background)',
20
+ }}
21
+ >
22
+ {intent.map((i) => {
23
+ return (
24
+ <div
25
+ key={i}
26
+ style={{
27
+ display: 'grid',
28
+ gridTemplateColumns: 'repeat(5, minmax(0, 1fr)',
29
+ gap: '32px',
30
+ marginBottom: '32px',
31
+ }}
32
+ >
33
+ {variant.map((v) => {
34
+ return (
35
+ <Button
36
+ key={`${i}-${v}`}
37
+ intent={i}
38
+ variant={v}
39
+ >{`${capitalize(i)} ${v}`}</Button>
40
+ )
41
+ })}
42
+ </div>
43
+ )
44
+ })}
45
+ </div>
46
+ <div
47
+ className="dark"
48
+ style={{
49
+ maxWidth: '1100px',
50
+ margin: '2rem auto',
51
+ padding: '2rem',
52
+ borderRadius: '6px',
53
+ backgroundColor: 'var(--theme-800)',
54
+ }}
55
+ >
56
+ {intent.map((i) => {
57
+ return (
58
+ <div
59
+ key={i}
60
+ style={{
61
+ display: 'grid',
62
+ gridTemplateColumns: 'repeat(5, minmax(0, 1fr)',
63
+ gap: '32px',
64
+ marginBottom: '32px',
65
+ }}
66
+ >
67
+ {variant.map((v) => {
68
+ return (
69
+ <Button
70
+ key={`${i}-${v}`}
71
+ intent={i}
72
+ variant={v}
73
+ >{`${capitalize(i)} ${v}`}</Button>
74
+ )
75
+ })}
76
+ </div>
77
+ )
78
+ })}
79
+ </div>
80
+ </>
81
+ )
82
+ }
83
+
84
+ export const ButtonIntents: Story = {
85
+ render: () => <AllIntents />,
86
+ }
87
+
88
+ const meta: Meta<typeof Button> = {
89
+ /* 👇 The title prop is optional.
90
+ * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
91
+ * to learn how to generate automatic titles
92
+ */
93
+ title: 'Components/Button',
94
+ component: Button,
95
+ }
96
+
97
+ export default meta
@@ -0,0 +1,59 @@
1
+ import type React from 'react'
2
+
3
+ import type { Meta, StoryObj } from '@storybook/react-vite'
4
+
5
+ import { Button } from './button.js'
6
+
7
+ type Story = StoryObj<typeof Button>
8
+
9
+ const AllOverrides = (): React.JSX.Element => {
10
+ return (
11
+ <>
12
+ <div style={{ maxWidth: '600px', margin: '2rem auto' }}>
13
+ <div
14
+ style={{
15
+ width: '300px',
16
+ padding: '1rem',
17
+ borderRadius: '8px',
18
+ border: '1px solid var(--stroke-primary)',
19
+ backgroundColor: 'var(--gray-25)',
20
+ }}
21
+ >
22
+ <Button className="not-dark" variant="filled" size="sm" style={{ marginRight: '1rem' }}>
23
+ Force Light
24
+ </Button>
25
+ </div>
26
+ </div>
27
+ <div className="dark" style={{ maxWidth: '600px', margin: '2rem auto' }}>
28
+ <div
29
+ style={{
30
+ width: '300px',
31
+ padding: '1rem',
32
+ borderRadius: '8px',
33
+ border: '1px solid var(--stroke-primary)',
34
+ backgroundColor: 'var(--canvas-800)',
35
+ }}
36
+ >
37
+ <Button variant="filled" size="sm" style={{ marginRight: '1rem' }}>
38
+ Force Dark
39
+ </Button>
40
+ </div>
41
+ </div>
42
+ </>
43
+ )
44
+ }
45
+
46
+ export const ButtonOverrides: Story = {
47
+ render: () => <AllOverrides />,
48
+ }
49
+
50
+ const meta: Meta<typeof Button> = {
51
+ /* 👇 The title prop is optional.
52
+ * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
53
+ * to learn how to generate automatic titles
54
+ */
55
+ title: 'Components/Button',
56
+ component: Button,
57
+ }
58
+
59
+ export default meta
@@ -0,0 +1,59 @@
1
+ import type React from 'react'
2
+
3
+ import type { Meta, StoryObj } from '@storybook/react-vite'
4
+
5
+ import { Button } from './button.js'
6
+
7
+ type Story = StoryObj<typeof Button>
8
+
9
+ const AllTests = (): React.JSX.Element => {
10
+ return (
11
+ <>
12
+ <div style={{ maxWidth: '600px', margin: '2rem auto' }}>
13
+ <div
14
+ style={{
15
+ width: '300px',
16
+ padding: '1rem',
17
+ borderRadius: '8px',
18
+ border: '1px solid var(--stroke-primary)',
19
+ backgroundColor: 'var(--gray-25)',
20
+ }}
21
+ >
22
+ <Button className="not-dark" variant="outlined" size="md" style={{ marginRight: '1rem' }}>
23
+ Force Light
24
+ </Button>
25
+ </div>
26
+ </div>
27
+ <div className="dark" style={{ maxWidth: '600px', margin: '2rem auto' }}>
28
+ <div
29
+ style={{
30
+ width: '300px',
31
+ padding: '1rem',
32
+ borderRadius: '8px',
33
+ border: '1px solid var(--stroke-primary)',
34
+ backgroundColor: 'var(--primary-800)',
35
+ }}
36
+ >
37
+ <Button variant="outlined" size="md" style={{ marginRight: '1rem' }}>
38
+ Force Dark
39
+ </Button>
40
+ </div>
41
+ </div>
42
+ </>
43
+ )
44
+ }
45
+
46
+ export const ButtonTests: Story = {
47
+ render: () => <AllTests />,
48
+ }
49
+
50
+ const meta: Meta<typeof Button> = {
51
+ /* 👇 The title prop is optional.
52
+ * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
53
+ * to learn how to generate automatic titles
54
+ */
55
+ title: 'Components/Button',
56
+ component: Button,
57
+ }
58
+
59
+ export default meta