Components · v0.1 · Stable

Button

Nova's most-used control. Polymorphic, accessible, and tuned for physical feedback — a soft downward compress on press and a diagonal sheen on hover.

Example

The primary call to action. Filled variants carry the signature gloss.

Installation

Install via the Nova CLI, or copy the component into your project.

CLI

tsx
npx @novix-ui/cli add button

Import

tsx
import { Button } from "@novix-ui/react";

Playground

Change any prop. The preview updates instantly.

Playground

primary
md

Variants

Seven variants cover the intent spectrum. Reserve accent for a single hero action per view.

Sizes

Loading and icons

As child

Set asChild to render the button styles onto a child element — commonly a router link. All button props, states, and events flow through.

tsx
import { Link } from "@tanstack/react-router";
import { Button } from "@novix-ui/react";
 
<Button asChild>
<Link to="/pricing">See pricing</Link>
</Button>

API

Prop
Type
Default
Description
  • variant
    "primary" | "accent" | "secondary" | "outline" | "ghost" | "destructive" | "link"
    "primary"
    Visual intent. Filled variants ship with the Nova gloss sheen.
  • size
    "sm" | "md" | "lg" | "icon"
    "md"
    Height and horizontal padding. Use size='icon' for square icon-only buttons.
  • asChild
    boolean
    false
    Merge props onto the child element instead of rendering a <button>. Use with <Link>, <a>, etc.
  • loading
    boolean
    false
    Replaces the leading icon with a spinner and marks the button aria-busy.
  • leadingIcon
    ReactNode
    Icon rendered before the label. Automatically sized to match the text.
  • trailingIcon
    ReactNode
    Icon rendered after the label. Ideal for arrows, external-link glyphs.

Keyboard

KeyAction
TabMove focus to the button.
Enter / SpaceActivate the button.
Shift + TabMove focus to the previous focusable element.

Accessibility

  • Rendered as a native <button> unless asChild is set.
  • Icon-only buttons must receive aria-label. Prefer IconButton which enforces it at the type level.
  • Loading state applies aria-busy and blocks pointer events without collapsing size.
  • Focus ring uses two layers so it stays visible on any background.

Design guidelines

One hero per view

Reserve the accent variant for the primary action of a screen. Multiple accents cancel each other out.

Label with a verb

"Save changes" beats "OK". Buttons commit to an outcome — say what happens next.

Size matches surface

sm for dense toolbars, md for forms, lg for landing heroes. Don't mix in the same row.

Destructive gets confirmation

Pair destructive with a dialog or undo. Never a single-click delete.

Common mistakes

  • Wrapping a Link in a Button instead of using asChild — produces invalid nested interactives.
  • Using size="icon" without an aria-label. Screen readers will announce "button" with no name.
  • Disabling a button during async work instead of using loading. Disabled buttons drop out of the tab order and hide progress.