Add this component

npx zentauri-ui add buttons

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

Static imports do not pull framer-motion. Use the animated entry only when you want motion and have framer-motion installed.

Actions

Buttons for primary actions

Action buttons with variants, sizes, and motion presets for React interfaces. Drop them into Next.js forms and toolbars while keeping focus rings consistent with your Tailwind theme.

Link

Button variants playground

Pick an appearance, size, and animation to preview the button live. Toggle Show output / Show code and the snippet updates to match the selected variant.


All appearances

Every shipped appearance token at a glance. Click any swatch to load it into the playground above.

Buttons API

Generated from the package prop types and variant definitions.

Button

ButtonProps

Variants

PropTypeDefault
appearance
amberaquabluecrimsoncyandefaultdestructiveelectricemeraldforestghostglass+37
default
size
10xl2xl3xl4xl5xl6xl7xl8xl9xliconlgmd+2
md

Behavior

PropTypeDefault
as'button' | 'link' | undefinednone
asChildboolean | undefinednone
onClickMouseEventHandler<HTMLButtonElement> | MouseEventHandler<HTMLElement> | MouseEventHandler<HTMLAnchorElement> | undefinednone

Content

PropTypeDefault
childrenReactNode | ReactElement<{ "aria-disabled"?: boolean | 'false' | 'true'; className?: string; "data-slot"?: string; disabled?: boolean; onClick?: MouseEventHandler<HTMLElement>; tabIndex?: number; }, string | JSXElementConstructor<any>>none
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

ButtonAnimated

ButtonAnimatedProps

animated

Behavior

PropTypeDefault
animationButtonAnimation | undefinednone
appearance'default' | 'outline' | 'ghost' | 'blue' | 'cyan' | 'green' | 'lime' | 'mint' | 'ocean' | 'sapphire' | 'lavender' | 'ruby' | 'red' | 'slate' | 'zinc' | 'stone' | 'royal' | 'electric' | 'forest' | 'sunset' | 'magenta' | 'crimson' | 'aqua' | 'plum' | 'sky' | 'rose' | 'purple' | 'pink' | 'orange' | 'yellow' | 'teal' | 'indigo' | 'emerald' | 'gradient-blue' | 'gradient-green' | 'gradient-red' | 'gradient-yellow' | 'gradient-purple' | 'gradient-teal' | 'gradient-indigo' | 'gradient-pink' | 'gradient-orange' | 'link' | 'gray' | 'violet' | 'glass' | 'secondary' | 'destructive' | 'amber' | null | undefinednone
as'button' | 'link' | undefinednone
size'md' | 'sm' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl' | '8xl' | '9xl' | '10xl' | 'icon' | null | undefinednone
Inherited HTML props
PropTypeDefault
childrenReactNode | MotionValueNumber | MotionValueStringnone
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLButtonElement> | MouseEventHandler<HTMLAnchorElement> | undefinednone
style The React DOM `style` prop, enhanced with support for `MotionValue`s and separate `transform` values. ```jsx export const MyComponent = () => { const x = useMotionValue(0) return <motion.div style={{ x, opacity: 1, scale: 0.5 }} /> } ```MotionStyle | undefinednone
titlestring | undefinednone
CSS variable overrides

Button CSS variables

Override these button variables on :root, a theme selector, or a component wrapper.

