Files
tailwind-ui-library/dev/src/pages/buttons.tsx
T
tben 73a25f54c2 Add bunext playground for local component development
Runs at http://localhost:7010 via bun run dev. The playground imports the library from src through a committed symlink and tsconfig path alias, so component edits hot-reload without a build step. It has its own install root and is excluded from the published package.
2026-10-19 04:23:07 +01:00

175 lines
6.3 KiB
TypeScript

import { useState } from "react";
import { ArrowRight, Download, Plus, Sparkles, Trash2 } from "lucide-react";
import Button, {
TWUIButtonColors,
TWUIButtonSizes,
TWUIButtonVariants,
} from "@moduletrace/twui/layout/Button";
import Divider from "@moduletrace/twui/layout/Divider";
import H1 from "@moduletrace/twui/layout/H1";
import P from "@moduletrace/twui/layout/P";
import Row from "@moduletrace/twui/layout/Row";
import Span from "@moduletrace/twui/layout/Span";
import Stack from "@moduletrace/twui/layout/Stack";
import DemoSection from "../(components)/DemoSection";
export default function ButtonsPage() {
const [saving, setSaving] = useState(false);
function save() {
setSaving(true);
window.setTimeout(() => setSaving(false), 1500);
}
return (
<Stack className="w-full gap-10">
<Stack className="gap-2">
<H1 className="!mb-0">Buttons</H1>
<P className="!pt-0 opacity-70">
Every color is paired with the three variants. Classes are
merged with <code>twMerge</code>, so a consumer{" "}
<code>className</code> always wins.
</P>
</Stack>
{TWUIButtonVariants.map((variant) => (
<DemoSection
key={variant}
title={`${variant} variant`}
description={`variant="${variant}" across TWUIButtonColors.`}
>
<Row className="gap-3">
{TWUIButtonColors.map((color) => (
<Button
key={color}
title={`${color} ${variant} button`}
color={color}
variant={variant}
>
{color}
</Button>
))}
</Row>
</DemoSection>
))}
<DemoSection
title="Sizes"
description="smaller, small, normal, large and larger."
>
<Row className="items-center gap-3">
{TWUIButtonSizes.map((size) => (
<Button
key={size}
title={`${size} button`}
size={size}
>
{size}
</Button>
))}
</Row>
</DemoSection>
<DemoSection
title="Icons and loading"
description="Icons accept a lucide name or a React element. Loading keeps the label in place and swaps in a spinner."
>
<Row className="gap-3">
<Button
title="Create button"
beforeIcon={<Plus size={16} />}
>
Create
</Button>
<Button
title="Sparkle button"
color="secondary"
afterIcon={<Sparkles size={16} />}
>
Enhance
</Button>
<Button
title="Download button"
color="success"
after_icon_name="Download"
>
Download
</Button>
<Button
title="Delete button"
color="error"
variant="outlined"
beforeIcon={<Trash2 size={16} />}
>
Delete
</Button>
<Button
title="Saving button"
color="primary"
loading={saving}
onClick={save}
>
{saving ? "Saving" : "Save changes"}
</Button>
<Button
title="Disabled button"
disabled
color="gray"
variant="outlined"
>
Disabled
</Button>
</Row>
</DemoSection>
<DemoSection
title="Links and arrows"
description="Passing href renders an anchor around the button markup."
>
<Stack className="gap-3">
<Row className="gap-3">
<Button
title="Open buttons page"
href="#"
afterIcon={<ArrowRight size={16} />}
>
Anchor button
</Button>
<Button
title="Download from link"
href="#"
color="secondary"
variant="outlined"
before_icon_name="Download"
>
Outlined link
</Button>
</Row>
<Divider />
<Row className="gap-2">
<Span variant="faded" size="small">
Sizes map to the lucide icon scale too:
</Span>
<Button
title="Smaller download"
size="smaller"
variant="ghost"
beforeIcon={<Download size={14} />}
>
Smaller
</Button>
<Button
title="Larger arrow"
size="larger"
variant="ghost"
afterIcon={<ArrowRight size={20} />}
>
Larger
</Button>
</Row>
</Stack>
</DemoSection>
</Stack>
);
}