@vygruppen/spor-react 11.3.9 → 12.0.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 (322) hide show
  1. package/.turbo/turbo-build.log +32 -11
  2. package/.turbo/turbo-typegen.log +23 -0
  3. package/CHANGELOG.md +245 -0
  4. package/dist/index.d.mts +2552 -8319
  5. package/dist/index.d.ts +2552 -8319
  6. package/dist/index.js +9609 -8607
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +9487 -8454
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +21 -13
  11. package/src/accordion/Accordion.tsx +96 -45
  12. package/src/accordion/Expandable.tsx +54 -127
  13. package/src/accordion/helpers.ts +31 -0
  14. package/src/accordion/types.ts +60 -0
  15. package/src/alert/Alert.tsx +101 -0
  16. package/src/alert/AlertIcon.tsx +63 -45
  17. package/src/alert/ExpandableAlert.tsx +96 -64
  18. package/src/alert/ServiceAlert.tsx +127 -125
  19. package/src/alert/{index.tsx → index.ts} +1 -2
  20. package/src/breadcrumb/Breadcrumb.tsx +39 -24
  21. package/src/button/Button.tsx +86 -105
  22. package/src/button/ButtonGroup.tsx +45 -20
  23. package/src/button/Clipboard.tsx +82 -0
  24. package/src/button/CloseButton.tsx +4 -3
  25. package/src/button/FloatingActionButton.tsx +35 -41
  26. package/src/button/IconButton.tsx +34 -30
  27. package/src/button/index.tsx +1 -0
  28. package/src/color-mode/color-mode.tsx +75 -0
  29. package/src/color-mode/index.ts +1 -0
  30. package/src/datepicker/Calendar.tsx +17 -8
  31. package/src/datepicker/CalendarCell.tsx +20 -13
  32. package/src/datepicker/CalendarGrid.tsx +18 -10
  33. package/src/datepicker/CalendarHeader.tsx +2 -0
  34. package/src/datepicker/CalendarNavigationButton.tsx +1 -0
  35. package/src/datepicker/CalendarTriggerButton.tsx +43 -45
  36. package/src/datepicker/DateField.tsx +21 -12
  37. package/src/datepicker/DatePicker.tsx +61 -58
  38. package/src/datepicker/DateRangePicker.tsx +52 -58
  39. package/src/datepicker/DateTimeSegment.tsx +13 -5
  40. package/src/datepicker/RangeCalendar.tsx +13 -7
  41. package/src/datepicker/StyledField.tsx +25 -17
  42. package/src/datepicker/TimeField.tsx +10 -8
  43. package/src/datepicker/TimePicker.tsx +48 -45
  44. package/src/datepicker/types.ts +5 -0
  45. package/src/dialog/Dialog.tsx +56 -0
  46. package/src/dialog/Drawer.tsx +187 -0
  47. package/src/dialog/index.ts +2 -0
  48. package/src/dialog/types.ts +26 -0
  49. package/src/image/index.tsx +2 -2
  50. package/src/index.tsx +5 -3
  51. package/src/input/AttachedInputs.tsx +17 -42
  52. package/src/input/CardSelect.tsx +75 -162
  53. package/src/input/Checkbox.tsx +30 -6
  54. package/src/input/CheckboxGroup.tsx +25 -16
  55. package/src/input/ChoiceChip.tsx +58 -77
  56. package/src/input/Combobox.tsx +172 -172
  57. package/src/input/CountryCodeSelect.tsx +42 -28
  58. package/src/input/Dialog.tsx +1 -0
  59. package/src/input/Field.tsx +71 -0
  60. package/src/input/Fieldset.tsx +7 -0
  61. package/src/input/Input.tsx +68 -73
  62. package/src/input/InputGroup.tsx +66 -0
  63. package/src/input/ListBox.tsx +83 -70
  64. package/src/input/NativeSelect.tsx +68 -33
  65. package/src/input/NumericStepper.tsx +173 -171
  66. package/src/input/PasswordInput.tsx +99 -52
  67. package/src/input/PhoneNumberInput.tsx +69 -72
  68. package/src/input/Popover.tsx +1 -0
  69. package/src/input/Radio.tsx +37 -17
  70. package/src/input/SearchInput.tsx +24 -86
  71. package/src/input/Select.tsx +237 -0
  72. package/src/input/Switch.tsx +60 -18
  73. package/src/input/Textarea.tsx +53 -101
  74. package/src/input/{index.tsx → index.ts} +2 -8
  75. package/src/layout/PressableCard.tsx +12 -21
  76. package/src/layout/RadioCard.tsx +68 -100
  77. package/src/layout/Separator.tsx +32 -0
  78. package/src/layout/StaticCard.tsx +13 -33
  79. package/src/layout/index.tsx +3 -7
  80. package/src/linjetag/InfoTag.tsx +16 -9
  81. package/src/linjetag/LineIcon.tsx +74 -28
  82. package/src/linjetag/TravelTag.tsx +38 -27
  83. package/src/link/TextLink.tsx +25 -16
  84. package/src/list/index.tsx +24 -2
  85. package/src/loader/ClientOnly.tsx +8 -7
  86. package/src/loader/ColorInlineLoader.tsx +4 -3
  87. package/src/loader/ColorSpinner.tsx +5 -4
  88. package/src/loader/ContentLoader.tsx +6 -4
  89. package/src/loader/DarkFullScreenLoader.tsx +11 -3
  90. package/src/loader/DarkInlineLoader.tsx +5 -3
  91. package/src/loader/DarkSpinner.tsx +7 -3
  92. package/src/loader/LightFullScreenLoader.tsx +11 -3
  93. package/src/loader/LightInlineLoader.tsx +11 -3
  94. package/src/loader/LightSpinner.tsx +5 -3
  95. package/src/loader/Lottie.tsx +3 -3
  96. package/src/loader/ProgressBar.tsx +83 -84
  97. package/src/loader/ProgressLoader.tsx +120 -75
  98. package/src/loader/Skeleton.tsx +94 -19
  99. package/src/loader/index.tsx +0 -2
  100. package/src/loader/useHydrated.tsx +1 -0
  101. package/src/loader/useRotatingLabel.tsx +2 -1
  102. package/src/logo/CargonetLogo.tsx +89 -89
  103. package/src/logo/VyLogo.tsx +61 -42
  104. package/src/logo/VyLogoPride.tsx +137 -139
  105. package/src/media-controller/JumpButton.tsx +48 -38
  106. package/src/media-controller/PlayPauseButton.tsx +31 -29
  107. package/src/media-controller/SkipButton.tsx +38 -37
  108. package/src/nudge/Nudge.tsx +195 -123
  109. package/src/nudge/index.tsx +0 -1
  110. package/src/pagination/Pagination.tsx +221 -118
  111. package/src/pagination/types.ts +23 -0
  112. package/src/popover/index.tsx +67 -0
  113. package/src/progress-indicator/ProgressDot.tsx +11 -10
  114. package/src/progress-indicator/ProgressIndicator.tsx +28 -15
  115. package/src/provider/SporProvider.tsx +17 -14
  116. package/src/stepper/Stepper.tsx +88 -85
  117. package/src/stepper/StepperContext.tsx +2 -1
  118. package/src/stepper/StepperStep.tsx +28 -21
  119. package/src/tab/Tabs.tsx +62 -12
  120. package/src/tab/index.tsx +1 -9
  121. package/src/table/Table.tsx +35 -30
  122. package/src/table/index.tsx +11 -7
  123. package/src/theme/brand.ts +7 -0
  124. package/src/theme/index.ts +45 -37
  125. package/src/theme/recipes/attached-inputs.ts +43 -0
  126. package/src/theme/recipes/badge.ts +104 -0
  127. package/src/theme/recipes/button.ts +124 -0
  128. package/src/theme/recipes/choice-chip.ts +144 -0
  129. package/src/theme/recipes/close-button.ts +41 -0
  130. package/src/theme/recipes/code.ts +14 -0
  131. package/src/theme/recipes/group.ts +19 -0
  132. package/src/theme/recipes/index.ts +29 -0
  133. package/src/theme/recipes/input.ts +89 -0
  134. package/src/theme/recipes/link.ts +64 -0
  135. package/src/theme/recipes/nudge.ts +12 -0
  136. package/src/theme/recipes/pressable-card.ts +83 -0
  137. package/src/theme/recipes/progress-loader.ts +14 -0
  138. package/src/theme/recipes/separator.ts +85 -0
  139. package/src/theme/recipes/skeleton.ts +57 -0
  140. package/src/theme/recipes/static-card.ts +39 -0
  141. package/src/theme/recipes/textarea.ts +27 -0
  142. package/src/theme/semantic-tokens/colors.ts +22 -0
  143. package/src/theme/semantic-tokens/index.ts +24 -0
  144. package/src/theme/semantic-tokens/radii.ts +14 -0
  145. package/src/theme/semantic-tokens/shadows.ts +17 -0
  146. package/src/theme/slot-recipes/accordion.ts +131 -0
  147. package/src/theme/slot-recipes/alert-expandable.ts +133 -0
  148. package/src/theme/slot-recipes/alert-service.ts +66 -0
  149. package/src/theme/slot-recipes/alert.ts +72 -0
  150. package/src/theme/slot-recipes/anatomy.ts +269 -0
  151. package/src/theme/slot-recipes/breadcrumb.ts +61 -0
  152. package/src/theme/slot-recipes/checkbox.ts +89 -0
  153. package/src/theme/slot-recipes/datepicker.ts +214 -0
  154. package/src/theme/slot-recipes/dialog.ts +221 -0
  155. package/src/theme/slot-recipes/drawer.ts +205 -0
  156. package/src/theme/slot-recipes/field.ts +79 -0
  157. package/src/theme/slot-recipes/floating-action-button.ts +131 -0
  158. package/src/theme/slot-recipes/index.ts +65 -0
  159. package/src/theme/slot-recipes/info-tag.ts +62 -0
  160. package/src/theme/slot-recipes/line-icon.ts +140 -0
  161. package/src/theme/slot-recipes/list.ts +45 -0
  162. package/src/theme/slot-recipes/listbox.ts +72 -0
  163. package/src/theme/slot-recipes/media-controller-button.ts +131 -0
  164. package/src/theme/slot-recipes/native-select.ts +54 -0
  165. package/src/theme/slot-recipes/numeric-stepper.ts +65 -0
  166. package/src/theme/slot-recipes/pagination.ts +41 -0
  167. package/src/theme/slot-recipes/popover.ts +78 -0
  168. package/src/theme/slot-recipes/progress-bar.ts +39 -0
  169. package/src/theme/slot-recipes/progress-indicator.ts +22 -0
  170. package/src/theme/slot-recipes/radio-card.ts +112 -0
  171. package/src/theme/slot-recipes/radio.ts +80 -0
  172. package/src/theme/slot-recipes/select.ts +243 -0
  173. package/src/theme/slot-recipes/stepper.ts +92 -0
  174. package/src/theme/slot-recipes/switch.ts +147 -0
  175. package/src/theme/slot-recipes/table.ts +200 -0
  176. package/src/theme/slot-recipes/tabs.ts +169 -0
  177. package/src/theme/slot-recipes/toast.ts +56 -0
  178. package/src/theme/slot-recipes/travel-tag.ts +192 -0
  179. package/src/theme/tokens/animation-styles.ts +50 -0
  180. package/src/theme/tokens/animations.ts +22 -0
  181. package/src/theme/tokens/aspect-ratios.ts +22 -0
  182. package/src/theme/tokens/blurs.ts +28 -0
  183. package/src/theme/tokens/borders.ts +26 -0
  184. package/src/theme/{foundations → tokens}/breakpoints.ts +0 -1
  185. package/src/theme/tokens/colors.ts +10 -0
  186. package/src/theme/tokens/config.ts +10 -0
  187. package/src/theme/tokens/cursor.ts +28 -0
  188. package/src/theme/tokens/durations.ts +25 -0
  189. package/src/theme/tokens/easings.ts +16 -0
  190. package/src/theme/tokens/font-sizes.ts +30 -0
  191. package/src/theme/tokens/font-weights.ts +31 -0
  192. package/src/theme/tokens/fonts.ts +8 -0
  193. package/src/theme/tokens/global-css.ts +18 -0
  194. package/src/theme/tokens/index.ts +37 -0
  195. package/src/theme/tokens/keyframes.ts +255 -0
  196. package/src/theme/tokens/letter-spacings.ts +19 -0
  197. package/src/theme/tokens/line-heights.ts +19 -0
  198. package/src/theme/tokens/radii.ts +13 -0
  199. package/src/theme/tokens/sizes.ts +51 -0
  200. package/src/theme/tokens/spacing.ts +20 -0
  201. package/src/theme/tokens/text-styles.ts +89 -0
  202. package/src/theme/tokens/z-index.ts +17 -0
  203. package/src/theme/utils/accent-utils.ts +8 -21
  204. package/src/theme/utils/bg-utils.ts +4 -6
  205. package/src/theme/utils/brand-utils.ts +6 -19
  206. package/src/theme/utils/core-utils.ts +91 -0
  207. package/src/theme/utils/floating-utils.ts +20 -39
  208. package/src/theme/utils/ghost-utils.ts +7 -21
  209. package/src/theme/utils/input-utils.ts +32 -37
  210. package/src/theme/utils/outline-utils.ts +4 -11
  211. package/src/theme/utils/surface-utils.ts +5 -19
  212. package/src/theme/utils/types.ts +1 -0
  213. package/src/toast/index.tsx +1 -1
  214. package/src/toast/toast.tsx +105 -0
  215. package/src/transition/index.ts +2 -8
  216. package/src/typography/Badge.tsx +15 -61
  217. package/src/typography/Code.tsx +16 -28
  218. package/src/typography/Heading.tsx +34 -19
  219. package/src/typography/Text.tsx +9 -6
  220. package/src/typography/{index.tsx → index.ts} +1 -0
  221. package/src/util/externals.tsx +13 -27
  222. package/tsconfig.json +5 -1
  223. package/src/accordion/Accordion.test.tsx +0 -20
  224. package/src/alert/BaseAlert.test.tsx +0 -37
  225. package/src/alert/BaseAlert.tsx +0 -34
  226. package/src/alert/ClosableAlert.test.tsx +0 -37
  227. package/src/alert/ClosableAlert.tsx +0 -85
  228. package/src/alert/ExpandableAlert.test.tsx +0 -84
  229. package/src/alert/StaticAlert.tsx +0 -33
  230. package/src/button/Button.test.tsx +0 -23
  231. package/src/datepicker/TimePicker.test.tsx +0 -74
  232. package/src/input/FormControl.tsx +0 -2
  233. package/src/input/FormErrorMessage.tsx +0 -95
  234. package/src/input/FormLabel.tsx +0 -11
  235. package/src/input/InfoSelect.tsx +0 -274
  236. package/src/input/InputElement.tsx +0 -44
  237. package/src/input/RadioGroup.tsx +0 -47
  238. package/src/layout/Divider.tsx +0 -27
  239. package/src/layout/RadioCardGroup.tsx +0 -79
  240. package/src/layout/Stack.tsx +0 -42
  241. package/src/loader/SkeletonCircle.tsx +0 -13
  242. package/src/loader/SkeletonText.tsx +0 -14
  243. package/src/media-controller/index.test.tsx +0 -59
  244. package/src/modal/Drawer.tsx +0 -120
  245. package/src/modal/FullScreenDrawer.tsx +0 -239
  246. package/src/modal/Modal.tsx +0 -15
  247. package/src/modal/ModalHeader.tsx +0 -31
  248. package/src/modal/SimpleDrawer.tsx +0 -51
  249. package/src/modal/index.tsx +0 -5
  250. package/src/nudge/WizardNudge.tsx +0 -107
  251. package/src/theme/components/accordion.ts +0 -102
  252. package/src/theme/components/alert-expandable.ts +0 -125
  253. package/src/theme/components/alert-service.ts +0 -98
  254. package/src/theme/components/alert.ts +0 -71
  255. package/src/theme/components/badge.ts +0 -109
  256. package/src/theme/components/breadcrumb.ts +0 -60
  257. package/src/theme/components/button.ts +0 -125
  258. package/src/theme/components/card-select.ts +0 -117
  259. package/src/theme/components/checkbox.ts +0 -88
  260. package/src/theme/components/choice-chip.ts +0 -161
  261. package/src/theme/components/close-button.ts +0 -48
  262. package/src/theme/components/code.ts +0 -17
  263. package/src/theme/components/datepicker.ts +0 -198
  264. package/src/theme/components/divider.ts +0 -50
  265. package/src/theme/components/drawer.ts +0 -95
  266. package/src/theme/components/fab.ts +0 -109
  267. package/src/theme/components/form-label.ts +0 -17
  268. package/src/theme/components/form.ts +0 -27
  269. package/src/theme/components/index.ts +0 -45
  270. package/src/theme/components/info-select.ts +0 -85
  271. package/src/theme/components/info-tag.ts +0 -63
  272. package/src/theme/components/input.ts +0 -28
  273. package/src/theme/components/line-icon.ts +0 -129
  274. package/src/theme/components/link.ts +0 -78
  275. package/src/theme/components/list.ts +0 -23
  276. package/src/theme/components/listbox.ts +0 -77
  277. package/src/theme/components/media-controller-button.ts +0 -97
  278. package/src/theme/components/modal.ts +0 -96
  279. package/src/theme/components/numeric-stepper.ts +0 -65
  280. package/src/theme/components/pagination.ts +0 -74
  281. package/src/theme/components/popover.ts +0 -68
  282. package/src/theme/components/pressable-card.ts +0 -72
  283. package/src/theme/components/progress-bar.ts +0 -47
  284. package/src/theme/components/progress-indicator.ts +0 -44
  285. package/src/theme/components/radio-card.ts +0 -134
  286. package/src/theme/components/radio.ts +0 -68
  287. package/src/theme/components/select.ts +0 -74
  288. package/src/theme/components/skeleton.ts +0 -40
  289. package/src/theme/components/static-card.ts +0 -82
  290. package/src/theme/components/stepper.ts +0 -100
  291. package/src/theme/components/switch.ts +0 -112
  292. package/src/theme/components/table.ts +0 -161
  293. package/src/theme/components/tabs.ts +0 -135
  294. package/src/theme/components/textarea.ts +0 -33
  295. package/src/theme/components/toast.ts +0 -28
  296. package/src/theme/components/travel-tag.ts +0 -256
  297. package/src/theme/foundations/borders.ts +0 -11
  298. package/src/theme/foundations/colors.ts +0 -12
  299. package/src/theme/foundations/config.ts +0 -5
  300. package/src/theme/foundations/fontSizes.ts +0 -29
  301. package/src/theme/foundations/fontWeights.ts +0 -5
  302. package/src/theme/foundations/fonts.ts +0 -7
  303. package/src/theme/foundations/index.ts +0 -15
  304. package/src/theme/foundations/lineHeights.ts +0 -6
  305. package/src/theme/foundations/radii.ts +0 -12
  306. package/src/theme/foundations/shadows.ts +0 -8
  307. package/src/theme/foundations/sizes.ts +0 -36
  308. package/src/theme/foundations/spacing.ts +0 -31
  309. package/src/theme/foundations/styles.ts +0 -12
  310. package/src/theme/foundations/textStyles.ts +0 -74
  311. package/src/theme/foundations/zIndices.ts +0 -17
  312. package/src/theme/utils/base-utils.ts +0 -104
  313. package/src/theme/utils/focus-utils.ts +0 -10
  314. package/src/toast/ActionToast.test.tsx +0 -22
  315. package/src/toast/ActionToast.tsx +0 -28
  316. package/src/toast/BaseToast.test.tsx +0 -27
  317. package/src/toast/BaseToast.tsx +0 -75
  318. package/src/toast/ClosableToast.test.tsx +0 -17
  319. package/src/toast/ClosableToast.tsx +0 -40
  320. package/src/toast/useToast.tsx +0 -121
  321. package/src/tooltip/Tooltip.tsx +0 -70
  322. package/src/tooltip/index.tsx +0 -1
