GitHub

Button

A flexible button component with multiple variants, sizes, loading states, and CMS integration support.

Basic Usage

Loading...

Installation

pnpm add @corew500/ui

Usage

import { Button } from "@corew500/ui/button"

<Button>Content</Button>

Variants

buttonVariants

AxisValuesDefault
variant
defaultoutlinesecondaryghostdestructivelink
default
size
defaultxssmlgiconicon-xsicon-smicon-lg
default
animated
truefalse
true

Variants

Six visual variants for different contexts and emphasis levels.

Sizes

Loading...

With Icons

Use `iconStart` and `iconEnd` props for consistent icon placement and sizing.
Loading...

Loading State

Set `loading` to show a spinner and disable the button.
Loading...

Glow Effect

Add an animated gradient underline on hover with the `glow` prop.
Loading...

As Link

Use the `render` prop to compose Button with Next.js Link or any anchor element.
Loading...

Usage with Payload CMS

The buttonFields() factory from @corew500/cms-payload generates a complete set of Payload fields for label, variant, size, icon, and link — with localization built in. Spread it into any block to give editors full control over button appearance.
import { buttonFields } from "@corew500/cms-payload"
import type { Block } from "payload"

const HeroBlock: Block = {
  slug: "hero",
  fields: [
    { name: "headline", type: "text", localized: true },
    ...buttonFields("cta"),
  ],
}
Localization
The label field created by buttonFields() is automatically localized. Editors see one input per locale, and the correct translation is resolved before the Button component renders.

Composition Patterns

Button supports polymorphic rendering via the render prop, allowing it to compose with routing links, external anchors, or any custom element while preserving all button styling and variants.
import Link from "next/link"
import { Button } from "@corew500/ui/button"

// Renders as a Next.js Link with button styling
<Button variant="outline" render={<Link href="/docs" />}>
  View Documentation
</Button>

// Renders as an external anchor
<Button
  variant="ghost"
  render={<a href="https://github.com" target="_blank" rel="noopener noreferrer" />}
>
  GitHub
</Button>
This pattern is preferred over wrapping a Button inside a Link, because the rendered element is a single <a> tag with button styles — better for accessibility and avoiding nested interactive elements.

CMS Integration

CMSPayload CMS Integration
Use buttonFields() from @corew500/cms-payload to add configurable button fields to any Payload block.
Loading...

API Reference

Props

PropTypeDefaultDescription
loadingenumfalseShow loading spinner and disable the button. When true, replaces iconStart with a spinner and sets aria-busy.
iconStartenumIcon to display at the start (left) of the button text. Automatically hidden when loading is true.
iconEndenumIcon to display at the end (right) of the button text. Remains visible during loading state.
animatedenumtrueEnable hover scale and active press micro-interactions. Uses motion-safe media query to respect user preferences.
fullWidthenumfalseMake the button expand to fill its container width.
glowenumfalseEnable animated gradient glow effect on hover. Adds decorative gradient lines below the button.
focusableWhenDisabledenumfalseWhether the button should be focusable when disabled.
nativeButtonenumtrueWhether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (e.g. `<div>`).
styleenumStyle applied to the element, or a function that returns a style object based on the component’s state.
classNameenumCSS class applied to the element, or a function that returns a class based on the component’s state.
renderenumAllows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
variantenumdefault
sizeenumdefault

Accessibility

Keyboard Navigation

  • Supports keyboard navigation (Enter/Space to activate)
  • Disabled state removes from tab order and announces as disabled
  • Focus ring visible for keyboard navigation

Screen Readers

  • Sets `aria-busy="true"` during loading state

Additional

  • - Uses native button semantics via Base UI primitive

Localization

Translatable Content

  • - Pass translated strings as children
  • Loading text should be localized when using loading state with children

Related

Related Components