@saas-ui/react 2.11.2 → 3.0.0-alpha.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 (343) hide show
  1. package/CHANGELOG.md +13 -148
  2. package/dist/chunk-32JGENDB.js +19 -0
  3. package/dist/chunk-FZW2DYK3.js +19 -0
  4. package/dist/chunk-KHRLZUV4.js +35 -0
  5. package/dist/chunk-KTLWEUNW.js +1 -0
  6. package/dist/chunk-PKI6YH2V.js +31 -0
  7. package/dist/chunk-RTMS5TJN.js +10 -0
  8. package/dist/chunk-VBIVLREP.js +45 -0
  9. package/dist/chunk-VDXTEASE.js +117 -0
  10. package/dist/components/app-shell/index.cjs +68 -0
  11. package/dist/components/app-shell/index.d.cts +30 -0
  12. package/dist/components/app-shell/index.d.ts +30 -0
  13. package/dist/components/app-shell/index.js +45 -0
  14. package/dist/components/breadcrumbs/index.cjs +60 -0
  15. package/dist/components/breadcrumbs/index.d.cts +18 -0
  16. package/dist/components/breadcrumbs/index.d.ts +18 -0
  17. package/dist/components/breadcrumbs/index.js +37 -0
  18. package/dist/components/button/index.cjs +65 -0
  19. package/dist/components/button/index.d.cts +12 -0
  20. package/dist/components/button/index.d.ts +12 -0
  21. package/dist/components/button/index.js +45 -0
  22. package/dist/components/checkbox/index.cjs +45 -0
  23. package/dist/components/checkbox/index.d.cts +11 -0
  24. package/dist/components/checkbox/index.d.ts +11 -0
  25. package/dist/components/checkbox/index.js +20 -0
  26. package/dist/components/close-button/index.cjs +142 -0
  27. package/dist/components/close-button/index.d.cts +8 -0
  28. package/dist/components/close-button/index.d.ts +8 -0
  29. package/dist/components/close-button/index.js +9 -0
  30. package/dist/components/command/index.cjs +56 -0
  31. package/dist/components/command/index.d.cts +6 -0
  32. package/dist/components/command/index.d.ts +6 -0
  33. package/dist/components/command/index.js +33 -0
  34. package/dist/components/dialog/index.cjs +243 -0
  35. package/dist/components/dialog/index.d.cts +27 -0
  36. package/dist/components/dialog/index.d.ts +27 -0
  37. package/dist/components/dialog/index.js +73 -0
  38. package/dist/components/drawer/index.cjs +237 -0
  39. package/dist/components/drawer/index.d.cts +28 -0
  40. package/dist/components/drawer/index.d.ts +28 -0
  41. package/dist/components/drawer/index.js +65 -0
  42. package/dist/components/icon-badge/index.cjs +70 -0
  43. package/dist/components/icon-badge/index.d.cts +16 -0
  44. package/dist/components/icon-badge/index.d.ts +16 -0
  45. package/dist/components/icon-badge/index.js +38 -0
  46. package/dist/components/icons/index.cjs +155 -0
  47. package/dist/components/icons/index.d.cts +19 -0
  48. package/dist/components/icons/index.d.ts +19 -0
  49. package/dist/components/icons/index.js +35 -0
  50. package/dist/components/input-group/index.cjs +56 -0
  51. package/dist/components/input-group/index.d.cts +13 -0
  52. package/dist/components/input-group/index.d.ts +13 -0
  53. package/dist/components/input-group/index.js +8 -0
  54. package/dist/components/link/index.cjs +71 -0
  55. package/dist/components/link/index.d.cts +13 -0
  56. package/dist/components/link/index.d.ts +13 -0
  57. package/dist/components/link/index.js +20 -0
  58. package/dist/components/loading-overlay/index.cjs +1921 -0
  59. package/dist/components/loading-overlay/index.d.cts +13 -0
  60. package/dist/components/loading-overlay/index.d.ts +13 -0
  61. package/dist/components/loading-overlay/index.js +1878 -0
  62. package/dist/components/navbar/index.cjs +65 -0
  63. package/dist/components/navbar/index.d.cts +18 -0
  64. package/dist/components/navbar/index.d.ts +18 -0
  65. package/dist/components/navbar/index.js +42 -0
  66. package/dist/components/number-input/index.cjs +82 -0
  67. package/dist/components/number-input/index.d.cts +13 -0
  68. package/dist/components/number-input/index.d.ts +13 -0
  69. package/dist/components/number-input/index.js +32 -0
  70. package/dist/components/password-input/index.cjs +284 -0
  71. package/dist/components/password-input/index.d.cts +18 -0
  72. package/dist/components/password-input/index.d.ts +18 -0
  73. package/dist/components/password-input/index.js +231 -0
  74. package/dist/components/persona/index.cjs +181 -0
  75. package/dist/components/persona/index.d.cts +93 -0
  76. package/dist/components/persona/index.d.ts +93 -0
  77. package/dist/components/persona/index.js +149 -0
  78. package/dist/components/pin-input/index.cjs +51 -0
  79. package/dist/components/pin-input/index.d.cts +12 -0
  80. package/dist/components/pin-input/index.d.ts +12 -0
  81. package/dist/components/pin-input/index.js +26 -0
  82. package/dist/components/radio/index.cjs +48 -0
  83. package/dist/components/radio/index.d.cts +12 -0
  84. package/dist/components/radio/index.d.ts +12 -0
  85. package/dist/components/radio/index.js +22 -0
  86. package/dist/components/search-input/index.cjs +244 -0
  87. package/dist/components/search-input/index.d.cts +15 -0
  88. package/dist/components/search-input/index.d.ts +15 -0
  89. package/dist/components/search-input/index.js +120 -0
  90. package/dist/components/select/index.cjs +233 -0
  91. package/dist/components/select/index.d.cts +32 -0
  92. package/dist/components/select/index.d.ts +32 -0
  93. package/dist/components/select/index.js +100 -0
  94. package/dist/components/sidebar/index.cjs +134 -0
  95. package/dist/components/sidebar/index.d.cts +85 -0
  96. package/dist/components/sidebar/index.d.ts +85 -0
  97. package/dist/components/sidebar/index.js +108 -0
  98. package/dist/components/spinner/index.cjs +44 -0
  99. package/dist/components/spinner/index.d.cts +10 -0
  100. package/dist/components/spinner/index.d.ts +10 -0
  101. package/dist/components/spinner/index.js +8 -0
  102. package/dist/components/steps/index.cjs +191 -0
  103. package/dist/components/steps/index.d.cts +31 -0
  104. package/dist/components/steps/index.d.ts +31 -0
  105. package/dist/components/steps/index.js +71 -0
  106. package/dist/components/switch/index.cjs +48 -0
  107. package/dist/components/switch/index.d.cts +18 -0
  108. package/dist/components/switch/index.d.ts +18 -0
  109. package/dist/components/switch/index.js +23 -0
  110. package/dist/index.cjs +8460 -0
  111. package/dist/index.d.cts +26 -0
  112. package/dist/index.d.ts +25 -7
  113. package/dist/index.js +8395 -36
  114. package/package.json +26 -22
  115. package/src/components/app-shell/app-shell.recipe.ts +52 -0
  116. package/src/components/app-shell/app-shell.stories.tsx +51 -0
  117. package/src/components/app-shell/app-shell.tsx +94 -0
  118. package/src/components/app-shell/index.ts +3 -0
  119. package/src/components/breadcrumbs/breadcrumb.stories.tsx +17 -0
  120. package/src/components/breadcrumbs/breadcrumb.tsx +36 -0
  121. package/src/components/breadcrumbs/index.ts +1 -0
  122. package/src/components/breadcrumbs/namespace.ts +8 -0
  123. package/src/components/button/button.recipe.ts +182 -0
  124. package/src/components/button/button.stories.tsx +99 -0
  125. package/src/components/button/button.tsx +55 -0
  126. package/src/components/button/index.ts +2 -0
  127. package/src/components/checkbox/checkbox.tsx +26 -0
  128. package/src/components/checkbox/index.ts +2 -0
  129. package/src/components/close-button/close-button.stories.tsx +12 -0
  130. package/src/components/close-button/close-button.tsx +18 -0
  131. package/src/components/close-button/index.ts +2 -0
  132. package/src/components/command/command.recipe.ts +17 -0
  133. package/src/components/command/command.stories.tsx +47 -0
  134. package/src/components/command/command.tsx +50 -0
  135. package/src/components/command/index.ts +1 -0
  136. package/src/components/dialog/dialog.tsx +67 -0
  137. package/src/components/dialog/index.ts +1 -0
  138. package/src/components/dialog/namespace.ts +18 -0
  139. package/src/components/drawer/drawer.tsx +57 -0
  140. package/src/components/drawer/index.ts +3 -0
  141. package/src/components/drawer/namespace.ts +19 -0
  142. package/src/components/grid-list/grid-list.recipe.ts +113 -0
  143. package/src/components/icon-badge/icon-badge.recipe.ts +57 -0
  144. package/src/components/icon-badge/icon-badge.stories.tsx +38 -0
  145. package/src/components/icon-badge/icon-badge.tsx +59 -0
  146. package/src/components/icon-badge/index.ts +2 -0
  147. package/src/components/icons/create-icon.tsx +41 -0
  148. package/src/components/icons/icons.tsx +119 -0
  149. package/src/components/icons/index.ts +1 -0
  150. package/src/components/input-group/index.ts +1 -0
  151. package/src/components/input-group/input-group.tsx +46 -0
  152. package/src/components/link/index.ts +2 -0
  153. package/src/components/link/link.stories.tsx +17 -0
  154. package/src/components/link/link.test.tsx +33 -0
  155. package/src/components/link/link.tsx +27 -0
  156. package/src/components/loading-overlay/index.ts +1 -0
  157. package/src/components/loading-overlay/loading-overlay.recipe.ts +61 -0
  158. package/src/components/loading-overlay/loading-overlay.stories.tsx +68 -0
  159. package/src/components/loading-overlay/loading-overlay.tsx +54 -0
  160. package/src/components/loading-overlay/namespace.ts +7 -0
  161. package/src/components/navbar/index.ts +1 -0
  162. package/src/components/navbar/namespace.ts +9 -0
  163. package/src/components/navbar/navbar.recipe.ts +109 -0
  164. package/src/components/navbar/navbar.stories.tsx +435 -0
  165. package/src/components/navbar/navbar.test.tsx +49 -0
  166. package/src/components/navbar/navbar.tsx +39 -0
  167. package/src/components/number-input/index.ts +2 -0
  168. package/src/components/number-input/number-input.tsx +41 -0
  169. package/src/components/password-input/index.ts +2 -0
  170. package/src/components/password-input/password-input.tsx +93 -0
  171. package/src/components/persona/index.ts +2 -0
  172. package/src/components/persona/namespace.ts +18 -0
  173. package/src/components/persona/persona-primitive.tsx +220 -0
  174. package/src/components/persona/persona.recipe.ts +94 -0
  175. package/src/components/persona/persona.stories.tsx +101 -0
  176. package/src/components/persona/persona.tsx +142 -0
  177. package/src/components/pin-input/index.ts +2 -0
  178. package/src/components/pin-input/pin-input.tsx +36 -0
  179. package/src/components/radio/index.ts +2 -0
  180. package/src/components/radio/radio.tsx +27 -0
  181. package/src/components/search-input/index.ts +2 -0
  182. package/src/components/search-input/search-input.stories.tsx +63 -0
  183. package/src/components/search-input/search-input.tsx +134 -0
  184. package/src/components/select/index.ts +1 -0
  185. package/src/components/select/namespace.ts +18 -0
  186. package/src/components/select/select.tsx +135 -0
  187. package/src/components/sidebar/index.ts +7 -0
  188. package/src/components/sidebar/namespace.ts +27 -0
  189. package/src/components/sidebar/sidebar-item.recipe.ts +65 -0
  190. package/src/components/sidebar/sidebar.recipe.ts +237 -0
  191. package/src/components/sidebar/sidebar.stories.tsx +903 -0
  192. package/src/components/sidebar/sidebar.tsx +208 -0
  193. package/src/components/spinner/index.ts +2 -0
  194. package/src/components/spinner/spinner.stories.tsx +19 -0
  195. package/src/components/spinner/spinner.tsx +21 -0
  196. package/src/components/steps/index.ts +1 -0
  197. package/src/components/steps/namespace.ts +16 -0
  198. package/src/components/steps/steps.tsx +82 -0
  199. package/src/components/switch/index.ts +3 -0
  200. package/src/components/switch/switch.tsx +39 -0
  201. package/src/compositions/accordion.tsx +47 -0
  202. package/src/compositions/action-bar.tsx +40 -0
  203. package/src/compositions/alert.tsx +51 -0
  204. package/src/compositions/avatar.tsx +74 -0
  205. package/src/compositions/blockquote.tsx +31 -0
  206. package/src/compositions/checkbox-card.tsx +57 -0
  207. package/src/compositions/checkbox.tsx +25 -0
  208. package/src/compositions/clipboard.tsx +107 -0
  209. package/src/compositions/color-mode.tsx +65 -0
  210. package/src/compositions/data-list.tsx +37 -0
  211. package/src/compositions/empty-state.tsx +34 -0
  212. package/src/compositions/field.tsx +33 -0
  213. package/src/compositions/file-button.tsx +166 -0
  214. package/src/compositions/hover-card.tsx +35 -0
  215. package/src/compositions/link-button.tsx +12 -0
  216. package/src/compositions/menu.tsx +108 -0
  217. package/src/compositions/native-select.tsx +57 -0
  218. package/src/compositions/pagination.tsx +207 -0
  219. package/src/compositions/popover.tsx +58 -0
  220. package/src/compositions/progress-circle.tsx +37 -0
  221. package/src/compositions/progress.tsx +40 -0
  222. package/src/compositions/prose.tsx +264 -0
  223. package/src/compositions/provider.tsx +12 -0
  224. package/src/compositions/radio-card.tsx +57 -0
  225. package/src/compositions/radio.tsx +24 -0
  226. package/src/compositions/rating.tsx +27 -0
  227. package/src/compositions/segmented-control.tsx +47 -0
  228. package/src/compositions/skeleton.tsx +44 -0
  229. package/src/compositions/slider.tsx +53 -0
  230. package/src/compositions/stat.tsx +75 -0
  231. package/src/compositions/status.tsx +29 -0
  232. package/src/compositions/stepper-input.tsx +49 -0
  233. package/src/compositions/tag.tsx +39 -0
  234. package/src/compositions/timeline.tsx +17 -0
  235. package/src/compositions/toaster.tsx +43 -0
  236. package/src/compositions/toggle-tip.tsx +62 -0
  237. package/src/compositions/tooltip.tsx +46 -0
  238. package/src/index.ts +6 -7
  239. package/src/preset.ts +9 -0
  240. package/src/provider/index.ts +4 -0
  241. package/src/provider/sui-provider.tsx +34 -0
  242. package/src/provider/use-link.test.tsx +60 -0
  243. package/src/provider/use-link.tsx +13 -0
  244. package/src/styled-system/create-recipe-context.tsx +91 -0
  245. package/src/styled-system/create-slot-recipe-context.tsx +188 -0
  246. package/src/styled-system/empty.ts +7 -0
  247. package/src/styled-system/factory.types.ts +11 -0
  248. package/src/theme/animation-styles.ts +53 -0
  249. package/src/theme/breakpoints.ts +11 -0
  250. package/src/theme/conditions.ts +26 -0
  251. package/src/theme/fluid-font-sizes.ts +65 -0
  252. package/src/theme/global-css.ts +94 -0
  253. package/src/theme/index.ts +72 -0
  254. package/src/theme/layer-styles.ts +116 -0
  255. package/src/theme/recipes/chakra/accordion.ts +145 -0
  256. package/src/theme/recipes/chakra/action-bar.ts +62 -0
  257. package/src/theme/recipes/chakra/alert.ts +157 -0
  258. package/src/theme/recipes/chakra/avatar.ts +141 -0
  259. package/src/theme/recipes/chakra/badge.ts +67 -0
  260. package/src/theme/recipes/chakra/blockquote.ts +83 -0
  261. package/src/theme/recipes/chakra/breadcrumb.ts +94 -0
  262. package/src/theme/recipes/chakra/card.ts +99 -0
  263. package/src/theme/recipes/chakra/checkbox-card.ts +212 -0
  264. package/src/theme/recipes/chakra/checkbox.ts +70 -0
  265. package/src/theme/recipes/chakra/checkmark.ts +83 -0
  266. package/src/theme/recipes/chakra/code.ts +17 -0
  267. package/src/theme/recipes/chakra/collapsible.ts +20 -0
  268. package/src/theme/recipes/chakra/container.ts +26 -0
  269. package/src/theme/recipes/chakra/data-list.ts +80 -0
  270. package/src/theme/recipes/chakra/dialog.ts +225 -0
  271. package/src/theme/recipes/chakra/drawer.ts +201 -0
  272. package/src/theme/recipes/chakra/editable.ts +88 -0
  273. package/src/theme/recipes/chakra/empty-state.ts +88 -0
  274. package/src/theme/recipes/chakra/field.ts +68 -0
  275. package/src/theme/recipes/chakra/fieldset.ts +62 -0
  276. package/src/theme/recipes/chakra/file-upload.ts +96 -0
  277. package/src/theme/recipes/chakra/heading.ts +27 -0
  278. package/src/theme/recipes/chakra/hover-card.ts +68 -0
  279. package/src/theme/recipes/chakra/icon.ts +30 -0
  280. package/src/theme/recipes/chakra/input-addon.ts +40 -0
  281. package/src/theme/recipes/chakra/input.ts +96 -0
  282. package/src/theme/recipes/chakra/kbd.ts +60 -0
  283. package/src/theme/recipes/chakra/link.ts +37 -0
  284. package/src/theme/recipes/chakra/list.ts +67 -0
  285. package/src/theme/recipes/chakra/mark.ts +27 -0
  286. package/src/theme/recipes/chakra/menu.ts +124 -0
  287. package/src/theme/recipes/chakra/native-select.ts +140 -0
  288. package/src/theme/recipes/chakra/number-input.ts +115 -0
  289. package/src/theme/recipes/chakra/pin-input.ts +27 -0
  290. package/src/theme/recipes/chakra/popover.ts +86 -0
  291. package/src/theme/recipes/chakra/progress-circle.ts +94 -0
  292. package/src/theme/recipes/chakra/progress.ts +127 -0
  293. package/src/theme/recipes/chakra/radio-card.ts +220 -0
  294. package/src/theme/recipes/chakra/radio-group.ts +72 -0
  295. package/src/theme/recipes/chakra/radiomark.ts +107 -0
  296. package/src/theme/recipes/chakra/rating-group.ts +94 -0
  297. package/src/theme/recipes/chakra/segment-group.ts +117 -0
  298. package/src/theme/recipes/chakra/select.ts +282 -0
  299. package/src/theme/recipes/chakra/separator.ts +51 -0
  300. package/src/theme/recipes/chakra/skeleton.ts +53 -0
  301. package/src/theme/recipes/chakra/skip-nav-link.ts +34 -0
  302. package/src/theme/recipes/chakra/slider.ts +178 -0
  303. package/src/theme/recipes/chakra/spinner.ts +32 -0
  304. package/src/theme/recipes/chakra/stat.ts +79 -0
  305. package/src/theme/recipes/chakra/status.ts +48 -0
  306. package/src/theme/recipes/chakra/steps.ts +218 -0
  307. package/src/theme/recipes/chakra/switch.ts +167 -0
  308. package/src/theme/recipes/chakra/table.ts +172 -0
  309. package/src/theme/recipes/chakra/tabs.ts +280 -0
  310. package/src/theme/recipes/chakra/tag.ts +131 -0
  311. package/src/theme/recipes/chakra/textarea.ts +88 -0
  312. package/src/theme/recipes/chakra/timeline.ts +138 -0
  313. package/src/theme/recipes/chakra/toast.ts +96 -0
  314. package/src/theme/recipes/chakra/tooltip.ts +40 -0
  315. package/src/theme/recipes.ts +46 -0
  316. package/src/theme/semantic-tokens/colors.ts +403 -0
  317. package/src/theme/semantic-tokens/radii.ts +7 -0
  318. package/src/theme/semantic-tokens/shadows.ts +52 -0
  319. package/src/theme/slot-recipes.ts +104 -0
  320. package/src/theme/text-styles.ts +39 -0
  321. package/src/theme/tokens/animations.ts +8 -0
  322. package/src/theme/tokens/aspect-ratios.ts +10 -0
  323. package/src/theme/tokens/blurs.ts +12 -0
  324. package/src/theme/tokens/borders.ts +9 -0
  325. package/src/theme/tokens/colors.ts +177 -0
  326. package/src/theme/tokens/cursor.ts +12 -0
  327. package/src/theme/tokens/durations.ts +11 -0
  328. package/src/theme/tokens/easings.ts +10 -0
  329. package/src/theme/tokens/font-sizes.ts +20 -0
  330. package/src/theme/tokens/font-weights.ts +13 -0
  331. package/src/theme/tokens/fonts.ts +15 -0
  332. package/src/theme/tokens/keyframes.ts +173 -0
  333. package/src/theme/tokens/letter-spacing.ts +9 -0
  334. package/src/theme/tokens/line-heights.ts +19 -0
  335. package/src/theme/tokens/radius.ts +18 -0
  336. package/src/theme/tokens/sizes.ts +71 -0
  337. package/src/theme/tokens/spacing.ts +38 -0
  338. package/src/theme/tokens/z-indices.ts +34 -0
  339. package/src/theme/utils.ts +46 -0
  340. package/dist/index.d.mts +0 -8
  341. package/dist/index.js.map +0 -1
  342. package/dist/index.mjs +0 -11
  343. package/dist/index.mjs.map +0 -1
