Button
Trigger an action. Six visual variants and four sizes.
Preview
Code
import { Button } from "@/components/ui/button";
export function Example() {
return (
<div className="flex items-center gap-3">
<Button>Solid</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="subtle">Subtle</Button>
<Button variant="danger">Danger</Button>
<Button variant="link">Link</Button>
</div>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "solid" | "outline" | "ghost" | "subtle" | "danger" | "link" | "solid" | Visual style. solid for primary CTAs, outline for secondary, ghost for tertiary, subtle for repeated dense UIs, danger for destructive, link for inline anchors. |
| size | "sm" | "md" | "lg" | "icon" | "md" | sm for dense rows, md default, lg for hero CTAs, icon for square 36×36 icon-only buttons (always pair with aria-label). |
| disabled | boolean | false | Disables interaction and dims the button. |
| className | string | — | Additional Tailwind classes, merged with the component's defaults via cn(). |
Spreads all `<button>` props (type, onClick, disabled, etc.). Forwards `ref` to the underlying button element. Defaults `type` to `"button"` to prevent accidental form submission.
All components also accept standard HTML attributes for their root element (e.g. `id`, `aria-*`, `data-*`, event handlers) and forward `ref` where applicable.
Source
The full implementation of components/ui/button.tsx is below — copy it into your project and own it. Some components import the cn helper from lib/utils or other primitives; copy those too.
import { cn } from "@/lib/utils";
import { type VariantProps, cva } from "class-variance-authority";
import { type ButtonHTMLAttributes, forwardRef } from "react";
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium transition-colors focus-visible:outline-1 focus-visible:outline-offset-0 focus-visible:outline-accent disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
solid: "bg-accent text-accent-fg hover:bg-accent-hover",
outline: "border border-border bg-bg text-fg hover:bg-bg-muted",
ghost: "text-fg hover:bg-bg-muted",
subtle: "bg-bg-muted text-fg hover:bg-bg-subtle",
danger: "bg-danger text-danger-fg hover:opacity-90",
link: "text-accent underline-offset-4 hover:underline",
},
size: {
sm: "h-8 px-3 text-xs",
md: "h-9 px-4 text-sm",
lg: "h-11 px-6 text-base",
icon: "h-9 w-9",
},
},
defaultVariants: { variant: "solid", size: "md" },
},
);
export interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, type = "button", ...props }, ref) => (
<button
ref={ref}
type={type}
className={cn(buttonVariants({ variant, size }), className)}
{...props}
/>
),
);
Button.displayName = "Button";
export { buttonVariants };JavaFX
Ships in the PRIZM JavaFX library for thick-client C3 apps as PrizmButton (extends Button). Run the gallery to see it natively.
import design.prizm.fx.controls.PrizmButton;
PrizmButton()
PrizmButton(String text)
PrizmButton(String text, Variant variant)| Prop | Type | Default | Description |
|---|---|---|---|
| Variant | enum { SOLID, OUTLINE, GHOST, SUBTLE, DANGER, LINK } | SOLID | Visual style. Mirrors the React Button variants. SOLID for primary CTAs, OUTLINE for secondary, GHOST for tertiary, SUBTLE for dense UIs, DANGER for destructive, LINK for inline. |
| Size | enum { SM, MD, LG, ICON } | MD | Control size. ICON is a square 36×36 for icon-only buttons. |
| setVariant | (Variant) → void | — | Swap the variant; updates the style class. |
| setSize | (Size) → void | — | Swap the size; updates the style class. |
Inherits all Button behaviour (actions, keyboard, accessibility). Variant/size map to style classes consumed by prizm.css. In spec parity with components/ui/button.tsx.