Button
A versatile button component powered by the shared useButtonBase hook for consistent behavior (focus, disabled/loading guards, optional toggle state, and ARIA).
Demo
Usage
- TypeScript
- JavaScript
import React, { useState } from "react";
import { Button } from "@libdev-ui/base";
export default function Example(): JSX.Element {
const [pressed, setPressed] = useState<boolean>(false);
return (
<div style={{ display: "grid", gap: 12, maxWidth: 520 }}>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button>Default</Button>
<Button variant="outlined">Outlined</Button>
<Button variant="ghost">Ghost</Button>
</div>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button color="primary">Primary</Button>
<Button color="secondary">Secondary</Button>
<Button color="success">Success</Button>
<Button color="danger">Danger</Button>
<Button color="warning">Warning</Button>
<Button color="info">Info</Button>
<Button color="var(--color-accent)">Custom var()</Button>
</div>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button loading>Loading…</Button>
<Button disabled>Disabled</Button>
</div>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button toggleable pressed={pressed} onPressedChange={setPressed}>
{pressed ? "On" : "Off"}
</Button>
<Button preventFocusOnPress>Prevent focus on press</Button>
</div>
</div>
);
}
import React, { useState } from "react";
import { Button } from "@libdev-ui/base";
export default function Example() {
const [pressed, setPressed] = useState(false);
return (
<div style={{ display: "grid", gap: 12, maxWidth: 520 }}>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button>Default</Button>
<Button variant="outlined">Outlined</Button>
<Button variant="ghost">Ghost</Button>
</div>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button color="primary">Primary</Button>
<Button color="secondary">Secondary</Button>
<Button color="success">Success</Button>
<Button color="danger">Danger</Button>
<Button color="warning">Warning</Button>
<Button color="info">Info</Button>
<Button color="var(--color-accent)">Custom var()</Button>
</div>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button loading>Loading…</Button>
<Button disabled>Disabled</Button>
</div>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<Button toggleable pressed={pressed} onPressedChange={setPressed}>
{pressed ? "On" : "Off"}
</Button>
<Button preventFocusOnPress>Prevent focus on press</Button>
</div>
</div>
);
}
Variants
- TypeScript
- JavaScript
import { Button } from "@libdev-ui/base";
export default function VariantsDemo(): JSX.Element {
return (
<div style={{ display: "grid", gap: 12 }}>
<Button variant="filled">Filled (default)</Button>
<Button variant="outlined">Outlined</Button>
<Button variant="ghost">Ghost</Button>
</div>
);
}
import { Button } from "@libdev-ui/base";
export default function VariantsDemo() {
return (
<div style={{ display: "grid", gap: 12 }}>
<Button variant="filled">Filled (default)</Button>
<Button variant="outlined">Outlined</Button>
<Button variant="ghost">Ghost</Button>
</div>
);
}
Sizes
- TypeScript
- JavaScript
import { Button } from "@libdev-ui/base";
export default function SizesDemo(): JSX.Element {
return (
<div style={{ display: "grid", gap: 12 }}>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
);
}
import { Button } from "@libdev-ui/base";
export default function SizesDemo() {
return (
<div style={{ display: "grid", gap: 12 }}>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
);
}
Colors
- TypeScript
- JavaScript
import { Button } from "@libdev-ui/base";
export default function ColorsDemo(): JSX.Element {
return (
<div style={{ display: "grid", gap: 12, flexWrap: "wrap" }}>
<Button color="primary">Primary</Button>
<Button color="secondary">Secondary</Button>
<Button color="success">Success</Button>
<Button color="danger">Danger</Button>
<Button color="warning">Warning</Button>
<Button color="info">Info</Button>
<Button color="var(--color-accent)">Custom var()</Button>
<Button color="#22c55e">Custom HEX</Button>
</div>
);
}
import { Button } from "@libdev-ui/base";
export default function ColorsDemo() {
return (
<div style={{ display: "grid", gap: 12, flexWrap: "wrap" }}>
<Button color="primary">Primary</Button>
<Button color="secondary">Secondary</Button>
<Button color="success">Success</Button>
<Button color="danger">Danger</Button>
<Button color="warning">Warning</Button>
<Button color="info">Info</Button>
<Button color="var(--color-accent)">Custom var()</Button>
<Button color="#22c55e">Custom HEX</Button>
</div>
);
}
Toggle
- TypeScript
- JavaScript
import React, { useState } from "react";
import { Button } from "@libdev-ui/base";
export default function ToggleDemo(): JSX.Element {
const [pressed, setPressed] = useState<boolean>(false);
return (
<Button toggleable pressed={pressed} onPressedChange={setPressed}>
{pressed ? "On" : "Off"}
</Button>
);
}
import React, { useState } from "react";
import { Button } from "@libdev-ui/base";
export default function ToggleDemo() {
const [pressed, setPressed] = useState(false);
return (
<Button toggleable pressed={pressed} onPressedChange={setPressed}>
{pressed ? "On" : "Off"}
</Button>
);
}
Loading & Disabled
- TypeScript
- JavaScript
import { Button } from "@libdev-ui/base";
export default function StatesDemo(): JSX.Element {
return (
<div style={{ display: "grid", gap: 12 }}>
<Button loading>Loading…</Button>
<Button disabled>Disabled</Button>
</div>
);
}
import { Button } from "@libdev-ui/base";
export default function StatesDemo() {
return (
<div style={{ display: "grid", gap: 12 }}>
<Button loading>Loading…</Button>
<Button disabled>Disabled</Button>
</div>
);
}
Prevent focus on press
- TypeScript
- JavaScript
import { Button } from "@libdev-ui/base";
export default function FocusDemo(): JSX.Element {
return <Button preventFocusOnPress>Click me without focusing</Button>;
}
import { Button } from "@libdev-ui/base";
export default function FocusDemo() {
return <Button preventFocusOnPress>Click me without focusing</Button>;
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Button content. |
variant | "filled" | "outlined" | "ghost" | "filled" | Visual variant. |
color | "primary" | "secondary" | "success" | "danger" | "warning" | "info" | string | "primary" | Palette token or custom CSS color (e.g., var(--brand), #22c55e). |
size | "sm" | "md" | "lg" | "md" | Size token. |
radius | "sm" | "md" | "lg" | "md" | Corner radius token. |
disabled | boolean | false | Disables interaction. |
loading | boolean | false | Adds aria-busy and disables interaction. |
preventFocusOnPress | boolean | false | Prevents browser auto-focus on mousedown. |
autoFocus | boolean | false | Focus on mount. |
toggleable | boolean | false | Enables toggle behavior. |
pressed | boolean | — | Controlled pressed state. |
defaultPressed | boolean | false | Uncontrolled initial pressed state. |
onPressedChange | (pressed: boolean) => void | — | Fired when pressed changes. |
sl | React.CSSProperties | — | Escape hatch for inline styles. |
| …native | Standard <button> attributes | — | type, name, value, events, etc. |
Accessibility:
useButtonBaseautomatically addsaria-disabled,aria-busy, and whentoggleableis set —aria-pressed.
Data attributes (styling)
Added on the root wrapper (via useButtonBase):
data-focused— element has DOM focusdata-focus-visible— keyboard (focus-ring) focusdata-disabled— disabled statedata-loading— loading statedata-pressed— whentoggleableand pressed
Theming (CSS variables)
:root {
--color-primary: #3b82f6;
--color-secondary:#64748b;
--color-success: #22c55e;
--color-danger: #ef4444;
--color-warning: #f59e0b;
--color-info: #0ea5e9;
--radius-sm: 6px;
--radius-md: 10px;
--radius-lg: 14px;
}
Related hook
See useButtonBase for the centralized behavior and ARIA details.