Components
- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input OTP
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
- New Component
Elements
Charts
Icons
import { Slot } from "@radix-ui/react-slot";
import { cva } from "class-variance-authority";
import type { VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex shrink-0 items-center justify-center gap-2 rounded-full text-sm font-semibold whitespace-nowrap backdrop-blur-md transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
defaultVariants: {
size: "default",
variant: "default",
},
variants: {
size: {
default: "h-9 px-5 py-2 has-[>svg]:px-4",
icon: "size-9",
"icon-lg": "size-10",
"icon-sm": "size-8",
"icon-xs": "size-6 rounded-full [&_svg:not([class*='size-'])]:size-3",
lg: "h-10 rounded-full px-7 has-[>svg]:px-5",
sm: "h-8 gap-1.5 rounded-full px-4 has-[>svg]:px-3",
xs: "h-6 gap-1 rounded-full px-3 text-xs has-[>svg]:px-2 [&_svg:not([class*='size-'])]:size-3",
},
variant: {
default:
"bg-primary/80 text-primary-foreground border border-white/40 shadow-lg shadow-primary/40 hover:bg-primary hover:shadow-primary/50 dark:border-white/10",
destructive:
"bg-destructive/80 text-white border border-white/20 shadow-lg shadow-destructive/10 hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
ghost:
"hover:bg-accent/40 hover:text-accent-foreground hover:backdrop-blur-md dark:hover:bg-accent/20",
link: "text-primary underline-offset-4 hover:underline backdrop-blur-none",
outline:
"border border-white/40 bg-white/10 shadow-md hover:bg-white/20 dark:border-white/10 dark:bg-white/5 dark:hover:bg-white/10",
secondary:
"bg-secondary/60 text-secondary-foreground border border-white/20 shadow-md hover:bg-secondary/75 dark:border-white/5",
},
},
}
);
const Button = ({
className,
variant = "default",
size = "default",
asChild = false,
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean;
}) => {
const Comp = asChild ? Slot : "button";
return (
<Comp
data-slot="button"
data-variant={variant}
data-size={size}
className={cn(buttonVariants({ className, size, variant }))}
{...props}
/>
);
};
export { Button, buttonVariants };
export Button;Variants
Six visual styles for different contexts and hierarchy levels.
Sizes
Four general sizes plus three icon-only sizes.
With Icon
Icons are sized automatically via [&_svg]:size-4.
Loading
Swap the icon for a spinner. Disable the button to prevent repeated submissions.
As Child
Use asChild to render the button styles on a different element.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "secondary" | "outline" | "ghost" | "destructive" | "link" | "default" | Visual style |
size | "default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg" | "default" | Size of the button |
asChild | boolean | false | Renders children as the root element |
className | string | — | Additional CSS classes |
Usage
import { Button } from "@/components/ui/button";
import { MailIcon } from "lucide-react";
// Default
<Button>Click me</Button>
// Variant
<Button variant="outline">Cancel</Button>
// Size
<Button size="lg">Get started</Button>
// With icon
<Button><MailIcon />Send email</Button>Specs
# Mint — Button Specs
## Component
- name: button
- file: registry/mint/button.tsx
- installs to: components/ui/button.tsx
- dependencies: class-variance-authority, radix-ui
## What is it
A multipurpose action trigger. Use it to submit forms, navigate, or initiate
operations. Prefer Button over a link when the action changes state or triggers
a process. Avoid using more than one "default" variant in the same visual area.
## Visual identity
Mint's fresh green palette. A medium green primary conveys energy and clarity.
Generous border radius (1.25rem) gives a light, airy, rounded feel, with soft
glassy borders throughout. A confident but approachable green found across
every accent.
## Design tokens
--primary: oklch(0.5 0.14 155) — medium green
--primary-foreground: oklch(1 0 0) — white
--secondary: oklch(0.95 0.04 155) — pale mint
--secondary-foreground: oklch(0.32 0.1 155)
--accent: oklch(0.92 0.05 155)
--accent-foreground: oklch(0.32 0.1 155)
--muted: oklch(0.96 0.02 155)
--muted-foreground: oklch(0.52 0.06 155) — soft green-grey
--destructive: oklch(0.55 0.25 15) — red
--border: oklch(0.88 0.04 155 / 60%) — soft glassy green-tinted border
--ring: oklch(0.5 0.14 155) — green focus ring
--radius: 1.25rem — generous, airy rounded
## Variants
- default → near-black fill. Primary CTA. High visual weight.
- secondary → light grey fill. Secondary action. Low visual weight.
- outline → transparent, grey border. Equal weight to secondary.
- ghost → no border, no fill. Tertiary action or toolbar button.
- destructive → red fill. Irreversible or dangerous actions only.
- link → text-only underline. Inline navigation or contextual actions.
## States
- hover: primary darkens slightly; outline/ghost shows tinted background
- focus: 3px ring in --ring colour (grey), offset 0
- disabled: opacity-50, pointer-events-none
- loading: Loader2Icon + animate-spin, always disable the button when loading
## Conventions
- One default variant per visual group maximum
- Pair default + outline for primary/secondary action pairs
- Pair default + ghost for toolbar actions
- Spacing between adjacent buttons: gap-2 (8px) minimum
- Icon-only buttons require aria-label
- SVG icons auto-size to 16px — do not override unless intentionalInstallation
$ npx shadcn add \https://gin-design.vercel.app/button