@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.
- package/CHANGELOG.md +12 -0
- package/dist/components/app-shell/index.d.cts +1 -1
- package/dist/components/app-shell/index.d.ts +1 -1
- package/dist/components/navbar/index.d.cts +3 -3
- package/dist/components/navbar/index.d.ts +3 -3
- package/dist/components/persona/index.d.cts +1 -1
- package/dist/components/persona/index.d.ts +1 -1
- package/dist/components/sidebar/index.d.cts +12 -12
- package/dist/components/sidebar/index.d.ts +12 -12
- package/dist/index.cjs +2 -12
- package/dist/index.js +2 -12
- package/package.json +4 -6
- package/src/components/app-shell/app-shell.recipe.ts +0 -52
- package/src/components/app-shell/app-shell.stories.tsx +0 -51
- package/src/components/app-shell/app-shell.tsx +0 -94
- package/src/components/app-shell/index.ts +0 -3
- package/src/components/breadcrumbs/breadcrumb.stories.tsx +0 -17
- package/src/components/breadcrumbs/breadcrumb.tsx +0 -36
- package/src/components/breadcrumbs/index.ts +0 -1
- package/src/components/breadcrumbs/namespace.ts +0 -8
- package/src/components/button/button.recipe.ts +0 -182
- package/src/components/button/button.stories.tsx +0 -99
- package/src/components/button/button.tsx +0 -55
- package/src/components/button/index.ts +0 -2
- package/src/components/checkbox/checkbox.tsx +0 -26
- package/src/components/checkbox/index.ts +0 -2
- package/src/components/close-button/close-button.stories.tsx +0 -12
- package/src/components/close-button/close-button.tsx +0 -18
- package/src/components/close-button/index.ts +0 -2
- package/src/components/command/command.recipe.ts +0 -17
- package/src/components/command/command.stories.tsx +0 -47
- package/src/components/command/command.tsx +0 -50
- package/src/components/command/index.ts +0 -1
- package/src/components/dialog/dialog.tsx +0 -67
- package/src/components/dialog/index.ts +0 -1
- package/src/components/dialog/namespace.ts +0 -18
- package/src/components/drawer/drawer.tsx +0 -57
- package/src/components/drawer/index.ts +0 -3
- package/src/components/drawer/namespace.ts +0 -19
- package/src/components/grid-list/grid-list.recipe.ts +0 -113
- package/src/components/icon-badge/icon-badge.recipe.ts +0 -57
- package/src/components/icon-badge/icon-badge.stories.tsx +0 -38
- package/src/components/icon-badge/icon-badge.tsx +0 -59
- package/src/components/icon-badge/index.ts +0 -2
- package/src/components/icons/create-icon.tsx +0 -41
- package/src/components/icons/icons.tsx +0 -119
- package/src/components/icons/index.ts +0 -1
- package/src/components/input-group/index.ts +0 -1
- package/src/components/input-group/input-group.tsx +0 -46
- package/src/components/link/index.ts +0 -2
- package/src/components/link/link.stories.tsx +0 -17
- package/src/components/link/link.test.tsx +0 -33
- package/src/components/link/link.tsx +0 -27
- package/src/components/loading-overlay/index.ts +0 -1
- package/src/components/loading-overlay/loading-overlay.recipe.ts +0 -61
- package/src/components/loading-overlay/loading-overlay.stories.tsx +0 -68
- package/src/components/loading-overlay/loading-overlay.tsx +0 -54
- package/src/components/loading-overlay/namespace.ts +0 -7
- package/src/components/navbar/index.ts +0 -1
- package/src/components/navbar/namespace.ts +0 -9
- package/src/components/navbar/navbar.recipe.ts +0 -109
- package/src/components/navbar/navbar.stories.tsx +0 -435
- package/src/components/navbar/navbar.test.tsx +0 -49
- package/src/components/navbar/navbar.tsx +0 -39
- package/src/components/number-input/index.ts +0 -2
- package/src/components/number-input/number-input.tsx +0 -41
- package/src/components/password-input/index.ts +0 -2
- package/src/components/password-input/password-input.tsx +0 -93
- package/src/components/persona/index.ts +0 -2
- package/src/components/persona/namespace.ts +0 -18
- package/src/components/persona/persona-primitive.tsx +0 -220
- package/src/components/persona/persona.recipe.ts +0 -94
- package/src/components/persona/persona.stories.tsx +0 -101
- package/src/components/persona/persona.tsx +0 -142
- package/src/components/pin-input/index.ts +0 -2
- package/src/components/pin-input/pin-input.tsx +0 -36
- package/src/components/radio/index.ts +0 -2
- package/src/components/radio/radio.tsx +0 -27
- package/src/components/search-input/index.ts +0 -2
- package/src/components/search-input/search-input.stories.tsx +0 -63
- package/src/components/search-input/search-input.tsx +0 -134
- package/src/components/select/index.ts +0 -1
- package/src/components/select/namespace.ts +0 -18
- package/src/components/select/select.tsx +0 -135
- package/src/components/sidebar/index.ts +0 -7
- package/src/components/sidebar/namespace.ts +0 -27
- package/src/components/sidebar/sidebar-item.recipe.ts +0 -65
- package/src/components/sidebar/sidebar.recipe.ts +0 -237
- package/src/components/sidebar/sidebar.stories.tsx +0 -903
- package/src/components/sidebar/sidebar.tsx +0 -208
- package/src/components/spinner/index.ts +0 -2
- package/src/components/spinner/spinner.stories.tsx +0 -19
- package/src/components/spinner/spinner.tsx +0 -21
- package/src/components/steps/index.ts +0 -1
- package/src/components/steps/namespace.ts +0 -16
- package/src/components/steps/steps.tsx +0 -82
- package/src/components/switch/index.ts +0 -3
- package/src/components/switch/switch.tsx +0 -39
- package/src/compositions/accordion.tsx +0 -47
- package/src/compositions/action-bar.tsx +0 -40
- package/src/compositions/alert.tsx +0 -51
- package/src/compositions/avatar.tsx +0 -74
- package/src/compositions/blockquote.tsx +0 -31
- package/src/compositions/checkbox-card.tsx +0 -57
- package/src/compositions/checkbox.tsx +0 -25
- package/src/compositions/clipboard.tsx +0 -107
- package/src/compositions/color-mode.tsx +0 -65
- package/src/compositions/data-list.tsx +0 -37
- package/src/compositions/empty-state.tsx +0 -34
- package/src/compositions/field.tsx +0 -33
- package/src/compositions/file-button.tsx +0 -166
- package/src/compositions/hover-card.tsx +0 -35
- package/src/compositions/link-button.tsx +0 -12
- package/src/compositions/menu.tsx +0 -108
- package/src/compositions/native-select.tsx +0 -57
- package/src/compositions/pagination.tsx +0 -207
- package/src/compositions/popover.tsx +0 -58
- package/src/compositions/progress-circle.tsx +0 -37
- package/src/compositions/progress.tsx +0 -40
- package/src/compositions/prose.tsx +0 -264
- package/src/compositions/provider.tsx +0 -12
- package/src/compositions/radio-card.tsx +0 -57
- package/src/compositions/radio.tsx +0 -24
- package/src/compositions/rating.tsx +0 -27
- package/src/compositions/segmented-control.tsx +0 -47
- package/src/compositions/skeleton.tsx +0 -44
- package/src/compositions/slider.tsx +0 -53
- package/src/compositions/stat.tsx +0 -75
- package/src/compositions/status.tsx +0 -29
- package/src/compositions/stepper-input.tsx +0 -49
- package/src/compositions/tag.tsx +0 -39
- package/src/compositions/timeline.tsx +0 -17
- package/src/compositions/toaster.tsx +0 -43
- package/src/compositions/toggle-tip.tsx +0 -62
- package/src/compositions/tooltip.tsx +0 -46
- package/src/index.ts +0 -7
- package/src/preset.ts +0 -9
- package/src/provider/index.ts +0 -4
- package/src/provider/sui-provider.tsx +0 -34
- package/src/provider/use-link.test.tsx +0 -60
- package/src/provider/use-link.tsx +0 -13
- package/src/styled-system/create-recipe-context.tsx +0 -91
- package/src/styled-system/create-slot-recipe-context.tsx +0 -188
- package/src/styled-system/empty.ts +0 -7
- package/src/styled-system/factory.types.ts +0 -11
- package/src/theme/animation-styles.ts +0 -53
- package/src/theme/breakpoints.ts +0 -11
- package/src/theme/conditions.ts +0 -26
- package/src/theme/fluid-font-sizes.ts +0 -65
- package/src/theme/global-css.ts +0 -94
- package/src/theme/index.ts +0 -72
- package/src/theme/layer-styles.ts +0 -116
- package/src/theme/recipes/chakra/accordion.ts +0 -145
- package/src/theme/recipes/chakra/action-bar.ts +0 -62
- package/src/theme/recipes/chakra/alert.ts +0 -157
- package/src/theme/recipes/chakra/avatar.ts +0 -141
- package/src/theme/recipes/chakra/badge.ts +0 -67
- package/src/theme/recipes/chakra/blockquote.ts +0 -83
- package/src/theme/recipes/chakra/breadcrumb.ts +0 -94
- package/src/theme/recipes/chakra/card.ts +0 -99
- package/src/theme/recipes/chakra/checkbox-card.ts +0 -212
- package/src/theme/recipes/chakra/checkbox.ts +0 -70
- package/src/theme/recipes/chakra/checkmark.ts +0 -83
- package/src/theme/recipes/chakra/code.ts +0 -17
- package/src/theme/recipes/chakra/collapsible.ts +0 -20
- package/src/theme/recipes/chakra/container.ts +0 -26
- package/src/theme/recipes/chakra/data-list.ts +0 -80
- package/src/theme/recipes/chakra/dialog.ts +0 -225
- package/src/theme/recipes/chakra/drawer.ts +0 -201
- package/src/theme/recipes/chakra/editable.ts +0 -88
- package/src/theme/recipes/chakra/empty-state.ts +0 -88
- package/src/theme/recipes/chakra/field.ts +0 -68
- package/src/theme/recipes/chakra/fieldset.ts +0 -62
- package/src/theme/recipes/chakra/file-upload.ts +0 -96
- package/src/theme/recipes/chakra/heading.ts +0 -27
- package/src/theme/recipes/chakra/hover-card.ts +0 -68
- package/src/theme/recipes/chakra/icon.ts +0 -30
- package/src/theme/recipes/chakra/input-addon.ts +0 -40
- package/src/theme/recipes/chakra/input.ts +0 -96
- package/src/theme/recipes/chakra/kbd.ts +0 -60
- package/src/theme/recipes/chakra/link.ts +0 -37
- package/src/theme/recipes/chakra/list.ts +0 -67
- package/src/theme/recipes/chakra/mark.ts +0 -27
- package/src/theme/recipes/chakra/menu.ts +0 -124
- package/src/theme/recipes/chakra/native-select.ts +0 -140
- package/src/theme/recipes/chakra/number-input.ts +0 -115
- package/src/theme/recipes/chakra/pin-input.ts +0 -27
- package/src/theme/recipes/chakra/popover.ts +0 -86
- package/src/theme/recipes/chakra/progress-circle.ts +0 -94
- package/src/theme/recipes/chakra/progress.ts +0 -127
- package/src/theme/recipes/chakra/radio-card.ts +0 -220
- package/src/theme/recipes/chakra/radio-group.ts +0 -72
- package/src/theme/recipes/chakra/radiomark.ts +0 -107
- package/src/theme/recipes/chakra/rating-group.ts +0 -94
- package/src/theme/recipes/chakra/segment-group.ts +0 -117
- package/src/theme/recipes/chakra/select.ts +0 -282
- package/src/theme/recipes/chakra/separator.ts +0 -51
- package/src/theme/recipes/chakra/skeleton.ts +0 -53
- package/src/theme/recipes/chakra/skip-nav-link.ts +0 -34
- package/src/theme/recipes/chakra/slider.ts +0 -178
- package/src/theme/recipes/chakra/spinner.ts +0 -32
- package/src/theme/recipes/chakra/stat.ts +0 -79
- package/src/theme/recipes/chakra/status.ts +0 -48
- package/src/theme/recipes/chakra/steps.ts +0 -218
- package/src/theme/recipes/chakra/switch.ts +0 -167
- package/src/theme/recipes/chakra/table.ts +0 -172
- package/src/theme/recipes/chakra/tabs.ts +0 -280
- package/src/theme/recipes/chakra/tag.ts +0 -131
- package/src/theme/recipes/chakra/textarea.ts +0 -88
- package/src/theme/recipes/chakra/timeline.ts +0 -138
- package/src/theme/recipes/chakra/toast.ts +0 -96
- package/src/theme/recipes/chakra/tooltip.ts +0 -40
- package/src/theme/recipes.ts +0 -46
- package/src/theme/semantic-tokens/colors.ts +0 -403
- package/src/theme/semantic-tokens/radii.ts +0 -7
- package/src/theme/semantic-tokens/shadows.ts +0 -52
- package/src/theme/slot-recipes.ts +0 -104
- package/src/theme/text-styles.ts +0 -39
- package/src/theme/tokens/animations.ts +0 -8
- package/src/theme/tokens/aspect-ratios.ts +0 -10
- package/src/theme/tokens/blurs.ts +0 -12
- package/src/theme/tokens/borders.ts +0 -9
- package/src/theme/tokens/colors.ts +0 -177
- package/src/theme/tokens/cursor.ts +0 -12
- package/src/theme/tokens/durations.ts +0 -11
- package/src/theme/tokens/easings.ts +0 -10
- package/src/theme/tokens/font-sizes.ts +0 -20
- package/src/theme/tokens/font-weights.ts +0 -13
- package/src/theme/tokens/fonts.ts +0 -15
- package/src/theme/tokens/keyframes.ts +0 -173
- package/src/theme/tokens/letter-spacing.ts +0 -9
- package/src/theme/tokens/line-heights.ts +0 -19
- package/src/theme/tokens/radius.ts +0 -18
- package/src/theme/tokens/sizes.ts +0 -71
- package/src/theme/tokens/spacing.ts +0 -38
- package/src/theme/tokens/z-indices.ts +0 -34
- 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,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,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,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'
|