Skip to content
Components

Button

Give an action a clear place to land. Choose its emphasis, size and disabled state.

TS
import { … } from "@fungi.computer/caps/components/button";

Variants

TSX
import { Button } from "@fungi.computer/caps/components/button";
export default function Variants() {
return (
<div className="flex flex-wrap items-center gap-2">
<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="accent">Accent</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Delete</Button>
<Button variant="link">Link</Button>
</div>
);
}

Sizes

TSX
import { Button } from "@fungi.computer/caps/components/button";
export default function Sizes() {
return (
<div className="flex flex-wrap items-center gap-2">
<Button size="xs">Extra small</Button>
<Button size="sm">Small</Button>
<Button>Default</Button>
<Button size="lg">Large</Button>
</div>
);
}

Loading and result

TSX
import {
Button,
type ButtonResult,
} from "@fungi.computer/caps/components/button";
import { useState } from "react";
export default function LoadingAndResult() {
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<ButtonResult | undefined>();
const install = () => {
setResult(undefined);
setLoading(true);
window.setTimeout(() => {
setLoading(false);
setResult("done");
}, 900);
};
return (
<div className="flex flex-wrap items-center gap-2">
<Button
loading={loading}
result={result}
resultLabel="Installed"
onResultEnd={() => {
setResult(undefined);
}}
onClick={install}
>
Install
</Button>
<Button
variant="outline"
onClick={() => {
setResult("failed");
}}
>
Fail
</Button>
<Button disabled>Disabled</Button>
</div>
);
}

Icon and full width

TSX
import { Button } from "@fungi.computer/caps/components/button";
function MushroomIcon() {
return (
<svg
aria-hidden="true"
fill="currentColor"
height={16}
viewBox="0 0 24 24"
width={16}
>
<path d="M12 2c5 0 9 3 9 7H3c0-4 4-7 9-7Z" />
<rect x="10" y="9" width="4" height="11" rx="1.5" />
</svg>
);
}
export default function IconAndFullWidth() {
return (
<div className="flex w-full max-w-sm flex-col gap-2">
<Button className="w-full" variant="secondary">
<MushroomIcon />
Start foraging
</Button>
<Button className="w-full" variant="outline">
Save for later
</Button>
</div>
);
}

Props

ButtonProps

PropTypeDescription
asChild?boolean
loading?boolean
result?"done" | "failed"The outcome of the last action. Becoming done plays a short beat: a check (and resultLabel) springs in, holds, then settles back to the label. Becoming failed shakes the label by the theme's --stipe-motion-shake. Say what failed elsewhere, next to the action.
resultLabel?ReactNodeWhat the done beat says, such as "Installed". The button keeps the wider of its two labels, so nothing shifts.
onResultEnd()?() => voidCalled when the done beat has held long enough to read, just before it would settle back to the label. Replace the button here to hand off to what comes next (an "Installed" mark, an "Open" action).
size?"xs" | "sm" | "default" | "lg" | "icon" | "menubar"
variant?"primary" | "secondary" | "accent" | "destructive" | "outline" | "ghost" | "ghost-destructive" | "link"
  • asChild?boolean
  • loading?boolean
  • result?"done" | "failed"

    The outcome of the last action. Becoming done plays a short beat: a check (and resultLabel) springs in, holds, then settles back to the label. Becoming failed shakes the label by the theme's --stipe-motion-shake. Say what failed elsewhere, next to the action.

  • resultLabel?ReactNode

    What the done beat says, such as "Installed". The button keeps the wider of its two labels, so nothing shifts.

  • onResultEnd()?() => void

    Called when the done beat has held long enough to read, just before it would settle back to the label. Replace the button here to hand off to what comes next (an "Installed" mark, an "Open" action).

  • size?"xs" | "sm" | "default" | "lg" | "icon" | "menubar"
  • variant?"primary" | "secondary" | "accent" | "destructive" | "outline" | "ghost" | "ghost-destructive" | "link"

Full types: API reference.