Github

Button

Displays a button or a component that looks like a button.

import { ArrowUpIcon } from "lucide-react";
import { Button } from "@/components/ui/button";

export function ButtonDemo() {
	return (
		<div className="flex gap-3">
			<Button>Button</Button>
			<Button size="icon">
				<ArrowUpIcon />
			</Button>
		</div>
	);
}

Installation

pnpm dlx shadcn@latest add https://herocn.dev/r/button.json

Usage

import { Button } from "@/components/ui/button"
<Button>Click me</Button>

Variants

import { Button } from "@/components/ui/button";

function ButtonVariants() {
	return (
		<div className="flex flex-wrap items-center gap-3">
			<Button variant="default">Default</Button>
			<Button variant="secondary">Secondary</Button>
			<Button variant="tertiary">Tertiary</Button>
			<Button variant="outline">Outline</Button>
			<Button variant="ghost">Ghost</Button>
			<Button variant="link">Link</Button>
			<Button variant="destructive">Destructive</Button>
			<Button variant="destructive-soft">Destructive Soft</Button>
		</div>
	);
}

export ButtonVariants;

Sizes

import { SearchIcon } from "lucide-react";
import { Button } from "@/components/ui/button";

export function ButtonSizes() {
	return (
		<div className="flex flex-wrap items-center gap-3">
			<Button size="xs">Extra Small</Button>
			<Button size="sm">Small</Button>
			<Button>Default</Button>
			<Button size="lg">Large</Button>
			<Button size="icon-xs">
				<SearchIcon />
			</Button>
			<Button size="icon-sm">
				<SearchIcon />
			</Button>
			<Button size="icon">
				<SearchIcon />
			</Button>
			<Button size="icon-lg">
				<SearchIcon />
			</Button>
		</div>
	);
}

With icons

import {
	ArrowRightIcon,
	DownloadIcon,
	SearchIcon,
	Trash2Icon,
} from "lucide-react";
import { Button } from "@/components/ui/button";

export function ButtonIcons() {
	return (
		<div className="flex flex-wrap items-center gap-3">
			<Button>
				<SearchIcon data-icon="inline-start" />
				Search
			</Button>
			<Button variant="secondary">
				<DownloadIcon data-icon="inline-start" />
				Download
			</Button>
			<Button variant="outline">
				Next
				<ArrowRightIcon data-icon="inline-end" />
			</Button>
			<Button variant="destructive">
				Delete <Trash2Icon data-icon="inline-end" />
			</Button>
		</div>
	);
}

You can use the buttonVariants helper to make a link look like a button.

Do not use <Button render={<a />} nativeButton={false} /> for links. The Base UI Button component always applies role="button", which overrides the semantic link role on <a> elements. Use buttonVariants with a plain <a> tag instead.

"use client";
import { buttonVariants } from "@/components/ui/button";

export function ButtonRender() {
	return (
		<a
			href="#"
			className={buttonVariants({ variant: "secondary", size: "sm" })}
		>
			Login
		</a>
	);
}

RTL

"use client";

import { ArrowRightIcon, PlusIcon } from "lucide-react";
import {
	type Translations,
	useTranslation,
} from "@/components/language-selector";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";

const translations: Translations = {
	en: {
		dir: "ltr",
		values: {
			button: "Button",
			submit: "Submit",
			delete: "Delete",
			loading: "Loading",
		},
	},
	ar: {
		dir: "rtl",
		values: {
			button: "زر",
			submit: "إرسال",
			delete: "حذف",
			loading: "جاري التحميل",
		},
	},
	he: {
		dir: "rtl",
		values: {
			button: "כפתור",
			submit: "שלח",
			delete: "מחק",
			loading: "טוען",
		},
	},
};

export function ButtonRtl() {
	const { dir, language, t } = useTranslation(translations, "ar");

	return (
		<div
			className="flex flex-wrap items-center gap-2 md:flex-row"
			lang={language}
			dir={dir}
		>
			<Button variant="secondary">{t.button}</Button>
			<Button variant="destructive">{t.delete}</Button>
			<Button variant="secondary">
				{t.submit}
				<ArrowRightIcon className="rtl:rotate-180" data-icon="inline-end" />
			</Button>
			<Button variant="secondary" size="icon" aria-label="Add">
				<PlusIcon />
			</Button>
			<Button variant="tertiary" disabled>
				<Spinner data-icon="inline-start" /> {t.loading}
			</Button>
		</div>
	);
}

Reference

Props

The Button component accepts all props from @base-ui-components/react Button plus the following:

PropTypeDefault
variant"default" | "outline" | "secondary" | "tertiary" | "ghost" | "destructive" | "destructive-soft"
"default"
size"default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg"
"default"