Button (.ods-btn) is the primary way to commit an action. Per AGENTS.md's decision table, use -primary once per region — never more than one primary call-to-action in the same area — and reach for .ods-iconbtn instead for toolbar/row actions rather than a tiny text button.
Installation
HTML — already included if you loaded the 3 stylesheets. See the Installation guide.
React
npm install @operant/ui
@operant/ui is currently a monorepo workspace package, not yet published to the public npm registry.
Usage
HTML
<button type="button" class="ods-btn -primary">Approve</button>
React
import { Button } from "@operant/ui";
export default function Example() {
return <Button>Approve</Button>;
}
Examples
All variants
Six variants: primary (default) for the one committed action in a region, secondary for supporting actions, ghost for low-emphasis actions in dense UI, danger/danger-ghost for destructive actions (solid vs. outlined emphasis), and success for a completed/positive commit.
<button type="button" class="ods-btn -primary">Primary</button>
<button type="button" class="ods-btn -secondary">Secondary</button>
<button type="button" class="ods-btn -ghost">Ghost</button>
<button type="button" class="ods-btn -danger">Danger</button>
<button type="button" class="ods-btn -danger-ghost">Danger ghost</button>
<button type="button" class="ods-btn -success">Success</button>
import { Button } from "@operant/ui";
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="danger">Danger</Button>
<Button variant="danger-ghost">Danger ghost</Button>
<Button variant="success">Success</Button>;
Sizes
Three sizes: sm, md (default), lg.
<button type="button" class="ods-btn -primary -sm">Small</button>
<button type="button" class="ods-btn -primary">Medium</button>
<button type="button" class="ods-btn -primary -lg">Large</button>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>;
Block width
block (React) / -block (HTML) stretches the button to 100% of its container — use for full-width actions in narrow layouts like a mobile composer footer or a modal footer that only has one action.
<button type="button" class="ods-btn -primary -block">Continue</button>
<Button block>Continue</Button>
Disabled
Native disabled reduces opacity to 50% and removes pointer events (.ods-btn:disabled).
<button type="button" class="ods-btn -primary" disabled>Approve</button>
<Button disabled>Approve</Button>
With a keyboard hint
ApprovalBar composes Button with a trailing <kbd> to surface its shortcut — the same pattern works anywhere a button has a global hotkey.
<button type="button" class="ods-btn -primary">Approve <kbd>A</kbd></button>
<Button variant="primary">
Approve <kbd>A</kbd>
</Button>
API Reference
<Button>
Renders a native <button>.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "primary" | "secondary" | "ghost" | "danger" | "danger-ghost" | "success" | "primary" | Controls the visual style. primary is reserved for the single committed action per region. |
size | "sm" | "md" | "lg" | "md" | Controls height, padding, and font size. |
block | boolean | false | Stretches the button to 100% width. |
className | string | — | Additional classes merged with the variant/size classes. |
ref | Ref<HTMLButtonElement> | — | Forwarded to the underlying <button>. |
All other native <button> attributes (type, disabled, form, onClick, aria-*, data-*, etc.) are forwarded to the element.
HTML-side modifiers: .ods-btn (base) + one of -primary / -secondary / -ghost / -danger / -danger-ghost / -success, plus optional size (-sm / -lg; no suffix = md) and -block.
Accessibility
- Renders as a native
<button>— keyboard-focusable and operable via Enter or Space without any extra wiring. - Focus is visible only on keyboard navigation:
.ods-btn:focus-visibleapplies--shadow-focus, following the:focus-visiblespec rather than showing a ring on every mouse click. disabledsetsopacity: 0.5andpointer-events: nonetogether — always pair it with the nativedisabledattribute (not a visual-only class) so assistive tech reports the correct state.- Icon-only usage isn't a variant of this component — use
.ods-iconbtnand give it anaria-label, per the decision table ("Toolbar/row action" →.ods-iconbtn, not a bareButton). - AGENTS.md #9 flags more than one
-primaryper region, and buttons used for navigation, as anti-patterns — use a real<a>/Linkfor navigation instead.