tharaday 0.1.1

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 (247) hide show
  1. package/.gitignore +30 -0
  2. package/.prettierrc.json +10 -0
  3. package/.storybook/main.ts +8 -0
  4. package/.storybook/preview.ts +50 -0
  5. package/.versionrc.json +6 -0
  6. package/README.md +73 -0
  7. package/dist/components/Accordion/Accordion.d.ts +2 -0
  8. package/dist/components/Accordion/Accordion.stories.d.ts +14 -0
  9. package/dist/components/Accordion/Accordion.types.d.ts +18 -0
  10. package/dist/components/Avatar/Avatar.d.ts +2 -0
  11. package/dist/components/Avatar/Avatar.stories.d.ts +14 -0
  12. package/dist/components/Avatar/Avatar.types.d.ts +10 -0
  13. package/dist/components/Badge/Badge.d.ts +2 -0
  14. package/dist/components/Badge/Badge.stories.d.ts +33 -0
  15. package/dist/components/Badge/Badge.types.d.ts +9 -0
  16. package/dist/components/Box/Box.d.ts +2 -0
  17. package/dist/components/Box/Box.stories.d.ts +38 -0
  18. package/dist/components/Box/Box.types.d.ts +49 -0
  19. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +3 -0
  20. package/dist/components/Breadcrumbs/Breadcrumbs.stories.d.ts +13 -0
  21. package/dist/components/Breadcrumbs/Breadcrumbs.types.d.ts +11 -0
  22. package/dist/components/Button/Button.d.ts +2 -0
  23. package/dist/components/Button/Button.stories.d.ts +22 -0
  24. package/dist/components/Button/Button.types.d.ts +12 -0
  25. package/dist/components/Card/Card.d.ts +5 -0
  26. package/dist/components/Card/Card.stories.d.ts +27 -0
  27. package/dist/components/Card/Card.types.d.ts +15 -0
  28. package/dist/components/Checkbox/Checkbox.d.ts +2 -0
  29. package/dist/components/Checkbox/Checkbox.stories.d.ts +17 -0
  30. package/dist/components/Checkbox/Checkbox.types.d.ts +6 -0
  31. package/dist/components/Dropdown/Dropdown.d.ts +2 -0
  32. package/dist/components/Dropdown/Dropdown.stories.d.ts +12 -0
  33. package/dist/components/Dropdown/Dropdown.types.d.ts +24 -0
  34. package/dist/components/Header/Header.d.ts +2 -0
  35. package/dist/components/Header/Header.stories.d.ts +18 -0
  36. package/dist/components/Header/Header.types.d.ts +14 -0
  37. package/dist/components/Input/Input.d.ts +2 -0
  38. package/dist/components/Input/Input.stories.d.ts +29 -0
  39. package/dist/components/Input/Input.types.d.ts +8 -0
  40. package/dist/components/Loader/Loader.d.ts +2 -0
  41. package/dist/components/Loader/Loader.stories.d.ts +25 -0
  42. package/dist/components/Loader/Loader.types.d.ts +8 -0
  43. package/dist/components/Modal/Modal.d.ts +2 -0
  44. package/dist/components/Modal/Modal.stories.d.ts +22 -0
  45. package/dist/components/Modal/Modal.types.d.ts +12 -0
  46. package/dist/components/NavBar/NavBar.d.ts +6 -0
  47. package/dist/components/NavBar/NavBar.stories.d.ts +8 -0
  48. package/dist/components/NavBar/NavBar.types.d.ts +34 -0
  49. package/dist/components/Notification/Notification.d.ts +2 -0
  50. package/dist/components/Notification/Notification.stories.d.ts +26 -0
  51. package/dist/components/Notification/Notification.types.d.ts +8 -0
  52. package/dist/components/Pagination/Pagination.d.ts +2 -0
  53. package/dist/components/Pagination/Pagination.stories.d.ts +21 -0
  54. package/dist/components/Pagination/Pagination.types.d.ts +34 -0
  55. package/dist/components/ProgressBar/ProgressBar.d.ts +2 -0
  56. package/dist/components/ProgressBar/ProgressBar.stories.d.ts +32 -0
  57. package/dist/components/ProgressBar/ProgressBar.types.d.ts +12 -0
  58. package/dist/components/RadioButton/RadioButton.d.ts +2 -0
  59. package/dist/components/RadioButton/RadioButton.stories.d.ts +30 -0
  60. package/dist/components/RadioButton/RadioButton.types.d.ts +8 -0
  61. package/dist/components/Select/Select.d.ts +2 -0
  62. package/dist/components/Select/Select.stories.d.ts +29 -0
  63. package/dist/components/Select/Select.types.d.ts +15 -0
  64. package/dist/components/Skeleton/Skeleton.d.ts +2 -0
  65. package/dist/components/Skeleton/Skeleton.stories.d.ts +15 -0
  66. package/dist/components/Skeleton/Skeleton.types.d.ts +8 -0
  67. package/dist/components/Stepper/Step.d.ts +2 -0
  68. package/dist/components/Stepper/Step.types.d.ts +17 -0
  69. package/dist/components/Stepper/Stepper.d.ts +2 -0
  70. package/dist/components/Stepper/Stepper.stories.d.ts +15 -0
  71. package/dist/components/Stepper/Stepper.types.d.ts +13 -0
  72. package/dist/components/Stepper/stepper.utils.d.ts +3 -0
  73. package/dist/components/Switch/Switch.d.ts +2 -0
  74. package/dist/components/Switch/Switch.stories.d.ts +16 -0
  75. package/dist/components/Switch/Switch.types.d.ts +5 -0
  76. package/dist/components/Table/Table.d.ts +8 -0
  77. package/dist/components/Table/Table.stories.d.ts +27 -0
  78. package/dist/components/Table/Table.types.d.ts +17 -0
  79. package/dist/components/Tabs/Tabs.d.ts +2 -0
  80. package/dist/components/Tabs/Tabs.stories.d.ts +14 -0
  81. package/dist/components/Tabs/Tabs.types.d.ts +16 -0
  82. package/dist/components/Text/Text.d.ts +2 -0
  83. package/dist/components/Text/Text.stories.d.ts +35 -0
  84. package/dist/components/Text/Text.types.d.ts +21 -0
  85. package/dist/components/Textarea/Textarea.d.ts +2 -0
  86. package/dist/components/Textarea/Textarea.stories.d.ts +29 -0
  87. package/dist/components/Textarea/Textarea.types.d.ts +9 -0
  88. package/dist/components/Tooltip/Tooltip.d.ts +2 -0
  89. package/dist/components/Tooltip/Tooltip.stories.d.ts +10 -0
  90. package/dist/components/Tooltip/Tooltip.types.d.ts +12 -0
  91. package/dist/ds.css +1 -0
  92. package/dist/ds.js +1930 -0
  93. package/dist/ds.umd.cjs +1 -0
  94. package/dist/index.d.ts +63 -0
  95. package/dist/layouts/AppLayout/AppLayout.d.ts +8 -0
  96. package/dist/layouts/AppLayout/AppLayout.stories.d.ts +19 -0
  97. package/dist/layouts/AppLayout/AppLayout.types.d.ts +50 -0
  98. package/dist/layouts/AuthLayout/AuthLayout.d.ts +2 -0
  99. package/dist/layouts/AuthLayout/AuthLayout.stories.d.ts +12 -0
  100. package/dist/layouts/AuthLayout/AuthLayout.types.d.ts +7 -0
  101. package/dist/layouts/DashboardLayout/DashboardLayout.d.ts +2 -0
  102. package/dist/layouts/DashboardLayout/DashboardLayout.stories.d.ts +17 -0
  103. package/dist/layouts/DashboardLayout/DashboardLayout.types.d.ts +15 -0
  104. package/dist/layouts/SettingsLayout/SettingsLayout.d.ts +2 -0
  105. package/dist/layouts/SettingsLayout/SettingsLayout.stories.d.ts +17 -0
  106. package/dist/layouts/SettingsLayout/SettingsLayout.types.d.ts +14 -0
  107. package/eslint.config.js +45 -0
  108. package/package.json +100 -0
  109. package/src/components/Accordion/Accordion.module.css +158 -0
  110. package/src/components/Accordion/Accordion.stories.tsx +133 -0
  111. package/src/components/Accordion/Accordion.tsx +68 -0
  112. package/src/components/Accordion/Accordion.types.ts +21 -0
  113. package/src/components/Avatar/Avatar.module.css +58 -0
  114. package/src/components/Avatar/Avatar.stories.tsx +41 -0
  115. package/src/components/Avatar/Avatar.tsx +64 -0
  116. package/src/components/Avatar/Avatar.types.ts +12 -0
  117. package/src/components/Badge/Badge.module.css +98 -0
  118. package/src/components/Badge/Badge.stories.tsx +108 -0
  119. package/src/components/Badge/Badge.tsx +22 -0
  120. package/src/components/Badge/Badge.types.ts +11 -0
  121. package/src/components/Box/Box.module.css +638 -0
  122. package/src/components/Box/Box.stories.tsx +109 -0
  123. package/src/components/Box/Box.tsx +95 -0
  124. package/src/components/Box/Box.types.ts +65 -0
  125. package/src/components/Breadcrumbs/Breadcrumbs.module.css +41 -0
  126. package/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +40 -0
  127. package/src/components/Breadcrumbs/Breadcrumbs.tsx +54 -0
  128. package/src/components/Breadcrumbs/Breadcrumbs.types.ts +13 -0
  129. package/src/components/Button/Button.module.css +247 -0
  130. package/src/components/Button/Button.stories.tsx +93 -0
  131. package/src/components/Button/Button.tsx +31 -0
  132. package/src/components/Button/Button.types.ts +14 -0
  133. package/src/components/Card/Card.module.css +112 -0
  134. package/src/components/Card/Card.stories.tsx +86 -0
  135. package/src/components/Card/Card.tsx +70 -0
  136. package/src/components/Card/Card.types.ts +20 -0
  137. package/src/components/Checkbox/Checkbox.module.css +88 -0
  138. package/src/components/Checkbox/Checkbox.stories.tsx +65 -0
  139. package/src/components/Checkbox/Checkbox.tsx +57 -0
  140. package/src/components/Checkbox/Checkbox.types.ts +7 -0
  141. package/src/components/Dropdown/Dropdown.module.css +140 -0
  142. package/src/components/Dropdown/Dropdown.stories.tsx +86 -0
  143. package/src/components/Dropdown/Dropdown.tsx +251 -0
  144. package/src/components/Dropdown/Dropdown.types.ts +27 -0
  145. package/src/components/Header/Header.module.css +38 -0
  146. package/src/components/Header/Header.stories.tsx +53 -0
  147. package/src/components/Header/Header.tsx +49 -0
  148. package/src/components/Header/Header.types.ts +15 -0
  149. package/src/components/Input/Input.module.css +87 -0
  150. package/src/components/Input/Input.stories.tsx +101 -0
  151. package/src/components/Input/Input.tsx +41 -0
  152. package/src/components/Input/Input.types.ts +10 -0
  153. package/src/components/Loader/Loader.module.css +49 -0
  154. package/src/components/Loader/Loader.stories.tsx +75 -0
  155. package/src/components/Loader/Loader.tsx +15 -0
  156. package/src/components/Loader/Loader.types.ts +9 -0
  157. package/src/components/Modal/Modal.module.css +88 -0
  158. package/src/components/Modal/Modal.stories.tsx +94 -0
  159. package/src/components/Modal/Modal.tsx +115 -0
  160. package/src/components/Modal/Modal.types.ts +13 -0
  161. package/src/components/NavBar/NavBar.module.css +77 -0
  162. package/src/components/NavBar/NavBar.stories.tsx +55 -0
  163. package/src/components/NavBar/NavBar.tsx +50 -0
  164. package/src/components/NavBar/NavBar.types.ts +36 -0
  165. package/src/components/Notification/Notification.module.css +72 -0
  166. package/src/components/Notification/Notification.stories.tsx +81 -0
  167. package/src/components/Notification/Notification.tsx +34 -0
  168. package/src/components/Notification/Notification.types.ts +10 -0
  169. package/src/components/Pagination/Pagination.module.css +31 -0
  170. package/src/components/Pagination/Pagination.stories.tsx +128 -0
  171. package/src/components/Pagination/Pagination.tsx +245 -0
  172. package/src/components/Pagination/Pagination.types.ts +37 -0
  173. package/src/components/ProgressBar/ProgressBar.module.css +67 -0
  174. package/src/components/ProgressBar/ProgressBar.stories.tsx +91 -0
  175. package/src/components/ProgressBar/ProgressBar.tsx +49 -0
  176. package/src/components/ProgressBar/ProgressBar.types.ts +13 -0
  177. package/src/components/RadioButton/RadioButton.module.css +162 -0
  178. package/src/components/RadioButton/RadioButton.stories.tsx +114 -0
  179. package/src/components/RadioButton/RadioButton.tsx +43 -0
  180. package/src/components/RadioButton/RadioButton.types.ts +10 -0
  181. package/src/components/Select/Select.module.css +88 -0
  182. package/src/components/Select/Select.stories.tsx +99 -0
  183. package/src/components/Select/Select.tsx +51 -0
  184. package/src/components/Select/Select.types.ts +18 -0
  185. package/src/components/Skeleton/Skeleton.module.css +71 -0
  186. package/src/components/Skeleton/Skeleton.stories.tsx +54 -0
  187. package/src/components/Skeleton/Skeleton.tsx +32 -0
  188. package/src/components/Skeleton/Skeleton.types.ts +10 -0
  189. package/src/components/Stepper/Step.module.css +162 -0
  190. package/src/components/Stepper/Step.tsx +62 -0
  191. package/src/components/Stepper/Step.types.ts +19 -0
  192. package/src/components/Stepper/Stepper.module.css +39 -0
  193. package/src/components/Stepper/Stepper.stories.tsx +88 -0
  194. package/src/components/Stepper/Stepper.tsx +47 -0
  195. package/src/components/Stepper/Stepper.types.ts +16 -0
  196. package/src/components/Stepper/stepper.utils.ts +41 -0
  197. package/src/components/Switch/Switch.module.css +74 -0
  198. package/src/components/Switch/Switch.stories.tsx +56 -0
  199. package/src/components/Switch/Switch.tsx +36 -0
  200. package/src/components/Switch/Switch.types.ts +6 -0
  201. package/src/components/Table/Table.module.css +78 -0
  202. package/src/components/Table/Table.stories.tsx +124 -0
  203. package/src/components/Table/Table.tsx +75 -0
  204. package/src/components/Table/Table.types.ts +29 -0
  205. package/src/components/Tabs/Tabs.module.css +74 -0
  206. package/src/components/Tabs/Tabs.stories.tsx +48 -0
  207. package/src/components/Tabs/Tabs.tsx +113 -0
  208. package/src/components/Tabs/Tabs.types.ts +18 -0
  209. package/src/components/Text/Text.module.css +126 -0
  210. package/src/components/Text/Text.stories.tsx +128 -0
  211. package/src/components/Text/Text.tsx +50 -0
  212. package/src/components/Text/Text.types.ts +43 -0
  213. package/src/components/Textarea/Textarea.module.css +82 -0
  214. package/src/components/Textarea/Textarea.stories.tsx +99 -0
  215. package/src/components/Textarea/Textarea.tsx +43 -0
  216. package/src/components/Textarea/Textarea.types.ts +11 -0
  217. package/src/components/Tooltip/Tooltip.module.css +125 -0
  218. package/src/components/Tooltip/Tooltip.stories.tsx +68 -0
  219. package/src/components/Tooltip/Tooltip.tsx +87 -0
  220. package/src/components/Tooltip/Tooltip.types.ts +14 -0
  221. package/src/index.ts +132 -0
  222. package/src/layouts/AppLayout/AppLayout.module.css +17 -0
  223. package/src/layouts/AppLayout/AppLayout.stories.tsx +124 -0
  224. package/src/layouts/AppLayout/AppLayout.tsx +46 -0
  225. package/src/layouts/AppLayout/AppLayout.types.ts +50 -0
  226. package/src/layouts/AuthLayout/AuthLayout.module.css +49 -0
  227. package/src/layouts/AuthLayout/AuthLayout.stories.tsx +109 -0
  228. package/src/layouts/AuthLayout/AuthLayout.tsx +27 -0
  229. package/src/layouts/AuthLayout/AuthLayout.types.tsx +8 -0
  230. package/src/layouts/DashboardLayout/DashboardLayout.module.css +37 -0
  231. package/src/layouts/DashboardLayout/DashboardLayout.stories.tsx +144 -0
  232. package/src/layouts/DashboardLayout/DashboardLayout.tsx +41 -0
  233. package/src/layouts/DashboardLayout/DashboardLayout.types.tsx +14 -0
  234. package/src/layouts/SettingsLayout/SettingsLayout.module.css +39 -0
  235. package/src/layouts/SettingsLayout/SettingsLayout.stories.tsx +103 -0
  236. package/src/layouts/SettingsLayout/SettingsLayout.tsx +37 -0
  237. package/src/layouts/SettingsLayout/SettingsLayout.types.tsx +13 -0
  238. package/src/styles/ds.css +12 -0
  239. package/src/styles/semantic.css +56 -0
  240. package/src/styles/themes/dark.css +58 -0
  241. package/src/styles/themes/light.css +58 -0
  242. package/src/styles/themes/retro.css +58 -0
  243. package/src/styles/tokens.css +138 -0
  244. package/tsconfig.app.json +28 -0
  245. package/tsconfig.json +7 -0
  246. package/tsconfig.node.json +26 -0
  247. package/vite.config.ts +33 -0
