@regardio/react 0.5.7 → 0.7.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 (214) hide show
  1. package/dist/background-slideshow/index.d.mts +34 -0
  2. package/dist/background-slideshow/index.mjs +110 -0
  3. package/dist/blurry-gradient/index.d.mts +16 -0
  4. package/dist/blurry-gradient/index.mjs +93 -0
  5. package/dist/button/index.d.mts +2 -0
  6. package/dist/button/index.mjs +3 -0
  7. package/dist/button-BiSQpBbc.mjs +129 -0
  8. package/dist/carousel/index.d.mts +74 -0
  9. package/dist/carousel/index.mjs +136 -0
  10. package/dist/checkbox/index.d.mts +28 -0
  11. package/dist/checkbox/index.mjs +70 -0
  12. package/dist/checkbox-group/index.d.mts +16 -0
  13. package/dist/checkbox-group/index.mjs +29 -0
  14. package/dist/chunk-BTpB_u-K.mjs +18 -0
  15. package/dist/countdown/index.d.mts +4 -0
  16. package/dist/countdown/index.mjs +58 -0
  17. package/dist/field/index.d.mts +68 -0
  18. package/dist/field/index.mjs +115 -0
  19. package/dist/fieldset/index.d.mts +34 -0
  20. package/dist/fieldset/index.mjs +61 -0
  21. package/dist/form/index.d.mts +21 -0
  22. package/dist/form/index.mjs +31 -0
  23. package/dist/generic-error/index.d.mts +44 -0
  24. package/dist/generic-error/index.mjs +57 -0
  25. package/dist/grid/index.d.mts +101 -0
  26. package/dist/grid/index.mjs +219 -0
  27. package/dist/heading/index.d.mts +27 -0
  28. package/dist/heading/index.mjs +28 -0
  29. package/dist/highlight/index.d.mts +17 -0
  30. package/dist/highlight/index.mjs +35 -0
  31. package/dist/hooks/use-current-route-data.d.mts +8 -0
  32. package/dist/hooks/use-current-route-data.mjs +22 -0
  33. package/dist/hooks/{use-focus-search.d.ts → use-focus-search.d.mts} +4 -3
  34. package/dist/hooks/use-focus-search.mjs +23 -0
  35. package/dist/hooks/use-matches-data.d.mts +10 -0
  36. package/dist/hooks/use-matches-data.mjs +23 -0
  37. package/dist/hooks/use-media-query.d.mts +9 -0
  38. package/dist/hooks/use-media-query.mjs +28 -0
  39. package/dist/hooks/use-mobile.d.mts +4 -0
  40. package/dist/hooks/use-mobile.mjs +22 -0
  41. package/dist/hooks/use-nonce.d.mts +6 -0
  42. package/dist/hooks/use-nonce.mjs +13 -0
  43. package/dist/hooks/use-orientation.d.mts +12 -0
  44. package/dist/hooks/use-orientation.mjs +32 -0
  45. package/dist/hooks/use-user.d.mts +53 -0
  46. package/dist/hooks/use-user.mjs +39 -0
  47. package/dist/icon-button/index.d.mts +28 -0
  48. package/dist/icon-button/index.mjs +36 -0
  49. package/dist/if/index.d.mts +13 -0
  50. package/dist/if/index.mjs +21 -0
  51. package/dist/iframe/index.d.mts +11 -0
  52. package/dist/iframe/index.mjs +15 -0
  53. package/dist/index-Bj5_XfEC.d.mts +29 -0
  54. package/dist/index-C_evL5vG.d.mts +35 -0
  55. package/dist/input/index.d.mts +2 -0
  56. package/dist/input/index.mjs +3 -0
  57. package/dist/input-CtR6aRVi.mjs +73 -0
  58. package/dist/link/index.d.mts +71 -0
  59. package/dist/link/index.mjs +129 -0
  60. package/dist/list/index.d.mts +72 -0
  61. package/dist/list/index.mjs +54 -0
  62. package/dist/markdown-container/index.d.mts +23 -0
  63. package/dist/markdown-container/index.mjs +71 -0
  64. package/dist/password-input/index.d.mts +23 -0
  65. package/dist/password-input/index.mjs +92 -0
  66. package/dist/picture/index.d.mts +39 -0
  67. package/dist/picture/index.mjs +3 -0
  68. package/dist/picture-DkX3W5zl.mjs +69 -0
  69. package/dist/protected-email/index.d.mts +24 -0
  70. package/dist/protected-email/index.mjs +37 -0
  71. package/dist/radio/index.d.mts +28 -0
  72. package/dist/radio/index.mjs +72 -0
  73. package/dist/radio-group/index.d.mts +16 -0
  74. package/dist/radio-group/index.mjs +29 -0
  75. package/dist/slider/index.d.mts +63 -0
  76. package/dist/slider/index.mjs +133 -0
  77. package/dist/switch/index.d.mts +29 -0
  78. package/dist/switch/index.mjs +87 -0
  79. package/dist/text/index.d.mts +25 -0
  80. package/dist/text/index.mjs +32 -0
  81. package/dist/text-EQC4zJbE.mjs +52 -0
  82. package/dist/toggle/index.d.mts +25 -0
  83. package/dist/toggle/index.mjs +82 -0
  84. package/dist/utils/author/index.d.mts +4 -0
  85. package/dist/utils/author/index.mjs +26 -0
  86. package/dist/utils/text/{index.d.ts → index.d.mts} +9 -8
  87. package/dist/utils/text/index.mjs +3 -0
  88. package/package.json +131 -83
  89. package/src/background-slideshow/background-slideshow.tsx +1 -2
  90. package/src/blurry-gradient/blurry-gradient.tsx +1 -1
  91. package/src/button/button.stories.tsx +161 -0
  92. package/src/button/button.test.tsx +73 -0
  93. package/src/button/button.tsx +118 -0
  94. package/src/button/index.ts +2 -0
  95. package/src/carousel/carousel-content.tsx +17 -14
  96. package/src/carousel/carousel-item.tsx +18 -18
  97. package/src/carousel/carousel-next.tsx +22 -17
  98. package/src/carousel/carousel-previous.tsx +22 -17
  99. package/src/carousel/carousel-root.tsx +91 -86
  100. package/src/checkbox/checkbox.stories.tsx +118 -0
  101. package/src/checkbox/checkbox.tsx +102 -0
  102. package/src/checkbox/index.ts +2 -0
  103. package/src/checkbox-group/checkbox-group.tsx +40 -0
  104. package/src/checkbox-group/index.ts +2 -0
  105. package/src/countdown/countdown.tsx +1 -1
  106. package/src/field/field.stories.tsx +105 -0
  107. package/src/field/field.test.tsx +61 -0
  108. package/src/field/field.tsx +186 -0
  109. package/src/field/index.ts +12 -0
  110. package/src/fieldset/fieldset.stories.tsx +204 -0
  111. package/src/fieldset/fieldset.test.tsx +63 -0
  112. package/src/fieldset/fieldset.tsx +86 -0
  113. package/src/fieldset/index.ts +7 -0
  114. package/src/form/form.stories.tsx +230 -0
  115. package/src/form/form.test.tsx +68 -0
  116. package/src/form/form.tsx +38 -0
  117. package/src/form/index.ts +2 -0
  118. package/src/generic-error/generic-error.tsx +2 -3
  119. package/src/grid/grid-item.tsx +77 -36
  120. package/src/grid/grid-root.tsx +49 -22
  121. package/src/heading/heading.tsx +7 -3
  122. package/src/highlight/highlight.tsx +1 -1
  123. package/src/hooks/use-current-route-data.ts +4 -2
  124. package/src/hooks/use-focus-search.ts +3 -1
  125. package/src/hooks/use-matches-data.ts +2 -0
  126. package/src/hooks/use-media-query.ts +2 -0
  127. package/src/hooks/use-mobile.ts +3 -1
  128. package/src/hooks/use-nonce.ts +3 -3
  129. package/src/hooks/use-orientation.ts +2 -0
  130. package/src/hooks/use-user.tsx +3 -2
  131. package/src/icon-button/icon-button.stories.tsx +128 -7
  132. package/src/icon-button/icon-button.test.tsx +152 -0
  133. package/src/icon-button/icon-button.tsx +43 -9
  134. package/src/if/if.tsx +3 -1
  135. package/src/input/index.ts +2 -0
  136. package/src/input/input.stories.tsx +151 -0
  137. package/src/input/input.test.tsx +65 -0
  138. package/src/input/input.tsx +113 -0
  139. package/src/link/link.tsx +4 -3
  140. package/src/list/list-item.tsx +10 -13
  141. package/src/list/list-root-context.ts +3 -3
  142. package/src/list/list-root.tsx +10 -13
  143. package/src/password-input/index.ts +1 -1
  144. package/src/password-input/password-input.tsx +104 -27
  145. package/src/protected-email/protected-email.tsx +6 -1
  146. package/src/radio/index.ts +2 -0
  147. package/src/radio/radio.tsx +103 -0
  148. package/src/radio-group/index.ts +2 -0
  149. package/src/radio-group/radio-group.tsx +40 -0
  150. package/src/slider/index.ts +18 -0
  151. package/src/slider/slider.tsx +201 -0
  152. package/src/switch/index.ts +2 -0
  153. package/src/switch/switch.stories.tsx +118 -0
  154. package/src/switch/switch.tsx +112 -0
  155. package/src/text/text.tsx +6 -1
  156. package/src/toggle/index.ts +2 -0
  157. package/src/toggle/toggle.stories.tsx +232 -0
  158. package/src/toggle/toggle.test.tsx +149 -0
  159. package/src/toggle/toggle.tsx +88 -0
  160. package/src/utils/text/text.tsx +8 -16
  161. package/dist/background-slideshow/index.d.ts +0 -24
  162. package/dist/background-slideshow/index.js +0 -165
  163. package/dist/blurry-gradient/index.d.ts +0 -16
  164. package/dist/blurry-gradient/index.js +0 -128
  165. package/dist/carousel/index.d.ts +0 -36
  166. package/dist/carousel/index.js +0 -171
  167. package/dist/countdown/index.d.ts +0 -5
  168. package/dist/countdown/index.js +0 -73
  169. package/dist/generic-error/index.d.ts +0 -43
  170. package/dist/generic-error/index.js +0 -47
  171. package/dist/grid/index.d.ts +0 -1196
  172. package/dist/grid/index.js +0 -239
  173. package/dist/heading/index.d.ts +0 -24
  174. package/dist/heading/index.js +0 -99
  175. package/dist/highlight/index.d.ts +0 -13
  176. package/dist/highlight/index.js +0 -59
  177. package/dist/hooks/use-current-route-data.d.ts +0 -7
  178. package/dist/hooks/use-current-route-data.js +0 -16
  179. package/dist/hooks/use-focus-search.js +0 -19
  180. package/dist/hooks/use-matches-data.d.ts +0 -9
  181. package/dist/hooks/use-matches-data.js +0 -15
  182. package/dist/hooks/use-media-query.d.ts +0 -8
  183. package/dist/hooks/use-media-query.js +0 -20
  184. package/dist/hooks/use-mobile.d.ts +0 -3
  185. package/dist/hooks/use-mobile.js +0 -19
  186. package/dist/hooks/use-nonce.d.ts +0 -7
  187. package/dist/hooks/use-nonce.js +0 -8
  188. package/dist/hooks/use-orientation.d.ts +0 -11
  189. package/dist/hooks/use-orientation.js +0 -29
  190. package/dist/hooks/use-user.d.ts +0 -50
  191. package/dist/hooks/use-user.js +0 -25
  192. package/dist/icon-button/index.d.ts +0 -9
  193. package/dist/icon-button/index.js +0 -17
  194. package/dist/if/index.d.ts +0 -10
  195. package/dist/if/index.js +0 -24
  196. package/dist/iframe/index.d.ts +0 -10
  197. package/dist/iframe/index.js +0 -17
  198. package/dist/link/index.d.ts +0 -55
  199. package/dist/link/index.js +0 -195
  200. package/dist/list/index.d.ts +0 -69
  201. package/dist/list/index.js +0 -65
  202. package/dist/markdown-container/index.d.ts +0 -22
  203. package/dist/markdown-container/index.js +0 -128
  204. package/dist/password-input/index.d.ts +0 -11
  205. package/dist/password-input/index.js +0 -46
  206. package/dist/picture/index.d.ts +0 -38
  207. package/dist/picture/index.js +0 -68
  208. package/dist/protected-email/index.d.ts +0 -20
  209. package/dist/protected-email/index.js +0 -30
  210. package/dist/text/index.d.ts +0 -20
  211. package/dist/text/index.js +0 -38
  212. package/dist/utils/author/index.d.ts +0 -3
  213. package/dist/utils/author/index.js +0 -33
  214. package/dist/utils/text/index.js +0 -73
