Button
Displays a button or a component that looks like a button.
The Button component is built on top of Kobalte Button, which provides the accessible button primitive.
import { ArrowUpIcon } from "lucide-solid";import { Button } from "~/components/ui/button";
export default function ButtonDemo() { return ( <div class="flex flex-wrap items-center gap-2 md:flex-row"> <Button variant="outline">Button</Button> <Button variant="outline" size="icon" aria-label="Submit"> <ArrowUpIcon /> </Button> </div> );}Installation
Usage
import { Button } from "~/components/ui/button";<Button variant="outline">Button</Button>Cursor
Tailwind v4 switched from cursor: pointer to cursor: default for button elements.
If you want to keep the cursor: pointer behavior, add the following code to your CSS file:
@layer base { button:not(:disabled), [role="button"]:not(:disabled) { cursor: pointer; }}Size
Use the size prop to change the size of the button.
import { ArrowUpRightIcon } from "lucide-solid";import { Button } from "~/components/ui/button";
export default function ButtonSize() { return ( <div class="flex flex-col items-start gap-8 sm:flex-row"> <div class="flex items-start gap-2"> <Button size="xs" variant="outline"> Extra Small </Button> <Button size="icon-xs" aria-label="Submit" variant="outline"> <ArrowUpRightIcon /> </Button> </div> <div class="flex items-start gap-2"> <Button size="sm" variant="outline"> Small </Button> <Button size="icon-sm" aria-label="Submit" variant="outline"> <ArrowUpRightIcon /> </Button> </div> <div class="flex items-start gap-2"> <Button variant="outline">Default</Button> <Button size="icon" aria-label="Submit" variant="outline"> <ArrowUpRightIcon /> </Button> </div> <div class="flex items-start gap-2"> <Button variant="outline" size="lg"> Large </Button> <Button size="icon-lg" aria-label="Submit" variant="outline"> <ArrowUpRightIcon /> </Button> </div> </div> );}Default
import { Button } from "~/components/ui/button";
export default function ButtonDefault() { return <Button>Button</Button>;}Outline
import { Button } from "~/components/ui/button";
export default function ButtonOutline() { return <Button variant="outline">Outline</Button>;}Secondary
import { Button } from "~/components/ui/button";
export default function ButtonSecondary() { return <Button variant="secondary">Secondary</Button>;}Ghost
import { Button } from "~/components/ui/button";
export default function ButtonGhost() { return <Button variant="ghost">Ghost</Button>;}Destructive
import { Button } from "~/components/ui/button";
export default function ButtonDestructive() { return <Button variant="destructive">Destructive</Button>;}Link
import { Button } from "~/components/ui/button";
export default function ButtonLink() { return <Button variant="link">Link</Button>;}Icon
import { CircleFadingArrowUpIcon } from "lucide-solid";import { Button } from "~/components/ui/button";
export default function ButtonIcon() { return ( <Button variant="outline" size="icon" aria-label="Move up"> <CircleFadingArrowUpIcon /> </Button> );}With Icon
Add the data-icon="inline-start" or data-icon="inline-end" attribute to an icon for correct spacing.
import { GitBranchIcon, GitForkIcon } from "lucide-solid";import { Button } from "~/components/ui/button";
export default function ButtonWithIcon() { return ( <div class="flex gap-2"> <Button variant="outline"> <GitBranchIcon data-icon="inline-start" /> New Branch </Button> <Button variant="outline"> Fork <GitForkIcon data-icon="inline-end" /> </Button> </div> );}Rounded
Use the rounded-full class to make a button rounded.
import { ArrowUpIcon } from "lucide-solid";import { Button } from "~/components/ui/button";
export default function ButtonRounded() { return ( <div class="flex gap-2"> <Button class="rounded-full">Get Started</Button> <Button variant="outline" size="icon" class="rounded-full" aria-label="Move up"> <ArrowUpIcon /> </Button> </div> );}Spinner
Render a <Spinner /> inside the button to show a loading state. Add data-icon="inline-start" or data-icon="inline-end" to the spinner for correct spacing.
import { Button } from "~/components/ui/button";import { Spinner } from "~/components/ui/spinner";
export default function ButtonSpinner() { return ( <div class="flex gap-2"> <Button variant="outline" disabled> <Spinner data-icon="inline-start" /> Generating </Button> <Button variant="secondary" disabled> Downloading <Spinner data-icon="inline-end" /> </Button> </div> );}Button Group
To create a button group, use the ButtonGroup component. See the Button Group documentation for more details.
import { ArchiveIcon, ArrowLeftIcon, CalendarPlusIcon, ClockIcon, ListFilterIcon, MailCheckIcon, MoreHorizontalIcon, TagIcon, Trash2Icon,} from "lucide-solid";import { createSignal } from "solid-js";import { Button } from "~/components/ui/button";import { ButtonGroup } from "~/components/ui/button-group";import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger,} from "~/components/ui/dropdown-menu";
export default function ButtonGroupDemo() { const [label, setLabel] = createSignal("personal");
return ( <ButtonGroup> <ButtonGroup class="hidden sm:flex"> <Button variant="outline" size="icon" aria-label="Go back"> <ArrowLeftIcon /> </Button> </ButtonGroup> <ButtonGroup> <Button variant="outline">Archive</Button> <Button variant="outline">Report</Button> </ButtonGroup> <ButtonGroup> <Button variant="outline">Snooze</Button> <DropdownMenu placement="bottom-end"> <DropdownMenuTrigger as={Button} variant="outline" size="icon" class="w-fit" aria-label="More options" > <MoreHorizontalIcon /> </DropdownMenuTrigger> <DropdownMenuContent class="w-40"> <DropdownMenuGroup> <DropdownMenuItem> <MailCheckIcon /> Mark as Read </DropdownMenuItem> <DropdownMenuItem> <ArchiveIcon /> Archive </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem> <ClockIcon /> Snooze </DropdownMenuItem> <DropdownMenuItem> <CalendarPlusIcon /> Add to Calendar </DropdownMenuItem> <DropdownMenuItem> <ListFilterIcon /> Add to List </DropdownMenuItem> <DropdownMenuSub> <DropdownMenuSubTrigger> <TagIcon /> Label As... </DropdownMenuSubTrigger> <DropdownMenuSubContent> <DropdownMenuRadioGroup value={label()} onChange={setLabel}> <DropdownMenuRadioItem value="personal">Personal</DropdownMenuRadioItem> <DropdownMenuRadioItem value="work">Work</DropdownMenuRadioItem> <DropdownMenuRadioItem value="other">Other</DropdownMenuRadioItem> </DropdownMenuRadioGroup> </DropdownMenuSubContent> </DropdownMenuSub> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem variant="destructive"> <Trash2Icon /> Trash </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </ButtonGroup> </ButtonGroup> );}As Link
Use the buttonVariants helper to make a link look like a button while preserving native link semantics.
import { buttonVariants } from "~/components/ui/button";
export default function ButtonRender() { return ( <a href="/login" class={buttonVariants({ variant: "secondary", size: "sm" })}> Login </a> );}API Reference
Button
The Button component is a wrapper around the button element that adds a variety of styles and functionality.
For primitive props, see the Kobalte Button API reference.