Skip to main content

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

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>
);
}

Variants

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>
);
}

Sizes

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>
);
}

Colors

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>
);
}

Toggle

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>
);
}

Loading & Disabled

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>
);
}

Prevent focus on press

import { Button } from "@libdev-ui/base";

export default function FocusDemo(): JSX.Element {
return <Button preventFocusOnPress>Click me without focusing</Button>;
}

Props

PropTypeDefaultDescription
childrenReactNodeButton 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.
disabledbooleanfalseDisables interaction.
loadingbooleanfalseAdds aria-busy and disables interaction.
preventFocusOnPressbooleanfalsePrevents browser auto-focus on mousedown.
autoFocusbooleanfalseFocus on mount.
toggleablebooleanfalseEnables toggle behavior.
pressedbooleanControlled pressed state.
defaultPressedbooleanfalseUncontrolled initial pressed state.
onPressedChange(pressed: boolean) => voidFired when pressed changes.
slReact.CSSPropertiesEscape hatch for inline styles.
…nativeStandard <button> attributestype, name, value, events, etc.

Accessibility: useButtonBase automatically adds aria-disabled, aria-busy, and when toggleable is set — aria-pressed.


Data attributes (styling)

Added on the root wrapper (via useButtonBase):

  • data-focused — element has DOM focus
  • data-focus-visible — keyboard (focus-ring) focus
  • data-disabled — disabled state
  • data-loading — loading state
  • data-pressed — when toggleable and 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;
}

See useButtonBase for the centralized behavior and ARIA details.