@commercetools/nimbus 0.0.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 (298) hide show
  1. package/.storybook/apca-check/index.ts +150 -0
  2. package/.storybook/main.ts +64 -0
  3. package/.storybook/preview.tsx +92 -0
  4. package/.storybook/vitest.setup.ts +13 -0
  5. package/README.md +13 -0
  6. package/docs/architecture-decisions/adr-0001-consumer-component-apis.md +177 -0
  7. package/docs/architecture-decisions/adr-0002-compound-component-extraction.md +82 -0
  8. package/package.json +64 -0
  9. package/src/components/accordion/accordion-context.tsx +17 -0
  10. package/src/components/accordion/accordion.mdx +172 -0
  11. package/src/components/accordion/accordion.recipe.tsx +98 -0
  12. package/src/components/accordion/accordion.slots.tsx +39 -0
  13. package/src/components/accordion/accordion.stories.tsx +188 -0
  14. package/src/components/accordion/accordion.tsx +16 -0
  15. package/src/components/accordion/accordion.types.tsx +54 -0
  16. package/src/components/accordion/components/accordion-content.tsx +28 -0
  17. package/src/components/accordion/components/accordion-group.tsx +27 -0
  18. package/src/components/accordion/components/accordion-header.tsx +63 -0
  19. package/src/components/accordion/components/accordion-item.tsx +87 -0
  20. package/src/components/accordion/index.ts +2 -0
  21. package/src/components/alert/alert.mdx +92 -0
  22. package/src/components/alert/alert.recipe.tsx +65 -0
  23. package/src/components/alert/alert.slots.tsx +46 -0
  24. package/src/components/alert/alert.stories.tsx +308 -0
  25. package/src/components/alert/alert.tsx +18 -0
  26. package/src/components/alert/alert.types.tsx +70 -0
  27. package/src/components/alert/components/alert.actions.tsx +27 -0
  28. package/src/components/alert/components/alert.description.tsx +27 -0
  29. package/src/components/alert/components/alert.dismiss-button.tsx +41 -0
  30. package/src/components/alert/components/alert.root.tsx +92 -0
  31. package/src/components/alert/components/alert.title.tsx +29 -0
  32. package/src/components/alert/index.ts +2 -0
  33. package/src/components/avatar/avatar.mdx +80 -0
  34. package/src/components/avatar/avatar.recipe.tsx +36 -0
  35. package/src/components/avatar/avatar.slots.tsx +16 -0
  36. package/src/components/avatar/avatar.stories.tsx +136 -0
  37. package/src/components/avatar/avatar.tsx +34 -0
  38. package/src/components/avatar/avatar.types.ts +33 -0
  39. package/src/components/avatar/index.ts +2 -0
  40. package/src/components/badge/badge.mdx +91 -0
  41. package/src/components/badge/badge.recipe.tsx +72 -0
  42. package/src/components/badge/badge.slots.tsx +8 -0
  43. package/src/components/badge/badge.stories.tsx +124 -0
  44. package/src/components/badge/badge.tsx +35 -0
  45. package/src/components/badge/badge.types.tsx +40 -0
  46. package/src/components/badge/index.ts +2 -0
  47. package/src/components/bleed/bleed.tsx +1 -0
  48. package/src/components/bleed/index.ts +1 -0
  49. package/src/components/box/box.mdx +115 -0
  50. package/src/components/box/box.stories.tsx +71 -0
  51. package/src/components/box/box.tsx +11 -0
  52. package/src/components/box/index.ts +1 -0
  53. package/src/components/button/button.mdx +169 -0
  54. package/src/components/button/button.recipe.ts +185 -0
  55. package/src/components/button/button.slots.tsx +45 -0
  56. package/src/components/button/button.stories.tsx +369 -0
  57. package/src/components/button/button.tsx +37 -0
  58. package/src/components/button/button.types.ts +14 -0
  59. package/src/components/button/index.ts +2 -0
  60. package/src/components/card/card.mdx +92 -0
  61. package/src/components/card/card.recipe.tsx +71 -0
  62. package/src/components/card/card.slots.tsx +50 -0
  63. package/src/components/card/card.stories.tsx +175 -0
  64. package/src/components/card/card.tsx +9 -0
  65. package/src/components/card/card.types.ts +22 -0
  66. package/src/components/card/components/card.content.tsx +29 -0
  67. package/src/components/card/components/card.header.tsx +28 -0
  68. package/src/components/card/components/card.root.tsx +62 -0
  69. package/src/components/card/index.ts +2 -0
  70. package/src/components/checkbox/checkbox.mdx +78 -0
  71. package/src/components/checkbox/checkbox.recipe.tsx +116 -0
  72. package/src/components/checkbox/checkbox.slots.tsx +33 -0
  73. package/src/components/checkbox/checkbox.stories.tsx +200 -0
  74. package/src/components/checkbox/checkbox.tsx +77 -0
  75. package/src/components/checkbox/checkbox.types.tsx +22 -0
  76. package/src/components/checkbox/index.ts +2 -0
  77. package/src/components/code/code.mdx +17 -0
  78. package/src/components/code/code.recipe.ts +63 -0
  79. package/src/components/code/code.tsx +1 -0
  80. package/src/components/code/index.ts +1 -0
  81. package/src/components/dialog/dialog.mdx +20 -0
  82. package/src/components/dialog/dialog.recipe.ts +254 -0
  83. package/src/components/dialog/dialog.tsx +61 -0
  84. package/src/components/dialog/index.ts +1 -0
  85. package/src/components/em/em.mdx +17 -0
  86. package/src/components/em/em.tsx +1 -0
  87. package/src/components/em/index.ts +1 -0
  88. package/src/components/flex/flex.mdx +41 -0
  89. package/src/components/flex/flex.tsx +1 -0
  90. package/src/components/flex/index.ts +1 -0
  91. package/src/components/grid/grid.mdx +156 -0
  92. package/src/components/grid/grid.stories.tsx +151 -0
  93. package/src/components/grid/grid.tsx +29 -0
  94. package/src/components/grid/index.ts +1 -0
  95. package/src/components/heading/heading.mdx +23 -0
  96. package/src/components/heading/heading.recipe.ts +49 -0
  97. package/src/components/heading/heading.tsx +1 -0
  98. package/src/components/heading/index.ts +1 -0
  99. package/src/components/highlight/highlight.mdx +18 -0
  100. package/src/components/highlight/highlight.tsx +1 -0
  101. package/src/components/highlight/index.ts +1 -0
  102. package/src/components/icon-button/icon-button.mdx +98 -0
  103. package/src/components/icon-button/icon-button.stories.tsx +188 -0
  104. package/src/components/icon-button/icon-button.tsx +21 -0
  105. package/src/components/icon-button/icon-button.types.tsx +10 -0
  106. package/src/components/icon-button/index.ts +2 -0
  107. package/src/components/index.ts +33 -0
  108. package/src/components/input/index.ts +1 -0
  109. package/src/components/input/input.mdx +20 -0
  110. package/src/components/input/input.recipe.ts +95 -0
  111. package/src/components/input/input.tsx +1 -0
  112. package/src/components/input-group/index.ts +1 -0
  113. package/src/components/input-group/input-group.mdx +20 -0
  114. package/src/components/input-group/input-group.tsx +44 -0
  115. package/src/components/kbd/index.ts +1 -0
  116. package/src/components/kbd/kbd.mdx +18 -0
  117. package/src/components/kbd/kbd.recipe.ts +57 -0
  118. package/src/components/kbd/kbd.tsx +1 -0
  119. package/src/components/link/index.ts +2 -0
  120. package/src/components/link/link.mdx +77 -0
  121. package/src/components/link/link.recipe.ts +52 -0
  122. package/src/components/link/link.slots.tsx +29 -0
  123. package/src/components/link/link.stories.tsx +204 -0
  124. package/src/components/link/link.tsx +38 -0
  125. package/src/components/link/link.types.tsx +26 -0
  126. package/src/components/list/index.ts +1 -0
  127. package/src/components/list/list.mdx +18 -0
  128. package/src/components/list/list.recipe.ts +68 -0
  129. package/src/components/list/list.tsx +9 -0
  130. package/src/components/loading-spinner/index.ts +2 -0
  131. package/src/components/loading-spinner/loading-spinner.mdx +92 -0
  132. package/src/components/loading-spinner/loading-spinner.recipe.tsx +70 -0
  133. package/src/components/loading-spinner/loading-spinner.slots.tsx +38 -0
  134. package/src/components/loading-spinner/loading-spinner.stories.tsx +97 -0
  135. package/src/components/loading-spinner/loading-spinner.tsx +50 -0
  136. package/src/components/loading-spinner/loading-spinner.types.tsx +21 -0
  137. package/src/components/nimbus-provider/color-mode.tsx +32 -0
  138. package/src/components/nimbus-provider/index.ts +2 -0
  139. package/src/components/nimbus-provider/nimbus-provider.mdx +21 -0
  140. package/src/components/nimbus-provider/nimbus-provider.tsx +51 -0
  141. package/src/components/select/components/select.clear-button.tsx +31 -0
  142. package/src/components/select/components/select.option-group.tsx +48 -0
  143. package/src/components/select/components/select.option.tsx +21 -0
  144. package/src/components/select/components/select.options.tsx +23 -0
  145. package/src/components/select/components/select.root.tsx +81 -0
  146. package/src/components/select/index.ts +2 -0
  147. package/src/components/select/select.mdx +170 -0
  148. package/src/components/select/select.recipe.tsx +216 -0
  149. package/src/components/select/select.slots.tsx +58 -0
  150. package/src/components/select/select.stories.tsx +841 -0
  151. package/src/components/select/select.tsx +18 -0
  152. package/src/components/select/select.types.tsx +37 -0
  153. package/src/components/simple-grid/index.ts +1 -0
  154. package/src/components/simple-grid/simple-grid.mdx +133 -0
  155. package/src/components/simple-grid/simple-grid.stories.tsx +143 -0
  156. package/src/components/simple-grid/simple-grid.tsx +31 -0
  157. package/src/components/stack/index.ts +1 -0
  158. package/src/components/stack/stack.mdx +88 -0
  159. package/src/components/stack/stack.stories.tsx +82 -0
  160. package/src/components/stack/stack.tsx +15 -0
  161. package/src/components/table/index.ts +1 -0
  162. package/src/components/table/table.mdx +23 -0
  163. package/src/components/table/table.recipe.ts +170 -0
  164. package/src/components/table/table.tsx +43 -0
  165. package/src/components/text/index.ts +1 -0
  166. package/src/components/text/text.mdx +244 -0
  167. package/src/components/text/text.tsx +23 -0
  168. package/src/components/text-input/index.ts +2 -0
  169. package/src/components/text-input/text-input.mdx +118 -0
  170. package/src/components/text-input/text-input.recipe.tsx +68 -0
  171. package/src/components/text-input/text-input.slots.tsx +24 -0
  172. package/src/components/text-input/text-input.stories.tsx +282 -0
  173. package/src/components/text-input/text-input.tsx +39 -0
  174. package/src/components/text-input/text-input.types.ts +7 -0
  175. package/src/components/toggle-button-group/components/toggle-button-group.button.tsx +14 -0
  176. package/src/components/toggle-button-group/components/toggle-button-group.root.tsx +15 -0
  177. package/src/components/toggle-button-group/index.ts +2 -0
  178. package/src/components/toggle-button-group/toggle-button-group.mdx +94 -0
  179. package/src/components/toggle-button-group/toggle-button-group.recipe.tsx +64 -0
  180. package/src/components/toggle-button-group/toggle-button-group.slots.tsx +26 -0
  181. package/src/components/toggle-button-group/toggle-button-group.stories.tsx +311 -0
  182. package/src/components/toggle-button-group/toggle-button-group.tsx +12 -0
  183. package/src/components/toggle-button-group/toggle-button-group.types.tsx +62 -0
  184. package/src/components/tooltip/index.ts +4 -0
  185. package/src/components/tooltip/make-element-focusable.stories.tsx +56 -0
  186. package/src/components/tooltip/make-element-focusable.tsx +57 -0
  187. package/src/components/tooltip/tooltip-trigger.stories.tsx +157 -0
  188. package/src/components/tooltip/tooltip-trigger.tsx +15 -0
  189. package/src/components/tooltip/tooltip.mdx +48 -0
  190. package/src/components/tooltip/tooltip.recipe.ts +26 -0
  191. package/src/components/tooltip/tooltip.slots.ts +35 -0
  192. package/src/components/tooltip/tooltip.stories.tsx +139 -0
  193. package/src/components/tooltip/tooltip.tsx +31 -0
  194. package/src/components/tooltip/tooltip.types.ts +44 -0
  195. package/src/components/visually-hidden/index.ts +1 -0
  196. package/src/components/visually-hidden/visually-hidden.mdx +61 -0
  197. package/src/components/visually-hidden/visually-hidden.stories.tsx +124 -0
  198. package/src/components/visually-hidden/visually-hidden.tsx +18 -0
  199. package/src/docs/accessibility.mdx +21 -0
  200. package/src/docs/background.mdx +154 -0
  201. package/src/docs/border.mdx +226 -0
  202. package/src/docs/changelog.mdx +17 -0
  203. package/src/docs/components-layout.mdx +22 -0
  204. package/src/docs/components.mdx +17 -0
  205. package/src/docs/data-display.mdx +23 -0
  206. package/src/docs/display.mdx +55 -0
  207. package/src/docs/effects.mdx +73 -0
  208. package/src/docs/feedback.mdx +22 -0
  209. package/src/docs/filters.mdx +268 -0
  210. package/src/docs/flex-and-grid.mdx +445 -0
  211. package/src/docs/forms.mdx +22 -0
  212. package/src/docs/generated/index.mdx +16 -0
  213. package/src/docs/getting-started.mdx +17 -0
  214. package/src/docs/home.mdx +56 -0
  215. package/src/docs/hooks.mdx +16 -0
  216. package/src/docs/inputs.mdx +21 -0
  217. package/src/docs/installation.mdx +60 -0
  218. package/src/docs/interactivity.mdx +278 -0
  219. package/src/docs/known-issues.mdx +19 -0
  220. package/src/docs/layout.mdx +301 -0
  221. package/src/docs/list.mdx +82 -0
  222. package/src/docs/markdown.mdx +234 -0
  223. package/src/docs/media.mdx +22 -0
  224. package/src/docs/naivgation.mdx +22 -0
  225. package/src/docs/playground.mdx +16 -0
  226. package/src/docs/rfcs-component-structure-rfcs.mdx +17 -0
  227. package/src/docs/rfcs-component-structure.mdx +74 -0
  228. package/src/docs/rfcs-hook-structure.mdx +59 -0
  229. package/src/docs/sizing.mdx +210 -0
  230. package/src/docs/spacing.mdx +193 -0
  231. package/src/docs/style-props-typography.mdx +373 -0
  232. package/src/docs/style-props.mdx +15 -0
  233. package/src/docs/svg.mdx +58 -0
  234. package/src/docs/tables.mdx +95 -0
  235. package/src/docs/toc.mdx +39 -0
  236. package/src/docs/tokens/animations.mdx +68 -0
  237. package/src/docs/tokens/aspect-ratios.mdx +21 -0
  238. package/src/docs/tokens/blurs.mdx +20 -0
  239. package/src/docs/tokens/borders.mdx +25 -0
  240. package/src/docs/tokens/breakpoints.mdx +35 -0
  241. package/src/docs/tokens/colors.mdx +86 -0
  242. package/src/docs/tokens/cursors.mdx +21 -0
  243. package/src/docs/tokens/radii.mdx +23 -0
  244. package/src/docs/tokens/shadows.mdx +21 -0
  245. package/src/docs/tokens/sizes.mdx +54 -0
  246. package/src/docs/tokens/spacing.mdx +35 -0
  247. package/src/docs/tokens/typography.mdx +61 -0
  248. package/src/docs/tokens/z-indices.mdx +23 -0
  249. package/src/docs/tokens-other.mdx +17 -0
  250. package/src/docs/tokens.mdx +16 -0
  251. package/src/docs/transforms.mdx +150 -0
  252. package/src/docs/transitions.mdx +164 -0
  253. package/src/docs/typography.mdx +17 -0
  254. package/src/docs/utilities.mdx +17 -0
  255. package/src/hooks/index.ts +2 -0
  256. package/src/hooks/use-copy-to-clipboard/use-copy-to-clipboard.mdx +54 -0
  257. package/src/hooks/use-copy-to-clipboard/use-copy-to-clipboard.ts +1 -0
  258. package/src/hooks/use-hotkeys/use-hotkeys.mdx +48 -0
  259. package/src/hooks/use-hotkeys/use-hotkeys.stories.tsx +69 -0
  260. package/src/hooks/use-hotkeys/use-hotkeys.ts +1 -0
  261. package/src/index.ts +3 -0
  262. package/src/test/utils.tsx +20 -0
  263. package/src/theme/animation-styles.ts +52 -0
  264. package/src/theme/breakpoints.ts +32 -0
  265. package/src/theme/global-css.ts +53 -0
  266. package/src/theme/index.ts +35 -0
  267. package/src/theme/keyframes.ts +192 -0
  268. package/src/theme/layer-styles.ts +12 -0
  269. package/src/theme/recipes/index.ts +21 -0
  270. package/src/theme/semantic-tokens/colors.ts +55 -0
  271. package/src/theme/semantic-tokens/index.ts +9 -0
  272. package/src/theme/semantic-tokens/radii.ts +3 -0
  273. package/src/theme/semantic-tokens/shadows.ts +4 -0
  274. package/src/theme/slot-recipes/index.ts +15 -0
  275. package/src/theme/text-styles.ts +8 -0
  276. package/src/theme/tokens/animations.ts +4 -0
  277. package/src/theme/tokens/aspect-ratios.ts +5 -0
  278. package/src/theme/tokens/blurs.ts +5 -0
  279. package/src/theme/tokens/borders.ts +4 -0
  280. package/src/theme/tokens/colors.ts +8 -0
  281. package/src/theme/tokens/cursor.ts +4 -0
  282. package/src/theme/tokens/durations.ts +4 -0
  283. package/src/theme/tokens/easings.ts +4 -0
  284. package/src/theme/tokens/font-sizes.ts +4 -0
  285. package/src/theme/tokens/font-weights.ts +4 -0
  286. package/src/theme/tokens/fonts.ts +4 -0
  287. package/src/theme/tokens/index.ts +57 -0
  288. package/src/theme/tokens/letter-spacings.ts +24 -0
  289. package/src/theme/tokens/line-heights.ts +4 -0
  290. package/src/theme/tokens/radii.ts +4 -0
  291. package/src/theme/tokens/sizes.ts +120 -0
  292. package/src/theme/tokens/spacing.ts +4 -0
  293. package/src/theme/tokens/z-index.ts +4 -0
  294. package/src/utils/extractStyleProps.ts +26 -0
  295. package/src/utils/fixedForwardRef.ts +17 -0
  296. package/tsconfig.json +38 -0
  297. package/vite.config.ts +54 -0
  298. package/vitest.config.ts +50 -0
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: Kbd
3
+ title: Kbd
4
+ description: marks a string as keyboard input
5
+ documentState: InitialDraft
6
+ order: 999
7
+ menu:
8
+ - Components
9
+ - Typography
10
+ - Kbd
11
+ tags:
12
+ - keyboard
13
+ - key
14
+ ---
15
+
16
+ # Kbd
17
+
18
+ Add description later.
@@ -0,0 +1,57 @@
1
+ import { defineRecipe } from "@chakra-ui/react";
2
+
3
+ export const kbdRecipe = defineRecipe({
4
+ className: "nimbus-kbd",
5
+ base: {
6
+ display: "inline-flex",
7
+ alignItems: "center",
8
+ fontWeight: "medium",
9
+ fontFamily: "mono",
10
+ flexShrink: "0",
11
+ whiteSpace: "nowrap",
12
+ wordSpacing: "-0.5em",
13
+ userSelect: "none",
14
+ px: "100",
15
+ borderRadius: "100",
16
+ },
17
+ variants: {
18
+ variant: {
19
+ raised: {
20
+ bg: "colorPalette.subtle",
21
+ color: "colorPalette.fg",
22
+ borderWidth: "1px",
23
+ borderBottomWidth: "2px",
24
+ borderColor: "colorPalette.muted",
25
+ },
26
+ outline: {
27
+ borderWidth: "1px",
28
+ color: "colorPalette.fg",
29
+ },
30
+ subtle: {
31
+ bg: "colorPalette.muted",
32
+ color: "colorPalette.fg",
33
+ },
34
+ plain: {
35
+ color: "colorPalette.fg",
36
+ },
37
+ },
38
+ size: {
39
+ sm: {
40
+ textStyle: "xs",
41
+ height: "450",
42
+ },
43
+ md: {
44
+ textStyle: "sm",
45
+ height: "500",
46
+ },
47
+ lg: {
48
+ textStyle: "md",
49
+ height: "600",
50
+ },
51
+ },
52
+ },
53
+ defaultVariants: {
54
+ size: "md",
55
+ variant: "raised",
56
+ },
57
+ });
@@ -0,0 +1 @@
1
+ export { Kbd } from "@chakra-ui/react";
@@ -0,0 +1,2 @@
1
+ export * from "./link";
2
+ export * from "./link.types";
@@ -0,0 +1,77 @@
1
+ ---
2
+ id: Components-link
3
+ title: link
4
+ description: To allow a user to navigate to a different page or resource
5
+ documentState: InitialDraft
6
+ order: 999
7
+ menu:
8
+ - Components
9
+ - Navigation
10
+ - link
11
+ tags:
12
+ - component
13
+ figmaLink: >-
14
+ https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=384-5726&m=dev
15
+ ---
16
+
17
+ # Link
18
+
19
+ Allows a user to navigate to a different page or resource.
20
+
21
+ ## Basic Usage
22
+
23
+ If unconfigured it will default to a neutral state. It is important to configure
24
+ the Link properly to ensure it displays as intended.
25
+
26
+ ```jsx-live
27
+ const App = () => <Link href="#">I am Link!</Link>
28
+ ```
29
+
30
+ ### Sizes
31
+
32
+ Available sizes.
33
+
34
+ ```jsx-live
35
+ const App = () => {
36
+
37
+ const sizes = ['md', 'sm', 'xs'].reverse();
38
+
39
+ return (
40
+ <Stack direction="horizontal" alignItems="center">
41
+ {sizes.map(size => (
42
+ <Link key={size} size={size}>'{size}' Link</Link>
43
+ ))}
44
+ </Stack>
45
+ )
46
+ }
47
+ ```
48
+
49
+ ### Colors
50
+
51
+ The Link component will default to it's surrounding context for color. You can
52
+ also specify a color directly.
53
+
54
+ ```jsx-live
55
+ const App = () => {
56
+ const sizes = ['md', 'sm', 'xs'].reverse();
57
+ const colors = ["primary", "inherit"];
58
+
59
+ return (
60
+ <Stack>
61
+ {colors.map((color) => (
62
+ <Stack key={color} direction="horizontal">
63
+ {sizes.map((size) => (
64
+ <Link fontColor={color} key={size} size={size}>
65
+ '{size}' Link w/ color '{color}'
66
+ </Link>
67
+ ))}
68
+ </Stack>
69
+ ))}
70
+ </Stack>
71
+ );
72
+ };
73
+ ```
74
+
75
+ ## Props
76
+
77
+ <PropTable id="Link" />
@@ -0,0 +1,52 @@
1
+ import { defineRecipe } from "@chakra-ui/react";
2
+
3
+ /**
4
+ * Recipe configuration for the Link component.
5
+ * Defines the styling variants and base styles using Chakra UI's recipe system.
6
+ */
7
+ export const linkRecipe = defineRecipe({
8
+ className: "nimbus-link",
9
+ // Base styles applied to all instances of the component
10
+ base: {
11
+ display: "inline-flex",
12
+ alignItems: "center",
13
+ color: "colorPalette.11",
14
+ borderRadius: "100",
15
+ focusVisibleRing: "outside",
16
+ bg: "transparent",
17
+ outline: "none",
18
+ cursor: "pointer",
19
+ textDecoration: "underline",
20
+ textUnderlineOffset: "3px",
21
+ _hover: {
22
+ textDecorationThickness: "12%",
23
+ },
24
+ },
25
+ // Available variants for customizing the component's appearance
26
+ variants: {
27
+ // Size variants from smallest to largest
28
+ size: {
29
+ xs: {
30
+ fontSize: "300",
31
+ lineHeight: "450",
32
+ },
33
+ sm: {
34
+ fontSize: "350",
35
+ lineHeight: "500",
36
+ },
37
+ md: {
38
+ fontSize: "400",
39
+ lineHeight: "600",
40
+ },
41
+ },
42
+ // style variants
43
+ fontColor: {
44
+ primary: {
45
+ color: "primary",
46
+ },
47
+ inherit: {
48
+ color: "inherit",
49
+ },
50
+ },
51
+ },
52
+ });
@@ -0,0 +1,29 @@
1
+ import {
2
+ type HTMLChakraProps,
3
+ type RecipeProps,
4
+ type UnstyledProp,
5
+ createRecipeContext,
6
+ } from "@chakra-ui/react";
7
+
8
+ import { linkRecipe } from "./link.recipe";
9
+
10
+ /**
11
+ * Base recipe props interface that combines Chakra UI's recipe props
12
+ * with the unstyled prop option for the a element.
13
+ */
14
+ interface LinkRecipeProps extends RecipeProps<"a">, UnstyledProp {}
15
+
16
+ /**
17
+ * Root props interface that extends Chakra's HTML props with our recipe props.
18
+ * This creates a complete set of props for the root element, combining
19
+ * HTML attributes, Chakra's styling system, and our custom recipe props.
20
+ */
21
+ export type LinkRootProps = HTMLChakraProps<"a", LinkRecipeProps>;
22
+
23
+ const { withContext } = createRecipeContext({ recipe: linkRecipe });
24
+
25
+ /**
26
+ * Root component that provides the styling context for the Link component.
27
+ * Uses Chakra UI's recipe context system for consistent styling across instances.
28
+ */
29
+ export const LinkRoot = withContext<HTMLAnchorElement, LinkRootProps>("a");
@@ -0,0 +1,204 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Link } from "./link";
3
+ import { Box, Stack } from "@/components";
4
+ import type { LinkProps } from "./link.types";
5
+ import { userEvent, within, expect, fn } from "@storybook/test";
6
+ import { createRef } from "react";
7
+
8
+ const sizes: LinkProps["size"][] = ["xs", "sm", "md"];
9
+ const fontColors: LinkProps["fontColor"][] = ["primary", "inherit"];
10
+
11
+ /**
12
+ * The Link component allows a user to navigate to a different page or resource.
13
+ */
14
+ const meta: Meta<typeof Link> = {
15
+ title: "components/Link",
16
+ component: Link,
17
+ };
18
+
19
+ export default meta;
20
+
21
+ /**
22
+ * Story type for TypeScript support
23
+ * StoryObj provides type checking for our story configurations
24
+ */
25
+ type Story = StoryObj<typeof Link>;
26
+
27
+ /**
28
+ * Base story
29
+ * Demonstrates the most basic implementation
30
+ * Uses the args pattern for dynamic control panel inputs
31
+ */
32
+ export const Base: Story = {
33
+ args: {
34
+ children: "Demo Link",
35
+ onClick: fn(),
36
+ ["data-testid"]: "link-test",
37
+ ["aria-label"]: "link-to-somewhere",
38
+ ["href"]: "#",
39
+ },
40
+ play: async ({ canvasElement, step }) => {
41
+ const canvas = within(canvasElement);
42
+ const link = canvas.getByTestId("link-test");
43
+
44
+ await step("Uses an <a> element by default", async () => {
45
+ await expect(link.tagName).toBe("A");
46
+ });
47
+
48
+ await step("Forwards data- & aria-attributes", async () => {
49
+ await expect(link).toHaveAttribute("data-testid", "link-test");
50
+ await expect(link).toHaveAttribute("aria-label", "link-to-somewhere");
51
+ });
52
+
53
+ await step("Renders children", async () => {
54
+ await expect(link).toHaveTextContent("Demo Link");
55
+ });
56
+
57
+ await step("Is focusable with <tab> key", async () => {
58
+ await userEvent.tab();
59
+ await expect(link).toHaveFocus();
60
+ });
61
+ },
62
+ };
63
+
64
+ /**
65
+ * Showcase Sizes
66
+ */
67
+ export const Sizes: Story = {
68
+ render: (args) => {
69
+ return (
70
+ <Stack direction="row" gap="400" alignItems="center">
71
+ {sizes.map((size) => (
72
+ <Link key={size as string} {...args} size={size} />
73
+ ))}
74
+ </Stack>
75
+ );
76
+ },
77
+
78
+ args: {
79
+ children: "Demo Link",
80
+ },
81
+ };
82
+
83
+ /**
84
+ * Showcase FontColors
85
+ */
86
+ export const FontColors: Story = {
87
+ render: (args) => {
88
+ return (
89
+ <Box p="400" bg="primary.7">
90
+ <Stack direction="row" gap="500" alignItems="center">
91
+ {fontColors.map((color) => (
92
+ <p key={color as string} style={{ color: "white" }}>
93
+ This is a {JSON.stringify(color)}{" "}
94
+ <Link key={color as string} {...args} fontColor={color} /> in
95
+ action.
96
+ </p>
97
+ ))}
98
+ </Stack>
99
+ </Box>
100
+ );
101
+ },
102
+
103
+ args: {
104
+ children: "Link",
105
+ },
106
+ };
107
+
108
+ /**
109
+ * Showcase asChild
110
+ */
111
+ export const AsChild: Story = {
112
+ render: (args) => {
113
+ return (
114
+ <Stack direction="row" gap="400" alignItems="center">
115
+ <Link {...args}>{args.children}</Link>
116
+ </Stack>
117
+ );
118
+ },
119
+
120
+ args: {
121
+ children: <span>I am just a span</span>,
122
+ asChild: true,
123
+ ["data-testid"]: "test",
124
+ },
125
+ play: async ({ canvasElement, step }) => {
126
+ const canvas = within(canvasElement);
127
+ const link = canvas.getByTestId("test");
128
+
129
+ await step("Uses a <span> element", async () => {
130
+ await expect(link.tagName).toBe("SPAN");
131
+ });
132
+
133
+ await step("Is focusable with <tab> key", async () => {
134
+ await userEvent.tab();
135
+ await expect(link).toHaveFocus();
136
+ });
137
+ },
138
+ };
139
+
140
+ /**
141
+ * Showcase withRef
142
+ */
143
+ const linkRef = createRef<HTMLAnchorElement>();
144
+ export const WithRef: Story = {
145
+ args: {
146
+ children: "Demo Link",
147
+ ["data-testid"]: "ref-test",
148
+ },
149
+ render: (args) => {
150
+ return (
151
+ <Link ref={linkRef} {...args}>
152
+ {args.children}
153
+ </Link>
154
+ );
155
+ },
156
+ play: async ({ canvasElement, step }) => {
157
+ const canvas = within(canvasElement);
158
+ const button = canvas.getByTestId("ref-test");
159
+
160
+ await step("Does accept ref's", async () => {
161
+ await expect(linkRef.current).toBe(button);
162
+ });
163
+ },
164
+ };
165
+
166
+ export const withCustomHref: Story = {
167
+ args: {
168
+ children: "Demo Link",
169
+ href: "https://commercetools.com",
170
+ },
171
+ render: (args) => {
172
+ return <Link {...args}>{args.children}</Link>;
173
+ },
174
+ play: async ({ canvasElement, step }) => {
175
+ const canvas = within(canvasElement);
176
+ const link = canvas.getByText("Demo Link");
177
+
178
+ await step("Uses the provided href", async () => {
179
+ await expect(link).toHaveAttribute("href", "https://commercetools.com");
180
+ });
181
+ },
182
+ };
183
+
184
+ export const SmokeTest: Story = {
185
+ args: {
186
+ children: "Demo Link",
187
+ ["data-testid"]: "smoke-test",
188
+ },
189
+ render: (args) => {
190
+ return (
191
+ <Stack gap="1200">
192
+ {fontColors.map((color) => (
193
+ <Stack key={color as string} direction="row" gap="400">
194
+ {sizes.map((size) => (
195
+ <Stack direction="row" key={size as string}>
196
+ <Link {...args} size={size} fontColor={color} />
197
+ </Stack>
198
+ ))}
199
+ </Stack>
200
+ ))}
201
+ </Stack>
202
+ );
203
+ },
204
+ };
@@ -0,0 +1,38 @@
1
+ import { forwardRef, useRef } from "react";
2
+ import { LinkRoot } from "./link.slots";
3
+ import type { LinkProps } from "./link.types";
4
+ import { useLink, useObjectRef, mergeProps } from "react-aria";
5
+ import { mergeRefs } from "@chakra-ui/react";
6
+
7
+ /**
8
+ * Link
9
+ * ============================================================
10
+ * To allow a user to navigate to a different page or resource
11
+ *
12
+ * Features:
13
+ *
14
+ * - allows forwarding refs to the underlying DOM element
15
+ * - accepts all native html 'HTMLAnchorElement' attributes (including aria- & data-attributes)
16
+ * - supports 'variants', 'sizes', etc. configured in the recipe
17
+ * - allows overriding styles by using style-props
18
+ * - supports 'asChild' and 'as' to modify the underlying html-element (polymorphic)
19
+ */
20
+ export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
21
+ (props, forwardedRef) => {
22
+ const { as, asChild, children, ...rest } = props;
23
+
24
+ const localRef = useRef<HTMLAnchorElement>(null);
25
+ const ref = useObjectRef(mergeRefs(localRef, forwardedRef));
26
+
27
+ const elementType = (as as string) || (asChild ? "span" : "a") || "a";
28
+ const { linkProps } = useLink({ ...rest, elementType }, ref);
29
+
30
+ return (
31
+ <LinkRoot {...mergeProps(rest, linkProps, { as, asChild, ref })}>
32
+ {children}
33
+ </LinkRoot>
34
+ );
35
+ }
36
+ );
37
+
38
+ Link.displayName = "Link";
@@ -0,0 +1,26 @@
1
+ import type { LinkRootProps } from "./link.slots";
2
+ import type { RecipeVariantProps } from "@chakra-ui/react";
3
+ import type { AriaLinkOptions } from "react-aria";
4
+ import { linkRecipe } from "./link.recipe";
5
+
6
+ /**
7
+ * Combines the root props with Chakra UI's recipe variant props.
8
+ * This allows the component to accept both structural props from Root
9
+ * and styling variants from the recipe.
10
+ *
11
+ * Differences between LinkRootProps and LinkVariantProps necessitate
12
+ * the use of Omit and Pick to ensure the correct props are passed
13
+ */
14
+ type LinkVariantProps = Omit<LinkRootProps, "onFocus" | "onBlur"> &
15
+ Pick<AriaLinkOptions, "onFocus" | "onBlur"> &
16
+ RecipeVariantProps<typeof linkRecipe> & {
17
+ [key: `data-${string}`]: string;
18
+ };
19
+ /**
20
+ * Main props interface for the Link component.
21
+ * Extends LinkVariantProps to include both root props and variant props,
22
+ * while adding support for React children.
23
+ */
24
+ export interface LinkProps extends LinkVariantProps {
25
+ children?: React.ReactNode;
26
+ }
@@ -0,0 +1 @@
1
+ export * from "./list.tsx";
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: List
3
+ title: List
4
+ description: displays a list
5
+ documentState: InitialDraft
6
+ order: 999
7
+ menu:
8
+ - Components
9
+ - Typography
10
+ - List
11
+ tags:
12
+ - list
13
+ - collections
14
+ ---
15
+
16
+ # List
17
+
18
+ Add description later.
@@ -0,0 +1,68 @@
1
+ import { defineSlotRecipe } from "@chakra-ui/react";
2
+
3
+ export const listSlotRecipe = defineSlotRecipe({
4
+ className: "chakra-list",
5
+ slots: ["root", "item", "indicator"],
6
+ base: {
7
+ root: {
8
+ display: "flex",
9
+ flexDirection: "column",
10
+ gap: "var(--list-gap)",
11
+ "& :where(ul, ol)": {
12
+ marginTop: "var(--list-gap)",
13
+ },
14
+ },
15
+ item: {
16
+ whiteSpace: "normal",
17
+ display: "list-item",
18
+ },
19
+ indicator: {
20
+ marginEnd: "200",
21
+ minHeight: "1lh",
22
+ flexShrink: 0,
23
+ display: "inline-block",
24
+ verticalAlign: "middle",
25
+ },
26
+ },
27
+ variants: {
28
+ variant: {
29
+ marker: {
30
+ root: {
31
+ listStyle: "revert",
32
+ listStylePosition: "inside",
33
+ },
34
+ item: {
35
+ _marker: {
36
+ color: "fg.subtle",
37
+ },
38
+ },
39
+ },
40
+ plain: {
41
+ item: {
42
+ alignItems: "flex-start",
43
+ display: "inline-flex",
44
+ },
45
+ },
46
+ },
47
+ align: {
48
+ center: {
49
+ item: {
50
+ alignItems: "center",
51
+ },
52
+ },
53
+ start: {
54
+ item: {
55
+ alignItems: "flex-start",
56
+ },
57
+ },
58
+ end: {
59
+ item: {
60
+ alignItems: "flex-end",
61
+ },
62
+ },
63
+ },
64
+ },
65
+ defaultVariants: {
66
+ variant: "marker",
67
+ },
68
+ });
@@ -0,0 +1,9 @@
1
+ import { List } from "@chakra-ui/react";
2
+
3
+ export type ListRootType = React.ComponentProps<typeof List.Root>;
4
+ export type ListItemType = React.ComponentProps<typeof List.Item>;
5
+
6
+ const ListRoot = (props: ListRootType) => <List.Root {...props} />;
7
+ const ListItem = (props: ListItemType) => <List.Item {...props} />;
8
+
9
+ export { List, ListRoot, ListItem };
@@ -0,0 +1,2 @@
1
+ export * from "./loading-spinner";
2
+ export * from "./loading-spinner.types";