@a2v2ai/uikit 0.0.36 → 0.0.38
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/Alert/Alert.stories.tsx +121 -0
- package/Alert/Alert.tsx +71 -0
- package/AlertDialog/AlertDialog.stories.tsx +665 -0
- package/AlertDialog/AlertDialog.tsx +241 -0
- package/Avatar/Avatar.stories.tsx +128 -0
- package/Avatar/Avatar.tsx +71 -0
- package/Badge/Badge.stories.tsx +76 -0
- package/Badge/Badge.tsx +39 -0
- package/Breadcrumb/Breadcrumb.stories.tsx +231 -0
- package/Breadcrumb/Breadcrumb.tsx +114 -0
- package/Button/Button.stories.tsx +684 -0
- package/Button/Button.tsx +107 -0
- package/Calendar/Calendar.stories.tsx +291 -0
- package/Calendar/Calendar.tsx +246 -0
- package/Card/Card.stories.tsx +136 -0
- package/Card/Card.tsx +96 -0
- package/Carousel/Carousel.stories.tsx +256 -0
- package/Carousel/Carousel.tsx +301 -0
- package/ChatBubble/ChatBubble.stories.tsx +339 -0
- package/ChatBubble/ChatBubble.tsx +179 -0
- package/Checkbox/Checkbox.stories.tsx +137 -0
- package/Checkbox/Checkbox.tsx +53 -0
- package/DataTable/DataTable.stories.tsx +400 -0
- package/DataTable/DataTable.tsx +207 -0
- package/Drawer/Drawer.stories.tsx +721 -0
- package/Drawer/Drawer.tsx +201 -0
- package/DropdownMenu/DropdownMenu.stories.tsx +251 -0
- package/DropdownMenu/DropdownMenu.tsx +199 -0
- package/ErrorMessage/ErrorMessage.stories.tsx +159 -0
- package/ErrorMessage/ErrorMessage.tsx +55 -0
- package/Flex/Flex.stories.tsx +390 -0
- package/Flex/Flex.tsx +102 -0
- package/IconButton/IconButton.stories.tsx +566 -0
- package/IconButton/IconButton.tsx +95 -0
- package/Input/Input.stories.tsx +566 -0
- package/Input/Input.tsx +168 -0
- package/InputOTP/InputOTP.stories.tsx +246 -0
- package/InputOTP/InputOTP.tsx +127 -0
- package/Label/Label.stories.tsx +110 -0
- package/Label/Label.tsx +44 -0
- package/Loader/Loader.stories.tsx +170 -0
- package/Loader/Loader.tsx +62 -0
- package/Menubar/Menubar.stories.tsx +382 -0
- package/Menubar/Menubar.tsx +274 -0
- package/Menubar/index.ts +18 -0
- package/Pagination/Pagination.stories.tsx +196 -0
- package/Pagination/Pagination.tsx +122 -0
- package/Popover/Popover.stories.tsx +133 -0
- package/Popover/Popover.tsx +31 -0
- package/Progress/Progress.stories.tsx +146 -0
- package/Progress/Progress.tsx +67 -0
- package/RadioGroup/RadioGroup.stories.tsx +159 -0
- package/RadioGroup/RadioGroup.tsx +68 -0
- package/ScrollArea/ScrollArea.stories.tsx +136 -0
- package/ScrollArea/ScrollArea.tsx +46 -0
- package/Select/Select.stories.tsx +378 -0
- package/Select/Select.tsx +230 -0
- package/Separator/Separator.stories.tsx +110 -0
- package/Separator/Separator.tsx +29 -0
- package/Sidebar/Sidebar.stories.tsx +340 -0
- package/Sidebar/Sidebar.tsx +414 -0
- package/Sidebar/index.ts +28 -0
- package/Skeleton/Skeleton.stories.tsx +117 -0
- package/Skeleton/Skeleton.tsx +16 -0
- package/Slider/Slider.stories.tsx +216 -0
- package/Slider/Slider.tsx +29 -0
- package/Spinner/Spinner.stories.tsx +210 -0
- package/Spinner/Spinner.tsx +78 -0
- package/Switch/Switch.stories.tsx +146 -0
- package/Switch/Switch.tsx +59 -0
- package/Table/Table.stories.tsx +510 -0
- package/Table/Table.tsx +114 -0
- package/Tabs/Tabs.stories.tsx +197 -0
- package/Tabs/Tabs.tsx +74 -0
- package/Textarea/Textarea.stories.tsx +187 -0
- package/Textarea/Textarea.tsx +73 -0
- package/Toast/Toast.stories.tsx +285 -0
- package/Toast/Toast.tsx +59 -0
- package/Tooltip/Tooltip.stories.tsx +463 -0
- package/Tooltip/Tooltip.tsx +96 -0
- package/Typography/Typography.stories.tsx +425 -0
- package/Typography/Typography.tsx +106 -0
- package/helpers.ts +5 -0
- package/{icons.js → icons.ts} +1 -1
- package/index.ts +217 -0
- package/lib/typography-types.ts +223 -0
- package/lib/utils.ts +15 -0
- package/package.json +36 -33
- package/tsconfig.json +22 -0
- package/Alert/Alert.d.ts +0 -13
- package/Alert/Alert.js +0 -25
- package/AlertDialog/AlertDialog.d.ts +0 -43
- package/AlertDialog/AlertDialog.js +0 -71
- package/Avatar/Avatar.d.ts +0 -14
- package/Avatar/Avatar.js +0 -25
- package/Badge/Badge.d.ts +0 -11
- package/Badge/Badge.js +0 -23
- package/Breadcrumb/Breadcrumb.d.ts +0 -19
- package/Breadcrumb/Breadcrumb.js +0 -23
- package/Button/Button.d.ts +0 -23
- package/Button/Button.js +0 -52
- package/Calendar/Calendar.d.ts +0 -20
- package/Calendar/Calendar.js +0 -78
- package/Card/Card.d.ts +0 -16
- package/Card/Card.js +0 -28
- package/Carousel/Carousel.d.ts +0 -37
- package/Carousel/Carousel.js +0 -132
- package/ChatBubble/ChatBubble.d.ts +0 -33
- package/ChatBubble/ChatBubble.js +0 -107
- package/Checkbox/Checkbox.d.ts +0 -12
- package/Checkbox/Checkbox.js +0 -20
- package/DataTable/DataTable.d.ts +0 -35
- package/DataTable/DataTable.js +0 -51
- package/Dialog/Dialog.d.ts +0 -35
- package/Dialog/Dialog.js +0 -130
- package/Drawer/Drawer.d.ts +0 -33
- package/Drawer/Drawer.js +0 -55
- package/DropdownMenu/DropdownMenu.d.ts +0 -27
- package/DropdownMenu/DropdownMenu.js +0 -35
- package/ErrorMessage/ErrorMessage.d.ts +0 -27
- package/ErrorMessage/ErrorMessage.js +0 -14
- package/Flex/Flex.d.ts +0 -31
- package/Flex/Flex.js +0 -64
- package/IconButton/IconButton.d.ts +0 -23
- package/IconButton/IconButton.js +0 -48
- package/Input/Input.d.ts +0 -27
- package/Input/Input.js +0 -42
- package/InputOTP/InputOTP.d.ts +0 -20
- package/InputOTP/InputOTP.js +0 -44
- package/Label/Label.d.ts +0 -13
- package/Label/Label.js +0 -19
- package/Loader/Loader.d.ts +0 -21
- package/Loader/Loader.js +0 -30
- package/Menubar/Menubar.d.ts +0 -26
- package/Menubar/Menubar.js +0 -54
- package/Menubar/index.d.ts +0 -1
- package/Menubar/index.js +0 -1
- package/Pagination/Pagination.d.ts +0 -35
- package/Pagination/Pagination.js +0 -37
- package/Popover/Popover.d.ts +0 -7
- package/Popover/Popover.js +0 -10
- package/Progress/Progress.d.ts +0 -17
- package/Progress/Progress.js +0 -33
- package/RadioGroup/RadioGroup.d.ts +0 -13
- package/RadioGroup/RadioGroup.js +0 -26
- package/ScrollArea/ScrollArea.d.ts +0 -5
- package/ScrollArea/ScrollArea.js +0 -11
- package/Select/Select.d.ts +0 -29
- package/Select/Select.js +0 -50
- package/Separator/Separator.d.ts +0 -4
- package/Separator/Separator.js +0 -7
- package/Sidebar/Sidebar.d.ts +0 -48
- package/Sidebar/Sidebar.js +0 -116
- package/Sidebar/index.d.ts +0 -2
- package/Sidebar/index.js +0 -1
- package/Skeleton/Skeleton.d.ts +0 -4
- package/Skeleton/Skeleton.js +0 -7
- package/Slider/Slider.d.ts +0 -6
- package/Slider/Slider.js +0 -7
- package/Spinner/Spinner.d.ts +0 -19
- package/Spinner/Spinner.js +0 -31
- package/Switch/Switch.d.ts +0 -12
- package/Switch/Switch.js +0 -30
- package/Table/Table.d.ts +0 -10
- package/Table/Table.js +0 -20
- package/Tabs/Tabs.d.ts +0 -15
- package/Tabs/Tabs.js +0 -24
- package/Textarea/Textarea.d.ts +0 -19
- package/Textarea/Textarea.js +0 -31
- package/Toast/Toast.d.ts +0 -12
- package/Toast/Toast.js +0 -25
- package/Tooltip/Tooltip.d.ts +0 -17
- package/Tooltip/Tooltip.js +0 -29
- package/Typography/Typography.d.ts +0 -20
- package/Typography/Typography.js +0 -43
- package/helpers.d.ts +0 -4
- package/helpers.js +0 -5
- package/icons.d.ts +0 -1
- package/index.d.ts +0 -42
- package/index.js +0 -45
- package/lib/typography-types.d.ts +0 -4
- package/lib/typography-types.js +0 -90
- package/lib/utils.d.ts +0 -3
- package/lib/utils.js +0 -14
- package/tmpclaude-2407-cwd +0 -1
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
+
import { ChevronDown, ChevronRight } from "lucide-react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "../lib/utils"
|
|
6
|
+
|
|
7
|
+
/* -----------------------------------------------------------------------------
|
|
8
|
+
* Context for Sidebar collapsed state
|
|
9
|
+
* -------------------------------------------------------------------------- */
|
|
10
|
+
|
|
11
|
+
interface SidebarContextValue {
|
|
12
|
+
collapsed: boolean
|
|
13
|
+
setCollapsed: (collapsed: boolean) => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const SidebarContext = React.createContext<SidebarContextValue | undefined>(undefined)
|
|
17
|
+
|
|
18
|
+
function useSidebar() {
|
|
19
|
+
const context = React.useContext(SidebarContext)
|
|
20
|
+
if (!context) {
|
|
21
|
+
throw new Error("useSidebar must be used within a Sidebar")
|
|
22
|
+
}
|
|
23
|
+
return context
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* -----------------------------------------------------------------------------
|
|
27
|
+
* Sidebar (Main Container)
|
|
28
|
+
* -------------------------------------------------------------------------- */
|
|
29
|
+
|
|
30
|
+
export interface SidebarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
31
|
+
collapsed?: boolean
|
|
32
|
+
onCollapsedChange?: (collapsed: boolean) => void
|
|
33
|
+
defaultCollapsed?: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const Sidebar = React.forwardRef<HTMLDivElement, SidebarProps>(
|
|
37
|
+
({ className, collapsed: controlledCollapsed, onCollapsedChange, defaultCollapsed = false, children, ...props }, ref) => {
|
|
38
|
+
const [uncontrolledCollapsed, setUncontrolledCollapsed] = React.useState(defaultCollapsed)
|
|
39
|
+
|
|
40
|
+
const isControlled = controlledCollapsed !== undefined
|
|
41
|
+
const collapsed = isControlled ? controlledCollapsed : uncontrolledCollapsed
|
|
42
|
+
|
|
43
|
+
const setCollapsed = React.useCallback((value: boolean) => {
|
|
44
|
+
if (!isControlled) {
|
|
45
|
+
setUncontrolledCollapsed(value)
|
|
46
|
+
}
|
|
47
|
+
onCollapsedChange?.(value)
|
|
48
|
+
}, [isControlled, onCollapsedChange])
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<SidebarContext.Provider value={{ collapsed, setCollapsed }}>
|
|
52
|
+
<div
|
|
53
|
+
ref={ref}
|
|
54
|
+
data-slot="sidebar"
|
|
55
|
+
data-collapsed={collapsed}
|
|
56
|
+
className={cn(
|
|
57
|
+
"flex h-full flex-col bg-white border-r border-grey-200 transition-all duration-300",
|
|
58
|
+
collapsed ? "w-[52px]" : "w-[240px]",
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
</div>
|
|
65
|
+
</SidebarContext.Provider>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
Sidebar.displayName = "Sidebar"
|
|
70
|
+
|
|
71
|
+
/* -----------------------------------------------------------------------------
|
|
72
|
+
* SidebarHeader
|
|
73
|
+
* -------------------------------------------------------------------------- */
|
|
74
|
+
|
|
75
|
+
export type SidebarHeaderProps = React.HTMLAttributes<HTMLDivElement>
|
|
76
|
+
|
|
77
|
+
const SidebarHeader = React.forwardRef<HTMLDivElement, SidebarHeaderProps>(
|
|
78
|
+
({ className, children, ...props }, ref) => {
|
|
79
|
+
const { collapsed } = useSidebar()
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<div
|
|
83
|
+
ref={ref}
|
|
84
|
+
data-slot="sidebar-header"
|
|
85
|
+
className={cn(
|
|
86
|
+
"flex shrink-0 items-center",
|
|
87
|
+
collapsed ? "justify-center p-2" : "p-4",
|
|
88
|
+
className
|
|
89
|
+
)}
|
|
90
|
+
{...props}
|
|
91
|
+
>
|
|
92
|
+
{children}
|
|
93
|
+
</div>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
SidebarHeader.displayName = "SidebarHeader"
|
|
98
|
+
|
|
99
|
+
/* -----------------------------------------------------------------------------
|
|
100
|
+
* SidebarContent
|
|
101
|
+
* -------------------------------------------------------------------------- */
|
|
102
|
+
|
|
103
|
+
export type SidebarContentProps = React.HTMLAttributes<HTMLDivElement>
|
|
104
|
+
|
|
105
|
+
const SidebarContent = React.forwardRef<HTMLDivElement, SidebarContentProps>(
|
|
106
|
+
({ className, children, ...props }, ref) => {
|
|
107
|
+
const { collapsed } = useSidebar()
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<div
|
|
111
|
+
ref={ref}
|
|
112
|
+
data-slot="sidebar-content"
|
|
113
|
+
className={cn(
|
|
114
|
+
"flex-1 overflow-y-auto",
|
|
115
|
+
collapsed ? "px-2 py-4" : "p-4",
|
|
116
|
+
className
|
|
117
|
+
)}
|
|
118
|
+
{...props}
|
|
119
|
+
>
|
|
120
|
+
{children}
|
|
121
|
+
</div>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
SidebarContent.displayName = "SidebarContent"
|
|
126
|
+
|
|
127
|
+
/* -----------------------------------------------------------------------------
|
|
128
|
+
* SidebarFooter
|
|
129
|
+
* -------------------------------------------------------------------------- */
|
|
130
|
+
|
|
131
|
+
export type SidebarFooterProps = React.HTMLAttributes<HTMLDivElement>
|
|
132
|
+
|
|
133
|
+
const SidebarFooter = React.forwardRef<HTMLDivElement, SidebarFooterProps>(
|
|
134
|
+
({ className, children, ...props }, ref) => {
|
|
135
|
+
const { collapsed } = useSidebar()
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<div
|
|
139
|
+
ref={ref}
|
|
140
|
+
data-slot="sidebar-footer"
|
|
141
|
+
className={cn(
|
|
142
|
+
"flex shrink-0 items-center border-t border-grey-200",
|
|
143
|
+
collapsed ? "justify-center p-2" : "p-4",
|
|
144
|
+
className
|
|
145
|
+
)}
|
|
146
|
+
{...props}
|
|
147
|
+
>
|
|
148
|
+
{children}
|
|
149
|
+
</div>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
SidebarFooter.displayName = "SidebarFooter"
|
|
154
|
+
|
|
155
|
+
/* -----------------------------------------------------------------------------
|
|
156
|
+
* SidebarGroup
|
|
157
|
+
* -------------------------------------------------------------------------- */
|
|
158
|
+
|
|
159
|
+
export type SidebarGroupProps = React.HTMLAttributes<HTMLDivElement>
|
|
160
|
+
|
|
161
|
+
const SidebarGroup = React.forwardRef<HTMLDivElement, SidebarGroupProps>(
|
|
162
|
+
({ className, children, ...props }, ref) => {
|
|
163
|
+
const { collapsed } = useSidebar()
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<div
|
|
167
|
+
ref={ref}
|
|
168
|
+
data-slot="sidebar-group"
|
|
169
|
+
className={cn(
|
|
170
|
+
"flex flex-col",
|
|
171
|
+
collapsed ? "gap-1" : "gap-0.5",
|
|
172
|
+
className
|
|
173
|
+
)}
|
|
174
|
+
{...props}
|
|
175
|
+
>
|
|
176
|
+
{children}
|
|
177
|
+
</div>
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
)
|
|
181
|
+
SidebarGroup.displayName = "SidebarGroup"
|
|
182
|
+
|
|
183
|
+
/* -----------------------------------------------------------------------------
|
|
184
|
+
* SidebarGroupLabel
|
|
185
|
+
* -------------------------------------------------------------------------- */
|
|
186
|
+
|
|
187
|
+
export type SidebarGroupLabelProps = React.HTMLAttributes<HTMLDivElement>
|
|
188
|
+
|
|
189
|
+
const SidebarGroupLabel = React.forwardRef<HTMLDivElement, SidebarGroupLabelProps>(
|
|
190
|
+
({ className, children, ...props }, ref) => {
|
|
191
|
+
const { collapsed } = useSidebar()
|
|
192
|
+
|
|
193
|
+
if (collapsed) return null
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<div
|
|
197
|
+
ref={ref}
|
|
198
|
+
data-slot="sidebar-group-label"
|
|
199
|
+
className={cn(
|
|
200
|
+
"px-3 py-2 text-xs font-normal text-grey-500",
|
|
201
|
+
className
|
|
202
|
+
)}
|
|
203
|
+
{...props}
|
|
204
|
+
>
|
|
205
|
+
{children}
|
|
206
|
+
</div>
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
)
|
|
210
|
+
SidebarGroupLabel.displayName = "SidebarGroupLabel"
|
|
211
|
+
|
|
212
|
+
/* -----------------------------------------------------------------------------
|
|
213
|
+
* SidebarMenuItem
|
|
214
|
+
* -------------------------------------------------------------------------- */
|
|
215
|
+
|
|
216
|
+
const sidebarMenuItemVariants = cva(
|
|
217
|
+
"flex items-center gap-2 px-3 py-2 rounded-md text-sm font-normal cursor-pointer transition-colors outline-none",
|
|
218
|
+
{
|
|
219
|
+
variants: {
|
|
220
|
+
active: {
|
|
221
|
+
true: "bg-grey-100 text-grey-900",
|
|
222
|
+
false: "text-grey-600 hover:bg-grey-50",
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
defaultVariants: {
|
|
226
|
+
active: false,
|
|
227
|
+
},
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
export interface SidebarMenuItemProps
|
|
232
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
233
|
+
VariantProps<typeof sidebarMenuItemVariants> {
|
|
234
|
+
icon?: React.ReactNode
|
|
235
|
+
label: string
|
|
236
|
+
labelClassName?: string
|
|
237
|
+
badge?: React.ReactNode
|
|
238
|
+
hasChildren?: boolean
|
|
239
|
+
expanded?: boolean
|
|
240
|
+
onExpandedChange?: (expanded: boolean) => void
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const SidebarMenuItem = React.forwardRef<HTMLDivElement, SidebarMenuItemProps>(
|
|
244
|
+
({ className, icon, label, labelClassName, badge, active, hasChildren, expanded, onExpandedChange, children, onClick, ...props }, ref) => {
|
|
245
|
+
const { collapsed } = useSidebar()
|
|
246
|
+
const [internalExpanded, setInternalExpanded] = React.useState(expanded ?? false)
|
|
247
|
+
|
|
248
|
+
const isExpanded = expanded !== undefined ? expanded : internalExpanded
|
|
249
|
+
|
|
250
|
+
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
251
|
+
if (hasChildren) {
|
|
252
|
+
const newExpanded = !isExpanded
|
|
253
|
+
setInternalExpanded(newExpanded)
|
|
254
|
+
onExpandedChange?.(newExpanded)
|
|
255
|
+
}
|
|
256
|
+
onClick?.(e)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (collapsed) {
|
|
260
|
+
return (
|
|
261
|
+
<div
|
|
262
|
+
ref={ref}
|
|
263
|
+
data-slot="sidebar-menu-item"
|
|
264
|
+
className={cn(
|
|
265
|
+
"flex items-center justify-center size-9 rounded-lg cursor-pointer transition-colors mx-auto",
|
|
266
|
+
active ? "bg-grey-100 text-grey-900" : "text-grey-600 hover:bg-grey-50",
|
|
267
|
+
className
|
|
268
|
+
)}
|
|
269
|
+
onClick={onClick}
|
|
270
|
+
{...props}
|
|
271
|
+
>
|
|
272
|
+
{icon && <span className="size-4">{icon}</span>}
|
|
273
|
+
</div>
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return (
|
|
278
|
+
<div data-slot="sidebar-menu-item-wrapper">
|
|
279
|
+
<div
|
|
280
|
+
ref={ref}
|
|
281
|
+
data-slot="sidebar-menu-item"
|
|
282
|
+
className={cn(sidebarMenuItemVariants({ active }), className)}
|
|
283
|
+
onClick={handleClick}
|
|
284
|
+
{...props}
|
|
285
|
+
>
|
|
286
|
+
{icon && <span className="size-4 shrink-0">{icon}</span>}
|
|
287
|
+
<span className={cn("flex-1 truncate", labelClassName)}>{label}</span>
|
|
288
|
+
{badge && <span className="shrink-0">{badge}</span>}
|
|
289
|
+
{hasChildren && (
|
|
290
|
+
<span className="size-4 shrink-0 text-grey-400">
|
|
291
|
+
{isExpanded ? <ChevronDown className="size-4" /> : <ChevronRight className="size-4" />}
|
|
292
|
+
</span>
|
|
293
|
+
)}
|
|
294
|
+
</div>
|
|
295
|
+
{hasChildren && isExpanded && children && (
|
|
296
|
+
<div className="ml-6 mt-1 flex flex-col">
|
|
297
|
+
{children}
|
|
298
|
+
</div>
|
|
299
|
+
)}
|
|
300
|
+
</div>
|
|
301
|
+
)
|
|
302
|
+
}
|
|
303
|
+
)
|
|
304
|
+
SidebarMenuItem.displayName = "SidebarMenuItem"
|
|
305
|
+
|
|
306
|
+
/* -----------------------------------------------------------------------------
|
|
307
|
+
* SidebarSubMenuItem
|
|
308
|
+
* -------------------------------------------------------------------------- */
|
|
309
|
+
|
|
310
|
+
const sidebarSubMenuItemVariants = cva(
|
|
311
|
+
"flex items-center px-3 py-2 rounded-md text-sm font-normal cursor-pointer transition-colors outline-none",
|
|
312
|
+
{
|
|
313
|
+
variants: {
|
|
314
|
+
active: {
|
|
315
|
+
true: "bg-grey-100 text-grey-900",
|
|
316
|
+
false: "text-grey-500 hover:bg-grey-50 hover:text-grey-700",
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
defaultVariants: {
|
|
320
|
+
active: false,
|
|
321
|
+
},
|
|
322
|
+
}
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
export interface SidebarSubMenuItemProps
|
|
326
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
327
|
+
VariantProps<typeof sidebarSubMenuItemVariants> {
|
|
328
|
+
label: string
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const SidebarSubMenuItem = React.forwardRef<HTMLDivElement, SidebarSubMenuItemProps>(
|
|
332
|
+
({ className, label, active, ...props }, ref) => {
|
|
333
|
+
return (
|
|
334
|
+
<div
|
|
335
|
+
ref={ref}
|
|
336
|
+
data-slot="sidebar-sub-menu-item"
|
|
337
|
+
className={cn(sidebarSubMenuItemVariants({ active }), className)}
|
|
338
|
+
{...props}
|
|
339
|
+
>
|
|
340
|
+
<span className="truncate">{label}</span>
|
|
341
|
+
</div>
|
|
342
|
+
)
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
SidebarSubMenuItem.displayName = "SidebarSubMenuItem"
|
|
346
|
+
|
|
347
|
+
/* -----------------------------------------------------------------------------
|
|
348
|
+
* SidebarSeparator
|
|
349
|
+
* -------------------------------------------------------------------------- */
|
|
350
|
+
|
|
351
|
+
export type SidebarSeparatorProps = React.HTMLAttributes<HTMLDivElement>
|
|
352
|
+
|
|
353
|
+
const SidebarSeparator = React.forwardRef<HTMLDivElement, SidebarSeparatorProps>(
|
|
354
|
+
({ className, ...props }, ref) => {
|
|
355
|
+
return (
|
|
356
|
+
<div
|
|
357
|
+
ref={ref}
|
|
358
|
+
data-slot="sidebar-separator"
|
|
359
|
+
className={cn("my-2 h-px bg-grey-200", className)}
|
|
360
|
+
{...props}
|
|
361
|
+
/>
|
|
362
|
+
)
|
|
363
|
+
}
|
|
364
|
+
)
|
|
365
|
+
SidebarSeparator.displayName = "SidebarSeparator"
|
|
366
|
+
|
|
367
|
+
/* -----------------------------------------------------------------------------
|
|
368
|
+
* SidebarToggle
|
|
369
|
+
* -------------------------------------------------------------------------- */
|
|
370
|
+
|
|
371
|
+
export type SidebarToggleProps = React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
372
|
+
|
|
373
|
+
const SidebarToggle = React.forwardRef<HTMLButtonElement, SidebarToggleProps>(
|
|
374
|
+
({ className, children, ...props }, ref) => {
|
|
375
|
+
const { collapsed, setCollapsed } = useSidebar()
|
|
376
|
+
|
|
377
|
+
return (
|
|
378
|
+
<button
|
|
379
|
+
ref={ref}
|
|
380
|
+
data-slot="sidebar-toggle"
|
|
381
|
+
type="button"
|
|
382
|
+
className={cn(
|
|
383
|
+
"flex items-center justify-center p-2 rounded-md text-grey-500 hover:bg-grey-100 hover:text-grey-700 transition-colors",
|
|
384
|
+
className
|
|
385
|
+
)}
|
|
386
|
+
onClick={() => setCollapsed(!collapsed)}
|
|
387
|
+
{...props}
|
|
388
|
+
>
|
|
389
|
+
{children}
|
|
390
|
+
</button>
|
|
391
|
+
)
|
|
392
|
+
}
|
|
393
|
+
)
|
|
394
|
+
SidebarToggle.displayName = "SidebarToggle"
|
|
395
|
+
|
|
396
|
+
/* -----------------------------------------------------------------------------
|
|
397
|
+
* Exports
|
|
398
|
+
* -------------------------------------------------------------------------- */
|
|
399
|
+
|
|
400
|
+
export {
|
|
401
|
+
Sidebar,
|
|
402
|
+
SidebarHeader,
|
|
403
|
+
SidebarContent,
|
|
404
|
+
SidebarFooter,
|
|
405
|
+
SidebarGroup,
|
|
406
|
+
SidebarGroupLabel,
|
|
407
|
+
SidebarMenuItem,
|
|
408
|
+
SidebarSubMenuItem,
|
|
409
|
+
SidebarSeparator,
|
|
410
|
+
SidebarToggle,
|
|
411
|
+
useSidebar,
|
|
412
|
+
sidebarMenuItemVariants,
|
|
413
|
+
sidebarSubMenuItemVariants,
|
|
414
|
+
}
|
package/Sidebar/index.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export {
|
|
2
|
+
Sidebar,
|
|
3
|
+
SidebarHeader,
|
|
4
|
+
SidebarContent,
|
|
5
|
+
SidebarFooter,
|
|
6
|
+
SidebarGroup,
|
|
7
|
+
SidebarGroupLabel,
|
|
8
|
+
SidebarMenuItem,
|
|
9
|
+
SidebarSubMenuItem,
|
|
10
|
+
SidebarSeparator,
|
|
11
|
+
SidebarToggle,
|
|
12
|
+
useSidebar,
|
|
13
|
+
sidebarMenuItemVariants,
|
|
14
|
+
sidebarSubMenuItemVariants,
|
|
15
|
+
} from "./Sidebar"
|
|
16
|
+
|
|
17
|
+
export type {
|
|
18
|
+
SidebarProps,
|
|
19
|
+
SidebarHeaderProps,
|
|
20
|
+
SidebarContentProps,
|
|
21
|
+
SidebarFooterProps,
|
|
22
|
+
SidebarGroupProps,
|
|
23
|
+
SidebarGroupLabelProps,
|
|
24
|
+
SidebarMenuItemProps,
|
|
25
|
+
SidebarSubMenuItemProps,
|
|
26
|
+
SidebarSeparatorProps,
|
|
27
|
+
SidebarToggleProps,
|
|
28
|
+
} from "./Sidebar"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
|
|
3
|
+
import { Flex } from "../Flex/Flex"
|
|
4
|
+
import { Typography } from "../Typography/Typography"
|
|
5
|
+
import { Skeleton } from "./Skeleton"
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Skeleton> = {
|
|
8
|
+
title: "Components/Skeleton",
|
|
9
|
+
component: Skeleton,
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: "centered",
|
|
12
|
+
},
|
|
13
|
+
tags: ["autodocs"],
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default meta
|
|
17
|
+
type Story = StoryObj<typeof meta>
|
|
18
|
+
|
|
19
|
+
export const Default: Story = {
|
|
20
|
+
render: () => <Skeleton className="w-[100px] h-[20px]" />,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const Card: Story = {
|
|
24
|
+
render: () => (
|
|
25
|
+
<div className="flex items-center space-x-4">
|
|
26
|
+
<Skeleton className="h-12 w-12 rounded-full" />
|
|
27
|
+
<div className="space-y-2">
|
|
28
|
+
<Skeleton className="h-4 w-[250px]" />
|
|
29
|
+
<Skeleton className="h-4 w-[200px]" />
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
),
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const Text: Story = {
|
|
36
|
+
render: () => (
|
|
37
|
+
<div className="space-y-2">
|
|
38
|
+
<Skeleton className="h-4 w-[300px]" />
|
|
39
|
+
<Skeleton className="h-4 w-[250px]" />
|
|
40
|
+
<Skeleton className="h-4 w-[280px]" />
|
|
41
|
+
</div>
|
|
42
|
+
),
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const Avatar: Story = {
|
|
46
|
+
render: () => <Skeleton className="h-12 w-12 rounded-full" />,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const Button: Story = {
|
|
50
|
+
render: () => <Skeleton className="h-9 w-[100px] rounded-lg" />,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const Image: Story = {
|
|
54
|
+
render: () => <Skeleton className="h-[200px] w-[300px] rounded-lg" />,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const AllVariants: Story = {
|
|
58
|
+
render: () => (
|
|
59
|
+
<Flex gap={8}>
|
|
60
|
+
<Typography variant="h4" className="text-white">Skeleton Loading States</Typography>
|
|
61
|
+
|
|
62
|
+
<Flex gap={4}>
|
|
63
|
+
<Typography variant="body2" className="text-grey-400">User Card</Typography>
|
|
64
|
+
<div className="flex items-center space-x-4 bg-white p-4 rounded-lg w-[350px]">
|
|
65
|
+
<Skeleton className="h-12 w-12 rounded-full" />
|
|
66
|
+
<div className="space-y-2 flex-1">
|
|
67
|
+
<Skeleton className="h-4 w-3/4" />
|
|
68
|
+
<Skeleton className="h-3 w-1/2" />
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</Flex>
|
|
72
|
+
|
|
73
|
+
<Flex gap={4}>
|
|
74
|
+
<Typography variant="body2" className="text-grey-400">Article Preview</Typography>
|
|
75
|
+
<div className="space-y-3 bg-white p-4 rounded-lg w-[350px]">
|
|
76
|
+
<Skeleton className="h-[150px] w-full rounded-md" />
|
|
77
|
+
<Skeleton className="h-5 w-3/4" />
|
|
78
|
+
<Skeleton className="h-4 w-full" />
|
|
79
|
+
<Skeleton className="h-4 w-5/6" />
|
|
80
|
+
<div className="flex items-center space-x-4 pt-2">
|
|
81
|
+
<Skeleton className="h-8 w-8 rounded-full" />
|
|
82
|
+
<Skeleton className="h-3 w-24" />
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</Flex>
|
|
86
|
+
|
|
87
|
+
<Flex gap={4}>
|
|
88
|
+
<Typography variant="body2" className="text-grey-400">Table Row</Typography>
|
|
89
|
+
<div className="space-y-2 bg-white p-4 rounded-lg w-[400px]">
|
|
90
|
+
{Array.from({ length: 3 }).map((_, i) => (
|
|
91
|
+
<div key={i} className="flex items-center space-x-4">
|
|
92
|
+
<Skeleton className="h-4 w-4" />
|
|
93
|
+
<Skeleton className="h-4 w-[120px]" />
|
|
94
|
+
<Skeleton className="h-4 w-[80px]" />
|
|
95
|
+
<Skeleton className="h-4 w-[60px]" />
|
|
96
|
+
</div>
|
|
97
|
+
))}
|
|
98
|
+
</div>
|
|
99
|
+
</Flex>
|
|
100
|
+
|
|
101
|
+
<Flex gap={4}>
|
|
102
|
+
<Typography variant="body2" className="text-grey-400">Form</Typography>
|
|
103
|
+
<div className="space-y-4 bg-white p-4 rounded-lg w-[300px]">
|
|
104
|
+
<div className="space-y-2">
|
|
105
|
+
<Skeleton className="h-4 w-16" />
|
|
106
|
+
<Skeleton className="h-9 w-full rounded-lg" />
|
|
107
|
+
</div>
|
|
108
|
+
<div className="space-y-2">
|
|
109
|
+
<Skeleton className="h-4 w-20" />
|
|
110
|
+
<Skeleton className="h-9 w-full rounded-lg" />
|
|
111
|
+
</div>
|
|
112
|
+
<Skeleton className="h-9 w-full rounded-lg" />
|
|
113
|
+
</div>
|
|
114
|
+
</Flex>
|
|
115
|
+
</Flex>
|
|
116
|
+
),
|
|
117
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "../lib/utils"
|
|
4
|
+
|
|
5
|
+
export type SkeletonProps = React.HTMLAttributes<HTMLDivElement>
|
|
6
|
+
|
|
7
|
+
function Skeleton({ className, ...props }: SkeletonProps) {
|
|
8
|
+
return (
|
|
9
|
+
<div
|
|
10
|
+
className={cn("animate-pulse rounded-md bg-grey-100", className)}
|
|
11
|
+
{...props}
|
|
12
|
+
/>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { Skeleton }
|