Skip to content
Dethink Components

ComponentsButton

Button

Run an action, such as saving a form or opening a dialog.

On this page

Use this component from the local workspace package. Follow the setup guide first. A public npm package and registry are not available yet.

View registry files

Import the component into your page or component file.

Usage
import { Button } from "@dethink/components";

export function Example() {
  return <Button variant="soft">Get started</Button>;
}

Try the examples, then open the code to use them in your app.

Variants

Use solid for the main action, outline for secondary actions, and destructive for actions such as deleting.

Show sourceexamples/button/variants.tsx
examples/button/variants.tsx
"use client";

import { Button } from "@dethink/components";

export function ButtonVariants() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-3">
      <Button variant="solid">Solid</Button>
      <Button variant="soft">Soft</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="link">Link</Button>
      <Button variant="destructive">Destructive</Button>
    </div>
  );
}

Sizes

Choose a size from xs to xl. Use IconButton for an action with no visible label.

Show sourceexamples/button/sizes.tsx
examples/button/sizes.tsx
"use client";

import { Button } from "@dethink/components";
import { Plus } from "lucide-react";

export function ButtonSizes() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-3">
      <Button size="xs">Extra small</Button>
      <Button size="sm">Small</Button>
      <Button size="md">Medium</Button>
      <Button size="lg">Large</Button>
      <Button size="xl">Extra large</Button>
      <Button size="icon" aria-label="Add item">
        <Plus className="size-4" />
      </Button>
    </div>
  );
}

With icons

Add an icon before or after the label with leftIcon or rightIcon. Keep the label clear without the icon.

Show sourceexamples/button/icons.tsx
examples/button/icons.tsx
"use client";

import { Button } from "@dethink/components";
import { ArrowRight, Mail, Sparkles } from "lucide-react";

export function ButtonIcons() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-3">
      <Button leftIcon={<Mail />}>Email us</Button>
      <Button variant="soft" rightIcon={<ArrowRight />}>
        Continue
      </Button>
      <Button
        variant="outline"
        leftIcon={<Sparkles />}
        rightIcon={<ArrowRight />}
      >
        Generate
      </Button>
    </div>
  );
}

Loading and disabled

Set loading while an action is running. It shows a spinner and prevents extra clicks.

Show sourceexamples/button/loading.tsx
examples/button/loading.tsx
"use client";

import { useState } from "react";
import { Button } from "@dethink/components";

export function ButtonLoading() {
  const [saving, setSaving] = useState(false);

  function save() {
    setSaving(true);
    setTimeout(() => setSaving(false), 1500);
  }

  return (
    <div className="flex flex-wrap items-center justify-center gap-3">
      <Button loading={saving} onClick={save}>
        {saving ? "Saving…" : "Save changes"}
      </Button>
      <Button variant="soft" loading>
        Processing
      </Button>
      <Button variant="outline" disabled>
        Disabled
      </Button>
    </div>
  );
}

Use asChild to style a link as a button. The link still takes users to another page.

Also accepts standard button props, such as onClick, type, and aria-label.

Button props
PropWhat it doesDefault
variant"solid" | "soft" | "outline" | "ghost" | "link" | "destructive"Sets the button style. Use solid for the main action or outline for a secondary action."solid"
size"xs" | "sm" | "md" | "lg" | "xl" | "icon"Sets the button size. The "icon" size is square and needs an aria-label."md"
loadingbooleanShows a spinner and blocks clicks while an action is running. Sets aria-busy for screen readers.false
leftIconReactNodeAn icon before the label. Screen readers read the label and ignore the icon.Not set
rightIconReactNodeAn icon after the label. Screen readers read the label and ignore the icon.Not set
asChildbooleanApplies button styles and behavior to its single child, such as a link.false
disabledbooleanBlocks interaction. Also enabled automatically while loading.false