Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
8d4da73
feat(storybook): move and expand Card story
myelinated-wackerow May 5, 2026
871be2d
feat(storybook): expand Tag story coverage
myelinated-wackerow May 5, 2026
8bcda06
feat(storybook): expand Table story coverage
myelinated-wackerow May 5, 2026
f06e0bf
feat(storybook): expand Alert story coverage
myelinated-wackerow May 5, 2026
c8a404c
feat(storybook): expand Button story coverage
myelinated-wackerow May 5, 2026
6eba98c
feat(storybook): expand ButtonLink story coverage
myelinated-wackerow May 5, 2026
6d14f79
feat(storybook): expand ButtonTwoLines story coverage
myelinated-wackerow May 5, 2026
b3d293e
feat(storybook): expand ButtonLinkTwoLines story coverage
myelinated-wackerow May 5, 2026
4e64bdf
feat(storybook): expand Link story coverage
myelinated-wackerow May 5, 2026
165ddff
feat(storybook): expand Accordion story coverage
myelinated-wackerow May 5, 2026
9bd35ca
feat(storybook): expand EdgeScrollContainer story coverage
myelinated-wackerow May 5, 2026
a80e931
feat(storybook): expand Avatar story coverage
myelinated-wackerow May 5, 2026
0ca3837
feat(storybook): expand TerminalTypewriter story coverage
myelinated-wackerow May 5, 2026
9e45eee
chore(storybook): remove ButtonTwoLines story
myelinated-wackerow May 6, 2026
a155874
chore(storybook): remove ButtonLinkTwoLines story
myelinated-wackerow May 6, 2026
d22020d
chore(storybook): disable Chromatic snapshots on new expand stories
myelinated-wackerow May 13, 2026
612b113
fix: consolidate `parameters` values
wackerow Jun 1, 2026
3a34107
Merge branch 'dev' into feat/storybook-expand-existing-stories
wackerow Jun 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions src/components/ui/__stories__/Accordion.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import type { Meta, StoryObj } from "@storybook/nextjs"

import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "../accordion"

const meta = {
title: "UI / Accordion",
component: Accordion,
decorators: [
(Story) => (
<div className="w-[420px]">
<Story />
</div>
),
],
parameters: {
chromatic: { disableSnapshot: true },
docs: {
description: {
component:
"Vertically-stacked disclosure built on Radix Accordion. `type='single'` allows only one open at a time (with optional `collapsible`); `type='multiple'` allows any combination. The chevron icon flips for RTL via `:dir(rtl)` and rotates open via `data-state=open`. Pass `hideIcon` to suppress the chevron and provide your own visual cue.",
},
},
},
} satisfies Meta<typeof Accordion>

export default meta

type Story = StoryObj

const SAMPLE = [
{
id: "item-1",
title: "What is Ethereum?",
body: "Ethereum is open access to digital money and data-friendly services for everyone -- no matter your background or location.",
},
{
id: "item-2",
title: "What is a layer 2?",
body: "Layer 2 networks scale Ethereum by handling transactions off the main chain while inheriting its security guarantees.",
},
{
id: "item-3",
title: "What is a validator?",
body: "Validators secure the network by proposing and attesting to blocks.",
},
]

export const SingleCollapsible: Story = {
parameters: {
docs: {
description: {
story:
"`type='single' collapsible` allows only one item open at a time, with the option to close the active item.",
},
},
},
render: () => (
<Accordion type="single" collapsible defaultValue="item-1">
{SAMPLE.map((item) => (
<AccordionItem key={item.id} value={item.id}>
<AccordionTrigger>{item.title}</AccordionTrigger>
<AccordionContent>{item.body}</AccordionContent>
</AccordionItem>
))}
</Accordion>
),
}

export const Multiple: Story = {
parameters: {
docs: {
description: {
story:
"`type='multiple'` allows any combination of items to be open simultaneously.",
},
},
},
render: () => (
<Accordion type="multiple" defaultValue={["item-1", "item-3"]}>
{SAMPLE.map((item) => (
<AccordionItem key={item.id} value={item.id}>
<AccordionTrigger>{item.title}</AccordionTrigger>
<AccordionContent>{item.body}</AccordionContent>
</AccordionItem>
))}
</Accordion>
),
}

export const HideIcon: Story = {
parameters: {
docs: {
description: {
story:
"`hideIcon` on `AccordionTrigger` removes the default chevron. Useful when supplying a custom visual cue.",
},
},
},
render: () => (
<Accordion type="single" collapsible defaultValue="item-1">
{SAMPLE.map((item) => (
<AccordionItem key={item.id} value={item.id}>
<AccordionTrigger hideIcon>{item.title}</AccordionTrigger>
<AccordionContent>{item.body}</AccordionContent>
</AccordionItem>
))}
</Accordion>
),
}