@@ -0,0 +1,158 @@
1
+ .root {
2
+ display: flex;
3
+ flex-direction: column;
4
+ width: 100%;
5
+ }
6
+
7
+ /* Variants */
8
+ .default {
9
+ border: 1px solid var(--ds-border-1);
10
+ border-radius: var(--ds-radius-md);
11
+ overflow: hidden;
12
+ }
13
+
14
+ .bordered .item {
15
+ border: 1px solid var(--ds-border-1);
16
+ border-radius: var(--ds-radius-md);
17
+ margin-bottom: var(--ds-space-2);
18
+ }
19
+
20
+ .bordered .item:last-child {
21
+ margin-bottom: 0;
22
+ }
23
+
24
+ .separated .item {
25
+ background-color: var(--ds-surface-1);
26
+ border-radius: var(--ds-radius-md);
27
+ margin-bottom: var(--ds-space-3);
28
+ }
29
+
30
+ .separated .item:last-child {
31
+ margin-bottom: 0;
32
+ }
33
+
34
+ .ghost .header {
35
+ background-color: transparent;
36
+ }
37
+
38
+ .ghost .item {
39
+ border-bottom: 1px solid var(--ds-border-2);
40
+ }
41
+
42
+ /* Items */
43
+ .default .item {
44
+ border-bottom: 1px solid var(--ds-border-1);
45
+ }
46
+
47
+ .default .item:last-child {
48
+ border-bottom: none;
49
+ }
50
+
51
+ .header {
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: space-between;
55
+ width: 100%;
56
+ background-color: var(--ds-surface-0);
57
+ border: none;
58
+ cursor: pointer;
59
+ text-align: left;
60
+ font-weight: var(--ds-font-weight-medium);
61
+ transition: background-color 0.2s;
62
+ }
63
+
64
+ /* Sizes */
65
+ .sm .header {
66
+ padding: var(--ds-space-2) var(--ds-space-3);
67
+ font-size: var(--ds-font-size-xs);
68
+ }
69
+
70
+ .md .header {
71
+ padding: var(--ds-space-4) var(--ds-space-5);
72
+ font-size: var(--ds-font-size-sm);
73
+ }
74
+
75
+ .lg .header {
76
+ padding: var(--ds-space-5) var(--ds-space-6);
77
+ font-size: var(--ds-font-size-base);
78
+ }
79
+
80
+ .header:hover:not(:disabled) {
81
+ background-color: var(--ds-surface-1);
82
+ }
83
+
84
+ .header:focus-visible {
85
+ outline: none;
86
+ box-shadow:
87
+ inset 0 0 0 2px var(--ds-ring-offset),
88
+ inset 0 0 0 4px var(--ds-ring);
89
+ z-index: 1;
90
+ }
91
+
92
+ .header:disabled {
93
+ cursor: not-allowed;
94
+ opacity: 0.5;
95
+ }
96
+
97
+ .icon {
98
+ transition: transform 0.2s;
99
+ font-size: 0.8em;
100
+ }
101
+
102
+ .iconExpanded {
103
+ transform: rotate(180deg);
104
+ }
105
+
106
+ .contentWrapper {
107
+ display: grid;
108
+ grid-template-rows: 0fr;
109
+ transition: grid-template-rows 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
110
+ overflow: hidden;
111
+ }
112
+
113
+ .contentExpanded {
114
+ grid-template-rows: 1fr;
115
+ }
116
+
117
+ .content {
118
+ min-height: 0;
119
+ }
120
+
121
+ .contentBody {
122
+ background-color: var(--ds-surface-0);
123
+ border-top: 1px solid var(--ds-border-2);
124
+ color: var(--ds-text-2);
125
+ overflow: hidden;
126
+ opacity: 0;
127
+ transform: translateY(-4px);
128
+ transition:
129
+ opacity 0.35s ease 0.05s,
130
+ transform 0.45s ease 0.05s;
131
+ will-change: opacity, transform;
132
+ }
133
+
134
+ .contentBodyExpanded {
135
+ opacity: 1;
136
+ transform: translateY(0);
137
+ }
138
+
139
+ .sm .contentBody {
140
+ padding: var(--ds-space-2) var(--ds-space-3);
141
+ font-size: var(--ds-font-size-xs);
142
+ }
143
+
144
+ .md .contentBody {
145
+ padding: var(--ds-space-4) var(--ds-space-5);
146
+ font-size: var(--ds-font-size-sm);
147
+ }
148
+
149
+ .lg .contentBody {
150
+ padding: var(--ds-space-5) var(--ds-space-6);
151
+ font-size: var(--ds-font-size-base);
152
+ }
153
+
154
+ .separated .contentBody,
155
+ .ghost .contentBody {
156
+ background-color: transparent;
157
+ border-top: none;
158
+ }
@@ -0,0 +1,133 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { Accordion } from './Accordion.tsx';
4
+ import { Badge } from '../Badge/Badge.tsx';
5
+ import { Button } from '../Button/Button.tsx';
6
+
7
+ const meta: Meta<typeof Accordion> = {
8
+ title: 'Components/Accordion',
9
+ component: Accordion,
10
+ tags: ['autodocs'],
11
+ };
12
+
13
+ export default meta;
14
+ type Story = StoryObj<typeof Accordion>;
15
+
16
+ const items = [
17
+ {
18
+ id: '1',
19
+ title: 'Section 1',
20
+ content: 'This is the content of section 1. It can contain any elements.',
21
+ },
22
+ {
23
+ id: '2',
24
+ title: 'Section 2',
25
+ content: 'This is the content of section 2. It is also very interesting.',
26
+ },
27
+ {
28
+ id: '3',
29
+ title: 'Disabled Section',
30
+ content: 'You should not see this.',
31
+ isDisabled: true,
32
+ },
33
+ ];
34
+
35
+ export const Default: Story = {
36
+ args: {
37
+ items,
38
+ variant: 'default',
39
+ },
40
+ };
41
+
42
+ export const Ghost: Story = {
43
+ args: {
44
+ items,
45
+ variant: 'ghost',
46
+ },
47
+ };
48
+
49
+ export const Bordered: Story = {
50
+ args: {
51
+ items,
52
+ variant: 'bordered',
53
+ },
54
+ };
55
+
56
+ export const Separated: Story = {
57
+ args: {
58
+ items,
59
+ variant: 'separated',
60
+ },
61
+ };
62
+
63
+ export const Small: Story = {
64
+ args: {
65
+ items,
66
+ size: 'sm',
67
+ },
68
+ };
69
+
70
+ export const Large: Story = {
71
+ args: {
72
+ items,
73
+ size: 'lg',
74
+ },
75
+ };
76
+
77
+ export const AllowMultiple: Story = {
78
+ args: {
79
+ items,
80
+ allowMultiple: true,
81
+ },
82
+ };
83
+
84
+ export const DefaultExpanded: Story = {
85
+ args: {
86
+ items,
87
+ defaultExpanded: ['1'],
88
+ },
89
+ };
90
+
91
+ export const ComplexContent: Story = {
92
+ args: {
93
+ items: [
94
+ {
95
+ id: '1',
96
+ title: 'Mixed Content',
97
+ content: (
98
+ <div>
99
+ <p style={{ marginBottom: '16px' }}>
100
+ This section contains various elements to demonstrate flexibility.
101
+ </p>
102
+ <div style={{ display: 'flex', gap: '8px', marginBottom: '16px' }}>
103
+ <Badge intent="success">Active</Badge>
104
+ <Badge intent="info">New</Badge>
105
+ </div>
106
+ <p style={{ marginBottom: '16px' }}>
107
+ You can nest buttons, images, or even other components here.
108
+ </p>
109
+ <Button size="sm">Action Item</Button>
110
+ </div>
111
+ ),
112
+ },
113
+ {
114
+ id: '2',
115
+ title: 'Long Text',
116
+ content: (
117
+ <div>
118
+ <p style={{ marginBottom: '12px' }}>
119
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
120
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
121
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
122
+ </p>
123
+ <p>
124
+ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat
125
+ nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
126
+ officia deserunt mollit anim id est laborum.
127
+ </p>
128
+ </div>
129
+ ),
130
+ },
131
+ ],
132
+ },
133
+ };
@@ -0,0 +1,68 @@
1
+ import clsx from 'clsx';
2
+ import { useState, useId } from 'react';
3
+
4
+ import styles from './Accordion.module.css';
5
+ import type { AccordionProps } from './Accordion.types.ts';
6
+
7
+ export const Accordion = ({
8
+ items,
9
+ allowMultiple = false,
10
+ defaultExpanded = [],
11
+ variant = 'default',
12
+ size = 'md',
13
+ className,
14
+ id,
15
+ }: AccordionProps) => {
16
+ const baseId = useId();
17
+ const componentId = id ?? `ds-accordion-${baseId}`;
18
+ const [expandedItems, setExpandedItems] = useState<string[]>(defaultExpanded);
19
+
20
+ const toggleItem = (id: string) => {
21
+ setExpandedItems((prev) => {
22
+ if (prev.includes(id)) {
23
+ return prev.filter((item) => item !== id);
24
+ }
25
+ if (allowMultiple) {
26
+ return [...prev, id];
27
+ }
28
+ return [id];
29
+ });
30
+ };
31
+
32
+ return (
33
+ <div id={componentId} className={clsx(styles.root, styles[variant], styles[size], className)}>
34
+ {items.map((item) => {
35
+ const isExpanded = expandedItems.includes(item.id);
36
+
37
+ return (
38
+ <div key={item.id} className={styles.item}>
39
+ <button
40
+ type="button"
41
+ id={`${componentId}-header-${item.id}`}
42
+ className={styles.header}
43
+ onClick={() => toggleItem(item.id)}
44
+ disabled={item.isDisabled}
45
+ aria-expanded={isExpanded}
46
+ aria-controls={`${componentId}-content-${item.id}`}
47
+ >
48
+ <span>{item.title}</span>
49
+ <span className={clsx(styles.icon, isExpanded && styles.iconExpanded)}>▼</span>
50
+ </button>
51
+ <div
52
+ id={`${componentId}-content-${item.id}`}
53
+ role="region"
54
+ aria-labelledby={`${componentId}-header-${item.id}`}
55
+ className={clsx(styles.contentWrapper, isExpanded && styles.contentExpanded)}
56
+ >
57
+ <div className={styles.content}>
58
+ <div className={clsx(styles.contentBody, isExpanded && styles.contentBodyExpanded)}>
59
+ {item.content}
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ );
65
+ })}
66
+ </div>
67
+ );
68
+ };
@@ -0,0 +1,21 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface AccordionItem {
4
+ id: string;
5
+ title: ReactNode;
6
+ content: ReactNode;
7
+ isDisabled?: boolean;
8
+ }
9
+
10
+ export type AccordionVariant = 'default' | 'ghost' | 'separated' | 'bordered';
11
+ export type AccordionSize = 'sm' | 'md' | 'lg';
12
+
13
+ export interface AccordionProps {
14
+ items: AccordionItem[];
15
+ allowMultiple?: boolean;
16
+ defaultExpanded?: string[];
17
+ variant?: AccordionVariant;
18
+ size?: AccordionSize;
19
+ className?: string;
20
+ id?: string;
21
+ }
@@ -0,0 +1,58 @@
1
+ .root {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ overflow: hidden;
6
+ user-select: none;
7
+ border-radius: var(--ds-radius-full);
8
+ background-color: var(--ds-surface-1);
9
+ color: var(--ds-text-2);
10
+ font-family: var(--ds-font-family-base);
11
+ font-weight: var(--ds-font-weight-medium);
12
+ }
13
+
14
+ .image {
15
+ width: 100%;
16
+ height: 100%;
17
+ object-fit: cover;
18
+ }
19
+
20
+ .defaultIcon {
21
+ padding: 20%;
22
+ }
23
+
24
+ .fallback {
25
+ display: flex;
26
+ align-items: center;
27
+ justify-content: center;
28
+ width: 100%;
29
+ height: 100%;
30
+ text-transform: uppercase;
31
+ }
32
+
33
+ /* Sizes */
34
+ .xs {
35
+ width: var(--ds-space-6);
36
+ height: var(--ds-space-6);
37
+ font-size: 0.625rem;
38
+ }
39
+ .sm {
40
+ width: var(--ds-space-8);
41
+ height: var(--ds-space-8);
42
+ font-size: var(--ds-font-size-xs);
43
+ }
44
+ .md {
45
+ width: var(--ds-space-10, 2.5rem);
46
+ height: var(--ds-space-10, 2.5rem);
47
+ font-size: var(--ds-font-size-sm);
48
+ }
49
+ .lg {
50
+ width: var(--ds-space-12);
51
+ height: var(--ds-space-12);
52
+ font-size: var(--ds-font-size-base);
53
+ }
54
+ .xl {
55
+ width: var(--ds-space-16, 4rem);
56
+ height: var(--ds-space-16, 4rem);
57
+ font-size: var(--ds-font-size-lg);
58
+ }
@@ -0,0 +1,41 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Avatar } from './Avatar.tsx';
4
+ import { Box } from '../Box/Box.tsx';
5
+
6
+ const meta = {
7
+ title: 'Components/Avatar',
8
+ component: Avatar,
9
+ tags: ['autodocs'],
10
+ parameters: {
11
+ layout: 'centered',
12
+ },
13
+ } satisfies Meta<typeof Avatar>;
14
+
15
+ export default meta;
16
+ type Story = StoryObj<typeof meta>;
17
+
18
+ export const Default: Story = {
19
+ args: {
20
+ name: 'Jane Doe',
21
+ },
22
+ };
23
+
24
+ export const WithImage: Story = {
25
+ args: {
26
+ src: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=crop&w=128&q=80',
27
+ name: 'Jane Doe',
28
+ },
29
+ };
30
+
31
+ export const Sizes: Story = {
32
+ render: () => (
33
+ <Box display="flex" alignItems="center" gap={4}>
34
+ <Avatar size="xs" name="John Doe" />
35
+ <Avatar size="sm" name="John Doe" />
36
+ <Avatar size="md" name="John Doe" />
37
+ <Avatar size="lg" name="John Doe" />
38
+ <Avatar size="xl" name="John Doe" />
39
+ </Box>
40
+ ),
41
+ };
@@ -0,0 +1,64 @@
1
+ import clsx from 'clsx';
2
+ import { useState } from 'react';
3
+
4
+ import styles from './Avatar.module.css';
5
+ import type { AvatarProps } from './Avatar.types.ts';
6
+
7
+ export const Avatar = ({
8
+ src,
9
+ alt,
10
+ name,
11
+ size = 'md',
12
+ fallback,
13
+ className,
14
+ ...props
15
+ }: AvatarProps) => {
16
+ const [hasError, setHasError] = useState(false);
17
+ const accessibleLabel = alt ?? name;
18
+
19
+ const getInitials = (name: string) => {
20
+ return name
21
+ .split(' ')
22
+ .map((n) => n[0])
23
+ .slice(0, 2)
24
+ .join('');
25
+ };
26
+
27
+ const renderContent = () => {
28
+ if (src && !hasError) {
29
+ return (
30
+ <img
31
+ src={src}
32
+ alt={accessibleLabel || ''}
33
+ className={styles.image}
34
+ onError={() => setHasError(true)}
35
+ />
36
+ );
37
+ }
38
+
39
+ if (fallback) {
40
+ return <span className={styles.fallback}>{fallback}</span>;
41
+ }
42
+ if (name) {
43
+ return <span className={styles.fallback}>{getInitials(name)}</span>;
44
+ }
45
+
46
+ return (
47
+ <svg
48
+ viewBox="0 0 24 24"
49
+ fill="currentColor"
50
+ className={clsx(styles.image, styles.defaultIcon)}
51
+ aria-hidden="true"
52
+ focusable="false"
53
+ >
54
+ <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
55
+ </svg>
56
+ );
57
+ };
58
+
59
+ return (
60
+ <div className={clsx(styles.root, styles[size], className)} {...props}>
61
+ {renderContent()}
62
+ </div>
63
+ );
64
+ };
@@ -0,0 +1,12 @@
1
+ import type { HTMLAttributes } from 'react';
2
+
3
+ export type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
4
+
5
+ export interface AvatarProps extends HTMLAttributes<HTMLDivElement> {
6
+ src?: string;
7
+ alt?: string;
8
+ name?: string;
9
+ size?: AvatarSize;
10
+ fallback?: string;
11
+ className?: string;
12
+ }
@@ -0,0 +1,98 @@
1
+ .root {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ font-family: var(--ds-font-family-base);
6
+ font-weight: var(--ds-font-weight-medium);
7
+ border-radius: var(--ds-radius-full);
8
+ white-space: nowrap;
9
+ }
10
+
11
+ /* Sizes */
12
+ .sm {
13
+ height: var(--ds-space-5, 1.25rem);
14
+ padding: 0 var(--ds-space-2);
15
+ font-size: 0.625rem;
16
+ }
17
+
18
+ .md {
19
+ height: var(--ds-space-6);
20
+ padding: 0 var(--ds-space-3);
21
+ font-size: var(--ds-font-size-xs);
22
+ }
23
+
24
+ .lg {
25
+ height: var(--ds-space-8);
26
+ padding: 0 var(--ds-space-4);
27
+ font-size: var(--ds-font-size-sm);
28
+ }
29
+
30
+ /* Solid Variant */
31
+ .solid.neutral {
32
+ background-color: var(--ds-neutral);
33
+ color: var(--ds-text-on-brand);
34
+ }
35
+ .solid.success {
36
+ background-color: var(--ds-success);
37
+ color: var(--ds-text-on-brand);
38
+ }
39
+ .solid.warning {
40
+ background-color: var(--ds-warning);
41
+ color: var(--ds-text-on-brand);
42
+ }
43
+ .solid.danger {
44
+ background-color: var(--ds-danger);
45
+ color: var(--ds-text-on-brand);
46
+ }
47
+ .solid.info {
48
+ background-color: var(--ds-info);
49
+ color: var(--ds-text-on-brand);
50
+ }
51
+
52
+ /* Subtle Variant */
53
+ .subtle.neutral {
54
+ background-color: var(--ds-surface-1);
55
+ color: var(--ds-neutral-active);
56
+ }
57
+ .subtle.success {
58
+ background-color: var(--ds-success-subtle);
59
+ color: var(--ds-success-active);
60
+ }
61
+ .subtle.warning {
62
+ background-color: var(--ds-warning-subtle);
63
+ color: var(--ds-warning-active);
64
+ }
65
+ .subtle.danger {
66
+ background-color: var(--ds-danger-subtle);
67
+ color: var(--ds-danger-active);
68
+ }
69
+ .subtle.info {
70
+ background-color: var(--ds-info-subtle);
71
+ color: var(--ds-info-active);
72
+ }
73
+
74
+ /* Outline Variant */
75
+ .outline {
76
+ background-color: transparent;
77
+ border: 1px solid currentColor;
78
+ }
79
+ .outline.neutral {
80
+ color: var(--ds-neutral);
81
+ border-color: var(--ds-border-1);
82
+ }
83
+ .outline.success {
84
+ color: var(--ds-success);
85
+ border-color: var(--ds-success);
86
+ }
87
+ .outline.warning {
88
+ color: var(--ds-warning);
89
+ border-color: var(--ds-warning);
90
+ }
91
+ .outline.danger {
92
+ color: var(--ds-danger);
93
+ border-color: var(--ds-danger);
94
+ }
95
+ .outline.info {
96
+ color: var(--ds-info);
97
+ border-color: var(--ds-info);
98
+ }