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,43 @@
1
+ import clsx from 'clsx';
2
+ import { useId } from 'react';
3
+
4
+ import styles from './Textarea.module.css';
5
+ import type { TextareaProps } from './Textarea.types.ts';
6
+
7
+ export const Textarea = ({
8
+ size = 'md',
9
+ error,
10
+ label,
11
+ helperText,
12
+ className,
13
+ id,
14
+ rows = 4,
15
+ ...props
16
+ }: TextareaProps) => {
17
+ const baseId = useId();
18
+ const componentId = id ?? `ds-textarea-${baseId}`;
19
+ const helperId = helperText ? `${componentId}-help` : undefined;
20
+
21
+ return (
22
+ <div className={clsx(styles.wrapper, className)}>
23
+ {label && (
24
+ <label htmlFor={componentId} className={styles.label}>
25
+ {label}
26
+ </label>
27
+ )}
28
+ <textarea
29
+ id={componentId}
30
+ rows={rows}
31
+ className={clsx(styles.textareaRoot, styles[size], error && styles.error)}
32
+ aria-describedby={helperId}
33
+ aria-invalid={error || undefined}
34
+ {...props}
35
+ />
36
+ {helperText && (
37
+ <span id={helperId} className={clsx(styles.helperText, error && styles.errorText)}>
38
+ {helperText}
39
+ </span>
40
+ )}
41
+ </div>
42
+ );
43
+ };
@@ -0,0 +1,11 @@
1
+ import type { TextareaHTMLAttributes } from 'react';
2
+
3
+ export type TextareaSize = 'sm' | 'md' | 'lg';
4
+
5
+ export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
6
+ size?: TextareaSize;
7
+ error?: boolean;
8
+ label?: string;
9
+ helperText?: string;
10
+ rows?: number;
11
+ }
@@ -0,0 +1,125 @@
1
+ .root {
2
+ position: relative;
3
+ display: inline-block;
4
+ }
5
+
6
+ .trigger {
7
+ display: inline-block;
8
+ }
9
+
10
+ .tooltip {
11
+ position: absolute;
12
+ z-index: 1000;
13
+ padding: var(--ds-space-2) var(--ds-space-3);
14
+ font-size: var(--ds-font-size-xs);
15
+ border-radius: var(--ds-radius-sm);
16
+ white-space: nowrap;
17
+ pointer-events: none;
18
+ opacity: 0;
19
+ transition: opacity 0.2s;
20
+ }
21
+
22
+ .dark {
23
+ background-color: var(--neutral-900);
24
+ color: var(--neutral-0);
25
+ }
26
+
27
+ .light {
28
+ background-color: var(--ds-surface-0);
29
+ color: var(--ds-text-1);
30
+ border: 1px solid var(--ds-border-1);
31
+ box-shadow: var(--ds-shadow-md);
32
+ }
33
+
34
+ .visible {
35
+ opacity: 1;
36
+ }
37
+
38
+ /* Positions */
39
+ .top {
40
+ bottom: 100%;
41
+ left: 50%;
42
+ transform: translateX(-50%) translateY(calc(-1 * var(--ds-space-2)));
43
+ }
44
+
45
+ .bottom {
46
+ top: 100%;
47
+ left: 50%;
48
+ transform: translateX(-50%) translateY(var(--ds-space-2));
49
+ }
50
+
51
+ .left {
52
+ top: 50%;
53
+ right: 100%;
54
+ transform: translateY(-50%) translateX(calc(-1 * var(--ds-space-2)));
55
+ }
56
+
57
+ .right {
58
+ top: 50%;
59
+ left: 100%;
60
+ transform: translateY(-50%) translateX(var(--ds-space-2));
61
+ }
62
+
63
+ /* Arrow (optional, simple version) */
64
+ .tooltip::after {
65
+ content: '';
66
+ position: absolute;
67
+ border-width: 0.3125rem;
68
+ border-style: solid;
69
+ }
70
+
71
+ .top::after {
72
+ top: 100%;
73
+ left: 50%;
74
+ margin-left: -0.3125rem;
75
+ }
76
+
77
+ .top.dark::after {
78
+ border-color: var(--neutral-900) transparent transparent transparent;
79
+ }
80
+
81
+ .top.light::after {
82
+ border-color: var(--ds-border-1) transparent transparent transparent;
83
+ }
84
+
85
+ .bottom::after {
86
+ bottom: 100%;
87
+ left: 50%;
88
+ margin-left: -0.3125rem;
89
+ }
90
+
91
+ .bottom.dark::after {
92
+ border-color: transparent transparent var(--neutral-900) transparent;
93
+ }
94
+
95
+ .bottom.light::after {
96
+ border-color: transparent transparent var(--ds-border-1) transparent;
97
+ }
98
+
99
+ .left::after {
100
+ left: 100%;
101
+ top: 50%;
102
+ margin-top: -0.3125rem;
103
+ }
104
+
105
+ .left.dark::after {
106
+ border-color: transparent transparent transparent var(--neutral-900);
107
+ }
108
+
109
+ .left.light::after {
110
+ border-color: transparent transparent transparent var(--ds-border-1);
111
+ }
112
+
113
+ .right::after {
114
+ right: 100%;
115
+ top: 50%;
116
+ margin-top: -0.3125rem;
117
+ }
118
+
119
+ .right.dark::after {
120
+ border-color: transparent var(--neutral-900) transparent transparent;
121
+ }
122
+
123
+ .right.light::after {
124
+ border-color: transparent var(--ds-border-1) transparent transparent;
125
+ }
@@ -0,0 +1,68 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { Tooltip } from './Tooltip.tsx';
4
+ import { Button } from '../Button/Button.tsx';
5
+
6
+ const meta: Meta<typeof Tooltip> = {
7
+ title: 'Components/Tooltip',
8
+ component: Tooltip,
9
+ tags: ['autodocs'],
10
+ decorators: [
11
+ (Story) => (
12
+ <div
13
+ style={{
14
+ display: 'flex',
15
+ justifyContent: 'center',
16
+ alignItems: 'center',
17
+ height: '200px',
18
+ width: '100%',
19
+ }}
20
+ >
21
+ <Story />
22
+ </div>
23
+ ),
24
+ ],
25
+ };
26
+
27
+ export default meta;
28
+ type Story = StoryObj<typeof Tooltip>;
29
+
30
+ export const Top: Story = {
31
+ args: {
32
+ content: 'Tooltip content',
33
+ children: <Button>Hover me</Button>,
34
+ position: 'top',
35
+ },
36
+ };
37
+
38
+ export const Bottom: Story = {
39
+ args: {
40
+ content: 'Tooltip content',
41
+ children: <Button>Hover me</Button>,
42
+ position: 'bottom',
43
+ },
44
+ };
45
+
46
+ export const Left: Story = {
47
+ args: {
48
+ content: 'Tooltip content',
49
+ children: <Button>Hover me</Button>,
50
+ position: 'left',
51
+ },
52
+ };
53
+
54
+ export const Right: Story = {
55
+ args: {
56
+ content: 'Tooltip content',
57
+ children: <Button>Hover me</Button>,
58
+ position: 'right',
59
+ },
60
+ };
61
+
62
+ export const LightVariant: Story = {
63
+ args: {
64
+ content: 'Light Tooltip',
65
+ children: <Button variant="subtle">Hover me (Light)</Button>,
66
+ variant: 'light',
67
+ },
68
+ };
@@ -0,0 +1,87 @@
1
+ import clsx from 'clsx';
2
+ import {
3
+ useState,
4
+ useRef,
5
+ useId,
6
+ isValidElement,
7
+ cloneElement,
8
+ type KeyboardEvent,
9
+ type ReactElement,
10
+ } from 'react';
11
+
12
+ import styles from './Tooltip.module.css';
13
+ import type { TooltipProps } from './Tooltip.types.ts';
14
+
15
+ export const Tooltip = ({
16
+ content,
17
+ children,
18
+ position = 'top',
19
+ variant = 'dark',
20
+ delay = 200,
21
+ className,
22
+ id,
23
+ }: TooltipProps) => {
24
+ const [isVisible, setIsVisible] = useState(false);
25
+ const timeoutRef = useRef<number | null>(null);
26
+ const baseId = useId();
27
+ const componentId = id ?? `ds-tooltip-${baseId}`;
28
+ const tooltipId = `${componentId}-content`;
29
+
30
+ const showTooltip = () => {
31
+ timeoutRef.current = window.setTimeout(() => {
32
+ setIsVisible(true);
33
+ }, delay);
34
+ };
35
+
36
+ const hideTooltip = () => {
37
+ if (timeoutRef.current) {
38
+ window.clearTimeout(timeoutRef.current);
39
+ }
40
+ setIsVisible(false);
41
+ };
42
+
43
+ const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
44
+ if (event.key === 'Escape') {
45
+ hideTooltip();
46
+ }
47
+ };
48
+
49
+ const trigger = isValidElement(children)
50
+ ? (() => {
51
+ const child = children as ReactElement<{ 'aria-describedby'?: string }>;
52
+ return cloneElement(child, {
53
+ 'aria-describedby': [child.props['aria-describedby'], tooltipId]
54
+ .filter(Boolean)
55
+ .join(' '),
56
+ });
57
+ })()
58
+ : children;
59
+
60
+ return (
61
+ <div
62
+ id={componentId}
63
+ className={clsx(styles.root, className)}
64
+ onMouseEnter={showTooltip}
65
+ onMouseLeave={hideTooltip}
66
+ onFocus={showTooltip}
67
+ onBlur={hideTooltip}
68
+ onKeyDown={handleKeyDown}
69
+ >
70
+ <div className={styles.trigger}>{trigger}</div>
71
+ {isVisible && (
72
+ <div
73
+ className={clsx(
74
+ styles.tooltip,
75
+ styles[position],
76
+ styles[variant],
77
+ isVisible && styles.visible
78
+ )}
79
+ id={tooltipId}
80
+ role="tooltip"
81
+ >
82
+ {content}
83
+ </div>
84
+ )}
85
+ </div>
86
+ );
87
+ };
@@ -0,0 +1,14 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
4
+ export type TooltipVariant = 'dark' | 'light';
5
+
6
+ export interface TooltipProps {
7
+ id?: string;
8
+ content: ReactNode;
9
+ children: ReactNode;
10
+ position?: TooltipPosition;
11
+ variant?: TooltipVariant;
12
+ delay?: number;
13
+ className?: string;
14
+ }
package/src/index.ts ADDED
@@ -0,0 +1,132 @@
1
+ // styles
2
+ import './styles/ds.css';
3
+
4
+ // components
5
+ export { Accordion } from './components/Accordion/Accordion.tsx';
6
+ export type { AccordionProps, AccordionItem } from './components/Accordion/Accordion.types.ts';
7
+ export { Avatar } from './components/Avatar/Avatar.tsx';
8
+ export type { AvatarProps, AvatarSize } from './components/Avatar/Avatar.types.ts';
9
+ export { Badge } from './components/Badge/Badge.tsx';
10
+ export type {
11
+ BadgeProps,
12
+ BadgeSize,
13
+ BadgeIntent,
14
+ BadgeVariant,
15
+ } from './components/Badge/Badge.types.ts';
16
+ export { Box } from './components/Box/Box.tsx';
17
+ export type {
18
+ BoxProps,
19
+ BoxPadding,
20
+ BoxGap,
21
+ BoxDisplay,
22
+ BoxFlexDirection,
23
+ BoxAlignItems,
24
+ BoxJustifyContent,
25
+ } from './components/Box/Box.types.ts';
26
+ export { Breadcrumbs, BreadcrumbItem } from './components/Breadcrumbs/Breadcrumbs.tsx';
27
+ export type {
28
+ BreadcrumbsProps,
29
+ BreadcrumbItemProps,
30
+ } from './components/Breadcrumbs/Breadcrumbs.types.ts';
31
+ export { Button } from './components/Button/Button.tsx';
32
+ export type {
33
+ ButtonProps,
34
+ ButtonSize,
35
+ ButtonVariant,
36
+ ButtonIntent,
37
+ } from './components/Button/Button.types.ts';
38
+ export { Card, CardContent, CardFooter, CardHeader } from './components/Card/Card.tsx';
39
+ export type {
40
+ CardProps,
41
+ CardContentProps,
42
+ CardFooterProps,
43
+ CardHeaderProps,
44
+ } from './components/Card/Card.types.ts';
45
+ export { Checkbox } from './components/Checkbox/Checkbox.tsx';
46
+ export type { CheckboxProps } from './components/Checkbox/Checkbox.types.ts';
47
+ export { Dropdown } from './components/Dropdown/Dropdown.tsx';
48
+ export type {
49
+ DropdownProps,
50
+ DropdownOption,
51
+ DropdownSize,
52
+ } from './components/Dropdown/Dropdown.types.ts';
53
+ export { Header } from './components/Header/Header.tsx';
54
+ export type { HeaderProps } from './components/Header/Header.types.ts';
55
+ export { NavBar } from './components/NavBar/NavBar.tsx';
56
+ export type { NavBarProps, NavBarItem } from './components/NavBar/NavBar.types.ts';
57
+ export { Input } from './components/Input/Input.tsx';
58
+ export type { InputProps } from './components/Input/Input.types.ts';
59
+ export { Loader } from './components/Loader/Loader.tsx';
60
+ export type { LoaderProps, LoaderSize } from './components/Loader/Loader.types.ts';
61
+ export { Modal } from './components/Modal/Modal.tsx';
62
+ export type { ModalProps } from './components/Modal/Modal.types.ts';
63
+ export { Notification } from './components/Notification/Notification.tsx';
64
+ export type { NotificationProps } from './components/Notification/Notification.types.ts';
65
+ export { Pagination } from './components/Pagination/Pagination.tsx';
66
+ export type {
67
+ PaginationProps,
68
+ PaginationLabels,
69
+ } from './components/Pagination/Pagination.types.ts';
70
+ export { ProgressBar } from './components/ProgressBar/ProgressBar.tsx';
71
+ export type {
72
+ ProgressBarProps,
73
+ ProgressBarSize,
74
+ ProgressBarIntent,
75
+ } from './components/ProgressBar/ProgressBar.types.ts';
76
+ export { RadioButton } from './components/RadioButton/RadioButton.tsx';
77
+ export type { RadioButtonProps } from './components/RadioButton/RadioButton.types.ts';
78
+ export { Skeleton } from './components/Skeleton/Skeleton.tsx';
79
+ export type { SkeletonProps } from './components/Skeleton/Skeleton.types.ts';
80
+ export { Stepper } from './components/Stepper/Stepper.tsx';
81
+ export type {
82
+ StepperProps,
83
+ StepperOrientation,
84
+ StepperSize,
85
+ } from './components/Stepper/Stepper.types.ts';
86
+ export type { StepOptions, StepperStatus } from './components/Stepper/Step.types.ts';
87
+ export { Select } from './components/Select/Select.tsx';
88
+ export type { SelectProps, SelectOption, SelectSize } from './components/Select/Select.types.ts';
89
+ export { Switch } from './components/Switch/Switch.tsx';
90
+ export type { SwitchProps } from './components/Switch/Switch.types.ts';
91
+ export {
92
+ Table,
93
+ TableBody,
94
+ TableCell,
95
+ TableFooter,
96
+ TableHead,
97
+ TableHeader,
98
+ TableRow,
99
+ } from './components/Table/Table.tsx';
100
+ export type {
101
+ TableProps,
102
+ TableBodyProps,
103
+ TableCellProps,
104
+ TableFooterProps,
105
+ TableHeadProps,
106
+ TableRowProps,
107
+ TableHeaderProps,
108
+ } from './components/Table/Table.types.ts';
109
+ export { Tabs } from './components/Tabs/Tabs.tsx';
110
+ export type { TabsProps, TabItem } from './components/Tabs/Tabs.types.ts';
111
+ export { Text } from './components/Text/Text.tsx';
112
+ export type {
113
+ TextProps,
114
+ TextAlign,
115
+ TextColor,
116
+ TextVariant,
117
+ FontWeight,
118
+ } from './components/Text/Text.types.ts';
119
+ export { Textarea } from './components/Textarea/Textarea.tsx';
120
+ export type { TextareaProps, TextareaSize } from './components/Textarea/Textarea.types.ts';
121
+ export { Tooltip } from './components/Tooltip/Tooltip.tsx';
122
+ export type { TooltipProps, TooltipPosition } from './components/Tooltip/Tooltip.types.ts';
123
+
124
+ // layouts
125
+ export { AppLayout } from './layouts/AppLayout/AppLayout.tsx';
126
+ export type { AppLayoutProps } from './layouts/AppLayout/AppLayout.types.ts';
127
+ export { AuthLayout } from './layouts/AuthLayout/AuthLayout.tsx';
128
+ export type { AuthLayoutProps } from './layouts/AuthLayout/AuthLayout.types.tsx';
129
+ export { DashboardLayout } from './layouts/DashboardLayout/DashboardLayout.tsx';
130
+ export type { DashboardLayoutProps } from './layouts/DashboardLayout/DashboardLayout.types.tsx';
131
+ export { SettingsLayout } from './layouts/SettingsLayout/SettingsLayout.tsx';
132
+ export type { SettingsLayoutProps } from './layouts/SettingsLayout/SettingsLayout.types.tsx';
@@ -0,0 +1,17 @@
1
+ .root {
2
+ display: flex;
3
+ flex-direction: column;
4
+ min-height: 100vh;
5
+ background-color: var(--ds-surface-1);
6
+ }
7
+
8
+ .main {
9
+ flex: 1;
10
+ padding: var(--ds-space-6) 0;
11
+ }
12
+
13
+ .container {
14
+ max-width: 75rem;
15
+ margin: 0 auto;
16
+ padding: 0 var(--ds-space-4);
17
+ }
@@ -0,0 +1,124 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { fn } from 'storybook/test';
3
+
4
+ import { AppLayout } from './AppLayout.tsx';
5
+ import { Box } from '../../components/Box/Box.tsx';
6
+ import { Button } from '../../components/Button/Button.tsx';
7
+ import { Card, CardHeader, CardContent } from '../../components/Card/Card.tsx';
8
+ import { Text } from '../../components/Text/Text.tsx';
9
+
10
+ const meta = {
11
+ title: 'Layouts/AppLayout',
12
+ component: AppLayout,
13
+ parameters: {
14
+ layout: 'fullscreen',
15
+ },
16
+ args: {
17
+ headerTitle: 'Tharaday',
18
+ onLogin: fn(),
19
+ onLogout: fn(),
20
+ onCreateAccount: fn(),
21
+ onNavItemClick: fn(),
22
+ },
23
+ } satisfies Meta<typeof AppLayout>;
24
+
25
+ export default meta;
26
+ type Story = StoryObj<typeof meta>;
27
+
28
+ const logo = (
29
+ <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
30
+ <g fill="none" fillRule="evenodd">
31
+ <path
32
+ d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
33
+ fill="#3b82f6"
34
+ />
35
+ <path d="M16 8l8 12H8l8-12z" fill="#FFF" />
36
+ </g>
37
+ </svg>
38
+ );
39
+
40
+ const navItems = [
41
+ { id: 'dashboard', label: 'Dashboard' },
42
+ { id: 'components', label: 'Components' },
43
+ { id: 'tokens', label: 'Design Tokens' },
44
+ { id: 'settings', label: 'Settings' },
45
+ ];
46
+
47
+ export const Default: Story = {
48
+ args: {
49
+ headerLogo: logo,
50
+ user: { name: 'John Doe' },
51
+ navItems,
52
+ activeNavId: 'dashboard',
53
+ navActions: (
54
+ <Button size="sm" variant="outline">
55
+ Feedback
56
+ </Button>
57
+ ),
58
+ children: (
59
+ <Box display="flex" flexDirection="column" gap={6}>
60
+ <Box>
61
+ <Text variant="h2">Dashboard Overview</Text>
62
+ <Text variant="body-lg" color="subtle">
63
+ Welcome to the demonstration of combined Header and NavBar.
64
+ </Text>
65
+ </Box>
66
+
67
+ <Box display="grid" gridTemplateColumns="1fr 1fr" gap={6}>
68
+ <Card bordered>
69
+ <CardHeader title="Role: Header" />
70
+ <CardContent>
71
+ <Text variant="body-md">
72
+ The top bar is the <strong>Header</strong>. It handles:
73
+ </Text>
74
+ <ul>
75
+ <li>Global Branding (Logo & Title)</li>
76
+ <li>User Identity (Welcome message)</li>
77
+ <li>Session State (Log out button)</li>
78
+ </ul>
79
+ </CardContent>
80
+ </Card>
81
+
82
+ <Card bordered>
83
+ <CardHeader title="Role: NavBar" />
84
+ <CardContent>
85
+ <Text variant="body-md">
86
+ The second bar is the <strong>NavBar</strong>. It handles:
87
+ </Text>
88
+ <ul>
89
+ <li>Information Architecture (Main sections)</li>
90
+ <li>Active State (Current location)</li>
91
+ <li>Contextual Actions (Feedback button)</li>
92
+ </ul>
93
+ </CardContent>
94
+ </Card>
95
+ </Box>
96
+
97
+ <Card bordered>
98
+ <CardHeader title="Why use both?" />
99
+ <CardContent>
100
+ <Text variant="body-md">
101
+ Using both components allows you to separate <strong>who</strong> the user is (Header)
102
+ from <strong>where</strong> the user is going (NavBar). This separation of concerns
103
+ keeps your UI clean and intuitive as the application grows in complexity.
104
+ </Text>
105
+ </CardContent>
106
+ </Card>
107
+ </Box>
108
+ ),
109
+ },
110
+ };
111
+
112
+ export const LoggedOut: Story = {
113
+ args: {
114
+ ...Default.args,
115
+ user: undefined,
116
+ navItems: [
117
+ { id: 'home', label: 'Home' },
118
+ { id: 'features', label: 'Features' },
119
+ { id: 'pricing', label: 'Pricing' },
120
+ { id: 'docs', label: 'Documentation' },
121
+ ],
122
+ activeNavId: 'home',
123
+ },
124
+ };
@@ -0,0 +1,46 @@
1
+ import styles from './AppLayout.module.css';
2
+ import type { AppLayoutProps } from './AppLayout.types.ts';
3
+ import { Header } from '../../components/Header/Header.tsx';
4
+ import { NavBar } from '../../components/NavBar/NavBar.tsx';
5
+
6
+ /**
7
+ * AppLayout provides a standard layout structure that includes both
8
+ * a Header (for branding and user state) and a NavBar (for navigation).
9
+ *
10
+ * This component demonstrates the distinct roles of Header and NavBar.
11
+ */
12
+ export const AppLayout = ({
13
+ headerLogo,
14
+ headerTitle = 'Tharaday',
15
+ user,
16
+ navItems,
17
+ activeNavId,
18
+ navActions,
19
+ children,
20
+ onLogin,
21
+ onLogout,
22
+ onCreateAccount,
23
+ onNavItemClick,
24
+ }: AppLayoutProps) => {
25
+ return (
26
+ <div className={styles.root}>
27
+ <Header
28
+ logo={headerLogo}
29
+ title={headerTitle}
30
+ user={user}
31
+ onLogin={onLogin}
32
+ onLogout={onLogout}
33
+ onCreateAccount={onCreateAccount}
34
+ />
35
+ <NavBar
36
+ items={navItems}
37
+ activeId={activeNavId}
38
+ actions={navActions}
39
+ onItemClick={onNavItemClick}
40
+ />
41
+ <main className={styles.main}>
42
+ <div className={styles.container}>{children}</div>
43
+ </main>
44
+ </div>
45
+ );
46
+ };