feat: add badge card avatar alert and progress
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import { Alert, AlertDescription, AlertTitle, Badge } from "@ai-ui/ui";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
function SparkIcon() {
|
||||
return (
|
||||
<svg aria-hidden="true" className="size-4" fill="none" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M8 1.75L9.45 5.2L12.9 6.65L9.45 8.1L8 11.55L6.55 8.1L3.1 6.65L6.55 5.2L8 1.75Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
const meta = {
|
||||
title: "Components/Alert",
|
||||
component: Alert,
|
||||
args: {
|
||||
variant: "default"
|
||||
},
|
||||
argTypes: {
|
||||
className: {
|
||||
control: false
|
||||
},
|
||||
icon: {
|
||||
control: false
|
||||
},
|
||||
variant: {
|
||||
control: "radio",
|
||||
options: ["default", "success", "warning", "destructive"]
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
layout: "centered"
|
||||
},
|
||||
tags: ["autodocs"]
|
||||
} satisfies Meta<typeof Alert>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Playground: Story = {
|
||||
render: (args) => (
|
||||
<Alert {...args} className="w-[460px]" icon={<SparkIcon />}>
|
||||
<AlertTitle>Release status updated</AlertTitle>
|
||||
<AlertDescription>
|
||||
The approval chain changed. Review the new ownership before publishing.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)
|
||||
};
|
||||
|
||||
export const Variants: Story = {
|
||||
render: () => (
|
||||
<div className="grid w-[760px] gap-4">
|
||||
<Alert icon={<SparkIcon />}>
|
||||
<AlertTitle>Informational callout</AlertTitle>
|
||||
<AlertDescription>
|
||||
Pair with a <Badge className="ml-1">live</Badge> badge when status can change in real time.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
<Alert icon={<SparkIcon />} variant="success">
|
||||
<AlertTitle>Release approved</AlertTitle>
|
||||
<AlertDescription>All reviewers signed off and rollout can begin.</AlertDescription>
|
||||
</Alert>
|
||||
<Alert icon={<SparkIcon />} variant="warning">
|
||||
<AlertTitle>Missing follow-up</AlertTitle>
|
||||
<AlertDescription>One checklist item is still unresolved for this launch.</AlertDescription>
|
||||
</Alert>
|
||||
<Alert icon={<SparkIcon />} variant="destructive">
|
||||
<AlertTitle>Publishing blocked</AlertTitle>
|
||||
<AlertDescription>Resolve validation issues before trying again.</AlertDescription>
|
||||
</Alert>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@ai-ui/ui";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
const avatarSrc =
|
||||
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop stop-color='%23b34f42'/%3E%3Cstop offset='1' stop-color='%23d8a26e'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='64' height='64' rx='20' fill='url(%23g)'/%3E%3Ccircle cx='32' cy='24' r='10' fill='rgba(255,255,255,0.78)'/%3E%3Cpath d='M16 54c2-10 10-16 16-16s14 6 16 16' fill='rgba(255,255,255,0.78)'/%3E%3C/svg%3E";
|
||||
|
||||
const meta = {
|
||||
title: "Components/Avatar",
|
||||
component: Avatar,
|
||||
args: {
|
||||
shape: "circle",
|
||||
size: "md",
|
||||
tone: "default"
|
||||
},
|
||||
argTypes: {
|
||||
className: {
|
||||
control: false
|
||||
},
|
||||
shape: {
|
||||
control: "radio",
|
||||
options: ["circle", "rounded"]
|
||||
},
|
||||
size: {
|
||||
control: "radio",
|
||||
options: ["sm", "md", "lg", "xl"]
|
||||
},
|
||||
tone: {
|
||||
control: "radio",
|
||||
options: ["default", "subtle", "accent"]
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
layout: "centered"
|
||||
},
|
||||
tags: ["autodocs"]
|
||||
} satisfies Meta<typeof Avatar>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Playground: Story = {
|
||||
render: (args) => (
|
||||
<Avatar {...args}>
|
||||
<AvatarImage alt="Avery Carter" src={avatarSrc} />
|
||||
<AvatarFallback>AC</AvatarFallback>
|
||||
</Avatar>
|
||||
)
|
||||
};
|
||||
|
||||
export const Sizes: Story = {
|
||||
render: () => (
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
{(["sm", "md", "lg", "xl"] as const).map((size) => (
|
||||
<Avatar key={size} size={size}>
|
||||
<AvatarImage alt={`${size} avatar`} src={avatarSrc} />
|
||||
<AvatarFallback>{size.slice(0, 2)}</AvatarFallback>
|
||||
</Avatar>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
export const Fallbacks: Story = {
|
||||
render: () => (
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
<Avatar tone="subtle">
|
||||
<AvatarFallback delayMs={0}>JD</AvatarFallback>
|
||||
</Avatar>
|
||||
<Avatar shape="rounded" size="lg" tone="accent">
|
||||
<AvatarFallback delayMs={0}>MK</AvatarFallback>
|
||||
</Avatar>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Badge } from "@ai-ui/ui";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
const meta = {
|
||||
title: "Components/Badge",
|
||||
component: Badge,
|
||||
args: {
|
||||
children: "Stable",
|
||||
size: "md",
|
||||
tone: "neutral",
|
||||
variant: "subtle"
|
||||
},
|
||||
argTypes: {
|
||||
asChild: {
|
||||
control: "boolean"
|
||||
},
|
||||
children: {
|
||||
control: "text"
|
||||
},
|
||||
className: {
|
||||
control: false
|
||||
},
|
||||
size: {
|
||||
control: "radio",
|
||||
options: ["sm", "md"]
|
||||
},
|
||||
tone: {
|
||||
control: "select",
|
||||
options: ["neutral", "primary", "success", "warning", "destructive"]
|
||||
},
|
||||
variant: {
|
||||
control: "radio",
|
||||
options: ["subtle", "solid", "outline"]
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
layout: "centered"
|
||||
},
|
||||
tags: ["autodocs"]
|
||||
} satisfies Meta<typeof Badge>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Playground: Story = {};
|
||||
|
||||
export const Matrix: Story = {
|
||||
render: () => (
|
||||
<div className="grid w-[720px] gap-4">
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<Badge>Neutral</Badge>
|
||||
<Badge tone="primary">Primary</Badge>
|
||||
<Badge tone="success">Success</Badge>
|
||||
<Badge tone="warning">Warning</Badge>
|
||||
<Badge tone="destructive">Destructive</Badge>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<Badge variant="outline">Outline</Badge>
|
||||
<Badge tone="primary" variant="outline">
|
||||
Brand
|
||||
</Badge>
|
||||
<Badge tone="success" variant="solid">
|
||||
Shipped
|
||||
</Badge>
|
||||
<Badge size="sm" tone="warning" variant="solid">
|
||||
Needs review
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@ai-ui/ui";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
const meta = {
|
||||
title: "Components/Card",
|
||||
component: Card,
|
||||
args: {
|
||||
tone: "default",
|
||||
interactive: false
|
||||
},
|
||||
argTypes: {
|
||||
className: {
|
||||
control: false
|
||||
},
|
||||
interactive: {
|
||||
control: "boolean"
|
||||
},
|
||||
tone: {
|
||||
control: "radio",
|
||||
options: ["default", "subtle", "accent"]
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
layout: "centered"
|
||||
},
|
||||
tags: ["autodocs"]
|
||||
} satisfies Meta<typeof Card>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Playground: Story = {
|
||||
render: (args) => (
|
||||
<Card {...args} className="w-[420px]">
|
||||
<CardHeader>
|
||||
<CardTitle>Release card</CardTitle>
|
||||
<CardDescription>Summarize state, ownership, and next action.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
This surface is tuned for editorial dashboards and settings views.
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button size="sm">Open</Button>
|
||||
<Button size="sm" variant="ghost">
|
||||
Dismiss
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
};
|
||||
|
||||
export const Grid: Story = {
|
||||
render: () => (
|
||||
<div className="grid w-[760px] gap-4 md:grid-cols-2">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Default tone</CardTitle>
|
||||
<CardDescription>Standard elevated panel for data and form sections.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>Reliable baseline for most admin surfaces.</CardContent>
|
||||
</Card>
|
||||
<Card interactive tone="accent">
|
||||
<CardHeader>
|
||||
<CardTitle>Interactive accent</CardTitle>
|
||||
<CardDescription>Hover-capable treatment for navigable cards.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>Use sparingly for overview screens with clear primary actions.</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
import { Progress } from "@ai-ui/ui";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
const meta = {
|
||||
title: "Components/Progress",
|
||||
component: Progress,
|
||||
args: {
|
||||
size: "md",
|
||||
value: 64,
|
||||
variant: "default"
|
||||
},
|
||||
argTypes: {
|
||||
className: {
|
||||
control: false
|
||||
},
|
||||
size: {
|
||||
control: "radio",
|
||||
options: ["sm", "md", "lg"]
|
||||
},
|
||||
tone: {
|
||||
control: "radio",
|
||||
options: ["default", "subtle"]
|
||||
},
|
||||
value: {
|
||||
control: {
|
||||
type: "range",
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1
|
||||
}
|
||||
},
|
||||
variant: {
|
||||
control: "radio",
|
||||
options: ["default", "success", "warning", "destructive"]
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
layout: "centered"
|
||||
},
|
||||
tags: ["autodocs"]
|
||||
} satisfies Meta<typeof Progress>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Playground: Story = {
|
||||
render: (args) => <Progress aria-label="Upload progress" className="w-[320px]" {...args} />
|
||||
};
|
||||
|
||||
export const Variants: Story = {
|
||||
render: () => (
|
||||
<div className="grid w-[360px] gap-4">
|
||||
<Progress aria-label="Primary progress" value={42} variant="default" />
|
||||
<Progress aria-label="Success progress" value={74} variant="success" />
|
||||
<Progress aria-label="Warning progress" value={58} variant="warning" />
|
||||
<Progress aria-label="Destructive progress" value={86} variant="destructive" />
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
export const States: Story = {
|
||||
render: () => (
|
||||
<div className="grid w-[360px] gap-4">
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-medium">Determinate</p>
|
||||
<Progress aria-label="Determinate progress" value={68} />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-medium">Indeterminate</p>
|
||||
<Progress aria-label="Indeterminate progress" value={null} variant="success" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-medium">Complete</p>
|
||||
<Progress aria-label="Complete progress" value={100} variant="success" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
Reference in New Issue
Block a user