@@ -1,6 +1,5 @@
1
1
  'use client';
2
2
 
3
- import type { ReactElement } from 'react';
4
3
  import { isRouteErrorResponse, useRouteError } from 'react-router';
5
4
 
6
5
  /**
@@ -73,8 +72,8 @@ export function getErrorDescriptor(error: unknown): ErrorDescriptor {
73
72
  export function GenericError({
74
73
  renderMessage,
75
74
  }: {
76
- renderMessage?: (descriptor: ErrorDescriptor) => ReactElement;
77
- } = {}): ReactElement {
75
+ renderMessage?: (descriptor: ErrorDescriptor) => React.JSX.Element;
76
+ } = {}): React.JSX.Element {
78
77
  const error = useRouteError();
79
78
  const descriptor = getErrorDescriptor(error);
80
79
 
@@ -1,5 +1,40 @@
1
- import { tv, type VariantProps } from '@regardio/tailwind/utils';
2
- import { forwardRef, type HTMLAttributes } from 'react';
1
+ import { tv } from '@regardio/tailwind/utils';
2
+ import type { HTMLAttributes } from 'react';
3
+
4
+ const GRID_ITEM_VARIANTS = {
5
+ end: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 'auto'] as const,
6
+ rowSpan: [1, 2, 3, 4, 5, 6, 'full'] as const,
7
+ span: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'full'] as const,
8
+ spanLg: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'full'] as const,
9
+ spanMd: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'full'] as const,
10
+ spanSm: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'full'] as const,
11
+ spanXl: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'full'] as const,
12
+ spanXs: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'full'] as const,
13
+ start: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 'auto'] as const,
14
+ } as const;
15
+
16
+ interface GridItemVariantProps {
17
+ end?: (typeof GRID_ITEM_VARIANTS.end)[number];
18
+ rowSpan?: (typeof GRID_ITEM_VARIANTS.rowSpan)[number];
19
+ span?: (typeof GRID_ITEM_VARIANTS.span)[number];
20
+ spanLg?: (typeof GRID_ITEM_VARIANTS.spanLg)[number];
21
+ spanMd?: (typeof GRID_ITEM_VARIANTS.spanMd)[number];
22
+ spanSm?: (typeof GRID_ITEM_VARIANTS.spanSm)[number];
23
+ spanXl?: (typeof GRID_ITEM_VARIANTS.spanXl)[number];
24
+ spanXs?: (typeof GRID_ITEM_VARIANTS.spanXs)[number];
25
+ start?: (typeof GRID_ITEM_VARIANTS.start)[number];
26
+ }
27
+
28
+ interface GridItemSlotProps {
29
+ class?: string;
30
+ className?: string;
31
+ }
32
+
33
+ interface GridItemSlots {
34
+ root: (props?: GridItemSlotProps) => string;
35
+ }
36
+
37
+ type GridItemStyleFn = (props?: GridItemVariantProps) => GridItemSlots;
3
38
 
4
39
  const gridItem = tv({
5
40
  defaultVariants: {
@@ -141,48 +176,54 @@ const gridItem = tv({
141
176
  auto: { root: 'col-start-auto' },
142
177
  },
143
178
  },
144
- });
179
+ }) as GridItemStyleFn;
145
180
 
146
- export type GridItemVariants = VariantProps<typeof gridItem>;
181
+ export type GridItemVariants = GridItemVariantProps;
147
182
 
148
183
  export interface GridItemProps extends HTMLAttributes<HTMLDivElement>, GridItemVariants {
149
184
  classNames?: {
150
185
  root?: string;
151
186
  };
187
+ ref?: React.Ref<HTMLDivElement>;
152
188
  }
153
189
 
154
- export const GridItem = forwardRef<HTMLDivElement, GridItemProps>(
155
- (
156
- {
157
- children,
158
- className,
159
- classNames,
160
- span,
161
- spanXs,
162
- spanSm,
163
- spanMd,
164
- spanLg,
165
- spanXl,
166
- start,
167
- end,
168
- rowSpan,
169
- ...props
170
- },
171
- ref,
172
- ) => {
173
- const styles = gridItem({ end, rowSpan, span, spanLg, spanMd, spanSm, spanXl, spanXs, start });
190
+ export const GridItem = function GridItem({
191
+ children,
192
+ className,
193
+ classNames,
194
+ span,
195
+ spanXs,
196
+ spanSm,
197
+ spanMd,
198
+ spanLg,
199
+ spanXl,
200
+ start,
201
+ end,
202
+ rowSpan,
203
+ ref,
204
+ ...props
205
+ }: GridItemProps): React.JSX.Element {
206
+ const styles = gridItem({
207
+ end,
208
+ rowSpan,
209
+ span,
210
+ spanLg,
211
+ spanMd,
212
+ spanSm,
213
+ spanXl,
214
+ spanXs,
215
+ start,
216
+ });
174
217
 
175
- return (
176
- <div
177
- className={styles.root({ className: classNames?.root ?? className })}
178
- ref={ref}
179
- {...props}
180
- >
181
- {children}
182
- </div>
183
- );
184
- },
185
- );
186
- GridItem.displayName = 'GridItem';
218
+ return (
219
+ <div
220
+ className={styles.root({ className: classNames?.root ?? className })}
221
+ ref={ref}
222
+ {...props}
223
+ >
224
+ {children}
225
+ </div>
226
+ );
227
+ };
187
228
 
188
229
  export { gridItem };
@@ -1,5 +1,26 @@
1
- import { tv, type VariantProps } from '@regardio/tailwind/utils';
2
- import { createContext, forwardRef, type HTMLAttributes, useContext } from 'react';
1
+ import { tv } from '@regardio/tailwind/utils';
2
+ import { createContext, type HTMLAttributes, useContext } from 'react';
3
+
4
+ const GRID_VARIANTS = {
5
+ align: ['center', 'end', 'start', 'stretch'] as const,
6
+ flow: ['column', 'dense', 'row'] as const,
7
+ } as const;
8
+
9
+ interface GridVariantProps {
10
+ align?: (typeof GRID_VARIANTS.align)[number];
11
+ flow?: (typeof GRID_VARIANTS.flow)[number];
12
+ }
13
+
14
+ interface GridSlotProps {
15
+ class?: string;
16
+ className?: string;
17
+ }
18
+
19
+ interface GridSlots {
20
+ root: (props?: GridSlotProps) => string;
21
+ }
22
+
23
+ type GridStyleFn = (props?: GridVariantProps) => GridSlots;
3
24
 
4
25
  const grid = tv({
5
26
  defaultVariants: {
@@ -28,9 +49,9 @@ const grid = tv({
28
49
  row: { root: 'grid-auto-flow-row' },
29
50
  },
30
51
  },
31
- });
52
+ }) as GridStyleFn;
32
53
 
33
- type GridVariants = VariantProps<typeof grid>;
54
+ type GridVariants = GridVariantProps;
34
55
 
35
56
  interface GridContextValue {
36
57
  styles: ReturnType<typeof grid>;
@@ -38,7 +59,7 @@ interface GridContextValue {
38
59
 
39
60
  const GridContext = createContext<GridContextValue | null>(null);
40
61
 
41
- export function useGrid() {
62
+ export function useGrid(): GridContextValue {
42
63
  const context = useContext(GridContext);
43
64
  if (!context) {
44
65
  throw new Error('useGrid must be used within a <Grid.Root />');
@@ -50,23 +71,29 @@ export interface GridRootProps extends HTMLAttributes<HTMLDivElement>, GridVaria
50
71
  classNames?: {
51
72
  root?: string;
52
73
  };
74
+ ref?: React.Ref<HTMLDivElement>;
53
75
  }
54
76
 
55
- export const GridRoot = forwardRef<HTMLDivElement, GridRootProps>(
56
- ({ children, className, classNames, flow, align, ...props }, ref) => {
57
- const styles = grid({ align, flow });
77
+ export const GridRoot = function GridRoot({
78
+ children,
79
+ className,
80
+ classNames,
81
+ flow,
82
+ align,
83
+ ref,
84
+ ...props
85
+ }: GridRootProps): React.JSX.Element {
86
+ const styles = grid({ align, flow });
58
87
 
59
- return (
60
- <GridContext.Provider value={{ styles }}>
61
- <div
62
- className={styles.root({ className: classNames?.root ?? className })}
63
- ref={ref}
64
- {...props}
65
- >
66
- {children}
67
- </div>
68
- </GridContext.Provider>
69
- );
70
- },
71
- );
72
- GridRoot.displayName = 'GridRoot';
88
+ return (
89
+ <GridContext.Provider value={{ styles }}>
90
+ <div
91
+ className={styles.root({ className: classNames?.root ?? className })}
92
+ ref={ref}
93
+ {...props}
94
+ >
95
+ {children}
96
+ </div>
97
+ </GridContext.Provider>
98
+ );
99
+ };
@@ -30,7 +30,13 @@ export interface HeadingProps extends HTMLAttributes<HTMLHeadingElement> {
30
30
  locale?: string;
31
31
  }
32
32
 
33
- export const Heading = ({ as, children, className, level = 2, ...props }: HeadingProps) => {
33
+ export const Heading = function Heading({
34
+ as,
35
+ children,
36
+ className,
37
+ level = 2,
38
+ ...props
39
+ }: HeadingProps): React.JSX.Element {
34
40
  const word = lowerCaseSzett(shy(children));
35
41
  const Component: ElementType = as || `h${level}`;
36
42
 
@@ -48,5 +54,3 @@ export const Heading = ({ as, children, className, level = 2, ...props }: Headin
48
54
  </Component>
49
55
  );
50
56
  };
51
-
52
- Heading.displayName = 'Heading';
@@ -20,7 +20,7 @@ export interface HighlightProps extends ComponentProps<'mark'> {
20
20
  variant?: HighlightVariant;
21
21
  }
22
22
 
23
- export const Highlight = ({ children, className, variant }: HighlightProps) => {
23
+ export const Highlight = ({ children, className, variant }: HighlightProps): React.JSX.Element => {
24
24
  return (
25
25
  <mark
26
26
  className={highlight({
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  import { useMemo } from 'react';
2
4
  import { useLocation, useMatches } from 'react-router';
3
5
 
@@ -5,7 +7,7 @@ import { useLocation, useMatches } from 'react-router';
5
7
  * This base hook is used to access data related to the current route
6
8
  * @returns {JSON|undefined} The router data or undefined if not found
7
9
  */
