@saas-ui/react 3.0.0-alpha.1 → 3.0.0-alpha.2

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 (237) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/components/app-shell/index.d.cts +1 -1
  3. package/dist/components/app-shell/index.d.ts +1 -1
  4. package/dist/components/navbar/index.d.cts +3 -3
  5. package/dist/components/navbar/index.d.ts +3 -3
  6. package/dist/components/persona/index.d.cts +1 -1
  7. package/dist/components/persona/index.d.ts +1 -1
  8. package/dist/components/sidebar/index.d.cts +12 -12
  9. package/dist/components/sidebar/index.d.ts +12 -12
  10. package/dist/index.cjs +2 -12
  11. package/dist/index.js +2 -12
  12. package/package.json +4 -6
  13. package/src/components/app-shell/app-shell.recipe.ts +0 -52
  14. package/src/components/app-shell/app-shell.stories.tsx +0 -51
  15. package/src/components/app-shell/app-shell.tsx +0 -94
  16. package/src/components/app-shell/index.ts +0 -3
  17. package/src/components/breadcrumbs/breadcrumb.stories.tsx +0 -17
  18. package/src/components/breadcrumbs/breadcrumb.tsx +0 -36
  19. package/src/components/breadcrumbs/index.ts +0 -1
  20. package/src/components/breadcrumbs/namespace.ts +0 -8
  21. package/src/components/button/button.recipe.ts +0 -182
  22. package/src/components/button/button.stories.tsx +0 -99
  23. package/src/components/button/button.tsx +0 -55
  24. package/src/components/button/index.ts +0 -2
  25. package/src/components/checkbox/checkbox.tsx +0 -26
  26. package/src/components/checkbox/index.ts +0 -2
  27. package/src/components/close-button/close-button.stories.tsx +0 -12
  28. package/src/components/close-button/close-button.tsx +0 -18
  29. package/src/components/close-button/index.ts +0 -2
  30. package/src/components/command/command.recipe.ts +0 -17
  31. package/src/components/command/command.stories.tsx +0 -47
  32. package/src/components/command/command.tsx +0 -50
  33. package/src/components/command/index.ts +0 -1
  34. package/src/components/dialog/dialog.tsx +0 -67
  35. package/src/components/dialog/index.ts +0 -1
  36. package/src/components/dialog/namespace.ts +0 -18
  37. package/src/components/drawer/drawer.tsx +0 -57
  38. package/src/components/drawer/index.ts +0 -3
  39. package/src/components/drawer/namespace.ts +0 -19
  40. package/src/components/grid-list/grid-list.recipe.ts +0 -113
  41. package/src/components/icon-badge/icon-badge.recipe.ts +0 -57
  42. package/src/components/icon-badge/icon-badge.stories.tsx +0 -38
  43. package/src/components/icon-badge/icon-badge.tsx +0 -59
  44. package/src/components/icon-badge/index.ts +0 -2
  45. package/src/components/icons/create-icon.tsx +0 -41
  46. package/src/components/icons/icons.tsx +0 -119
  47. package/src/components/icons/index.ts +0 -1
  48. package/src/components/input-group/index.ts +0 -1
  49. package/src/components/input-group/input-group.tsx +0 -46
  50. package/src/components/link/index.ts +0 -2
  51. package/src/components/link/link.stories.tsx +0 -17
  52. package/src/components/link/link.test.tsx +0 -33
  53. package/src/components/link/link.tsx +0 -27
  54. package/src/components/loading-overlay/index.ts +0 -1
  55. package/src/components/loading-overlay/loading-overlay.recipe.ts +0 -61
  56. package/src/components/loading-overlay/loading-overlay.stories.tsx +0 -68
  57. package/src/components/loading-overlay/loading-overlay.tsx +0 -54
  58. package/src/components/loading-overlay/namespace.ts +0 -7
  59. package/src/components/navbar/index.ts +0 -1
  60. package/src/components/navbar/namespace.ts +0 -9
  61. package/src/components/navbar/navbar.recipe.ts +0 -109
  62. package/src/components/navbar/navbar.stories.tsx +0 -435
  63. package/src/components/navbar/navbar.test.tsx +0 -49
  64. package/src/components/navbar/navbar.tsx +0 -39
  65. package/src/components/number-input/index.ts +0 -2
  66. package/src/components/number-input/number-input.tsx +0 -41
  67. package/src/components/password-input/index.ts +0 -2
  68. package/src/components/password-input/password-input.tsx +0 -93
  69. package/src/components/persona/index.ts +0 -2
  70. package/src/components/persona/namespace.ts +0 -18
  71. package/src/components/persona/persona-primitive.tsx +0 -220
  72. package/src/components/persona/persona.recipe.ts +0 -94
  73. package/src/components/persona/persona.stories.tsx +0 -101
  74. package/src/components/persona/persona.tsx +0 -142
  75. package/src/components/pin-input/index.ts +0 -2
  76. package/src/components/pin-input/pin-input.tsx +0 -36
  77. package/src/components/radio/index.ts +0 -2
  78. package/src/components/radio/radio.tsx +0 -27
  79. package/src/components/search-input/index.ts +0 -2
  80. package/src/components/search-input/search-input.stories.tsx +0 -63
  81. package/src/components/search-input/search-input.tsx +0 -134
  82. package/src/components/select/index.ts +0 -1
  83. package/src/components/select/namespace.ts +0 -18
  84. package/src/components/select/select.tsx +0 -135
  85. package/src/components/sidebar/index.ts +0 -7
  86. package/src/components/sidebar/namespace.ts +0 -27
  87. package/src/components/sidebar/sidebar-item.recipe.ts +0 -65
  88. package/src/components/sidebar/sidebar.recipe.ts +0 -237
  89. package/src/components/sidebar/sidebar.stories.tsx +0 -903
  90. package/src/components/sidebar/sidebar.tsx +0 -208
  91. package/src/components/spinner/index.ts +0 -2
  92. package/src/components/spinner/spinner.stories.tsx +0 -19
  93. package/src/components/spinner/spinner.tsx +0 -21
  94. package/src/components/steps/index.ts +0 -1
  95. package/src/components/steps/namespace.ts +0 -16
  96. package/src/components/steps/steps.tsx +0 -82
  97. package/src/components/switch/index.ts +0 -3
  98. package/src/components/switch/switch.tsx +0 -39
  99. package/src/compositions/accordion.tsx +0 -47
  100. package/src/compositions/action-bar.tsx +0 -40
  101. package/src/compositions/alert.tsx +0 -51
  102. package/src/compositions/avatar.tsx +0 -74
  103. package/src/compositions/blockquote.tsx +0 -31
  104. package/src/compositions/checkbox-card.tsx +0 -57
  105. package/src/compositions/checkbox.tsx +0 -25
  106. package/src/compositions/clipboard.tsx +0 -107
  107. package/src/compositions/color-mode.tsx +0 -65
  108. package/src/compositions/data-list.tsx +0 -37
  109. package/src/compositions/empty-state.tsx +0 -34
  110. package/src/compositions/field.tsx +0 -33
  111. package/src/compositions/file-button.tsx +0 -166
  112. package/src/compositions/hover-card.tsx +0 -35
  113. package/src/compositions/link-button.tsx +0 -12
  114. package/src/compositions/menu.tsx +0 -108
  115. package/src/compositions/native-select.tsx +0 -57
  116. package/src/compositions/pagination.tsx +0 -207
  117. package/src/compositions/popover.tsx +0 -58
  118. package/src/compositions/progress-circle.tsx +0 -37
  119. package/src/compositions/progress.tsx +0 -40
  120. package/src/compositions/prose.tsx +0 -264
  121. package/src/compositions/provider.tsx +0 -12
  122. package/src/compositions/radio-card.tsx +0 -57
  123. package/src/compositions/radio.tsx +0 -24
  124. package/src/compositions/rating.tsx +0 -27
  125. package/src/compositions/segmented-control.tsx +0 -47
  126. package/src/compositions/skeleton.tsx +0 -44
  127. package/src/compositions/slider.tsx +0 -53
  128. package/src/compositions/stat.tsx +0 -75
  129. package/src/compositions/status.tsx +0 -29
  130. package/src/compositions/stepper-input.tsx +0 -49
  131. package/src/compositions/tag.tsx +0 -39
  132. package/src/compositions/timeline.tsx +0 -17
  133. package/src/compositions/toaster.tsx +0 -43
  134. package/src/compositions/toggle-tip.tsx +0 -62
  135. package/src/compositions/tooltip.tsx +0 -46
  136. package/src/index.ts +0 -7
  137. package/src/preset.ts +0 -9
  138. package/src/provider/index.ts +0 -4
  139. package/src/provider/sui-provider.tsx +0 -34
  140. package/src/provider/use-link.test.tsx +0 -60
  141. package/src/provider/use-link.tsx +0 -13
  142. package/src/styled-system/create-recipe-context.tsx +0 -91
  143. package/src/styled-system/create-slot-recipe-context.tsx +0 -188
  144. package/src/styled-system/empty.ts +0 -7
  145. package/src/styled-system/factory.types.ts +0 -11
  146. package/src/theme/animation-styles.ts +0 -53
  147. package/src/theme/breakpoints.ts +0 -11
  148. package/src/theme/conditions.ts +0 -26
  149. package/src/theme/fluid-font-sizes.ts +0 -65
  150. package/src/theme/global-css.ts +0 -94
  151. package/src/theme/index.ts +0 -72
  152. package/src/theme/layer-styles.ts +0 -116
  153. package/src/theme/recipes/chakra/accordion.ts +0 -145
  154. package/src/theme/recipes/chakra/action-bar.ts +0 -62
  155. package/src/theme/recipes/chakra/alert.ts +0 -157
  156. package/src/theme/recipes/chakra/avatar.ts +0 -141
  157. package/src/theme/recipes/chakra/badge.ts +0 -67
  158. package/src/theme/recipes/chakra/blockquote.ts +0 -83
  159. package/src/theme/recipes/chakra/breadcrumb.ts +0 -94
  160. package/src/theme/recipes/chakra/card.ts +0 -99
  161. package/src/theme/recipes/chakra/checkbox-card.ts +0 -212
  162. package/src/theme/recipes/chakra/checkbox.ts +0 -70
  163. package/src/theme/recipes/chakra/checkmark.ts +0 -83
  164. package/src/theme/recipes/chakra/code.ts +0 -17
  165. package/src/theme/recipes/chakra/collapsible.ts +0 -20
  166. package/src/theme/recipes/chakra/container.ts +0 -26
  167. package/src/theme/recipes/chakra/data-list.ts +0 -80
  168. package/src/theme/recipes/chakra/dialog.ts +0 -225
  169. package/src/theme/recipes/chakra/drawer.ts +0 -201
  170. package/src/theme/recipes/chakra/editable.ts +0 -88
  171. package/src/theme/recipes/chakra/empty-state.ts +0 -88
  172. package/src/theme/recipes/chakra/field.ts +0 -68
  173. package/src/theme/recipes/chakra/fieldset.ts +0 -62
  174. package/src/theme/recipes/chakra/file-upload.ts +0 -96
  175. package/src/theme/recipes/chakra/heading.ts +0 -27
  176. package/src/theme/recipes/chakra/hover-card.ts +0 -68
  177. package/src/theme/recipes/chakra/icon.ts +0 -30
  178. package/src/theme/recipes/chakra/input-addon.ts +0 -40
  179. package/src/theme/recipes/chakra/input.ts +0 -96
  180. package/src/theme/recipes/chakra/kbd.ts +0 -60
  181. package/src/theme/recipes/chakra/link.ts +0 -37
  182. package/src/theme/recipes/chakra/list.ts +0 -67
  183. package/src/theme/recipes/chakra/mark.ts +0 -27
  184. package/src/theme/recipes/chakra/menu.ts +0 -124
  185. package/src/theme/recipes/chakra/native-select.ts +0 -140
  186. package/src/theme/recipes/chakra/number-input.ts +0 -115
  187. package/src/theme/recipes/chakra/pin-input.ts +0 -27
  188. package/src/theme/recipes/chakra/popover.ts +0 -86
  189. package/src/theme/recipes/chakra/progress-circle.ts +0 -94
  190. package/src/theme/recipes/chakra/progress.ts +0 -127
  191. package/src/theme/recipes/chakra/radio-card.ts +0 -220
  192. package/src/theme/recipes/chakra/radio-group.ts +0 -72
  193. package/src/theme/recipes/chakra/radiomark.ts +0 -107
  194. package/src/theme/recipes/chakra/rating-group.ts +0 -94
  195. package/src/theme/recipes/chakra/segment-group.ts +0 -117
  196. package/src/theme/recipes/chakra/select.ts +0 -282
  197. package/src/theme/recipes/chakra/separator.ts +0 -51
  198. package/src/theme/recipes/chakra/skeleton.ts +0 -53
  199. package/src/theme/recipes/chakra/skip-nav-link.ts +0 -34
  200. package/src/theme/recipes/chakra/slider.ts +0 -178
  201. package/src/theme/recipes/chakra/spinner.ts +0 -32
  202. package/src/theme/recipes/chakra/stat.ts +0 -79
  203. package/src/theme/recipes/chakra/status.ts +0 -48
  204. package/src/theme/recipes/chakra/steps.ts +0 -218
  205. package/src/theme/recipes/chakra/switch.ts +0 -167
  206. package/src/theme/recipes/chakra/table.ts +0 -172
  207. package/src/theme/recipes/chakra/tabs.ts +0 -280
  208. package/src/theme/recipes/chakra/tag.ts +0 -131
  209. package/src/theme/recipes/chakra/textarea.ts +0 -88
  210. package/src/theme/recipes/chakra/timeline.ts +0 -138
  211. package/src/theme/recipes/chakra/toast.ts +0 -96
  212. package/src/theme/recipes/chakra/tooltip.ts +0 -40
  213. package/src/theme/recipes.ts +0 -46
  214. package/src/theme/semantic-tokens/colors.ts +0 -403
  215. package/src/theme/semantic-tokens/radii.ts +0 -7
  216. package/src/theme/semantic-tokens/shadows.ts +0 -52
  217. package/src/theme/slot-recipes.ts +0 -104
  218. package/src/theme/text-styles.ts +0 -39
  219. package/src/theme/tokens/animations.ts +0 -8
  220. package/src/theme/tokens/aspect-ratios.ts +0 -10
  221. package/src/theme/tokens/blurs.ts +0 -12
  222. package/src/theme/tokens/borders.ts +0 -9
  223. package/src/theme/tokens/colors.ts +0 -177
  224. package/src/theme/tokens/cursor.ts +0 -12
  225. package/src/theme/tokens/durations.ts +0 -11
  226. package/src/theme/tokens/easings.ts +0 -10
  227. package/src/theme/tokens/font-sizes.ts +0 -20
  228. package/src/theme/tokens/font-weights.ts +0 -13
  229. package/src/theme/tokens/fonts.ts +0 -15
  230. package/src/theme/tokens/keyframes.ts +0 -173
  231. package/src/theme/tokens/letter-spacing.ts +0 -9
  232. package/src/theme/tokens/line-heights.ts +0 -19
  233. package/src/theme/tokens/radius.ts +0 -18
  234. package/src/theme/tokens/sizes.ts +0 -71
  235. package/src/theme/tokens/spacing.ts +0 -38
  236. package/src/theme/tokens/z-indices.ts +0 -34
  237. package/src/theme/utils.ts +0 -46
