appos 0.4.3-0 → 0.5.1-0
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/dist/exports/api/index.d.mts +3 -3
- package/dist/exports/api/index.mjs +34 -9
- package/dist/exports/api/workflows/index.d.mts +2 -2
- package/dist/exports/api/workflows/index.mjs +2 -2
- package/dist/exports/{auth-By0xx0MI.d.mts → auth-BCOIpGDO.d.mts} +325 -214
- package/dist/exports/cli/index.d.mts +105 -106
- package/dist/exports/cli/index.mjs +87 -13
- package/dist/exports/{constants-BePPc_yF.mjs → constants-BicCnEiJ.mjs} +7 -1
- package/dist/exports/{index-Bpo5QE7k.d.mts → index-CiuTp085.d.mts} +580 -614
- package/dist/exports/{openapi-crG3j4xx.mjs → openapi-uisUTLq7.mjs} +45 -102
- package/dist/exports/{send-email-Bgcdjy-e.mjs → send-email-CXxlkfFL.mjs} +1 -1
- package/dist/exports/{server-BlNxgHUc.mjs → server-CA4aI0U6.mjs} +6 -2
- package/dist/exports/storybook/index.d.ts +40 -0
- package/dist/exports/storybook/index.js +43 -0
- package/dist/exports/tests/api.d.mts +2 -2
- package/dist/exports/tests/api.mjs +3 -3
- package/dist/exports/vite/index.d.mts +19 -3
- package/dist/exports/vite/index.mjs +82 -6
- package/dist/exports/web/index.d.ts +2247 -700
- package/dist/exports/web/index.js +2445 -754
- package/dist/exports/web/routes.d.mts +41 -43
- package/dist/exports/web/ssr.d.mts +2 -2
- package/package.json +48 -31
- package/src/storybook/.storybook/main.ts +119 -0
- package/src/storybook/.storybook/manager.ts +75 -0
- package/src/storybook/.storybook/preview.tsx +76 -0
- package/src/storybook/components/ColorGrid.tsx +324 -0
- package/src/storybook/components/IconGallery.tsx +268 -0
- package/src/storybook/components/SpacingScale.tsx +236 -0
- package/src/storybook/components/TypographyScale.tsx +277 -0
- package/src/storybook/components/index.ts +3 -0
- package/src/storybook/docs/Introduction.mdx +29 -0
- package/src/storybook/docs/foundations/Colors.mdx +27 -0
- package/src/storybook/docs/foundations/Icons.mdx +26 -0
- package/src/storybook/docs/foundations/Spacing.mdx +23 -0
- package/src/storybook/docs/foundations/Typography.mdx +39 -0
- package/src/storybook/index.ts +147 -0
- package/src/storybook/shims/void-elements.js +18 -0
- package/src/web/client/auth-paths.ts +148 -0
- package/src/web/client/auth.ts +218 -0
- package/src/web/client/i18n.d.ts +9 -0
- package/src/web/client/i18n.ts +127 -0
- package/src/web/client/react-router.ts +84 -0
- package/src/web/hooks/index.ts +1 -0
- package/src/web/hooks/use-mobile.ts +19 -0
- package/src/web/index.ts +42 -0
- package/src/web/lib/colors.ts +220 -0
- package/src/web/lib/utils.ts +52 -0
- package/src/web/routes/auth/_layout.tsx +5 -11
- package/src/web/routes.ts +101 -0
- package/src/web/server/context.ts +14 -0
- package/src/web/server/render.ts +11 -0
- package/src/web/ssr.ts +17 -0
- package/src/web/ui/accordion.stories.tsx +183 -0
- package/src/web/ui/accordion.tsx +134 -0
- package/src/web/ui/alert-dialog.stories.tsx +215 -0
- package/src/web/ui/alert-dialog.tsx +328 -0
- package/src/web/ui/alert.stories.tsx +224 -0
- package/src/web/ui/alert.tsx +136 -0
- package/src/web/ui/animated-check.stories.tsx +200 -0
- package/src/web/ui/animated-check.tsx +98 -0
- package/src/web/ui/aspect-ratio.stories.tsx +204 -0
- package/src/web/ui/aspect-ratio.tsx +36 -0
- package/src/web/ui/auth/__mocks__/auth-context.tsx +273 -0
- package/src/web/ui/auth/auth-card.stories.tsx +295 -0
- package/src/web/ui/auth/auth-card.tsx +124 -0
- package/src/web/ui/auth/auth-layout.stories.tsx +330 -0
- package/src/web/ui/auth/auth-layout.tsx +269 -0
- package/src/web/ui/auth/captcha-widget.stories.tsx +200 -0
- package/src/web/ui/auth/captcha-widget.tsx +197 -0
- package/src/web/ui/auth/context.tsx +87 -0
- package/src/web/ui/auth/email-input.stories.tsx +167 -0
- package/src/web/ui/auth/email-input.tsx +84 -0
- package/src/web/ui/auth/forms/email-otp-form.tsx +377 -0
- package/src/web/ui/auth/forms/forgot-password-form.tsx +240 -0
- package/src/web/ui/auth/forms/index.ts +40 -0
- package/src/web/ui/auth/forms/login-form.tsx +486 -0
- package/src/web/ui/auth/forms/phone-otp-form.tsx +388 -0
- package/src/web/ui/auth/forms/reset-password-form.tsx +331 -0
- package/src/web/ui/auth/forms/signup-form.tsx +499 -0
- package/src/web/ui/auth/forms/two-factor-form.tsx +410 -0
- package/src/web/ui/auth/forms/verify-email-form.tsx +373 -0
- package/src/web/ui/auth/hooks.ts +266 -0
- package/src/web/ui/auth/index.ts +31 -0
- package/src/web/ui/auth/magic-link-form.tsx +191 -0
- package/src/web/ui/auth/otp-input.stories.tsx +199 -0
- package/src/web/ui/auth/otp-input.tsx +157 -0
- package/src/web/ui/auth/passkey-button.stories.tsx +115 -0
- package/src/web/ui/auth/passkey-button.tsx +113 -0
- package/src/web/ui/auth/passkey-register-button.stories.tsx +109 -0
- package/src/web/ui/auth/passkey-register-button.tsx +106 -0
- package/src/web/ui/auth/password-input.stories.tsx +287 -0
- package/src/web/ui/auth/password-input.tsx +306 -0
- package/src/web/ui/auth/phone-input.stories.tsx +160 -0
- package/src/web/ui/auth/phone-input.tsx +89 -0
- package/src/web/ui/auth/social-buttons.stories.tsx +217 -0
- package/src/web/ui/auth/social-buttons.tsx +196 -0
- package/src/web/ui/auth/sso-button.stories.tsx +160 -0
- package/src/web/ui/auth/sso-button.tsx +108 -0
- package/src/web/ui/auth/trust-signals.stories.tsx +208 -0
- package/src/web/ui/auth/trust-signals.tsx +260 -0
- package/src/web/ui/avatar.stories.tsx +302 -0
- package/src/web/ui/avatar.tsx +189 -0
- package/src/web/ui/badge.stories.tsx +225 -0
- package/src/web/ui/badge.tsx +66 -0
- package/src/web/ui/brand.stories.tsx +266 -0
- package/src/web/ui/brand.tsx +162 -0
- package/src/web/ui/breadcrumb.stories.tsx +271 -0
- package/src/web/ui/breadcrumb.tsx +214 -0
- package/src/web/ui/button-group.stories.tsx +251 -0
- package/src/web/ui/button-group.tsx +87 -0
- package/src/web/ui/button.stories.tsx +264 -0
- package/src/web/ui/button.tsx +120 -0
- package/src/web/ui/calendar.stories.tsx +235 -0
- package/src/web/ui/calendar.tsx +221 -0
- package/src/web/ui/card.stories.tsx +262 -0
- package/src/web/ui/card.tsx +199 -0
- package/src/web/ui/carousel.stories.tsx +244 -0
- package/src/web/ui/carousel.tsx +241 -0
- package/src/web/ui/chart.stories.tsx +833 -0
- package/src/web/ui/chart.tsx +390 -0
- package/src/web/ui/checkbox.stories.tsx +208 -0
- package/src/web/ui/checkbox.tsx +39 -0
- package/src/web/ui/collapsible.stories.tsx +239 -0
- package/src/web/ui/collapsible.tsx +21 -0
- package/src/web/ui/command.stories.tsx +291 -0
- package/src/web/ui/command.tsx +189 -0
- package/src/web/ui/context-menu.stories.tsx +255 -0
- package/src/web/ui/context-menu.tsx +263 -0
- package/src/web/ui/dialog.stories.tsx +263 -0
- package/src/web/ui/dialog.tsx +273 -0
- package/src/web/ui/drawer.stories.tsx +299 -0
- package/src/web/ui/drawer.tsx +130 -0
- package/src/web/ui/dropdown-menu.stories.tsx +320 -0
- package/src/web/ui/dropdown-menu.tsx +263 -0
- package/src/web/ui/empty.stories.tsx +204 -0
- package/src/web/ui/empty.tsx +101 -0
- package/src/web/ui/error-page.stories.tsx +181 -0
- package/src/web/ui/error-page.tsx +136 -0
- package/src/web/ui/field.stories.tsx +364 -0
- package/src/web/ui/field.tsx +252 -0
- package/src/web/ui/globals.css +3 -0
- package/src/web/ui/hover-card.stories.tsx +261 -0
- package/src/web/ui/hover-card.tsx +50 -0
- package/src/web/ui/index.ts +55 -0
- package/src/web/ui/input-group.stories.tsx +290 -0
- package/src/web/ui/input-group.tsx +157 -0
- package/src/web/ui/input-otp.stories.tsx +235 -0
- package/src/web/ui/input-otp.tsx +86 -0
- package/src/web/ui/input.stories.tsx +205 -0
- package/src/web/ui/input.tsx +30 -0
- package/src/web/ui/item.stories.tsx +348 -0
- package/src/web/ui/item.tsx +200 -0
- package/src/web/ui/kbd.stories.tsx +236 -0
- package/src/web/ui/kbd.tsx +27 -0
- package/src/web/ui/label.stories.tsx +180 -0
- package/src/web/ui/label.tsx +32 -0
- package/src/web/ui/locales/en/ui.json +13 -30
- package/src/web/ui/locales/zh-CN/ui.json +17 -34
- package/src/web/ui/locales/zh-TW/ui.json +17 -34
- package/src/web/ui/menubar.stories.tsx +385 -0
- package/src/web/ui/menubar.tsx +273 -0
- package/src/web/ui/navigation-menu.stories.tsx +361 -0
- package/src/web/ui/navigation-menu.tsx +168 -0
- package/src/web/ui/pagination.stories.tsx +312 -0
- package/src/web/ui/pagination.tsx +221 -0
- package/src/web/ui/popover.stories.tsx +315 -0
- package/src/web/ui/popover.tsx +89 -0
- package/src/web/ui/progress.stories.tsx +239 -0
- package/src/web/ui/progress.tsx +128 -0
- package/src/web/ui/radio-group.stories.tsx +315 -0
- package/src/web/ui/radio-group.tsx +38 -0
- package/src/web/ui/resizable.stories.tsx +304 -0
- package/src/web/ui/resizable.tsx +53 -0
- package/src/web/ui/scroll-area.stories.tsx +276 -0
- package/src/web/ui/scroll-area.tsx +53 -0
- package/src/web/ui/select.stories.tsx +314 -0
- package/src/web/ui/select.tsx +312 -0
- package/src/web/ui/separator.stories.tsx +246 -0
- package/src/web/ui/separator.tsx +36 -0
- package/src/web/ui/sheet.stories.tsx +417 -0
- package/src/web/ui/sheet.tsx +133 -0
- package/src/web/ui/sidebar.stories.tsx +402 -0
- package/src/web/ui/sidebar.tsx +723 -0
- package/src/web/ui/skeleton.stories.tsx +235 -0
- package/src/web/ui/skeleton.tsx +26 -0
- package/src/web/ui/slider.stories.tsx +294 -0
- package/src/web/ui/slider.tsx +75 -0
- package/src/web/ui/sonner.stories.tsx +279 -0
- package/src/web/ui/sonner.tsx +46 -0
- package/src/web/ui/spinner.stories.tsx +204 -0
- package/src/web/ui/spinner.tsx +28 -0
- package/src/web/ui/switch.stories.tsx +285 -0
- package/src/web/ui/switch.tsx +43 -0
- package/src/web/ui/table.stories.tsx +362 -0
- package/src/web/ui/table.tsx +115 -0
- package/src/web/ui/tabs.stories.tsx +401 -0
- package/src/web/ui/tabs.tsx +136 -0
- package/src/web/ui/textarea.stories.tsx +272 -0
- package/src/web/ui/textarea.tsx +28 -0
- package/src/web/ui/toggle-group.stories.tsx +334 -0
- package/src/web/ui/toggle-group.tsx +88 -0
- package/src/web/ui/toggle.stories.tsx +264 -0
- package/src/web/ui/toggle.tsx +57 -0
- package/src/web/ui/tooltip.stories.tsx +342 -0
- package/src/web/ui/tooltip.tsx +116 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { IconHome, IconSlash } from "@tabler/icons-react";
|
|
3
|
+
import { Link } from "react-router";
|
|
4
|
+
import {
|
|
5
|
+
Breadcrumb,
|
|
6
|
+
BreadcrumbEllipsis,
|
|
7
|
+
BreadcrumbItem,
|
|
8
|
+
BreadcrumbLink,
|
|
9
|
+
BreadcrumbList,
|
|
10
|
+
BreadcrumbPage,
|
|
11
|
+
BreadcrumbSeparator,
|
|
12
|
+
} from "#src/web/ui/breadcrumb.tsx";
|
|
13
|
+
import {
|
|
14
|
+
DropdownMenu,
|
|
15
|
+
DropdownMenuContent,
|
|
16
|
+
DropdownMenuItem,
|
|
17
|
+
DropdownMenuTrigger,
|
|
18
|
+
} from "#src/web/ui/dropdown-menu.tsx";
|
|
19
|
+
|
|
20
|
+
const meta = {
|
|
21
|
+
title: "Base/Breadcrumb",
|
|
22
|
+
component: Breadcrumb,
|
|
23
|
+
tags: ["autodocs"],
|
|
24
|
+
parameters: {
|
|
25
|
+
layout: "centered",
|
|
26
|
+
docs: {
|
|
27
|
+
description: {
|
|
28
|
+
component:
|
|
29
|
+
"Displays the path to the current resource using a hierarchy of links. Helps users understand their location within the application and navigate back to parent pages.",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
} satisfies Meta<typeof Breadcrumb>;
|
|
34
|
+
|
|
35
|
+
export default meta;
|
|
36
|
+
type Story = StoryObj<typeof meta>;
|
|
37
|
+
|
|
38
|
+
export const Default: Story = {
|
|
39
|
+
render: () => (
|
|
40
|
+
<Breadcrumb>
|
|
41
|
+
<BreadcrumbList>
|
|
42
|
+
<BreadcrumbItem>
|
|
43
|
+
<BreadcrumbLink href="/">Home</BreadcrumbLink>
|
|
44
|
+
</BreadcrumbItem>
|
|
45
|
+
<BreadcrumbSeparator />
|
|
46
|
+
<BreadcrumbItem>
|
|
47
|
+
<BreadcrumbLink href="/products">Products</BreadcrumbLink>
|
|
48
|
+
</BreadcrumbItem>
|
|
49
|
+
<BreadcrumbSeparator />
|
|
50
|
+
<BreadcrumbItem>
|
|
51
|
+
<BreadcrumbPage>Electronics</BreadcrumbPage>
|
|
52
|
+
</BreadcrumbItem>
|
|
53
|
+
</BreadcrumbList>
|
|
54
|
+
</Breadcrumb>
|
|
55
|
+
),
|
|
56
|
+
parameters: {
|
|
57
|
+
docs: {
|
|
58
|
+
description: {
|
|
59
|
+
story:
|
|
60
|
+
"Default breadcrumb navigation showing a hierarchy of pages. The current page uses BreadcrumbPage for styling.",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const WithHomeIcon: Story = {
|
|
67
|
+
render: () => (
|
|
68
|
+
<Breadcrumb>
|
|
69
|
+
<BreadcrumbList>
|
|
70
|
+
<BreadcrumbItem>
|
|
71
|
+
<BreadcrumbLink href="/">
|
|
72
|
+
<IconHome className="size-4" />
|
|
73
|
+
</BreadcrumbLink>
|
|
74
|
+
</BreadcrumbItem>
|
|
75
|
+
<BreadcrumbSeparator />
|
|
76
|
+
<BreadcrumbItem>
|
|
77
|
+
<BreadcrumbLink href="/dashboard">Dashboard</BreadcrumbLink>
|
|
78
|
+
</BreadcrumbItem>
|
|
79
|
+
<BreadcrumbSeparator />
|
|
80
|
+
<BreadcrumbItem>
|
|
81
|
+
<BreadcrumbPage>Settings</BreadcrumbPage>
|
|
82
|
+
</BreadcrumbItem>
|
|
83
|
+
</BreadcrumbList>
|
|
84
|
+
</Breadcrumb>
|
|
85
|
+
),
|
|
86
|
+
parameters: {
|
|
87
|
+
docs: {
|
|
88
|
+
description: {
|
|
89
|
+
story:
|
|
90
|
+
"Breadcrumb with a home icon instead of text for the root level.",
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const WithEllipsis: Story = {
|
|
97
|
+
render: () => (
|
|
98
|
+
<Breadcrumb>
|
|
99
|
+
<BreadcrumbList>
|
|
100
|
+
<BreadcrumbItem>
|
|
101
|
+
<BreadcrumbLink href="/">Home</BreadcrumbLink>
|
|
102
|
+
</BreadcrumbItem>
|
|
103
|
+
<BreadcrumbSeparator />
|
|
104
|
+
<BreadcrumbItem>
|
|
105
|
+
<BreadcrumbEllipsis />
|
|
106
|
+
</BreadcrumbItem>
|
|
107
|
+
<BreadcrumbSeparator />
|
|
108
|
+
<BreadcrumbItem>
|
|
109
|
+
<BreadcrumbLink href="/products/electronics">
|
|
110
|
+
Electronics
|
|
111
|
+
</BreadcrumbLink>
|
|
112
|
+
</BreadcrumbItem>
|
|
113
|
+
<BreadcrumbSeparator />
|
|
114
|
+
<BreadcrumbItem>
|
|
115
|
+
<BreadcrumbPage>Smartphones</BreadcrumbPage>
|
|
116
|
+
</BreadcrumbItem>
|
|
117
|
+
</BreadcrumbList>
|
|
118
|
+
</Breadcrumb>
|
|
119
|
+
),
|
|
120
|
+
parameters: {
|
|
121
|
+
docs: {
|
|
122
|
+
description: {
|
|
123
|
+
story:
|
|
124
|
+
"Breadcrumb with ellipsis to truncate long paths. Use when the hierarchy is too deep to display fully.",
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const WithDropdown: Story = {
|
|
131
|
+
render: () => (
|
|
132
|
+
<Breadcrumb>
|
|
133
|
+
<BreadcrumbList>
|
|
134
|
+
<BreadcrumbItem>
|
|
135
|
+
<BreadcrumbLink href="/">Home</BreadcrumbLink>
|
|
136
|
+
</BreadcrumbItem>
|
|
137
|
+
<BreadcrumbSeparator />
|
|
138
|
+
<BreadcrumbItem>
|
|
139
|
+
<DropdownMenu>
|
|
140
|
+
<DropdownMenuTrigger className="flex items-center gap-1">
|
|
141
|
+
<BreadcrumbEllipsis />
|
|
142
|
+
</DropdownMenuTrigger>
|
|
143
|
+
<DropdownMenuContent align="start">
|
|
144
|
+
<DropdownMenuItem>Products</DropdownMenuItem>
|
|
145
|
+
<DropdownMenuItem>Categories</DropdownMenuItem>
|
|
146
|
+
<DropdownMenuItem>Electronics</DropdownMenuItem>
|
|
147
|
+
</DropdownMenuContent>
|
|
148
|
+
</DropdownMenu>
|
|
149
|
+
</BreadcrumbItem>
|
|
150
|
+
<BreadcrumbSeparator />
|
|
151
|
+
<BreadcrumbItem>
|
|
152
|
+
<BreadcrumbLink href="/products/electronics/phones">
|
|
153
|
+
Phones
|
|
154
|
+
</BreadcrumbLink>
|
|
155
|
+
</BreadcrumbItem>
|
|
156
|
+
<BreadcrumbSeparator />
|
|
157
|
+
<BreadcrumbItem>
|
|
158
|
+
<BreadcrumbPage>iPhone 15</BreadcrumbPage>
|
|
159
|
+
</BreadcrumbItem>
|
|
160
|
+
</BreadcrumbList>
|
|
161
|
+
</Breadcrumb>
|
|
162
|
+
),
|
|
163
|
+
parameters: {
|
|
164
|
+
docs: {
|
|
165
|
+
description: {
|
|
166
|
+
story:
|
|
167
|
+
"Breadcrumb with a dropdown menu for collapsed items. Allows users to navigate to hidden intermediate pages.",
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
export const CustomSeparator: Story = {
|
|
174
|
+
render: () => (
|
|
175
|
+
<Breadcrumb>
|
|
176
|
+
<BreadcrumbList>
|
|
177
|
+
<BreadcrumbItem>
|
|
178
|
+
<BreadcrumbLink href="/">Home</BreadcrumbLink>
|
|
179
|
+
</BreadcrumbItem>
|
|
180
|
+
<BreadcrumbSeparator>
|
|
181
|
+
<IconSlash className="size-3.5" />
|
|
182
|
+
</BreadcrumbSeparator>
|
|
183
|
+
<BreadcrumbItem>
|
|
184
|
+
<BreadcrumbLink href="/docs">Docs</BreadcrumbLink>
|
|
185
|
+
</BreadcrumbItem>
|
|
186
|
+
<BreadcrumbSeparator>
|
|
187
|
+
<IconSlash className="size-3.5" />
|
|
188
|
+
</BreadcrumbSeparator>
|
|
189
|
+
<BreadcrumbItem>
|
|
190
|
+
<BreadcrumbPage>Components</BreadcrumbPage>
|
|
191
|
+
</BreadcrumbItem>
|
|
192
|
+
</BreadcrumbList>
|
|
193
|
+
</Breadcrumb>
|
|
194
|
+
),
|
|
195
|
+
parameters: {
|
|
196
|
+
docs: {
|
|
197
|
+
description: {
|
|
198
|
+
story:
|
|
199
|
+
"Breadcrumb with a custom separator icon. Pass a child to BreadcrumbSeparator to override the default chevron.",
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export const WithRouterLink: Story = {
|
|
206
|
+
render: () => (
|
|
207
|
+
<Breadcrumb>
|
|
208
|
+
<BreadcrumbList>
|
|
209
|
+
<BreadcrumbItem>
|
|
210
|
+
<BreadcrumbLink render={<Link to="/" />}>Home</BreadcrumbLink>
|
|
211
|
+
</BreadcrumbItem>
|
|
212
|
+
<BreadcrumbSeparator />
|
|
213
|
+
<BreadcrumbItem>
|
|
214
|
+
<BreadcrumbLink render={<Link to="/settings" />}>
|
|
215
|
+
Settings
|
|
216
|
+
</BreadcrumbLink>
|
|
217
|
+
</BreadcrumbItem>
|
|
218
|
+
<BreadcrumbSeparator />
|
|
219
|
+
<BreadcrumbItem>
|
|
220
|
+
<BreadcrumbPage>Profile</BreadcrumbPage>
|
|
221
|
+
</BreadcrumbItem>
|
|
222
|
+
</BreadcrumbList>
|
|
223
|
+
</Breadcrumb>
|
|
224
|
+
),
|
|
225
|
+
parameters: {
|
|
226
|
+
docs: {
|
|
227
|
+
description: {
|
|
228
|
+
story:
|
|
229
|
+
"Breadcrumb with React Router Link components using the render prop for client-side navigation.",
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export const LongPath: Story = {
|
|
236
|
+
render: () => (
|
|
237
|
+
<Breadcrumb>
|
|
238
|
+
<BreadcrumbList>
|
|
239
|
+
<BreadcrumbItem>
|
|
240
|
+
<BreadcrumbLink href="/">Home</BreadcrumbLink>
|
|
241
|
+
</BreadcrumbItem>
|
|
242
|
+
<BreadcrumbSeparator />
|
|
243
|
+
<BreadcrumbItem>
|
|
244
|
+
<BreadcrumbLink href="/organization">Organization</BreadcrumbLink>
|
|
245
|
+
</BreadcrumbItem>
|
|
246
|
+
<BreadcrumbSeparator />
|
|
247
|
+
<BreadcrumbItem>
|
|
248
|
+
<BreadcrumbLink href="/organization/teams">Teams</BreadcrumbLink>
|
|
249
|
+
</BreadcrumbItem>
|
|
250
|
+
<BreadcrumbSeparator />
|
|
251
|
+
<BreadcrumbItem>
|
|
252
|
+
<BreadcrumbLink href="/organization/teams/engineering">
|
|
253
|
+
Engineering
|
|
254
|
+
</BreadcrumbLink>
|
|
255
|
+
</BreadcrumbItem>
|
|
256
|
+
<BreadcrumbSeparator />
|
|
257
|
+
<BreadcrumbItem>
|
|
258
|
+
<BreadcrumbPage>Members</BreadcrumbPage>
|
|
259
|
+
</BreadcrumbItem>
|
|
260
|
+
</BreadcrumbList>
|
|
261
|
+
</Breadcrumb>
|
|
262
|
+
),
|
|
263
|
+
parameters: {
|
|
264
|
+
docs: {
|
|
265
|
+
description: {
|
|
266
|
+
story:
|
|
267
|
+
"Full breadcrumb path without truncation. Consider using ellipsis for very deep hierarchies.",
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { mergeProps } from "@base-ui/react/merge-props";
|
|
2
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
3
|
+
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
|
|
4
|
+
import type * as React from "react";
|
|
5
|
+
import { cn } from "#src/web/lib/utils.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A navigation component that shows the user's current location in a hierarchy.
|
|
9
|
+
*
|
|
10
|
+
* Helps users understand their position within a site structure and navigate
|
|
11
|
+
* back to parent pages. Includes proper accessibility attributes.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <Breadcrumb>
|
|
16
|
+
* <BreadcrumbList>
|
|
17
|
+
* <BreadcrumbItem>
|
|
18
|
+
* <BreadcrumbLink href="/">Home</BreadcrumbLink>
|
|
19
|
+
* </BreadcrumbItem>
|
|
20
|
+
* <BreadcrumbSeparator />
|
|
21
|
+
* <BreadcrumbItem>
|
|
22
|
+
* <BreadcrumbPage>Current Page</BreadcrumbPage>
|
|
23
|
+
* </BreadcrumbItem>
|
|
24
|
+
* </BreadcrumbList>
|
|
25
|
+
* </Breadcrumb>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
|
|
29
|
+
return (
|
|
30
|
+
<nav
|
|
31
|
+
aria-label="breadcrumb"
|
|
32
|
+
data-slot="breadcrumb"
|
|
33
|
+
className={cn(className)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The ordered list container for breadcrumb items.
|
|
41
|
+
*
|
|
42
|
+
* Wraps BreadcrumbItem components and handles flex layout with proper spacing.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* <BreadcrumbList>
|
|
47
|
+
* <BreadcrumbItem>...</BreadcrumbItem>
|
|
48
|
+
* </BreadcrumbList>
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
|
52
|
+
return (
|
|
53
|
+
<ol
|
|
54
|
+
data-slot="breadcrumb-list"
|
|
55
|
+
className={cn(
|
|
56
|
+
"text-muted-foreground gap-1.5 text-sm sm:gap-2.5 flex flex-wrap items-center wrap-break-word",
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A single item in the breadcrumb navigation.
|
|
66
|
+
*
|
|
67
|
+
* Contains either a BreadcrumbLink for navigable items or BreadcrumbPage
|
|
68
|
+
* for the current page indicator.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```tsx
|
|
72
|
+
* <BreadcrumbItem>
|
|
73
|
+
* <BreadcrumbLink href="/products">Products</BreadcrumbLink>
|
|
74
|
+
* </BreadcrumbItem>
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
|
|
78
|
+
return (
|
|
79
|
+
<li
|
|
80
|
+
data-slot="breadcrumb-item"
|
|
81
|
+
className={cn("gap-1.5 inline-flex items-center", className)}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* A navigable link within a breadcrumb item.
|
|
89
|
+
*
|
|
90
|
+
* Use for all breadcrumb levels except the current page. Supports custom
|
|
91
|
+
* rendering via the `render` prop for integration with routing libraries.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```tsx
|
|
95
|
+
* <BreadcrumbLink href="/dashboard">Dashboard</BreadcrumbLink>
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
function BreadcrumbLink({
|
|
99
|
+
className,
|
|
100
|
+
render,
|
|
101
|
+
...props
|
|
102
|
+
}: useRender.ComponentProps<"a">) {
|
|
103
|
+
return useRender({
|
|
104
|
+
defaultTagName: "a",
|
|
105
|
+
props: mergeProps<"a">(
|
|
106
|
+
{
|
|
107
|
+
className: cn("hover:text-foreground transition-colors", className),
|
|
108
|
+
},
|
|
109
|
+
props,
|
|
110
|
+
),
|
|
111
|
+
render,
|
|
112
|
+
state: {
|
|
113
|
+
slot: "breadcrumb-link",
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The current page indicator in a breadcrumb trail.
|
|
120
|
+
*
|
|
121
|
+
* Non-interactive element that represents the user's current location.
|
|
122
|
+
* Includes proper ARIA attributes for accessibility.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```tsx
|
|
126
|
+
* <BreadcrumbPage>Settings</BreadcrumbPage>
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
|
130
|
+
return (
|
|
131
|
+
<span
|
|
132
|
+
data-slot="breadcrumb-page"
|
|
133
|
+
role="link"
|
|
134
|
+
aria-disabled="true"
|
|
135
|
+
aria-current="page"
|
|
136
|
+
className={cn("text-foreground font-normal", className)}
|
|
137
|
+
{...props}
|
|
138
|
+
/>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* A visual separator between breadcrumb items.
|
|
144
|
+
*
|
|
145
|
+
* Displays a chevron icon by default but accepts custom children.
|
|
146
|
+
* Hidden from screen readers as it's purely decorative.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```tsx
|
|
150
|
+
* <BreadcrumbSeparator />
|
|
151
|
+
* <BreadcrumbSeparator>/</BreadcrumbSeparator>
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
function BreadcrumbSeparator({
|
|
155
|
+
children,
|
|
156
|
+
className,
|
|
157
|
+
...props
|
|
158
|
+
}: React.ComponentProps<"li">) {
|
|
159
|
+
return (
|
|
160
|
+
<li
|
|
161
|
+
data-slot="breadcrumb-separator"
|
|
162
|
+
role="presentation"
|
|
163
|
+
aria-hidden="true"
|
|
164
|
+
className={cn("[&>svg]:size-3.5", className)}
|
|
165
|
+
{...props}
|
|
166
|
+
>
|
|
167
|
+
{children ?? <ChevronRightIcon />}
|
|
168
|
+
</li>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* An ellipsis indicator for truncated breadcrumb trails.
|
|
174
|
+
*
|
|
175
|
+
* Use when there are too many levels to display. Often combined with a
|
|
176
|
+
* dropdown menu to show hidden items.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```tsx
|
|
180
|
+
* <BreadcrumbItem>
|
|
181
|
+
* <BreadcrumbEllipsis />
|
|
182
|
+
* </BreadcrumbItem>
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
function BreadcrumbEllipsis({
|
|
186
|
+
className,
|
|
187
|
+
...props
|
|
188
|
+
}: React.ComponentProps<"span">) {
|
|
189
|
+
return (
|
|
190
|
+
<span
|
|
191
|
+
data-slot="breadcrumb-ellipsis"
|
|
192
|
+
role="presentation"
|
|
193
|
+
aria-hidden="true"
|
|
194
|
+
className={cn(
|
|
195
|
+
"size-5 [&>svg]:size-4 flex items-center justify-center",
|
|
196
|
+
className,
|
|
197
|
+
)}
|
|
198
|
+
{...props}
|
|
199
|
+
>
|
|
200
|
+
<MoreHorizontalIcon />
|
|
201
|
+
<span className="sr-only">More</span>
|
|
202
|
+
</span>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export {
|
|
207
|
+
Breadcrumb,
|
|
208
|
+
BreadcrumbList,
|
|
209
|
+
BreadcrumbItem,
|
|
210
|
+
BreadcrumbLink,
|
|
211
|
+
BreadcrumbPage,
|
|
212
|
+
BreadcrumbSeparator,
|
|
213
|
+
BreadcrumbEllipsis,
|
|
214
|
+
};
|