@@ -1,38 +1,80 @@
1
+ "use client";
1
2
  import {
3
+ RecipeVariantProps,
2
4
  Switch as ChakraSwitch,
3
- SwitchProps as ChakraSwitchProps,
4
- forwardRef,
5
+ ConditionalValue,
6
+ useSlotRecipe,
5
7
  } from "@chakra-ui/react";
6
- import { As } from "@chakra-ui/system";
7
- import React from "react";
8
+ import React, { forwardRef, PropsWithChildren } from "react";
9
+ import { switchSlotRecipe } from "../theme/slot-recipes/switch";
10
+ import { Field } from "./Field";
8
11
 
9
- export type SwitchProps = Omit<ChakraSwitchProps, "colorScheme" | "variant"> & {
10
- size?: "sm" | "md" | "lg";
11
- };
12
+ type SwitchVariants = RecipeVariantProps<typeof switchSlotRecipe>;
13
+
14
+ export type SwitchProps = Exclude<
15
+ ChakraSwitch.RootProps,
16
+ "size" | "colorPalette"
17
+ > &
18
+ PropsWithChildren<SwitchVariants> & {
19
+ inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
20
+ rootRef?: React.Ref<HTMLLabelElement>;
21
+ trackLabel?: { on: React.ReactNode; off: React.ReactNode };
22
+ thumbLabel?: { on: React.ReactNode; off: React.ReactNode };
23
+ size?: ConditionalValue<"sm" | "md" | "lg">;
24
+ label?: React.ReactNode;
25
+ onCheckedChange?: (checked: boolean) => void;
26
+ };
12
27
 