@@ -0,0 +1,220 @@
1
+ import React, { forwardRef } from 'react'
2
+
3
+ import {
4
+ Avatar,
5
+ type AvatarRootProps,
6
+ HTMLChakraProps,
7
+ type ImageProps,
8
+ SlotRecipeProps,
9
+ chakra,
10
+ createSlotRecipeContext,
11
+ } from '@chakra-ui/react'
12
+ import { dataAttr } from '@saas-ui/core/utils'
13
+
14
+ const {
15
+ useStyles: usePersonaStyles,
16
+ withProvider,
17
+ withContext,
18
+ } = createSlotRecipeContext({
19
+ key: 'persona',
20
+ })
21
+
22
+ export { usePersonaStyles }
23
+
24
+ export type Presence = 'online' | 'offline' | 'busy' | 'dnd' | 'away'
25
+
26
+ interface PresenceConfig {
27
+ label: string
28
+ color: string
29
+ }
30
+
31
+ export type PresenceOptions<P extends string = Presence> = Record<
32
+ P,
33
+ PresenceConfig
34
+ >
35
+
36
+ /**
37
+ * The presence configuration object.
38
+ *
39
+ * Default presence values: online, offline, busy, dnd, away
40
+ *
41
+ * You can overwrite colors in the theme semantic tokens.
42
+ * theme.semanticTokens.colors['presence.online'] = 'cyan.500'
43
+ *
44
+ * Or add a custom presence value
45
+ * theme.semanticTokens.colors['presence.vacay'] = 'blue.500'
46
+ *
47
+ * @see Docs https://saas-ui.dev/docs/components/data-display/persona
48
+ */
49
+ export const defaultPresenceOptions: PresenceOptions = {
50
+ online: {
51
+ label: 'Online',
52
+ color: 'presence.online',
53
+ },
54
+ offline: {
55
+ label: 'Offline',
56
+ color: 'presence.offline',
57
+ },
58
+ busy: {
59
+ label: 'Busy',
60
+ color: 'presence.busy',
61
+ },
62
+ dnd: {
63
+ label: 'Do-not-disturb',
64
+ color: 'presence.dnd',
65
+ },
66
+ away: {
67
+ label: 'Away',
68
+ color: 'presence.away',
69
+ },
70
+ }
71
+
72
+ export interface PersonaRootProps
73
+ extends HTMLChakraProps<'div'>,
74
+ SlotRecipeProps<'persona'> {
75
+ /**
76
+ * Indicates that a person is out of office. Changes the presence badge style.
77
+ */
78
+ outOfOffice?: boolean
79
+ /**
80
+ * The presence status of the person
81
+ */
82
+ presence?: Presence
83
+ }
84
+
85
+ /**
86
+ * The root component that provides context and styles.
87
+ *
88
+ * @see Docs https://saas-ui.dev/docs/components/data-display/persona
89
+ */
90
+ export const PersonaRoot = withProvider<HTMLDivElement, PersonaRootProps>(
91
+ forwardRef((props, ref) => {
92
+ const { outOfOffice, presence, ...rest } = props
93
+
94
+ return (
95
+ <chakra.div
96
+ ref={ref}
97
+ {...rest}
98
+ data-out-of-office={dataAttr(outOfOffice)}
99
+ data-presence={presence}
100
+ css={[
101
+ presence
102
+ ? {
103
+ '--persona-presence': `colors.presence.${presence}`,
104
+ }
105
+ : undefined,
106
+ rest.css,
107
+ ]}
108
+ />
109
+ )
110
+ }),
111
+ 'root',
112
+ )
113
+
114
+ interface PersonaAvatarOptions {
115
+ /**
116
+ * The name of the person in the avatar.
117
+ *
118
+ * - if `src` has loaded, the name will be used as the `alt` attribute of the `img`
119
+ * - If `src` is not loaded, the name will be used to create the initials
120
+ */
121
+ name?: string
122
+ }
123
+
124
+ export interface PersonaAvatarProps
125
+ extends PersonaAvatarOptions,
126
+ AvatarRootProps {
127
+ src?: string
128
+ srcSet?: string
129
+ loading?: ImageProps['loading']
130
+ icon?: React.ReactElement
131
+ fallback?: React.ReactNode
132
+ getInitials?: (name?: string | null) => string | null
133
+ }
134
+
135
+ /**
136
+ * An avatar with optional status badge.
137
+ *
138
+ * @see Docs https://saas-ui.dev/docs/components/data-display/persona
139
+ */
140
+ export const PersonaAvatar = forwardRef<HTMLDivElement, PersonaAvatarProps>(
141
+ (props, ref) => {
142
+ const {
143
+ name,
144
+ getInitials = (name?: string | null) => name?.[0],
145
+ icon,
146
+ loading,
147
+ onError,
148
+ src,
149
+ srcSet,
150
+ children,
151
+ ...rest
152
+ } = props
153
+
154
+ return (
155
+ <Avatar.Root ref={ref} {...rest}>
156
+ <Avatar.Fallback>{getInitials(name)}</Avatar.Fallback>
157
+ <Avatar.Image
158
+ src={src}
159
+ srcSet={srcSet}
160
+ loading={loading}
161
+ onError={onError}
162
+ />
163
+ {children}
164
+ </Avatar.Root>
165
+ )
166
+ },
167
+ )
168
+
169
+ export interface PersonaPresenceBadgeProps extends HTMLChakraProps<'span'> {}
170
+
171
+ export const PersonaPresenceBadge = withContext<
172
+ HTMLSpanElement,
173
+ PersonaPresenceBadgeProps
174
+ >('span', 'presence')
175
+
176
+ export interface PersonaDetailsProps extends HTMLChakraProps<'div'> {}
177
+
178
+ /**
179
+ * Wrapper component for the labels.
180
+ *
181
+ * @see Docs https://saas-ui.dev/docs/components/data-display/persona
182
+ */
183
+ export const PersonaDetails = withContext<HTMLDivElement, PersonaDetailsProps>(
184
+ 'div',
185
+ 'details',
186
+ )
187
+
188
+ export interface PersonaLabelProps extends HTMLChakraProps<'span'> {}
189
+
190
+ /**
191
+ * The main label, usually a name.
192
+ *
193
+ * @see Docs https://saas-ui.dev/docs/components/data-display/persona
194
+ */
195
+ export const PersonaLabel = withContext<HTMLSpanElement, PersonaLabelProps>(
196
+ 'span',
197
+ 'label',
198
+ )
199
+
200
+ PersonaLabel.displayName = 'PersonaLabel'
201
+
202
+ /**
203
+ * The secondary label, usually the role of a person.
204
+ *
205
+ * @see Docs https://saas-ui.dev/docs/components/data-display/persona
206
+ */
207
+ export const PersonaSecondaryLabel = withContext<
208
+ HTMLSpanElement,
209
+ PersonaLabelProps
210
+ >('span', 'secondaryLabel')
211
+
212
+ /**
213
+ * The tertiary label, typically a status message.
214
+ *
215
+ * @see Docs https://saas-ui.dev/docs/components/data-display/persona
216
+ */
217
+ export const PersonaTertiaryLabel = withContext<
218
+ HTMLSpanElement,
219
+ PersonaLabelProps
220
+ >('span', 'tertiaryLabel')
@@ -0,0 +1,94 @@
1
+ import { defineSlotRecipe, defineStyle } from '@chakra-ui/react'
2
+
3
+ const baseStyleLabel = defineStyle({
4
+ overflow: 'hidden',
5
+ whiteSpace: 'nowrap',
6
+ textOverflow: 'ellipsis',
7
+ minW: 0,
8
+ })
9
+
10
+ export const personaSlotRecipe = defineSlotRecipe({
11
+ className: 'sui-persona',
12
+ slots: [
13
+ 'root',
14
+ 'avatar',
15
+ 'presence',
16
+ 'details',
17
+ 'label',
18
+ 'secondaryLabel',
19
+ 'tertiaryLabel',
20
+ ],
21
+ base: {
22
+ root: {
23
+ display: 'flex',
24
+ flexDirection: 'row',
25
+ alignItems: 'center',
26
+ },
27
+ presence: {
28
+ display: 'flex',
29
+ alignItems: 'center',
30
+ justifyContent: 'center',
31
+ position: 'absolute',
32
+ bottom: 0,
33
+ right: 0,
34
+ boxSize: '1em',
35
+ transform: 'translate(15%, 15%)',
36
+ borderWidth: '0.15em',
37
+ borderRadius: '50%',
38
+ borderColor: 'bg.panel',
39
+ bg: 'var(--persona-presence)',
40
+ },
41
+ details: {
42
+ display: 'flex',
43
+ flexDirection: 'column',
44
+ minW: 0,
45
+ lineHeight: 'short',
46
+ },
47
+ label: baseStyleLabel,
48
+ secondaryLabel: {
49
+ ...baseStyleLabel,
50
+ color: 'fg.muted',
51
+ },
52
+ tertiaryLabel: {
53
+ ...baseStyleLabel,
54
+ color: 'fg.muted',
55
+ },
56
+ },
57
+ variants: {
58
+ size: {
59
+ xs: {
60
+ details: { ms: 2 },
61
+ label: { fontSize: 'xs' },
62
+ secondaryLabel: { display: 'none' },
63
+ tertiaryLabel: { display: 'none' },
64
+ },
65
+ sm: {
66
+ details: { ms: 2 },
67
+ label: { fontSize: 'sm' },
68
+ secondaryLabel: { fontSize: 'xs' },
69
+ tertiaryLabel: { display: 'none' },
70
+ },
71
+ md: {
72
+ details: { ms: 2 },
73
+ label: { fontSize: 'sm' },
74
+ secondaryLabel: { fontSize: 'xs' },
75
+ tertiaryLabel: { display: 'none' },
76
+ },
77
+ lg: {
78
+ details: { ms: 3 },
79
+ label: { fontSize: 'md' },
80
+ secondaryLabel: { fontSize: 'sm' },
81
+ tertiaryLabel: { fontSize: 'sm' },
82
+ },
83
+ xl: {
84
+ details: { ms: 4 },
85
+ label: { fontSize: 'lg' },
86
+ secondaryLabel: { fontSize: 'md' },
87
+ tertiaryLabel: { fontSize: 'md' },
88
+ },
89
+ },
90
+ },
91
+ defaultVariants: {
92
+ size: 'md',
93
+ },
94
+ })
@@ -0,0 +1,101 @@
1
+ import * as React from 'react'
2
+
3
+ import { Container, VStack } from '@chakra-ui/react'
4
+ import { FiMinus, FiPhone } from 'react-icons/fi'
5
+
6
+ import { Persona } from './persona.tsx'
7
+
8
+ export default {
9
+ title: 'Components/Persona',
10
+ decorators: [
11
+ (Story: any) => (
12
+ <Container mt="40px">
13
+ <Story />
14
+ </Container>
15
+ ),
16
+ ],
17
+ }
18
+
19
+ const persona = {
20
+ name: 'Elliot Alderson',
21
+ presence: 'online',
22
+ secondaryLabel: 'Mr Robot',
23
+ tertiaryLabel: 'Away for lunch',
24
+ }
25
+
26
+ export const Basic = () => (
27
+ <>
28
+ <VStack gap="8">
29
+ <Persona {...persona} presence="online" size="xs" />
30
+
31
+ <Persona {...persona} presence="online" size="sm" />
32
+
33
+ <Persona {...persona} presence="online" size="md" />
34
+
35
+ <Persona {...persona} presence="online" size="lg" />
36
+
37
+ <Persona {...persona} presence="online" size="xl" />
38
+ </VStack>
39
+ </>
40
+ )
41
+
42
+ export const HideDetails = () => (
43
+ <>
44
+ <VStack gap="8">
45
+ <Persona {...persona} hideDetails presence="offline" />
46
+ </VStack>
47
+ </>
48
+ )
49
+
50
+ export const BadgeIcon = () => (
51
+ <>
52
+ <VStack gap="8">
53
+ <Persona
54
+ {...persona}
55
+ presenceIcon={<FiMinus size="0.4em" />}
56
+ size="xl"
57
+ presence="busy"
58
+ />
59
+ </VStack>
60
+ </>
61
+ )
62
+
63
+ export const LabelWithIcon = () => (
64
+ <>
65
+ <VStack gap="8">
66
+ <Persona
67
+ {...persona}
68
+ presence="busy"
69
+ secondaryLabel={
70
+ <>
71
+ <FiPhone /> On a call
72
+ </>
73
+ }
74
+ />
75
+ </VStack>
76
+ </>
77
+ )
78
+
79
+ export const OutOfOffice = () => (
80
+ <>
81
+ <VStack gap="8">
82
+ <Persona {...persona} presence="offline" size="xs" isOutOfOffice />
83
+ <Persona {...persona} presence="online" isOutOfOffice />
84
+ <Persona {...persona} presence="away" size="xl" isOutOfOffice />
85
+ </VStack>
86
+ </>
87
+ )
88
+
89
+ export const Overflow = () => (
90
+ <>
91
+ <VStack gap="8">
92
+ <Persona
93
+ {...persona}
94
+ secondaryLabel="This is a very long text and should overflow."
95
+ presence="offline"
96
+ isOutOfOffice
97
+ maxW="200px"
98
+ />
99
+ </VStack>
100
+ </>
101
+ )
@@ -0,0 +1,142 @@
1
+ import * as React from 'react'
2
+
3
+ import * as PersonaPrimitive from './namespace.ts'
4
+
5
+ interface PersonaOptions {
6
+ /**
7
+ * The name of the person in the avatar.
8
+ *
9
+ * - if `src` has loaded, the name will be used as the `alt` attribute of the `img`
10
+ * - If `src` is not loaded, the name will be used to create the initials
11
+ */
12
+ name?: string
13
+ /**
14
+ * The presence status of the person
15
+ *
16
+ * If set will add an AvatarBadge with color configured in `Presence`
17
+ * Default presence options:
18
+ * - online
19
+ * - offline
20
+ * - busy
21
+ * - dnd
22
+ * - away
23
+ */
24
+ presence?: PersonaPrimitive.Presence
25
+ /**
26
+ * The icon shown in the AvatarBadge
27
+ */
28
+ presenceIcon?: React.ReactNode
29
+ /**
30
+ * Indicates that a person is out of office. Changes the presence badge style.
31
+ */
32
+ isOutOfOffice?: boolean
33
+ /**
34
+ * Primary label of the persona, defaults to the name
35
+ */
36
+ label?: React.ReactNode
37
+ /**
38
+ * Secondary label, usually the role of the person
39
+ * Only visible from md size and up.
40
+ */
41
+ secondaryLabel?: React.ReactNode
42
+ /**
43
+ * Tertiary label, usually the status of the person.
44
+ * Only visible from lg size and up.
45
+ */
46
+ tertiaryLabel?: React.ReactNode
47
+ /**
48
+ * Hide the persona details next to the avatar.
49
+ */
50
+ hideDetails?: boolean
51
+ }
52
+
53
+ export interface PersonaProps
54
+ extends PersonaOptions,
55
+ PersonaPrimitive.AvatarProps,
56
+ PersonaPrimitive.RootProps {}
57
+
58
+ /**
59
+ * The wrapper component that handles default composition.
60
+ *
61
+ * @see Docs https://saas-ui.dev/docs/components/data-display/persona
62
+ */
63
+ export const Persona = React.forwardRef<HTMLDivElement, PersonaProps>(
64
+ (props, ref) => {
65
+ const {
66
+ name,
67
+ presence,
68
+ presenceIcon,
69
+ isOutOfOffice,
70
+ label,
71
+ secondaryLabel,
72
+ tertiaryLabel,
73
+ size,
74
+ hideDetails,
75
+ children,
76
+ /** Avatar props */
77
+ getInitials,
78
+ icon,
79
+ loading,
80
+ onError,
81
+ src,
82
+ srcSet,
83
+ ...rest
84
+ } = props
85
+
86
+ return (
87
+ <PersonaPrimitive.Root
88
+ ref={ref}
89
+ outOfOffice={isOutOfOffice}
90
+ presence={presence}
91
+ {...rest}
92
+ >
93
+ <PersonaPrimitive.Avatar
94
+ name={name}
95
+ size={size}
96
+ getInitials={getInitials}
97
+ icon={icon}
98
+ loading={loading}
99
+ onError={onError}
100
+ src={src}
101
+ srcSet={srcSet}
102
+ >
103
+ <PersonaPrimitive.PresenceBadge>
104
+ {presenceIcon}
105
+ </PersonaPrimitive.PresenceBadge>
106
+ </PersonaPrimitive.Avatar>
107
+
108
+ {!hideDetails && (
109
+ <PersonaPrimitive.Details>
110
+ <PersonaPrimitive.Label>{label || name}</PersonaPrimitive.Label>
111
+ {secondaryLabel && (
112
+ <PersonaPrimitive.SecondaryLabel>
113
+ {secondaryLabel}
114
+ </PersonaPrimitive.SecondaryLabel>
115
+ )}
116
+ {tertiaryLabel && (
117
+ <PersonaPrimitive.TertiaryLabel>
118
+ {tertiaryLabel}
119
+ </PersonaPrimitive.TertiaryLabel>
120
+ )}
121
+ {children}
122
+ </PersonaPrimitive.Details>
123
+ )}
124
+ </PersonaPrimitive.Root>
125
+ )
126
+ },
127
+ )
128
+
129
+ Persona.displayName = 'Persona'
130
+
131
+ export interface PersonaAvatarProps
132
+ extends Omit<
133
+ PersonaProps,
134
+ 'hideDetails' | 'label' | 'secondaryLabel' | 'tertiaryLabel' | 'children'
135
+ > {}
136
+
137
+ export const PersonaAvatar = React.forwardRef<
138
+ HTMLDivElement,
139
+ PersonaAvatarProps
140
+ >(function PersonaAvatar(props, ref) {
141
+ return <Persona ref={ref} {...props} hideDetails />
142
+ })
@@ -0,0 +1,2 @@
1
+ export { PinInput } from './pin-input.tsx'
2
+ export type { PinInputProps } from './pin-input.tsx'
@@ -0,0 +1,36 @@
1
+ import { forwardRef } from 'react'
2
+
3
+ import { PinInput as ChakraPinInput, Group } from '@chakra-ui/react'
4
+
5
+ export interface PinInputProps extends ChakraPinInput.RootProps {
6
+ rootRef?: React.Ref<HTMLDivElement>
7
+ pinLength?: number
8
+ inputProps?: React.InputHTMLAttributes<HTMLInputElement>
9
+ attached?: boolean
10
+ }
11
+
12
+ export const PinInput = forwardRef<HTMLInputElement, PinInputProps>(
13
+ function PinInput(props, ref) {
14
+ const {
15
+ pinLength = 4,
16
+ inputProps,
17
+ rootRef,
18
+ attached,
19
+ gap = attached ? 0 : 2,
20
+ ...rest
21
+ } = props
22
+
23
+ return (
24
+ <ChakraPinInput.Root ref={rootRef} {...rest}>
25
+ <ChakraPinInput.HiddenInput ref={ref} {...inputProps} />
26
+ <ChakraPinInput.Control>
27
+ <Group attached={attached} gap={gap}>
28
+ {Array.from({ length: pinLength }).map((_, index) => (
29
+ <ChakraPinInput.Input key={index} index={index} />
30
+ ))}
31
+ </Group>
32
+ </ChakraPinInput.Control>
33
+ </ChakraPinInput.Root>
34
+ )
35
+ },
36
+ )
@@ -0,0 +1,2 @@
1
+ export { Radio, RadioGroup } from './radio'
2
+ export type { RadioProps, RadioGroupProps } from './radio'
@@ -0,0 +1,27 @@
1
+ import { forwardRef } from 'react'
2
+
3
+ import { RadioGroup as ChakraRadioGroup } from '@chakra-ui/react'
4
+
5
+ export interface RadioProps extends ChakraRadioGroup.ItemProps {
6
+ rootRef?: React.Ref<HTMLDivElement>
7
+ inputProps?: React.InputHTMLAttributes<HTMLInputElement>
8
+ }
9
+
10
+ export const Radio = forwardRef<HTMLInputElement, RadioProps>(
11
+ function Radio(props, ref) {
12
+ const { children, inputProps, rootRef, ...rest } = props
13
+ return (
14
+ <ChakraRadioGroup.Item ref={rootRef} {...rest}>
15
+ <ChakraRadioGroup.ItemHiddenInput ref={ref} {...inputProps} />
16
+ <ChakraRadioGroup.ItemIndicator />
17
+ {children && (
18
+ <ChakraRadioGroup.ItemText>{children}</ChakraRadioGroup.ItemText>
19
+ )}
20
+ </ChakraRadioGroup.Item>
21
+ )
22
+ },
23
+ )
24
+
25
+ export type RadioGroupProps = ChakraRadioGroup.RootProps
26
+
27
+ export const RadioGroup = ChakraRadioGroup.Root
@@ -0,0 +1,2 @@
1
+ export { SearchInput } from './search-input.tsx'
2
+ export type { SearchInputProps } from './search-input.tsx'
@@ -0,0 +1,63 @@
1
+ import React, { useState } from 'react'
2
+
3
+ import { Container, Stack } from '@chakra-ui/react'
4
+ import { StoryObj } from '@storybook/react'
5
+ import { RiCloseLine, RiSearch2Line } from 'react-icons/ri'
6
+
7
+ import { SearchInput, SearchInputProps } from './search-input'
8
+
9
+ export default {
10
+ title: 'Components/SearchInput',
11
+ component: SearchInput,
12
+ decorators: [
13
+ (Story: any) => (
14
+ <Container mt="40px">
15
+ <Story />
16
+ </Container>
17
+ ),
18
+ ],
19
+ }
20
+
21
+ type Story = StoryObj<SearchInputProps>
22
+
23
+ export const Basic: Story = {}
24
+
25
+ export const Sizes: Story = {
26
+ render: () => {
27
+ return (
28
+ <Stack>
29
+ <SearchInput size="lg" />
30
+ <SearchInput size="md" />
31
+ <SearchInput size="sm" />
32
+ <SearchInput size="xs" />
33
+ </Stack>
34
+ )
35
+ },
36
+ }
37
+
38
+ export const Disabled: Story = {
39
+ args: {
40
+ disabled: true,
41
+ },
42
+ }
43
+
44
+ export const CustomIcons: Story = {
45
+ args: {
46
+ icon: <RiSearch2Line />,
47
+ resetIcon: <RiCloseLine />,
48
+ },
49
+ }
50
+
51
+ export const Controlled: Story = {
52
+ render: (props: any) => {
53
+ const [value, setValue] = useState('')
54
+ return (
55
+ <SearchInput
56
+ value={value}
57
+ onChange={({ target }) => setValue(target.value)}
58
+ onReset={() => setValue('')}
59
+ {...props}
60
+ />
61
+ )
62
+ },
63
+ }