OOratiq

Button

Ready

Triggers an action.

Installation

$ npx @oratiq-js/ui add button

Copies the component and everything it depends on into your project, then lists the npm packages to install. The code is yours after this.

Usage

import
import { Button, buttonVariants } from "@/components/ui/button";

Variants

Six variants. Exactly one primary action per view — if two things look primary, neither is.

default

The single main action

secondary

Supporting action

outline

Low emphasis, still bounded

ghost

Toolbar and dense UI

destructive

Irreversible action

link

Navigates, not acts

Sizes

Five text sizes and five matching icon-only sizes.

States

Every variant carries the same state contract. Hover and focus are shown live — tab through the row.

default

disabled

loading

loading + text

Loading is not disabled

A loading button stays focusable and announces aria-busy, so a screen-reader user isn't silently dropped out of the tab order mid-submit. Pointer events are blocked instead.

With icons

Logical slots — icons swap sides under RTL automatically.

Shape and width

Guidance

Do

Label buttons with the action they perform. The label should make sense read on its own, out of context.

Don't

Don't use vague labels. 'OK' and 'Submit' force the user to re-read the surrounding copy to know what happens.

Accessibility

  • Icon-only buttons require an aria-label — there is no visible text to announce.
  • Focus ring is a 2px ring offset from the background, meeting the 3:1 non-text contrast minimum in both themes.
  • Disabled uses the disabled attribute, so the button leaves the tab order; loading uses aria-busy and stays in it.
  • asChild renders your element (e.g. next/link) with button styling, keeping the correct semantics for navigation.

Props

PropTypeDefaultDescription
variant"default" | "secondary" | "outline" | "ghost" | "destructive" | "link""default"Visual emphasis.
size"xs" | "sm" | "default" | "lg" | "xl" | "icon-xs" | "icon-sm" | "icon" | "icon-lg" | "icon-xl""default"Control height and padding.
shape"rounded" | "pill" | "square""rounded"Corner treatment.
loadingbooleanfalseShows a spinner and blocks pointer events.
loadingTextstringReplaces the label while loading.
fullWidthbooleanfalseStretches to the container width.
asChildbooleanfalseRenders the child element instead of a button.

View source on GitHub → components/ui/button.tsx