13
28
  /**
14
29
  * A switch lets you toggle between on and off, yes and no. It's an alternative to a checkbox.
15
30
  *
16
- * You can use a Switch component inside of a `FormControl` with an associated `FormLabel`:
31
+ * You can set a label inside of the Switch component by defining the `label` prop.
17
32
  *
18
33
  * ```tsx
19
- * <FormControl>
20
- * <FormLabel>Enable alerts?</FormLabel>
21
- * <Switch />
22
- * </FormControl>
34
+ * <Switch label="This is a label"/>
23
35
  * ```
24
36
  *
25
37
  * Switches are available in three different sizes - `sm`, `md` and `lg`.
26
38
  *
27
39
  * ```tsx
28
- * <FormControl>
29
- * <FormLabel>Enable alerts?</FormLabel>
40
+ *
30
41
  * <Switch size="sm" />
31
- * </FormControl>
42
+ *
32
43
  * ```
33
44
  */
34
- export const Switch = forwardRef<SwitchProps, "input">(
35
- ({ size = "md", as, ...props }, ref) => {
36
- return <ChakraSwitch as={as} size={size} {...props} ref={ref} />;
45
+
46
+ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
47
+ (props, ref) => {
48
+ const {
49
+ inputProps,
50
+ children,
51
+ rootRef,
52
+ trackLabel,
53
+ thumbLabel,
54
+ size = "md",
55
+ label,
56
+ onCheckedChange,
57
+ ...rest
58
+ } = props;
59
+
60
+ const recipe = useSlotRecipe({ key: "switch" });
61
+ const styles = recipe({ size });
62
+
63
+ return (
64
+ <Field style={{ width: "auto" }}>
65
+ <ChakraSwitch.Root
66
+ ref={rootRef}
67
+ {...rest}
68
+ checked={props.checked}
69
+ css={styles.root}
70
+ >
71
+ <ChakraSwitch.Label>{label}</ChakraSwitch.Label>
72
+ <ChakraSwitch.HiddenInput />
73
+ <ChakraSwitch.Control css={styles.control}>
74
+ <ChakraSwitch.Thumb />
75
+ </ChakraSwitch.Control>
76
+ </ChakraSwitch.Root>
77
+ </Field>
78
+ );
37
79
  },
38
80
  );
@@ -1,21 +1,37 @@
1
+ "use client";
2
+
1
3
  import {
2
- FormLabel,
3
- forwardRef,
4
+ RecipeVariantProps,
5
+ useRecipe,
4
6
  Textarea as ChakraTextarea,
5
7
  TextareaProps as ChakraTextareaProps,
6
- useFormControlContext,
7
- InputGroup,
8
+ FieldLabel,
8
9
  } from "@chakra-ui/react";
9
- import React, { useId, useLayoutEffect, useRef, useState } from "react";
10
+ import React, {
11
+ forwardRef,
12
+ PropsWithChildren,
13
+ ReactNode,
14
+ useLayoutEffect,
15
+ useRef,
16
+ useState,
17
+ } from "react";
18
+ import { textareaRecipe } from "../theme/recipes/textarea";
19
+ import { Field, FieldProps } from "./Field";
10
20
 
11
- export type TextareaProps = Exclude<ChakraTextareaProps, "size"> & {
12
- label?: string;
13
- };
21
+ type TextareaVariants = RecipeVariantProps<typeof textareaRecipe>;
22
+ export type TextareaProps = Exclude<
23
+ ChakraTextareaProps,
24
+ "size" | "colorPalette"
25
+ > &
26
+ FieldProps &
27
+ PropsWithChildren<TextareaVariants> & {
28
+ label: ReactNode;
29
+ };
14
30
 
15
31
  /**
16
32
  * Hook to calculate the height of the label element to adjust spacing for the input for floating label.
17
33
  */
18
- const useLabelHeight = (label: string | undefined) => {
34
+ const useLabelHeight = (label: ReactNode | undefined) => {
19
35
  const labelRef = useRef<HTMLLabelElement>(null);
20
36
  const [labelHeight, setLabelHeight] = useState(0);
21
37
 
@@ -45,103 +61,39 @@ const useLabelHeight = (label: string | undefined) => {
45
61
  };
46
62
 
47
63
  /**
48
- * Text area that works with the `FormControl` component.
49
64
  *
50
- * Providing a label is optional.
65
+ * A simple Textarea component:
51
66
  *
52
67
  * ```tsx
53
- * <FormControl>
54
- * <Textarea label="E-mail" />
55
- * </FormControl>
68
+ * <Textarea label="Description" />
56
69
  * ```
70
+ *
71
+ * Textarea has two variants core, and floating.
72
+ *
57
73
  */
58
- export const Textarea = forwardRef<TextareaProps, "textarea">((props, ref) => {
59
- const {
60
- spacingProps,
61
- remainingProps: { label, ...rest },
62
- } = getSpacingProps(props);
63
- const formControlProps = useFormControlContext();
64
- const fallbackId = `textarea-${useId()}`;
65
- const inputId = props.id ?? formControlProps?.id ?? fallbackId;
66
74
 
67
- const { labelRef, labelHeight } = useLabelHeight(label);
75
+ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
76
+ (props, ref) => {
77
+ const { label, variant = "core", ...fieldProps } = props;
78
+ const recipe = useRecipe({ key: "textarea" });
79
+ const styles = recipe({ variant });
68
80
 
69
- return (
70
- <InputGroup
71
- position="relative"
72
- {...spacingProps}
73
- style={{ "--label-height": `${labelHeight}px` } as React.CSSProperties}
74
- >
75
- <ChakraTextarea {...rest} id={inputId} ref={ref} placeholder=" " />
76
- {label && (
77
- <FormLabel
78
- ref={labelRef}
79
- htmlFor={inputId}
80
- id={`${inputId}-label`}
81
- pointerEvents="none"
82
- >
83
- {label}
84
- </FormLabel>
85
- )}
86
- </InputGroup>
87
- );
88
- });
81
+ const { labelRef, labelHeight } = useLabelHeight(label);
89
82
 
90
- function getSpacingProps<T extends TextareaProps>(props: T) {
91
- const {
92
- mt,
93
- mr,
94
- mb,
95
- ml,
96
- mx,
97
- my,
98
- marginTop,
99
- marginRight,
100
- marginBottom,
101
- marginLeft,
102
- marginX,
103
- marginY,
104
- pt,
105
- pr,
106
- pb,
107
- pl,
108
- px,
109
- py,
110
- paddingTop,
111
- paddingRight,
112
- paddingBottom,
113
- paddingLeft,
114
- paddingX,
115
- paddingY,
116
- ...remainingProps
117
- } = props;
118
- return {
119
- spacingProps: {
120
- mt,
121
- mr,
122
- mb,
123
- ml,
124
- mx,
125
- my,
126
- marginTop,
127
- marginRight,
128
- marginBottom,
129
- marginLeft,
130
- marginX,
131
- marginY,
132
- pt,
133
- pr,
134
- pb,
135
- pl,
136
- px,
137
- py,
138
- paddingTop,
139
- paddingRight,
140
- paddingBottom,
141
- paddingLeft,
142
- paddingX,
143
- paddingY,
144
- },
145
- remainingProps,
146
- };
147
- }
83
+ return (
84
+ <Field {...fieldProps} position="relative">
85
+ <ChakraTextarea
86
+ {...props}
87
+ css={styles}
88
+ className="peer"
89
+ ref={ref}
90
+ style={
91
+ { "--label-height": `${labelHeight}px` } as React.CSSProperties
92
+ }
93
+ placeholder=" "
94
+ />
95
+ <FieldLabel ref={labelRef}>{label}</FieldLabel>
96
+ </Field>
97
+ );
98
+ },
99
+ );
@@ -1,24 +1,18 @@
1
- export { FormHelperText, InputGroup } from "@chakra-ui/react";
2
- export type { InputGroupProps } from "@chakra-ui/react";
3
1
  export * from "./AttachedInputs";
4
2
  export * from "./CardSelect";
5
3
  export * from "./Checkbox";
6
4
  export * from "./CheckboxGroup";
7
5
  export * from "./ChoiceChip";
8
6
  export * from "./Combobox";
9
- export * from "./FormControl";
10
- export * from "./FormErrorMessage";
11
- export * from "./FormLabel";
12
- export * from "./InfoSelect";
7
+ export * from "./Fieldset";
13
8
  export * from "./Input";
14
- export * from "./InputElement";
15
9
  export * from "./ListBox";
16
10
  export * from "./NativeSelect";
17
11
  export * from "./NumericStepper";
18
12
  export * from "./PasswordInput";
19
13
  export * from "./PhoneNumberInput";
20
14
  export * from "./Radio";
21
- export * from "./RadioGroup";
22
15
  export * from "./SearchInput";
23
16
  export * from "./Switch";
24
17
  export * from "./Textarea";
18
+ export * from "./Select";
@@ -1,11 +1,7 @@
1
- import React from "react";
2
- import { Box, BoxProps, forwardRef, useStyleConfig } from "@chakra-ui/react";
3
- import { As } from "@chakra-ui/system";
4
-
5
- type PressableCardProps = BoxProps & {
6
- /** Defaults to "base" */
7
- variant?: "floating" | "accent" | "base";
8
- };
1
+ "use client";
2
+ import React, { forwardRef } from "react";
3
+ import { ButtonProps, chakra, RecipeVariantProps } from "@chakra-ui/react";
4
+ import { pressableCardRecipe } from "../theme/recipes/pressable-card";
9
5
 
10
6
  /**
11
7
  * `PressableCard` is a component that renders a pressable card.
@@ -14,7 +10,7 @@ type PressableCardProps = BoxProps & {
14
10
  * It can be rendered as a button, link, label, or any other HTML element by specifying the `as` prop.
15
11
  * If no `as` prop is provided, it defaults to a button.
16
12
  *
17
- * The `variant` prop can be used to control the style variant of the card. It defaults to "base".
13
+ * The `variant` prop can be used to control the style variant of the card. It defaults to "core".
18
14
  *
19
15
  * Example usage:
20
16
  *
@@ -32,21 +28,16 @@ type PressableCardProps = BoxProps & {
32
28
  * </PressableCard>
33
29
  * ```
34
30
  *
35
- * For a static card with other color schemes, use the `StaticCard` component.
31
+ * For a static card with other color palette, use the `StaticCard` component.
36
32
  *
37
33
  * @see StaticCard
38
34
  */
39
35
 
40
- export const PressableCard = forwardRef<PressableCardProps, As>(
41
- ({ children, variant = "floating", ...props }, ref) => {
42
- const styles = useStyleConfig("PressableCard", {
43
- variant,
44
- });
36
+ const PressableCardButton = chakra("button", pressableCardRecipe);
37
+
38
+ type PressableCardProps = RecipeVariantProps<typeof pressableCardRecipe> &
39
+ ButtonProps;
45
40
 
46
- return (
47
- <Box __css={styles} {...props} ref={ref}>
48
- {children}
49
- </Box>
50
- );
51
- },
41
+ export const PressableCard = forwardRef<HTMLDivElement, PressableCardProps>(
42
+ (props, ref) => <PressableCardButton {...props} ref={ref} />,
52
43
  );
@@ -1,127 +1,95 @@
1
+ "use client";
1
2
  import {
2
- Box,
3
- BoxProps,
4
- chakra,
5
- forwardRef,
6
- useMultiStyleConfig,
3
+ RadioCard as ChakraRadioCard,
4
+ RecipeVariantProps,
5
+ useSlotRecipe,
7
6
  } from "@chakra-ui/react";
8
- import React, { useContext, useEffect, useId, useState } from "react";
9
- import { RadioCardGroupContext } from "./RadioCardGroup";
10
- import { dataAttr } from "@chakra-ui/utils";
7
+ import React, { forwardRef, useId } from "react";
8
+ import { radioCardSlotRecipe } from "../theme/slot-recipes/radio-card";
11
9
 
12
10
  /**
13
11
  * Radio cards are used to present a set of options where only one option can be selected.
14
12
  *
15
- * RadioCard components must be wrapped in a RadioCardGroup component.
16
- *
17
13
  * @example
18
14
  * ```tsx
19
- * <RadioCardGroup name="ticket">
20
- * <RadioCard value="economy">Economy</RadioCard>
21
- * <RadioCard value="business">Business</RadioCard>
22
- * <RadioCard value="first-class">First Class</RadioCard>
15
+ * <RadioCardGroup defaultValue="economy">
16
+ * <RadioCardLabel>Choose your class</RadioCardLabel>
17
+ * <Stack direction="row">
18
+ * <RadioCard value="economy" label="Economy" />
19
+ * <RadioCard value="business" label="Business" />
20
+ * <RadioCard value="first-class" label="First Class" />
21
+ * </Stack>
23
22
  * </RadioCardGroup>
24
23
  * ```
25
24
  *
26
- * RadioCard inherits props from Box.
27
- *
28
- * Be advised to not use the `name` prop on the RadioCard component.
29
- *
30
- * Changing the semantics may also cause the component to not work as expected.
31
25
  *
32
26
  * @see Docs https://spor.vy.no/components/radiocard
33
27
  */
34
28
 
35
- export type RadioCardProps = BoxProps & {
36
- /** The value that will be passed to the `RadioCardGroup`'s `onChange` function if this `RadioCard` is selected.. */
37
- value: string;
38
- /** The content of the RadioCard. */
39
- children: React.ReactNode;
40
- /** Determines if the RadioCard is disabled. */
41
- isDisabled?: boolean;
42
- };
43
-
44
- export const RadioCard = forwardRef(
45
- ({ children, value, isDisabled, ...props }: RadioCardProps, ref) => {
46
- const context = useContext(RadioCardGroupContext);
47
-
48
- if (!context) {
49
- throw new Error(
50
- "RadioCard components must be wrapped in a RadioCardGroup component",
51
- );
52
- }
29
+ type RadioCardVariantProps = RecipeVariantProps<typeof radioCardSlotRecipe>;
53
30
 
54
- const { name, selectedValue, onChange, variant } = context;
31
+ type RadioCardItemProps = Exclude<
32
+ ChakraRadioCard.ItemProps,
33
+ "colorPalette" | "indicator" | "variant" | "size" | "addon"
34
+ > &
35
+ RadioCardVariantProps & {
36
+ inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
37
+ ariaLabel?: string;
38
+ };
55
39
 
56
- const styles = useMultiStyleConfig("RadioCard", { variant });
40
+ export const RadioCard = forwardRef<HTMLInputElement, RadioCardItemProps>(
41
+ (props, ref) => {
42
+ const { inputProps, children, value, ariaLabel } = props;
57
43
 
58
- const [isKeyboardUser, setKeyboardUser] = useState(false);
59
- const [isFocused, setFocus] = useState(false);
60
-
61
- const isChecked = selectedValue === value;
62
-
63
- useEffect(() => {
64
- const handleMouseDown = () => setKeyboardUser(false);
65
- const handleKeyDown = (event: KeyboardEvent) => {
66
- if (event.key === " ") {
67
- setFocus(false);
68
- } else {
69
- setKeyboardUser(true);
70
- }
71
- };
72
-
73
- window.addEventListener("mousedown", handleMouseDown);
74
- window.addEventListener("keydown", handleKeyDown);
44
+ return (
45
+ <ChakraRadioCard.Item {...props}>
46
+ <ChakraRadioCard.ItemHiddenInput
47
+ aria-label={ariaLabel ?? value}
48
+ ref={ref}
49
+ {...inputProps}
50
+ />
75
51
 
76
- return () => {
77
- window.removeEventListener("mousedown", handleMouseDown);
78
- window.removeEventListener("keydown", handleKeyDown);
79
- };
80
- }, []);
52
+ <ChakraRadioCard.ItemControl>{children}</ChakraRadioCard.ItemControl>
53
+ </ChakraRadioCard.Item>
54
+ );
55
+ },
56
+ );
81
57
 
82
- useEffect(() => {
83
- if (isKeyboardUser && isChecked) {
84
- setFocus(true);
85
- } else {
86
- setFocus(false);
87
- }
88
- }, [isKeyboardUser, isChecked]);
58
+ type RadioCardRootProps = RadioCardVariantProps &
59
+ Exclude<ChakraRadioCard.RootProps, "variant"> & {
60
+ children: React.ReactNode;
61
+ gap?: string | number;
62
+ direction?: "row" | "column";
63
+ display?: string;
64
+ };
89
65
 
90
- const inputId = `radio-card-${useId()}`;
66
+ export const RadioCardGroup = forwardRef<HTMLDivElement, RadioCardRootProps>(
67
+ (props, ref) => {
68
+ const {
69
+ children,
70
+ variant,
71
+ gap = 2,
72
+ direction = "column",
73
+ display = "flex",
74
+ ...rest
75
+ } = props;
76
+ const recipe = useSlotRecipe({ key: "radio-card" });
77
+ const styles = recipe({ variant });
91
78
 
92
79
  return (
93
- <Box
94
- onFocus={() => isKeyboardUser && setFocus(true)}
95
- onBlur={() => setFocus(false)}
80
+ <ChakraRadioCard.Root
81
+ ref={ref}
82
+ variant={variant}
83
+ css={styles}
84
+ display={display}
85
+ gap={gap}
86
+ flexDirection={direction}
87
+ {...rest}
96
88
  >
97
- <chakra.input
98
- type="radio"
99
- id={inputId}
100
- name={name}
101
- ref={ref}
102
- checked={isChecked}
103
- onChange={() => onChange(value)}
104
- disabled={isDisabled}
105
- __css={styles.radioInput}
106
- />
107
- <Box
108
- as="label"
109
- name={name}
110
- htmlFor={inputId}
111
- aria-checked={dataAttr(isChecked)}
112
- data-checked={dataAttr(isChecked)}
113
- data-disabled={dataAttr(isDisabled)}
114
- {...props}
115
- __css={{
116
- ...styles.container,
117
- ...(isChecked && styles.checked),
118
- ...(isFocused && !isChecked && styles.focused),
119
- ...(isChecked && isFocused && styles.focusedChecked),
120
- }}
121
- >
122
- {children}
123
- </Box>
124
- </Box>
89
+ {children}
90
+ </ChakraRadioCard.Root>
125
91
  );
126
92
  },
127
93
  );
94
+
95
+ export const RadioCardLabel = ChakraRadioCard.Label;
@@ -0,0 +1,32 @@
1
+ "use client";
2
+
3
+ import {
4
+ RecipeVariantProps,
5
+ useRecipe,
6
+ Separator as ChakraSeparator,
7
+ SeparatorProps as ChakraSeparatorProps,
8
+ } from "@chakra-ui/react";
9
+ import React, { forwardRef, PropsWithChildren } from "react";
10
+ import { separatorRecipe } from "../theme/recipes/separator";
11
+
12
+ type SeparatorVariantProps = RecipeVariantProps<typeof separatorRecipe>;
13
+
14
+ type SeparatorProps = Exclude<ChakraSeparatorProps, "size" | "variant"> &
15
+ PropsWithChildren<SeparatorVariantProps> & {
16
+ size?: "sm" | "md" | "lg";
17
+ variant?: "solid" | "dashed";
18
+ };
19
+
20
+ export const Separator = forwardRef<HTMLDivElement, SeparatorProps>(
21
+ (props, ref) => {
22
+ const {
23
+ size = "md",
24
+ variant = "solid",
25
+ orientation = "horizontal",
26
+ } = props;
27
+
28
+ const recipe = useRecipe({ recipe: separatorRecipe });
29
+ const styles = recipe({ size, variant, orientation });
30
+ return <ChakraSeparator css={styles} {...props} ref={ref} />;
31
+ },
32
+ );
@@ -1,22 +1,7 @@
1
- import React from "react";
2
- import { Box, BoxProps, useStyleConfig, forwardRef } from "@chakra-ui/react";
3
- import { As } from "@chakra-ui/system";
4
-
5
- export type StaticCardProps = BoxProps & {
6
- children: React.ReactNode;
7
- /** Defaults to "white" */
8
- colorScheme:
9
- | "white"
10
- | "grey"
11
- | "green"
12
- | "orange"
13
- | "red"
14
- | "yellow"
15
- | "blue"
16
- | "darkBlue"
17
- | "darkGreen"
18
- | "darkYellow";
19
- };
1
+ "use client";
2
+ import React, { forwardRef } from "react";
3
+ import { Box, BoxProps, chakra, RecipeVariantProps } from "@chakra-ui/react";
4
+ import { staticCardRecipe } from "../theme/recipes/static-card";
20
5
 
21
6
  /**
22
7
  * `StaticCard` is a component that renders a static card.
@@ -24,7 +9,7 @@ export type StaticCardProps = BoxProps & {
24
9
  * The `StaticCard` component can be used to create a card that does not respond to user interactions.
25
10
  * It can be rendered as any HTML element by specifying the `as` prop.
26
11
  *
27
- * The `colorScheme` prop can be used to control the color scheme of the card. It defaults to "white".
12
+ * The `colorPalette` prop can be used to control the color palette of the card. It defaults to "white".
28
13
  *
29
14
  * Example usage:
30
15
  *
@@ -42,10 +27,10 @@ export type StaticCardProps = BoxProps & {
42
27
  * </StaticCard>
43
28
  * ```
44
29
  *
45
- * To change the color scheme of the card, specify the `colorScheme` prop:
30
+ * To change the color palette of the card, specify the `colorPalette` prop:
46
31
  *
47
32
  * ```tsx
48
- * <StaticCard colorScheme="orange">
33
+ * <StaticCard colorPalette="orange">
49
34
  * An orange card
50
35
  * </StaticCard>
51
36
  * ```
@@ -55,16 +40,11 @@ export type StaticCardProps = BoxProps & {
55
40
  * @see PressableCard
56
41
  */
57
42
 
58
- export const StaticCard = forwardRef<StaticCardProps, As>(
59
- ({ colorScheme = "white", children, ...props }, ref) => {
60
- const styles = useStyleConfig("StaticCard", {
61
- colorScheme,
62
- });
43
+ const StyledCardBox = chakra("div", staticCardRecipe);
44
+
45
+ export type StaticCardProps = RecipeVariantProps<typeof staticCardRecipe> &
46
+ BoxProps;
63
47
 
64
- return (
65
- <Box __css={styles} {...props} ref={ref}>
66
- {children}
67
- </Box>
68
- );
69
- },
48
+ export const StaticCard = forwardRef<HTMLDivElement, StaticCardProps>(
49
+ (props, ref) => <StyledCardBox {...props} ref={ref}></StyledCardBox>,
70
50
  );