export const CustomTrigger: Story = {
parameters: {
docs: {
description: {
story:
"Build a custom trigger by passing structured children to `AccordionTrigger`. The default chevron stays at the end.",
},
},
},
render: () => (
<Accordion type="single" collapsible>
{SAMPLE.map((item, idx) => (
<AccordionItem key={item.id} value={item.id}>
<AccordionTrigger>
<span className="flex items-center gap-3">
<span className="grid size-6 place-items-center rounded-full bg-primary-low-contrast text-xs text-primary-high-contrast">
{idx + 1}
</span>
<span>{item.title}</span>
</span>
</AccordionTrigger>
<AccordionContent>{item.body}</AccordionContent>
</AccordionItem>
))}
</Accordion>
),
}

export const RtlChevron: Story = {
parameters: {
docs: {
description: {
story:
"The chevron uses `ChevronNext`, which rotates for RTL locales via `:dir(rtl)`. Toggle the locale in the Storybook toolbar to see the flip.",
},
},
},
render: () => (
<Accordion type="single" collapsible defaultValue="item-1">
<AccordionItem value="item-1">
<AccordionTrigger>Toggle locale to test RTL flip</AccordionTrigger>
<AccordionContent>
When the locale is RTL (Arabic, Urdu), the chevron points the other
way to match reading direction.
</AccordionContent>
</AccordionItem>
</Accordion>
),
}
71 changes: 70 additions & 1 deletion src/components/ui/__stories__/Alert.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Info } from "lucide-react"
import { Meta, StoryObj } from "@storybook/nextjs"
import type { Meta, StoryObj } from "@storybook/nextjs"

import {
Alert,
AlertCloseButton,
AlertContent,
AlertDescription,
AlertEmoji,
AlertIcon,
AlertTitle,
} from "../alert"
Expand All @@ -15,6 +16,12 @@ const meta = {
title: "Molecules / Action Feedback / Alerts",
component: Alert,
parameters: {
docs: {
description: {
component:
"Inline alert/callout. Six `variant` colors (`info | error | success | warning | update | banner`); `banner` renders edge-to-edge with no border-radius for top-of-page use. Sub-components: `AlertContent`, `AlertTitle`, `AlertDescription`, `AlertIcon` (lucide or other SVG), `AlertEmoji`, `AlertCloseButton`.",
},
},
layout: "none",
},
decorators: [
Expand All @@ -35,7 +42,26 @@ const DEMO_DESC = "This is an alert to be used for important information."

const VARIANTS = ["info", "error", "success", "warning", "update"] as const

export const Default: Story = {
parameters: { chromatic: { disableSnapshot: true } },
render: (args) => (
<Alert className="w-lg" {...args}>
<AlertContent>
<AlertTitle>{DEMO_TITLE}</AlertTitle>
<AlertDescription>{DEMO_DESC}</AlertDescription>
</AlertContent>
</Alert>
),
}

export const Variants: Story = {
parameters: {
docs: {
description: {
story: "All five `variant` options stacked for visual comparison.",
},
},
},
render: (args) => (
<div className="flex w-lg flex-col gap-4">
{VARIANTS.map((variant) => (
Expand Down Expand Up @@ -67,6 +93,14 @@ export const WithCloseButton: Story = {
}

export const WithIcon: Story = {
parameters: {
docs: {
description: {
story:
"`AlertIcon` wraps an SVG icon with `[&>svg]:size-6` to constrain size. Icon color inherits from the variant via the alert's `**:[svg]:text-*` class.",
},
},
},
render: (args) => (
<div className="flex flex-col gap-4">
{VARIANTS.map((variant) => (
Expand All @@ -84,6 +118,41 @@ export const WithIcon: Story = {
),
}

export const WithEmoji: Story = {
parameters: {
chromatic: { disableSnapshot: true },
docs: {
description: {
story:
"`AlertEmoji` renders the project's `Emoji` component at `text-4xl` aligned to the start of the alert.",
},
},
},
render: (args) => (
<div className="flex w-lg flex-col gap-4">
<Alert variant="update" {...args}>
<AlertEmoji text=":party_popper:" />
<AlertContent>
<AlertTitle>New feature</AlertTitle>
<AlertDescription>
Layer 2 network filtering is now live across the dapps directory.
</AlertDescription>
</AlertContent>
</Alert>
<Alert variant="info" {...args}>
<AlertEmoji text=":information_source:" />
<AlertContent>
<AlertTitle>Did you know?</AlertTitle>
<AlertDescription>
Validators secure the Ethereum network by proposing and attesting to
blocks.
</AlertDescription>
</AlertContent>
</Alert>
</div>
),
}

export const Banner: Story = {
render: (args) => (
<div className="w-full max-w-(--breakpoint-2xl)">
Expand Down
Loading
Loading