@@ -1,435 +0,0 @@
1
- import React, { type HTMLProps, forwardRef } from 'react'
2
-
3
- import {
4
- Box,
5
- Button,
6
- Container,
7
- Drawer,
8
- HStack,
9
- Menu,
10
- Skeleton as SkeletonPrimitive,
11
- type SkeletonProps,
12
- Stack,
13
- useDisclosure,
14
- } from '@chakra-ui/react'
15
- import { SaasUIIcon } from '@saas-ui/assets'
16
- import { Meta, StoryObj } from '@storybook/react'
17
- import { LuMenu as FiMenu, LuX as FiX, LuX } from 'react-icons/lu'
18
-
19
- import { AppShell } from '../app-shell'
20
- import { Persona } from '../persona'
21
- import { SearchInput } from '../search-input'
22
- import { Navbar } from './index.ts'
23
-
24
- export default {
25
- title: 'Components/Navbar',
26
- parameters: {
27
- layout: 'fullscreen',
28
- },
29
- argTypes: {
30
- position: {
31
- control: {
32
- type: 'select',
33
- },
34
- options: ['static', 'fixed'],
35
- },
36
- maxWidth: {
37
- control: {
38
- type: 'select',
39
- },
40
- options: ['sm', 'md', 'lg', 'xl', '2xl', 'full'],
41
- },
42
- },
43
- } as Meta
44
-
45
- type Story = StoryObj<typeof Navbar.Root>
46
-
47
- const AppLogo = () => <SaasUIIcon width="28px" height="28px" />
48
-
49
- const Link = forwardRef<HTMLAnchorElement, HTMLProps<HTMLAnchorElement>>(
50
- ({ children, ...props }, ref) => {
51
- return (
52
- <Link ref={ref} onClick={(e) => e.preventDefault()} {...props}>
53
- {children}
54
- </Link>
55
- )
56
- },
57
- )
58
-
59
- export interface SkeletonTextProps extends SkeletonProps {
60
- noOfLines?: number
61
- }
62
-
63
- const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(
64
- function Skeleton(props, ref) {
65
- return (
66
- <SkeletonPrimitive ref={ref} variant="none" bg="bg.subtle" {...props} />
67
- )
68
- },
69
- )
70
-
71
- const SkeletonText = forwardRef<HTMLDivElement, SkeletonTextProps>(
72
- function SkeletonText(props, ref) {
73
- const { noOfLines = 3, gap, ...rest } = props
74
- return (
75
- <Stack gap={gap} width="full" ref={ref}>
76
- {Array.from({ length: noOfLines }).map((_, index) => (
77
- <SkeletonPrimitive
78
- height="4"
79
- key={index}
80
- _last={{ maxW: '80%' }}
81
- variant="none"
82
- bg="bg.subtle"
83
- {...rest}
84
- />
85
- ))}
86
- </Stack>
87
- )
88
- },
89
- )
90
-
91
- const App = React.forwardRef(({ children, navbar }: any, ref: any) => {
92
- return (
93
- <AppShell header={navbar}>
94
- <Box ref={ref} height="100%" width="100%" overflowY="auto">
95
- {children}
96
- <Container
97
- maxW="container.xl"
98
- pt="8"
99
- px="8"
100
- display="flex"
101
- flexDirection="column"
102
- margin="0 auto"
103
- >
104
- <Stack gap="4" mb="14">
105
- <Skeleton width="100px" height="24px" />
106
- </Stack>
107
- <Stack direction="row" gap="8" mb="14">
108
- <Stack gap="4" flex="1">
109
- <Skeleton width="100px" height="20px" />
110
- <SkeletonText />
111
- </Stack>
112
- <Stack gap="4" flex="1">
113
- <Skeleton width="100px" height="20px" />
114
- <SkeletonText />
115
- </Stack>
116
- </Stack>
117
- <Stack direction="row" gap="8">
118
- <Stack gap="4" flex="1">
119
- <Skeleton width="100px" height="20px" />
120
- <SkeletonText />
121
- </Stack>
122
- <Stack gap="4" flex="1">
123
- <Skeleton width="100px" height="20px" />
124
- <SkeletonText />
125
- </Stack>
126
- </Stack>
127
- </Container>
128
- </Box>
129
- </AppShell>
130
- )
131
- })
132
-
133
- App.displayName = 'App'
134
-
135
- const Template = (args: Navbar.RootProps) => {
136
- const parentRef = React.useRef(null)
137
-
138
- return (
139
- <App ref={parentRef}>
140
- <Navbar.Root {...args} parentRef={parentRef}>
141
- <Navbar.Content>
142
- <Navbar.Brand>
143
- <AppLogo />
144
- </Navbar.Brand>
145
- <HStack display={{ base: 'hidden', md: 'flex' }}>
146
- <Navbar.Item asChild>
147
- <Link href="#">Features</Link>
148
- </Navbar.Item>
149
- <Navbar.Item active asChild>
150
- <Link href="#">Customers</Link>
151
- </Navbar.Item>
152
- <Navbar.Item asChild>
153
- <Link href="#">Integrations</Link>
154
- </Navbar.Item>
155
- <Navbar.Item asChild>
156
- <Link href="#">Pricing</Link>
157
- </Navbar.Item>
158
- </HStack>
159
- <HStack justifyContent="end" gap="2">
160
- <Navbar.Item asChild>
161
- <Link href="#">Login</Link>
162
- </Navbar.Item>
163
- <Button variant="solid" asChild>
164
- <Link href="#">Sign Up</Link>
165
- </Button>
166
- </HStack>
167
- </Navbar.Content>
168
- </Navbar.Root>
169
- </App>
170
- )
171
- }
172
-
173
- const WithMenuTemplate = (args: Navbar.RootProps) => {
174
- const parentRef = React.useRef(null)
175
- const mobileNav = useDisclosure()
176
- const menuItems = ['Features', 'Customers', 'Integrations', 'Pricing']
177
-
178
- return (
179
- <App ref={parentRef}>
180
- <Navbar.Root parentRef={parentRef} position="sticky" {...args}>
181
- <Navbar.Content>
182
- <Navbar.Brand>
183
- <AppLogo />
184
- </Navbar.Brand>
185
-
186
- <HStack display={{ base: 'none', sm: 'flex' }}>
187
- <Navbar.Item asChild>
188
- <Link href="#">Features</Link>
189
- </Navbar.Item>
190
- <Navbar.Item active asChild>
191
- <Link href="#">Customers</Link>
192
- </Navbar.Item>
193
- <Navbar.Item asChild>
194
- <Link href="#">Integrations</Link>
195
- </Navbar.Item>
196
- <Navbar.Item asChild>
197
- <Link href="#">Pricing</Link>
198
- </Navbar.Item>
199
- </HStack>
200
-
201
- <HStack justifyContent="end" gap="2">
202
- <Navbar.Item asChild>
203
- <Link href="#">Login</Link>
204
- </Navbar.Item>
205
-
206
- <Button variant="solid" asChild>
207
- <Link href="#">Sign Up</Link>
208
- </Button>
209
-
210
- <Button
211
- aria-label={mobileNav.open ? 'Close menu' : 'Open menu'}
212
- display={{ base: 'inline-flex', sm: 'none' }}
213
- onClick={mobileNav.onToggle}
214
- variant="ghost"
215
- >
216
- {mobileNav.open ? <FiX /> : <FiMenu />}
217
- </Button>
218
- </HStack>
219
- </Navbar.Content>
220
-
221
- <Drawer.Root open={mobileNav.open} onOpenChange={mobileNav.onToggle}>
222
- <Drawer.Backdrop />
223
- <Drawer.Content>
224
- <Drawer.Header>
225
- <Drawer.CloseTrigger>
226
- <Button variant="ghost">
227
- <LuX />
228
- </Button>
229
- </Drawer.CloseTrigger>
230
- </Drawer.Header>
231
- <Drawer.Body fontSize="md">
232
- <Stack direction="column" gap="4">
233
- {menuItems.map((item, index) => (
234
- <Navbar.Item key={`${item}-${index}`} width="full" asChild>
235
- <Link href="#">{item}</Link>
236
- </Navbar.Item>
237
- ))}
238
- </Stack>
239
- </Drawer.Body>
240
- </Drawer.Content>
241
- </Drawer.Root>
242
- </Navbar.Root>
243
- </App>
244
- )
245
- }
246
-
247
- const WithUserMenuTemplate = (args: Navbar.RootProps) => {
248
- return (
249
- <App>
250
- <Navbar.Root {...args}>
251
- <Navbar.Content>
252
- <Navbar.Brand>
253
- <AppLogo />
254
- </Navbar.Brand>
255
-
256
- <HStack display={{ base: 'hidden', sm: 'flex' }}>
257
- <Navbar.Item asChild active>
258
- <Link href="#">Inbox</Link>
259
- </Navbar.Item>
260
- <Navbar.Item asChild>
261
- <Link href="#">Contacts</Link>
262
- </Navbar.Item>
263
- <Navbar.Item asChild>
264
- <Link href="#">Tasks</Link>
265
- </Navbar.Item>
266
- </HStack>
267
-
268
- <Box>
269
- <Menu.Root>
270
- <Menu.Trigger>
271
- <Persona.Avatar
272
- src="/showcase-avatar.jpg"
273
- name="Beatriz"
274
- size="xs"
275
- >
276
- <Persona.PresenceBadge presence="online" />
277
- </Persona.Avatar>
278
- </Menu.Trigger>
279
- <Menu.Content>
280
- <Menu.ItemGroup title="beatriz@saas-ui.dev">
281
- <Menu.Item value="profile" asChild>
282
- <Link href="#">Profile</Link>
283
- </Menu.Item>
284
- <Menu.Item value="settings" asChild>
285
- <Link href="#">Settings</Link>
286
- </Menu.Item>
287
- <Menu.Item value="help" asChild>
288
- <Link href="#">Help & feedback</Link>
289
- </Menu.Item>
290
- </Menu.ItemGroup>
291
- <Menu.Separator />
292
- <Menu.Item value="logout" asChild>
293
- <Link href="#">Log out</Link>
294
- </Menu.Item>
295
- </Menu.Content>
296
- </Menu.Root>
297
- </Box>
298
- </Navbar.Content>
299
- </Navbar.Root>
300
- </App>
301
- )
302
- }
303
-
304
- const WithSearchInputTemplate = (args: Navbar.RootProps) => {
305
- return (
306
- <App>
307
- <Navbar.Root {...args}>
308
- <Navbar.Content>
309
- <Navbar.Brand>
310
- <AppLogo />
311
- </Navbar.Brand>
312
-
313
- <HStack display={{ base: 'hidden', sm: 'flex' }} gap="1">
314
- <Navbar.Item asChild>
315
- <Link href="#">Inbox</Link>
316
- </Navbar.Item>
317
- <Navbar.Item active asChild>
318
- <Link href="#">Contacts</Link>
319
- </Navbar.Item>
320
- <Navbar.Item asChild>
321
- <Link href="#">Tasks</Link>
322
- </Navbar.Item>
323
- </HStack>
324
-
325
- <HStack gap="4">
326
- <Box width="180px">
327
- <SearchInput size="sm" />
328
- </Box>
329
- <Menu.Root>
330
- <Menu.Trigger>
331
- <Persona.Avatar
332
- src="/showcase-avatar.jpg"
333
- name="Beatriz"
334
- size="xs"
335
- >
336
- <Persona.PresenceBadge presence="online" />
337
- </Persona.Avatar>
338
- </Menu.Trigger>
339
- <Menu.Content>
340
- <Menu.ItemGroup title="beatriz@saas-ui.dev">
341
- <Menu.Item value="profile" asChild>
342
- <Link href="#">Profile</Link>
343
- </Menu.Item>
344
- <Menu.Item value="settings" asChild>
345
- <Link href="#">Settings</Link>
346
- </Menu.Item>
347
- <Menu.Item value="help" asChild>
348
- <Link href="#">Help & feedback</Link>
349
- </Menu.Item>
350
- </Menu.ItemGroup>
351
- <Menu.Separator />
352
- <Menu.Item value="logout" asChild>
353
- <Link href="#">Log out</Link>
354
- </Menu.Item>
355
- </Menu.Content>
356
- </Menu.Root>
357
- </HStack>
358
- </Navbar.Content>
359
- </Navbar.Root>
360
- </App>
361
- )
362
- }
363
-
364
- export const Static: Story = {
365
- render: Template,
366
-
367
- args: {
368
- position: 'static',
369
- },
370
- }
371
-
372
- export const Sticky: Story = {
373
- render: Template,
374
-
375
- args: {
376
- position: 'sticky',
377
- },
378
- }
379
-
380
- export const Border: Story = {
381
- render: Template,
382
-
383
- args: {
384
- position: 'sticky',
385
- borderBottomWidth: '1px',
386
- },
387
- }
388
-
389
- export const BlurredBg: Story = {
390
- render: Template,
391
-
392
- args: {
393
- position: 'sticky',
394
- borderBottomWidth: '1px',
395
- background: 'transparent',
396
- backdropFilter: 'blur(4px)',
397
- },
398
- }
399
-
400
- export const Shadow: Story = {
401
- render: Template,
402
-
403
- args: {
404
- position: 'sticky',
405
- background: 'transparent',
406
- backdropFilter: 'blur(4px)',
407
- css: {
408
- '&:not([data-at-top])': {
409
- borderBottomWidth: '1px',
410
- boxShadow: 'lg',
411
- },
412
- },
413
- },
414
- }
415
-
416
- export const HideOnScroll: Story = {
417
- render: Template,
418
-
419
- args: {
420
- position: 'sticky',
421
- shouldHideOnScroll: true,
422
- },
423
- }
424
-
425
- export const WithMenu: Story = {
426
- render: WithMenuTemplate,
427
- }
428
-
429
- export const WithUserMenu: Story = {
430
- render: WithUserMenuTemplate,
431
- }
432
-
433
- export const WithSearchInput: Story = {
434
- render: WithSearchInputTemplate,
435
- }
@@ -1,49 +0,0 @@
1
- import * as React from 'react'
2
- import { render, testStories } from '@saas-ui/test-utils'
3
-
4
- import { Navbar, NavbarBrand, NavbarItem, NavbarContent } from './index'
5
-
6
- import * as stories from './navbar.stories'
7
-
8
- testStories<typeof stories>(stories)
9
-
10
- describe('Navbar', () => {
11
- it('should render correctly', () => {
12
- const wrapper = render(<Navbar />)
13
-
14
- expect(() => wrapper.unmount()).not.toThrow()
15
- })
16
-
17
- it('ref should be forwarded', () => {
18
- const ref = React.createRef<HTMLDivElement>()
19
-
20
- render(<Navbar ref={ref} />)
21
- expect(ref.current).not.toBeNull()
22
- })
23
-
24
- it('should render correctly with brand', () => {
25
- const wrapper = render(
26
- <Navbar>
27
- <NavbarBrand data-testid="navbar-test">Saas UI</NavbarBrand>
28
- </Navbar>
29
- )
30
-
31
- expect(wrapper.getByTestId('navbar-test')).toBeInTheDocument()
32
- })
33
-
34
- it('should render correctly content children', () => {
35
- const wrapper = render(
36
- <Navbar>
37
- <NavbarContent data-testid="navbar-content-test">
38
- <NavbarItem>Dashboard</NavbarItem>
39
- <NavbarItem>Contacts</NavbarItem>
40
- <NavbarItem>Settings</NavbarItem>
41
- </NavbarContent>
42
- </Navbar>
43
- )
44
-
45
- const navbarContent = wrapper.getByTestId('navbar-content-test')
46
-
47
- expect(navbarContent.children.length).toBe(3)
48
- })
49
- })
@@ -1,39 +0,0 @@
1
- import type { HTMLChakraProps } from '@chakra-ui/react'
2
- import { createSlotRecipeContext } from '@chakra-ui/react'
3
- import { Navbar } from '@saas-ui/core/navbar'
4
-
5
- const {
6
- withProvider,
7
- withContext,
8
- useStyles: useNavbarStyles,
9
- } = createSlotRecipeContext({
10
- key: 'navbar',
11
- })
12
-
13
- export { useNavbarStyles }
14
-
15
- export interface NavbarRootProps
16
- extends Navbar.RootProps,
17
- Omit<HTMLChakraProps<'div'>, keyof Navbar.RootProps> {}
18
-
19
- export const NavbarRoot = withProvider<HTMLDivElement, NavbarRootProps>(
20
- Navbar.Root,
21
- 'root',
22
- )
23
-
24
- export const NavbarBrand = withContext(Navbar.Brand, 'brand')
25
-
26
- export const NavbarContent = withContext<
27
- HTMLDivElement,
28
- HTMLChakraProps<'div'>
29
- >(Navbar.Content, 'content')
30
-
31
- export const NavbarItem = withContext<HTMLLIElement, HTMLChakraProps<'li'>>(
32
- Navbar.Item,
33
- 'item',
34
- )
35
-
36
- export const NavbarLink = withContext<HTMLAnchorElement, HTMLChakraProps<'a'>>(
37
- Navbar.Link,
38
- 'link',
39
- )
@@ -1,2 +0,0 @@
1
- export { NumberInput } from './number-input.tsx'
2
- export type { NumberInputProps } from './number-input.tsx'
@@ -1,41 +0,0 @@
1
- import { forwardRef } from 'react'
2
-
3
- import { NumberInput as ChakraNumberInput } from '@chakra-ui/react'
4
-
5
- import { InputGroup } from '#components/input-group/index.ts'
6
-
7
- export interface NumberInputProps
8
- extends Omit<ChakraNumberInput.RootProps, 'children'> {
9
- rootRef?: React.Ref<HTMLDivElement>
10
- hideControls?: boolean
11
- startElement?: React.ReactNode
12
- endElement?: React.ReactNode
13
- inputProps?: React.InputHTMLAttributes<HTMLInputElement>
14
- }
15
-
16
- export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
17
- function NumberInput(props, ref) {
18
- const {
19
- hideControls,
20
- startElement,
21
- endElement,
22
- inputProps,
23
- rootRef,
24
- ...rest
25
- } = props
26
- return (
27
- <ChakraNumberInput.Root ref={rootRef} {...rest}>
28
- <InputGroup startElement={startElement} endElement={endElement}>
29
- <ChakraNumberInput.Input ref={ref} {...inputProps} />
30
- </InputGroup>
31
-
32
- {!hideControls && !endElement ? (
33
- <ChakraNumberInput.Control>
34
- <ChakraNumberInput.IncrementTrigger />
35
- <ChakraNumberInput.DecrementTrigger />
36
- </ChakraNumberInput.Control>
37
- ) : null}
38
- </ChakraNumberInput.Root>
39
- )
40
- },
41
- )
@@ -1,2 +0,0 @@
1
- export { PasswordInput } from './password-input'
2
- export type { PasswordInputProps } from './password-input'
@@ -1,93 +0,0 @@
1
- 'use client'
2
-
3
- import { forwardRef, useRef } from 'react'
4
-
5
- import type { ButtonProps, GroupProps, InputProps } from '@chakra-ui/react'
6
- import {
7
- IconButton,
8
- Input,
9
- mergeRefs,
10
- useControllableState,
11
- } from '@chakra-ui/react'
12
- import { LuEye, LuEyeOff } from 'react-icons/lu'
13
-
14
- import { InputGroup } from '../input-group'
15
-
16
- export interface PasswordInputProps
17
- extends InputProps,
18
- PasswordVisibilityProps {
19
- rootProps?: GroupProps
20
- }
21
-
22
- export const PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(
23
- function PasswordInput(props, ref) {
24
- const {
25
- rootProps,
26
- defaultVisible,
27
- visible: visibleProp,
28
- onVisibleChange,
29
- visibilityIcon = { on: <LuEye />, off: <LuEyeOff /> },
30
- ...rest
31
- } = props
32
-
33
- const [visible, setVisible] = useControllableState({
34
- value: visibleProp,
35
- defaultValue: defaultVisible || false,
36
- onChange: onVisibleChange,
37
- })
38
-
39
- const inputRef = useRef<HTMLInputElement>(null)
40
-
41
- return (
42
- <InputGroup
43
- width="full"
44
- endElement={
45
- <VisibilityTrigger
46
- disabled={rest.disabled}
47
- onPointerDown={(e) => {
48
- if (rest.disabled) return
49
- if (e.button !== 0) return
50
- e.preventDefault()
51
- setVisible(!visible)
52
- }}
53
- >
54
- {visible ? visibilityIcon.off : visibilityIcon.on}
55
- </VisibilityTrigger>
56
- }
57
- {...rootProps}
58
- >
59
- <Input
60
- {...rest}
61
- ref={mergeRefs(ref, inputRef)}
62
- type={visible ? 'text' : 'password'}
63
- />
64
- </InputGroup>
65
- )
66
- },
67
- )
68
-
69
- export interface PasswordVisibilityProps {
70
- defaultVisible?: boolean
71
- visible?: boolean
72
- onVisibleChange?: (visible: boolean) => void
73
- visibilityIcon?: { on: React.ReactNode; off: React.ReactNode }
74
- }
75
-
76
- const VisibilityTrigger = forwardRef<HTMLButtonElement, ButtonProps>(
77
- function VisibilityTrigger(props, ref) {
78
- return (
79
- <IconButton
80
- tabIndex={-1}
81
- ref={ref}
82
- me="-2"
83
- aspectRatio="square"
84
- size="sm"
85
- variant="ghost"
86
- colorPalette="gray"
87
- height="calc(100% - {spacing.2})"
88
- aria-label="Toggle password visibility"
89
- {...props}
90
- />
91
- )
92
- },
93
- )
@@ -1,2 +0,0 @@
1
- export { Persona, PersonaAvatar } from './persona.tsx'
2
- export type { PersonaProps, PersonaAvatarProps } from './persona.tsx'
@@ -1,18 +0,0 @@
1
- export {
2
- PersonaRoot as Root,
3
- PersonaAvatar as Avatar,
4
- PersonaPresenceBadge as PresenceBadge,
5
- PersonaDetails as Details,
6
- PersonaLabel as Label,
7
- PersonaSecondaryLabel as SecondaryLabel,
8
- PersonaTertiaryLabel as TertiaryLabel,
9
- } from './persona-primitive.tsx'
10
-
11
- export type {
12
- PersonaRootProps as RootProps,
13
- PersonaAvatarProps as AvatarProps,
14
- PersonaPresenceBadgeProps as PresenceBadgeProps,
15
- PersonaDetailsProps as DetailsProps,
16
- PersonaLabelProps as LabelProps,
17
- Presence,
18
- } from './persona-primitive.tsx'