A button component that can be used as a child of other components. It supports different styles and sizes.
Different button variants.
<Button>Share</Button><Button subtle>Settings</Button><Button outline>Settings</Button><Button primary>Log In</Button><Button destructive>Share</Button><Button destructive subtle>Settings</Button><Button destructive outline>Settings</Button><Button destructive primary>Log In</Button>
Disabled button states.
<><Button disabled>Share</Button><Button outline disabled>Settings</Button><Button primary disabled><MingcuteLoading3Fill className="animate-spin" />Saving...</Button></>
Button with icons. Icons are mostly retrieved from icones.js.org
<><Button icon><CommentIcon /></Button><Button outline><CommentIcon />Comment</Button><Button primary>Next<LucideArrowRight /></Button></>
Button sizes.
<div className="flex flex-row @xs/previewcard:flex-col gap-2"><div className="flex flex-col @xs/previewcard:flex-row gap-2 items-center"><Button primary xs>Send</Button><Button primary sm>Send</Button><Button primary>Send</Button><Button primary lg>Send</Button><Button primary xl>Send</Button></div><div className="flex flex-col @xs/previewcard:flex-row gap-2 items-center"><Button icon primary xs><LucideArrowRight /></Button><Button icon primary sm><LucideArrowRight /></Button><Button primary>Send<LucideArrowRight /></Button><Button primary lg>Send<LucideArrowRight /></Button><Button primary xl>Send<LucideArrowRight /></Button></div></div>
Button without padding.
<div className="flex flex-col"><Button bare><LucideArrowLeft />Back to Posts</Button><Button bare><LucideArrowLeft />Settings</Button></div>
npm i @radix-ui/react-slot lazy-cn
import { Slot } from "@radix-ui/react-slot";import { cn } from "lazy-cn";import type { ComponentProps, SVGProps } from "react";export function Button({className,asChild,primary, outline, subtle, bare,destructive,icon,round,xs, sm, lg, xl,...props}: ComponentProps<"button"> & {asChild?: boolean,primary?: boolean, outline?: boolean, subtle?: boolean, bare?: boolean,destructive?: boolean,icon?: boolean,disabled?: boolean,xs?: boolean, sm?: boolean, lg?: boolean, xl?: boolean,round?: boolean,}) {const Comp = asChild ? Slot : "button";return (<Comp {...props} className={cn("flex items-center gap-2 box-border","h-8.5 px-4",icon && "px-3","rounded-md","text-sm leading-none font-medium text-nowrap","cursor-pointer select-none","transition-[translate] active:translate-y-0.5","hover:bg-foreground/5","focus-visible:outline-4","focus-visible:outline-focus","[&_svg]:size-4 [&_svg]:shrink-0",round && "rounded-full",xs && ["h-7 text-xs px-2", icon && "w-7 p-0 justify-center"],sm && ["h-8 px-3", icon && "w-8 p-0 justify-center"],lg && ["h-10 [&_svg]:size-4.5", icon && "w-10 p-0 justify-center"],xl && ["h-10 text-base px-5 [&_svg]:size-5 tracking-tight rounded-lg", icon && "w-11 p-0 justify-center"],primary && ["text-background","bg-primary hover:bg-primary-hover","shadow-sm"],subtle && "bg-primary/5 hover:bg-primary/10",outline && "border border-border shadow-xs active:bg-foreground/8",bare && "p-0 hover:bg-transparent text-foreground/75 hover:text-foreground",destructive && ["text-destructive","hover:bg-destructive/5","focus-visible:outline-destructive-focus",primary && ["text-background","bg-destructive hover:bg-destructive-hover",],subtle && "bg-destructive/5 shadow-xs",outline && "border-destructive-border",],props.disabled && ["cursor-not-allowed","opacity-50","pointer-events-none",],className,)} />)}
@theme {--color-destructive-border: --alpha(var(--color-destructive) / 0.25)--color-destructive-hover: color-mix(in oklab, var(--color-background) 8%, var(--color-destructive))--color-destructive-focus: --alpha(var(--color-destructive) / 0.25)--color-destructive: var(--color-red-600)--color-border: color-mix(in hsl, var(--color-foreground) 20%, var(--color-background))--color-primary-hover: color-mix(in oklab, var(--color-background) 8%, var(--color-primary))--color-primary: var(--color-neutral-700)--color-background: #fff--color-muted: color-mix(in hsl, var(--color-foreground) 50%, var(--color-background))--color-focus: color-mix(in oklab, var(--color-muted) 25%, transparent)--color-foreground: var(--color-neutral-700)}
A button that works under React 19 <form>.
import { Button } from "../components/button"import { useFormStatus } from "react-dom"import { cn } from "lazy-cn"export function SubmitButtonWithIcon({ className, ...props }:ComponentProps<typeof Button>) {const { pending } = useFormStatus()return (<Buttontype="submit"disabled={pending}primaryclassName={cn("[:where(&:disabled>svg:nth-child(2))]:hidden",className)}{...props}>{pending && <MingcuteLoading3Fill className="animate-spin" />}{props.children}</Button>)}export function MingcuteLoading3Fill(props: SVGProps<SVGSVGElement>) {return (<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" {...props}>{/* Icon from MingCute Icon by MingCute Design - https://github.com/Richard9394/MingCute/blob/main/LICENSE */}<g fill="none" fillRule="evenodd"><path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"></path><path fill="currentColor" d="M12 4.5a7.5 7.5 0 1 0 0 15a7.5 7.5 0 0 0 0-15M1.5 12C1.5 6.201 6.201 1.5 12 1.5S22.5 6.201 22.5 12S17.799 22.5 12 22.5S1.5 17.799 1.5 12" opacity=".1"></path><path fill="currentColor" d="M12 4.5a7.46 7.46 0 0 0-5.187 2.083a1.5 1.5 0 0 1-2.075-2.166A10.46 10.46 0 0 1 12 1.5a1.5 1.5 0 0 1 0 3"></path></g></svg>)}
A button that works as a link.
<Button asChild outline><a href="https://www.v0.dev/" target="_blank">Open in<SimpleIconsV0 /></a></Button>
A button with fully rounded corners.
<Button primary lg className="rounded-full px-5"><RiVercelFill />Start Deploying</Button>