@alpic-ai/ui 0.0.0-dev.4a35dc7 → 0.0.0-dev.85c8341
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/components/accordion-card.d.mts +1 -1
- package/dist/components/accordion.d.mts +1 -1
- package/dist/components/alert.d.mts +1 -1
- package/dist/components/attachment-tile.mjs +1 -1
- package/dist/components/avatar.d.mts +1 -1
- package/dist/components/breadcrumb.d.mts +1 -1
- package/dist/components/button.d.mts +1 -1
- package/dist/components/card.d.mts +1 -1
- package/dist/components/checkbox.d.mts +1 -1
- package/dist/components/collapsible.d.mts +1 -1
- package/dist/components/combobox.d.mts +1 -1
- package/dist/components/combobox.mjs +1 -1
- package/dist/components/command.d.mts +1 -1
- package/dist/components/copyable.d.mts +1 -1
- package/dist/components/copyable.mjs +1 -1
- package/dist/components/description-list.d.mts +1 -1
- package/dist/components/dialog.d.mts +1 -1
- package/dist/components/dropdown-menu.d.mts +1 -1
- package/dist/components/form.d.mts +119 -0
- package/dist/components/form.mjs +192 -0
- package/dist/components/input-group.d.mts +1 -1
- package/dist/components/input.d.mts +3 -1
- package/dist/components/input.mjs +20 -11
- package/dist/components/label.d.mts +1 -1
- package/dist/components/pagination.d.mts +1 -1
- package/dist/components/popover.d.mts +1 -1
- package/dist/components/radio-group.d.mts +1 -1
- package/dist/components/scroll-area.d.mts +1 -1
- package/dist/components/select-trigger-variants.mjs +1 -0
- package/dist/components/select.d.mts +1 -1
- package/dist/components/separator.d.mts +1 -1
- package/dist/components/sheet.d.mts +1 -1
- package/dist/components/sidebar.d.mts +1 -1
- package/dist/components/sidebar.mjs +2 -2
- package/dist/components/sonner.d.mts +1 -1
- package/dist/components/switch.d.mts +1 -1
- package/dist/components/table.d.mts +1 -1
- package/dist/components/tabs.d.mts +1 -1
- package/dist/components/tabs.mjs +1 -1
- package/dist/components/textarea.d.mts +3 -1
- package/dist/components/textarea.mjs +20 -11
- package/dist/components/toggle-group.d.mts +1 -1
- package/dist/components/toggle-group.mjs +1 -1
- package/dist/components/tooltip-icon-button.mjs +1 -1
- package/dist/components/tooltip.d.mts +1 -1
- package/package.json +4 -5
- package/src/components/form.tsx +343 -0
- package/src/components/input.tsx +12 -0
- package/src/components/select-trigger-variants.ts +1 -0
- package/src/components/textarea.tsx +12 -1
- package/src/stories/accordion-card.stories.tsx +53 -0
- package/src/stories/accordion.stories.tsx +65 -0
- package/src/stories/alert.stories.tsx +58 -0
- package/src/stories/attachment-tile.stories.tsx +37 -0
- package/src/stories/avatar.stories.tsx +54 -0
- package/src/stories/badge.stories.tsx +50 -0
- package/src/stories/breadcrumb.stories.tsx +107 -0
- package/src/stories/button.stories.tsx +342 -0
- package/src/stories/card.stories.tsx +89 -0
- package/src/stories/checkbox.stories.tsx +56 -0
- package/src/stories/collapsible.stories.tsx +69 -0
- package/src/stories/combobox.stories.tsx +214 -0
- package/src/stories/command.stories.tsx +95 -0
- package/src/stories/copyable.stories.tsx +29 -0
- package/src/stories/description-list.stories.tsx +71 -0
- package/src/stories/dialog.stories.tsx +135 -0
- package/src/stories/dropdown-menu.stories.tsx +191 -0
- package/src/stories/form.stories.tsx +91 -0
- package/src/stories/input-group.stories.tsx +63 -0
- package/src/stories/input.stories.tsx +72 -0
- package/src/stories/label.stories.tsx +26 -0
- package/src/stories/ladle.css +3 -0
- package/src/stories/pagination.stories.tsx +35 -0
- package/src/stories/popover.stories.tsx +34 -0
- package/src/stories/radio-group.stories.tsx +59 -0
- package/src/stories/scroll-area.stories.tsx +43 -0
- package/src/stories/select.stories.tsx +95 -0
- package/src/stories/separator.stories.tsx +36 -0
- package/src/stories/sheet.stories.tsx +76 -0
- package/src/stories/sidebar.stories.tsx +255 -0
- package/src/stories/skeleton.stories.tsx +47 -0
- package/src/stories/sonner.stories.tsx +91 -0
- package/src/stories/spinner.stories.tsx +66 -0
- package/src/stories/status-dot.stories.tsx +27 -0
- package/src/stories/switch.stories.tsx +46 -0
- package/src/stories/table.stories.tsx +242 -0
- package/src/stories/tabs.stories.tsx +169 -0
- package/src/stories/tag.stories.tsx +82 -0
- package/src/stories/textarea.stories.tsx +60 -0
- package/src/stories/toggle-group.stories.tsx +142 -0
- package/src/stories/tooltip-icon-button.stories.tsx +59 -0
- package/src/stories/tooltip.stories.tsx +54 -0
- package/README.md +0 -33
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Story } from "@ladle/react";
|
|
2
|
+
import {
|
|
3
|
+
AccordionCard,
|
|
4
|
+
AccordionCardContent,
|
|
5
|
+
AccordionCardHeader,
|
|
6
|
+
AccordionCardTitle,
|
|
7
|
+
} from "../components/accordion-card";
|
|
8
|
+
|
|
9
|
+
export const AllVariants: Story = () => (
|
|
10
|
+
<div className="flex flex-col gap-6 max-w-md">
|
|
11
|
+
<div className="flex flex-col gap-1.5">
|
|
12
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Default (collapsed)</p>
|
|
13
|
+
<AccordionCard>
|
|
14
|
+
<AccordionCardHeader>
|
|
15
|
+
<AccordionCardTitle>Logs</AccordionCardTitle>
|
|
16
|
+
</AccordionCardHeader>
|
|
17
|
+
<AccordionCardContent>Content inside the accordion card.</AccordionCardContent>
|
|
18
|
+
</AccordionCard>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div className="flex flex-col gap-1.5">
|
|
22
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Default open</p>
|
|
23
|
+
<AccordionCard defaultOpen>
|
|
24
|
+
<AccordionCardHeader>
|
|
25
|
+
<AccordionCardTitle>Build settings</AccordionCardTitle>
|
|
26
|
+
</AccordionCardHeader>
|
|
27
|
+
<AccordionCardContent>
|
|
28
|
+
This card starts open. The chevron rotates to indicate the open state.
|
|
29
|
+
</AccordionCardContent>
|
|
30
|
+
</AccordionCard>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div className="flex flex-col gap-1.5">
|
|
34
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Without title component</p>
|
|
35
|
+
<AccordionCard>
|
|
36
|
+
<AccordionCardHeader>
|
|
37
|
+
<span className="type-text-sm font-medium">Environment Variables</span>
|
|
38
|
+
</AccordionCardHeader>
|
|
39
|
+
<AccordionCardContent>Header text can be any element, not just AccordionCardTitle.</AccordionCardContent>
|
|
40
|
+
</AccordionCard>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div className="flex flex-col gap-1.5">
|
|
44
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Disabled</p>
|
|
45
|
+
<AccordionCard disabled>
|
|
46
|
+
<AccordionCardHeader>
|
|
47
|
+
<AccordionCardTitle>Disabled card</AccordionCardTitle>
|
|
48
|
+
</AccordionCardHeader>
|
|
49
|
+
<AccordionCardContent>Cannot be opened.</AccordionCardContent>
|
|
50
|
+
</AccordionCard>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Story } from "@ladle/react";
|
|
2
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../components/accordion";
|
|
3
|
+
|
|
4
|
+
export const AllVariants: Story = () => (
|
|
5
|
+
<div className="flex flex-col gap-10 max-w-md">
|
|
6
|
+
<div className="flex flex-col gap-1.5">
|
|
7
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Single (collapsible)</p>
|
|
8
|
+
<Accordion type="single" collapsible>
|
|
9
|
+
<AccordionItem value="item-1">
|
|
10
|
+
<AccordionTrigger>What is Alpic?</AccordionTrigger>
|
|
11
|
+
<AccordionContent>
|
|
12
|
+
Alpic is a multi-tenant SaaS platform for deploying MCP servers. It handles infrastructure, scaling, and
|
|
13
|
+
distribution so you can focus on building.
|
|
14
|
+
</AccordionContent>
|
|
15
|
+
</AccordionItem>
|
|
16
|
+
<AccordionItem value="item-2">
|
|
17
|
+
<AccordionTrigger>How do I deploy?</AccordionTrigger>
|
|
18
|
+
<AccordionContent>
|
|
19
|
+
Use the Alpic CLI to deploy your MCP server with a single command. The platform handles containerization,
|
|
20
|
+
routing, and scaling automatically.
|
|
21
|
+
</AccordionContent>
|
|
22
|
+
</AccordionItem>
|
|
23
|
+
<AccordionItem value="item-3">
|
|
24
|
+
<AccordionTrigger>What languages are supported?</AccordionTrigger>
|
|
25
|
+
<AccordionContent>
|
|
26
|
+
Any language that can run in a container. TypeScript, Python, Go, Rust, and more are all supported out of
|
|
27
|
+
the box with pre-built runtime images.
|
|
28
|
+
</AccordionContent>
|
|
29
|
+
</AccordionItem>
|
|
30
|
+
</Accordion>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div className="flex flex-col gap-1.5">
|
|
34
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Multiple</p>
|
|
35
|
+
<Accordion type="multiple" defaultValue={["item-1", "item-3"]}>
|
|
36
|
+
<AccordionItem value="item-1">
|
|
37
|
+
<AccordionTrigger>First item (open by default)</AccordionTrigger>
|
|
38
|
+
<AccordionContent>Content for the first item. Multiple items can be open at the same time.</AccordionContent>
|
|
39
|
+
</AccordionItem>
|
|
40
|
+
<AccordionItem value="item-2">
|
|
41
|
+
<AccordionTrigger>Second item</AccordionTrigger>
|
|
42
|
+
<AccordionContent>Content for the second item.</AccordionContent>
|
|
43
|
+
</AccordionItem>
|
|
44
|
+
<AccordionItem value="item-3">
|
|
45
|
+
<AccordionTrigger>Third item (open by default)</AccordionTrigger>
|
|
46
|
+
<AccordionContent>Content for the third item.</AccordionContent>
|
|
47
|
+
</AccordionItem>
|
|
48
|
+
</Accordion>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div className="flex flex-col gap-1.5">
|
|
52
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Disabled</p>
|
|
53
|
+
<Accordion type="single" collapsible>
|
|
54
|
+
<AccordionItem value="item-1">
|
|
55
|
+
<AccordionTrigger>Enabled item</AccordionTrigger>
|
|
56
|
+
<AccordionContent>This item can be toggled.</AccordionContent>
|
|
57
|
+
</AccordionItem>
|
|
58
|
+
<AccordionItem value="item-2" disabled>
|
|
59
|
+
<AccordionTrigger>Disabled item</AccordionTrigger>
|
|
60
|
+
<AccordionContent>This content cannot be reached.</AccordionContent>
|
|
61
|
+
</AccordionItem>
|
|
62
|
+
</Accordion>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Story } from "@ladle/react";
|
|
2
|
+
import { AlertCircle, AlertTriangle, CheckCircle2, Info } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
import { Alert, AlertDescription, AlertTitle, ErrorAlert, WarningAlert } from "../components/alert";
|
|
5
|
+
|
|
6
|
+
export const AllVariants: Story = () => (
|
|
7
|
+
<div className="flex flex-col gap-4 max-w-xl p-6">
|
|
8
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Default</p>
|
|
9
|
+
<Alert>
|
|
10
|
+
<Info />
|
|
11
|
+
<AlertTitle>Best on desktop</AlertTitle>
|
|
12
|
+
<AlertDescription>
|
|
13
|
+
This site isn't optimised for small screens. For the best experience we recommend using a desktop or tablet.
|
|
14
|
+
</AlertDescription>
|
|
15
|
+
</Alert>
|
|
16
|
+
|
|
17
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Destructive</p>
|
|
18
|
+
<Alert variant="destructive">
|
|
19
|
+
<AlertCircle />
|
|
20
|
+
<AlertTitle>Clone failed</AlertTitle>
|
|
21
|
+
<AlertDescription>Unable to clone the repository. Check your credentials and try again.</AlertDescription>
|
|
22
|
+
</Alert>
|
|
23
|
+
|
|
24
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Warning</p>
|
|
25
|
+
<Alert variant="warning">
|
|
26
|
+
<AlertTriangle />
|
|
27
|
+
<AlertTitle>API key expiring soon</AlertTitle>
|
|
28
|
+
<AlertDescription>Your API key expires in 3 days. Rotate it to avoid service interruption.</AlertDescription>
|
|
29
|
+
</Alert>
|
|
30
|
+
|
|
31
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Success</p>
|
|
32
|
+
<Alert variant="success">
|
|
33
|
+
<CheckCircle2 />
|
|
34
|
+
<AlertTitle>Deployment complete</AlertTitle>
|
|
35
|
+
<AlertDescription>Your project was deployed successfully and is now live.</AlertDescription>
|
|
36
|
+
</Alert>
|
|
37
|
+
|
|
38
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Description only (no title)</p>
|
|
39
|
+
<Alert variant="destructive">
|
|
40
|
+
<AlertCircle />
|
|
41
|
+
<AlertDescription>
|
|
42
|
+
This is the only time you'll be able to see this API key. Make sure to copy it and store it securely.
|
|
43
|
+
</AlertDescription>
|
|
44
|
+
</Alert>
|
|
45
|
+
|
|
46
|
+
<p className="type-text-xs font-medium text-subtle-foreground">ErrorAlert (pre-composed)</p>
|
|
47
|
+
<ErrorAlert />
|
|
48
|
+
|
|
49
|
+
<p className="type-text-xs font-medium text-subtle-foreground">ErrorAlert (custom)</p>
|
|
50
|
+
<ErrorAlert title="Error loading projects" description="Failed to fetch your projects. Please refresh the page." />
|
|
51
|
+
|
|
52
|
+
<p className="type-text-xs font-medium text-subtle-foreground">WarningAlert</p>
|
|
53
|
+
<WarningAlert
|
|
54
|
+
title="Save your API key"
|
|
55
|
+
description="This is the only time you'll be able to see this API key. Make sure to copy it and store it securely."
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Story } from "@ladle/react";
|
|
2
|
+
import { AttachmentTile } from "../components/attachment-tile";
|
|
3
|
+
|
|
4
|
+
export const AllVariants: Story = () => (
|
|
5
|
+
<div className="flex flex-col gap-10 p-10">
|
|
6
|
+
<div className="flex flex-col gap-1.5">
|
|
7
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Image attachment (with remove)</p>
|
|
8
|
+
<div className="flex gap-3">
|
|
9
|
+
<AttachmentTile
|
|
10
|
+
src="https://picsum.photos/seed/a/200/200"
|
|
11
|
+
isImage
|
|
12
|
+
onRemove={() => alert("Remove clicked")}
|
|
13
|
+
onClick={() => alert("Preview clicked")}
|
|
14
|
+
/>
|
|
15
|
+
<AttachmentTile
|
|
16
|
+
src="https://picsum.photos/seed/b/200/200"
|
|
17
|
+
isImage
|
|
18
|
+
onRemove={() => alert("Remove clicked")}
|
|
19
|
+
onClick={() => alert("Preview clicked")}
|
|
20
|
+
/>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div className="flex flex-col gap-1.5">
|
|
25
|
+
<p className="type-text-xs font-medium text-subtle-foreground">File attachment (fallback icon)</p>
|
|
26
|
+
<AttachmentTile onRemove={() => alert("Remove clicked")} onClick={() => alert("Preview clicked")} />
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div className="flex flex-col gap-1.5">
|
|
30
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Read-only (no remove button)</p>
|
|
31
|
+
<div className="flex gap-3">
|
|
32
|
+
<AttachmentTile src="https://picsum.photos/seed/c/200/200" isImage />
|
|
33
|
+
<AttachmentTile />
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Story } from "@ladle/react";
|
|
2
|
+
import { Avatar, AvatarFallback, AvatarImage, AvatarLabelGroup } from "../components/avatar";
|
|
3
|
+
|
|
4
|
+
const DEMO_SRC = "https://i.pravatar.cc/150";
|
|
5
|
+
const SIZES = ["xs", "sm", "md", "lg", "xl"] as const;
|
|
6
|
+
|
|
7
|
+
export const AllVariants: Story = () => (
|
|
8
|
+
<div className="flex flex-col gap-8 p-6 bg-background">
|
|
9
|
+
<div className="flex flex-col gap-3">
|
|
10
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Sizes — with image</p>
|
|
11
|
+
<div className="flex items-center gap-4">
|
|
12
|
+
{SIZES.map((size) => (
|
|
13
|
+
<Avatar key={size} size={size}>
|
|
14
|
+
<AvatarImage src={DEMO_SRC} alt="User" />
|
|
15
|
+
<AvatarFallback>JD</AvatarFallback>
|
|
16
|
+
</Avatar>
|
|
17
|
+
))}
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div className="flex flex-col gap-3">
|
|
22
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Sizes — fallback (no image)</p>
|
|
23
|
+
<div className="flex items-center gap-4">
|
|
24
|
+
{SIZES.map((size) => (
|
|
25
|
+
<Avatar key={size} size={size}>
|
|
26
|
+
<AvatarFallback>OR</AvatarFallback>
|
|
27
|
+
</Avatar>
|
|
28
|
+
))}
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div className="flex flex-col gap-3">
|
|
33
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Online status indicator</p>
|
|
34
|
+
<div className="flex items-center gap-4">
|
|
35
|
+
{SIZES.map((size) => (
|
|
36
|
+
<Avatar key={size} size={size} status="online">
|
|
37
|
+
<AvatarImage src={DEMO_SRC} alt="User" />
|
|
38
|
+
<AvatarFallback>JD</AvatarFallback>
|
|
39
|
+
</Avatar>
|
|
40
|
+
))}
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div className="flex flex-col gap-3">
|
|
45
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Label group</p>
|
|
46
|
+
<div className="flex flex-col gap-4">
|
|
47
|
+
<AvatarLabelGroup size="sm" src={DEMO_SRC} name="Alice Martin" label="alice@example.com" />
|
|
48
|
+
<AvatarLabelGroup size="md" src={DEMO_SRC} name="Bob Dupont" label="bob@example.com" />
|
|
49
|
+
<AvatarLabelGroup size="md" src={DEMO_SRC} name="Charly Bernard" label="charly@example.com" status="online" />
|
|
50
|
+
<AvatarLabelGroup size="md" name="Daniel Wilson" label="daniel@example.com" />
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Story } from "@ladle/react";
|
|
2
|
+
import { AlertTriangle, CheckCircle2, XCircle } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
import { Badge } from "../components/badge";
|
|
5
|
+
|
|
6
|
+
export const AllVariants: Story = () => (
|
|
7
|
+
<div className="flex flex-col gap-6">
|
|
8
|
+
<div className="flex flex-col gap-1.5">
|
|
9
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Medium (default)</p>
|
|
10
|
+
<div className="flex items-center gap-2">
|
|
11
|
+
<Badge variant="primary">Primary</Badge>
|
|
12
|
+
<Badge>Secondary</Badge>
|
|
13
|
+
<Badge variant="success">
|
|
14
|
+
<CheckCircle2 />
|
|
15
|
+
Success
|
|
16
|
+
</Badge>
|
|
17
|
+
<Badge variant="warning">
|
|
18
|
+
<AlertTriangle />
|
|
19
|
+
Warning
|
|
20
|
+
</Badge>
|
|
21
|
+
<Badge variant="error">
|
|
22
|
+
<XCircle />
|
|
23
|
+
Error
|
|
24
|
+
</Badge>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div className="flex flex-col gap-1.5">
|
|
29
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Small</p>
|
|
30
|
+
<div className="flex items-center gap-2">
|
|
31
|
+
<Badge size="sm" variant="primary">
|
|
32
|
+
Primary
|
|
33
|
+
</Badge>
|
|
34
|
+
<Badge size="sm">Secondary</Badge>
|
|
35
|
+
<Badge size="sm" variant="success">
|
|
36
|
+
<CheckCircle2 />
|
|
37
|
+
Success
|
|
38
|
+
</Badge>
|
|
39
|
+
<Badge size="sm" variant="warning">
|
|
40
|
+
<AlertTriangle />
|
|
41
|
+
Warning
|
|
42
|
+
</Badge>
|
|
43
|
+
<Badge size="sm" variant="error">
|
|
44
|
+
<XCircle />
|
|
45
|
+
Error
|
|
46
|
+
</Badge>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Story } from "@ladle/react";
|
|
2
|
+
import { Home } from "lucide-react";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import {
|
|
5
|
+
Breadcrumb,
|
|
6
|
+
BreadcrumbChevron,
|
|
7
|
+
BreadcrumbItem,
|
|
8
|
+
BreadcrumbLink,
|
|
9
|
+
BreadcrumbList,
|
|
10
|
+
BreadcrumbPage,
|
|
11
|
+
BreadcrumbSeparator,
|
|
12
|
+
} from "../components/breadcrumb";
|
|
13
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../components/dropdown-menu";
|
|
14
|
+
|
|
15
|
+
const TREE: Record<string, string[]> = {
|
|
16
|
+
Home: ["Projects", "Settings", "Billing"],
|
|
17
|
+
Projects: ["my-mcp-server", "weather-api", "slack-bot"],
|
|
18
|
+
"my-mcp-server": ["Deployments", "Logs", "Environment"],
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const AllVariants: Story = () => {
|
|
22
|
+
const [trail, setTrail] = useState(["Home", "Projects", "my-mcp-server"]);
|
|
23
|
+
|
|
24
|
+
function handleSelect(index: number, option: string) {
|
|
25
|
+
setTrail([...trail.slice(0, index + 1), option]);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className="flex flex-col gap-10">
|
|
30
|
+
<div className="flex flex-col gap-1.5">
|
|
31
|
+
<p className="type-text-xs font-medium text-subtle-foreground">
|
|
32
|
+
Interactive — click items to navigate, click chevrons for dropdown
|
|
33
|
+
</p>
|
|
34
|
+
<Breadcrumb>
|
|
35
|
+
<BreadcrumbList>
|
|
36
|
+
{trail.map((page, index) => {
|
|
37
|
+
const isLast = index === trail.length - 1;
|
|
38
|
+
const children = TREE[page];
|
|
39
|
+
return (
|
|
40
|
+
<li key={page} className="contents">
|
|
41
|
+
{index > 0 && <BreadcrumbSeparator />}
|
|
42
|
+
<DropdownMenu>
|
|
43
|
+
<DropdownMenuTrigger asChild>
|
|
44
|
+
<BreadcrumbItem className="cursor-pointer focus-visible:ring-2 focus-visible:ring-ring outline-none">
|
|
45
|
+
{isLast ? (
|
|
46
|
+
<BreadcrumbPage>{page}</BreadcrumbPage>
|
|
47
|
+
) : (
|
|
48
|
+
<span className="type-text-sm font-medium text-subtle-foreground">{page}</span>
|
|
49
|
+
)}
|
|
50
|
+
{children && <BreadcrumbChevron />}
|
|
51
|
+
</BreadcrumbItem>
|
|
52
|
+
</DropdownMenuTrigger>
|
|
53
|
+
{children && (
|
|
54
|
+
<DropdownMenuContent align="start">
|
|
55
|
+
{children.map((child) => (
|
|
56
|
+
<DropdownMenuItem key={child} onSelect={() => handleSelect(index, child)}>
|
|
57
|
+
{child}
|
|
58
|
+
</DropdownMenuItem>
|
|
59
|
+
))}
|
|
60
|
+
</DropdownMenuContent>
|
|
61
|
+
)}
|
|
62
|
+
</DropdownMenu>
|
|
63
|
+
</li>
|
|
64
|
+
);
|
|
65
|
+
})}
|
|
66
|
+
</BreadcrumbList>
|
|
67
|
+
</Breadcrumb>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div className="flex flex-col gap-1.5">
|
|
71
|
+
<p className="type-text-xs font-medium text-subtle-foreground">With home icon (static)</p>
|
|
72
|
+
<Breadcrumb>
|
|
73
|
+
<BreadcrumbList>
|
|
74
|
+
<BreadcrumbItem>
|
|
75
|
+
<BreadcrumbLink href="#">
|
|
76
|
+
<Home className="size-5" />
|
|
77
|
+
</BreadcrumbLink>
|
|
78
|
+
</BreadcrumbItem>
|
|
79
|
+
<BreadcrumbSeparator />
|
|
80
|
+
<BreadcrumbItem>
|
|
81
|
+
<BreadcrumbLink href="#">Projects</BreadcrumbLink>
|
|
82
|
+
</BreadcrumbItem>
|
|
83
|
+
<BreadcrumbSeparator />
|
|
84
|
+
<BreadcrumbItem>
|
|
85
|
+
<BreadcrumbPage>my-mcp-server</BreadcrumbPage>
|
|
86
|
+
</BreadcrumbItem>
|
|
87
|
+
</BreadcrumbList>
|
|
88
|
+
</Breadcrumb>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<div className="flex flex-col gap-1.5">
|
|
92
|
+
<p className="type-text-xs font-medium text-subtle-foreground">Simple — two levels</p>
|
|
93
|
+
<Breadcrumb>
|
|
94
|
+
<BreadcrumbList>
|
|
95
|
+
<BreadcrumbItem>
|
|
96
|
+
<BreadcrumbLink href="#">Projects</BreadcrumbLink>
|
|
97
|
+
</BreadcrumbItem>
|
|
98
|
+
<BreadcrumbSeparator />
|
|
99
|
+
<BreadcrumbItem>
|
|
100
|
+
<BreadcrumbPage>my-mcp-server</BreadcrumbPage>
|
|
101
|
+
</BreadcrumbItem>
|
|
102
|
+
</BreadcrumbList>
|
|
103
|
+
</Breadcrumb>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
};
|