335 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-button-radius: 0.75rem;
  --zui-button-ring-offset: #f8fafc;
  --zui-button-focus-ring: #475569;
  --zui-button-default-bg: #0f172a;
  --zui-button-default-fg: #f8fafc;
  --zui-button-default-shadow: 0 1px 2px #0f172a14;
  --zui-button-default-bg-hover: #000000;
  --zui-button-secondary-bg: #e2e8f0;
  --zui-button-secondary-fg: #0f172a;
  --zui-button-secondary-bg-hover: #cbd5e1;
  --zui-button-destructive-bg: #f43f5e;
  --zui-button-destructive-fg: #ffffff;
  --zui-button-destructive-bg-hover: #f43f5e;
  --zui-button-outline-border: #0000001a;
  --zui-button-outline-bg: #0000000d;
  --zui-button-outline-fg: #0f172a;
  --zui-button-outline-bg-hover: #0000001a;
  --zui-button-ghost-fg: #334155;
  --zui-button-ghost-bg-hover: #0000000d;
  --zui-button-link-fg: #0e7490;
  --zui-button-glass-border: #00000026;
  --zui-button-glass-bg: #0000001a;
  --zui-button-glass-fg: #0f172a;
  --zui-button-glass-bg-hover: #00000026;
  --zui-button-blue-bg: #2563eb;
  --zui-button-blue-fg: #ffffff;
  --zui-button-blue-bg-hover: #2563eb;
  --zui-button-cyan-bg: #0891b2;
  --zui-button-cyan-fg: #083344;
  --zui-button-cyan-bg-hover: #0891b2;
  --zui-button-green-bg: #16a34a;
  --zui-button-green-fg: #ffffff;
  --zui-button-green-bg-hover: #16a34a;
  --zui-button-lime-bg: #65a30d;
  --zui-button-lime-fg: #1a2e05;
  --zui-button-lime-bg-hover: #65a30d;
  --zui-button-mint-bg: #10b981;
  --zui-button-mint-fg: #064e3b;
  --zui-button-mint-bg-hover: #10b981;
  --zui-button-ocean-bg: #0284c7;
  --zui-button-ocean-fg: #082f49;
  --zui-button-ocean-bg-hover: #0284c7;
  --zui-button-sapphire-bg: #1d4ed8;
  --zui-button-sapphire-fg: #ffffff;
  --zui-button-sapphire-bg-hover: #1d4ed8;
  --zui-button-lavender-bg: #8b5cf6;
  --zui-button-lavender-fg: #ffffff;
  --zui-button-lavender-bg-hover: #8b5cf6;
  --zui-button-ruby-bg: #be123c;
  --zui-button-ruby-fg: #ffffff;
  --zui-button-ruby-bg-hover: #be123c;
  --zui-button-red-bg: #dc2626;
  --zui-button-red-fg: #ffffff;
  --zui-button-red-bg-hover: #dc2626;
  --zui-button-slate-bg: #475569;
  --zui-button-slate-fg: #ffffff;
  --zui-button-slate-bg-hover: #475569;
  --zui-button-zinc-bg: #52525b;
  --zui-button-zinc-fg: #ffffff;
  --zui-button-zinc-bg-hover: #52525b;
  --zui-button-stone-bg: #57534e;
  --zui-button-stone-fg: #ffffff;
  --zui-button-stone-bg-hover: #57534e;
  --zui-button-royal-bg: #4338ca;
  --zui-button-royal-fg: #ffffff;
  --zui-button-royal-bg-hover: #4338ca;
  --zui-button-electric-bg: #0ea5e9;
  --zui-button-electric-fg: #ffffff;
  --zui-button-electric-bg-hover: #0ea5e9;
  --zui-button-forest-bg: #166534;
  --zui-button-forest-fg: #ffffff;
  --zui-button-forest-bg-hover: #166534;
  --zui-button-sunset-bg: #ea580c;
  --zui-button-sunset-fg: #ffffff;
  --zui-button-sunset-bg-hover: #ea580c;
  --zui-button-magenta-bg: #c026d3;
  --zui-button-magenta-fg: #ffffff;
  --zui-button-magenta-bg-hover: #c026d3;
  --zui-button-crimson-bg: #b91c1c;
  --zui-button-crimson-fg: #ffffff;
  --zui-button-crimson-bg-hover: #b91c1c;
  --zui-button-aqua-bg: #0f766e;
  --zui-button-aqua-fg: #ffffff;
  --zui-button-aqua-bg-hover: #0f766e;
  --zui-button-plum-bg: #7e22ce;
  --zui-button-plum-fg: #ffffff;
  --zui-button-plum-bg-hover: #7e22ce;
  --zui-button-emerald-bg: #10b981;
  --zui-button-emerald-fg: #ffffff;
  --zui-button-emerald-bg-hover: #10b981;
  --zui-button-indigo-bg: #3730a3;
  --zui-button-indigo-fg: #ffffff;
  --zui-button-indigo-bg-hover: #3730a3;
  --zui-button-purple-bg: #6b21a8;
  --zui-button-purple-fg: #ffffff;
  --zui-button-purple-bg-hover: #6b21a8;
  --zui-button-pink-bg: #9d174d;
  --zui-button-pink-fg: #ffffff;
  --zui-button-pink-bg-hover: #9d174d;
  --zui-button-rose-bg: #9f1239;
  --zui-button-rose-fg: #ffffff;
  --zui-button-rose-bg-hover: #9f1239;
  --zui-button-sky-bg: #0ea5e9;
  --zui-button-sky-fg: #ffffff;
  --zui-button-sky-bg-hover: #0ea5e9;
  --zui-button-teal-bg: #14b8a6;
  --zui-button-teal-fg: #ffffff;
  --zui-button-teal-bg-hover: #14b8a6;
  --zui-button-yellow-bg: #eab308;
  --zui-button-yellow-fg: #ffffff;
  --zui-button-yellow-bg-hover: #eab308;
  --zui-button-orange-bg: #f97316;
  --zui-button-orange-fg: #ffffff;
  --zui-button-orange-bg-hover: #f97316;
  --zui-button-gray-bg: #6b7280;
  --zui-button-gray-fg: #ffffff;
  --zui-button-gray-bg-hover: #6b7280;
  --zui-button-amber-bg: #f59e0b;
  --zui-button-amber-fg: #ffffff;
  --zui-button-amber-bg-hover: #f59e0b;
  --zui-button-violet-bg: #5b21b6;
  --zui-button-violet-fg: #ffffff;
  --zui-button-violet-bg-hover: #5b21b6;
  --zui-button-gradient-blue-from: #1e40af;
  --zui-button-gradient-blue-to: #6b21a8;
  --zui-button-gradient-blue-fg: #ffffff;
  --zui-button-gradient-blue-from-hover: #1e40af;
  --zui-button-gradient-blue-to-hover: #6b21a8;
  --zui-button-gradient-green-from: #166534;
  --zui-button-gradient-green-to: #3f6212;
  --zui-button-gradient-green-fg: #ffffff;
  --zui-button-gradient-green-from-hover: #166534;
  --zui-button-gradient-green-to-hover: #3f6212;
  --zui-button-gradient-red-from: #991b1b;
  --zui-button-gradient-red-to: #9d174d;
  --zui-button-gradient-red-fg: #ffffff;
  --zui-button-gradient-red-from-hover: #991b1b;
  --zui-button-gradient-red-to-hover: #9d174d;
  --zui-button-gradient-yellow-from: #854d0e;
  --zui-button-gradient-yellow-to: #9a3412;
  --zui-button-gradient-yellow-fg: #ffffff;
  --zui-button-gradient-yellow-from-hover: #854d0e;
  --zui-button-gradient-yellow-to-hover: #9a3412;
  --zui-button-gradient-purple-from: #6b21a8;
  --zui-button-gradient-purple-to: #9d174d;
  --zui-button-gradient-purple-fg: #ffffff;
  --zui-button-gradient-purple-from-hover: #6b21a8;
  --zui-button-gradient-purple-to-hover: #9d174d;
  --zui-button-gradient-teal-from: #115e59;
  --zui-button-gradient-teal-to: #155e75;
  --zui-button-gradient-teal-fg: #ffffff;
  --zui-button-gradient-teal-from-hover: #115e59;
  --zui-button-gradient-teal-to-hover: #155e75;
  --zui-button-gradient-indigo-from: #3730a3;
  --zui-button-gradient-indigo-to: #6b21a8;
  --zui-button-gradient-indigo-fg: #ffffff;
  --zui-button-gradient-indigo-from-hover: #3730a3;
  --zui-button-gradient-indigo-to-hover: #6b21a8;
  --zui-button-gradient-pink-from: #9d174d;
  --zui-button-gradient-pink-to: #9f1239;
  --zui-button-gradient-pink-fg: #ffffff;
  --zui-button-gradient-pink-from-hover: #9d174d;
  --zui-button-gradient-pink-to-hover: #9f1239;
  --zui-button-gradient-orange-from: #9a3412;
  --zui-button-gradient-orange-to: #991b1b;
  --zui-button-gradient-orange-fg: #ffffff;
  --zui-button-gradient-orange-from-hover: #9a3412;
  --zui-button-gradient-orange-to-hover: #991b1b;
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-button-ring-offset-dark: #020617;
  --zui-button-focus-ring-dark: #cbd5e1;
}