8
- export function useCurrentRouteData<HeaderData>() {
10
+ export function useCurrentRouteData<HeaderData>(): HeaderData | undefined {
9
11
  const location = useLocation();
10
12
  const matchingRoutes = useMatches();
11
13
  const route = useMemo(() => {
@@ -14,5 +16,5 @@ export function useCurrentRouteData<HeaderData>() {
14
16
  });
15
17
  }, [matchingRoutes, location]);
16
18
 
17
- return route?.data || (undefined as HeaderData);
19
+ return (route?.loaderData as HeaderData) || undefined;
18
20
  }
@@ -1,8 +1,10 @@
1
+ 'use client';
2
+
1
3
  import type { RefObject } from 'react';
2
4
  import { useEffect } from 'react';
3
5
 
4
6
  /** Focuses on the field when user clicks cmd + k or ctrl + k */
5
- export function useFocusSearch(ref: RefObject<HTMLInputElement>) {
7
+ export function useFocusSearch(ref: RefObject<HTMLInputElement>): void {
6
8
  useEffect(() => {
7
9
  function handleKeyDown(event: KeyboardEvent) {
8
10
  if ((event.metaKey || event.ctrlKey) && event.key === 'k') {
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  import { useMemo } from 'react';
2
4
  import { useMatches } from 'react-router';
3
5
 
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  import { useEffect, useState } from 'react';
2
4
 
3
5
  /**
@@ -1,8 +1,10 @@
1
+ 'use client';
2
+
1
3
  import { useEffect, useState } from 'react';
2
4
 
3
5
  const MOBILE_BREAKPOINT = 768;
4
6
 
5
- export function useIsMobile() {
7
+ export function useIsMobile(): boolean {
6
8
  const [isMobile, setIsMobile] = useState<boolean | undefined>(undefined);
7
9
 
8
10
  useEffect(() => {
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { createContext, useContext } from 'react';
6
6
 
7
- export const NonceContext = createContext<string>('');
8
- export const NonceProvider = NonceContext.Provider;
7
+ export const NonceContext: React.Context<string> = createContext<string>('');
8
+ export const NonceProvider: React.Provider<string> = NonceContext.Provider;
9
9
 
10
- export const useNonce = () => useContext(NonceContext);
10
+ export const useNonce = (): string => useContext(NonceContext);
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  import { useEffect, useState } from 'react';
2
4
 
3
5
  /**
@@ -26,7 +26,8 @@ const defaultContextValue: UserContextType = {
26
26
  /**
27
27
  * Context for storing and accessing the current authenticated user
28
28
  */
29
- export const UserContext = createContext<UserContextType>(defaultContextValue);
29
+ export const UserContext: React.Context<UserContextType> =
30
+ createContext<UserContextType>(defaultContextValue);
30
31
 
31
32
  /**
32
33
  * Props for the UserContextProvider component
@@ -53,7 +54,7 @@ export function UserContextProvider({
53
54
  user,
54
55
  isLoading = false,
55
56
  children,
56
- }: UserContextProviderProps) {
57
+ }: UserContextProviderProps): React.JSX.Element {
57
58
  return <UserContext.Provider value={{ isLoading, user }}>{children}</UserContext.Provider>;
58
59
  }
59
60
 
@@ -2,6 +2,26 @@ import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import { IconButton } from './icon-button';
3
3
 
4
4
  const meta: Meta<typeof IconButton> = {
5
+ argTypes: {
6
+ disabled: {
7
+ control: 'boolean',
8
+ description: 'Disable the button',
9
+ },
10
+ size: {
11
+ control: 'select',
12
+ description: 'Icon button size',
13
+ options: ['sm', 'md', 'lg'],
14
+ },
15
+ title: {
16
+ control: 'text',
17
+ description: 'Title for tooltip and accessibility',
18
+ },
19
+ variant: {
20
+ control: 'select',
21
+ description: 'Button variant',
22
+ options: ['primary', 'secondary', 'outline', 'ghost', 'destructive'],
23
+ },
24
+ },
5
25
  component: IconButton,
6
26
  parameters: {
7
27
  layout: 'centered',
@@ -11,7 +31,7 @@ const meta: Meta<typeof IconButton> = {
11
31
  };
12
32
 
13
33
  export default meta;
14
- type Story = StoryObj<typeof IconButton>;
34
+ type Story = StoryObj<typeof meta>;
15
35
 
16
36
  const PlusIcon = () => (
17
37
  <svg
@@ -61,30 +81,131 @@ const CloseIcon = () => (
61
81
  </svg>
62
82
  );
63
83
 
84
+ const SettingsIcon = () => (
85
+ <svg
86
+ fill="none"
87
+ height="24"
88
+ stroke="currentColor"
89
+ strokeWidth="2"
90
+ viewBox="0 0 24 24"
91
+ width="24"
92
+ >
93
+ <circle
94
+ cx="12"
95
+ cy="12"
96
+ r="3"
97
+ />
98
+ <path d="m12 1v6m0 6v6m4.22-13.22 4.24 4.24M1.54 8.96l4.24 4.24m12.44 0 4.24 4.24M1.54 15.04l4.24-4.24" />
99
+ </svg>
100
+ );
101
+
64
102
  export const Default: Story = {
65
103
  args: {
66
104
  icon: <PlusIcon />,
105
+ title: 'Add',
67
106
  },
68
107
  };
69
108
 
70
109
  export const Close: Story = {
71
110
  args: {
72
111
  icon: <CloseIcon />,
112
+ title: 'Close',
113
+ variant: 'ghost',
114
+ },
115
+ };
116
+
117
+ export const Settings: Story = {
118
+ args: {
119
+ icon: <SettingsIcon />,
120
+ title: 'Settings',
121
+ variant: 'secondary',
122
+ },
123
+ };
124
+
125
+ export const Small: Story = {
126
+ args: {
127
+ icon: <PlusIcon />,
128
+ size: 'sm',
129
+ title: 'Add',
130
+ },
131
+ };
132
+
133
+ export const Large: Story = {
134
+ args: {
135
+ icon: <PlusIcon />,
136
+ size: 'lg',
137
+ title: 'Add',
73
138
  },
74
139
  };
75
140
 
76
- export const WithCustomClass: Story = {
141
+ export const Disabled: Story = {
77
142
  args: {
78
- className: 'p-2 bg-gray-100 rounded hover:bg-gray-200',
143
+ disabled: true,
79
144
  icon: <PlusIcon />,
145
+ title: 'Add',
146
+ },
147
+ };
148
+
149
+ export const WithAriaLabel: Story = {
150
+ args: {
151
+ 'aria-label': 'Close dialog',
152
+ icon: <CloseIcon />,
80
153
  },
81
154
  };
82
155
 
83
- export const AllIcons: Story = {
156
+ export const AllVariants: Story = {
84
157
  render: () => (
85
- <div style={{ display: 'flex', gap: '16px' }}>
86
- <IconButton icon={<PlusIcon />} />
87
- <IconButton icon={<CloseIcon />} />
158
+ <div className="flex gap-4">
159
+ <IconButton
160
+ icon={<PlusIcon />}
161
+ title="Add"
162
+ variant="primary"
163
+ />
164
+ <IconButton
165
+ icon={<SettingsIcon />}
166
+ title="Settings"
167
+ variant="secondary"
168
+ />
169
+ <IconButton
170
+ icon={<CloseIcon />}
171
+ title="Close"
172
+ variant="ghost"
173
+ />
174
+ <IconButton
175
+ icon={<PlusIcon />}
176
+ title="Delete"
177
+ variant="destructive"
178
+ />
88
179
  </div>
89
180
  ),
90
181
  };
182
+
183
+ export const AllSizes: Story = {
184
+ render: () => (
185
+ <div className="flex items-center gap-4">
186
+ <IconButton
187
+ icon={<PlusIcon />}
188
+ size="sm"
189
+ title="Small"
190
+ />
191
+ <IconButton
192
+ icon={<PlusIcon />}
193
+ size="md"
194
+ title="Medium"
195
+ />
196
+ <IconButton
197
+ icon={<PlusIcon />}
198
+ size="lg"
199
+ title="Large"
200
+ />
201
+ </div>
202
+ ),
203
+ };
204
+
205
+ export const Interactive: Story = {
206
+ args: {
207
+ icon: <PlusIcon />,
208
+ onClick: () => alert('Icon button clicked!'),
209
+ title: 'Add item',
210
+ },
211
+ };