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>
);
}
pnpm dlx shadcn@latest add https://herocn.dev/r/button.jsonimport { Button } from "@/components/ui/button"<Button>Click me</Button>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;
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>
);
}
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>
);
}
"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>
);
}
The Button component accepts all props from @base-ui-components/react Button plus the following:
| Prop | Type | Default |
|---|---|---|
| variant | "default" | "outline" | "secondary" | "tertiary" | "ghost" | "destructive" | "destructive-soft" | "default" |
| size | "default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg" | "default" |