What it does

Buttons wrap native elements so native disabled and focus behavior stay intact.

Loading states preserve width to avoid layout shift in toolbars.

Composition and API

Prefer compound subcomponents instead of one oversized prop bag. Export a small, documented API for your design system.

Pair every icon-only control with aria-label text supplied by your app.

Common use cases

  • Submit Next.js forms with optimistic loading feedback.
  • Drive modal and drawer footers with primary/secondary pairing.
  • Add icon-leading actions to dense data tables.
  • Gate destructive flows behind emphasized danger styles.

Accessibility

Keyboard order, focus rings, and ARIA attributes should match production usage. Test with your supported browsers and assistive technologies when semantics are non-trivial.

This preview page exposes a single h1 in the hero for a clean outline.

Next.js integration notes

Colocate examples under the App Router, keep server and client boundaries explicit, and avoid pulling interactive overlays into unexpected server layouts.

Set NEXT_PUBLIC_SITE_URL so canonical and Open Graph URLs resolve on deploy.

FAQ

Does the Button component work with Next.js App Router?

Yes. Import it like any other React component; keep interactive subtrees in client components when you need hooks or browser APIs, and leave static structure in server components where possible.

Can I customize button with Tailwind CSS?

Zentauri UI exposes class-friendly variants and slots so you can extend styles with Tailwind utilities without fighting inline styles.

Is this Button implementation accessible by default?

Primitives follow sensible defaults, but accessibility depends on how you label controls, manage focus, and wire keyboard handlers in your app. Validate critical flows with keyboard-only use and screen readers.