Skip to content

OButton ​

OButton renders an accessible native button with a default type of button.

Usage ​

@lucide/vue is Ooko's recommended and default icon library. Consuming applications can use Lucide directly or pass a compatible Vue icon component from any other icon library to OButton.

Step by step ​

  1. Import OButton from the ooko-ui/button public subpath.
  2. Put the action name in the default slot. Buttons are pill-shaped and use the neutral ink color by default; choose another semantic color only when it adds meaning.
  3. Add an icon or visual treatment, then handle native events such as click on the component.

Example ​

The rendered example and its source come from the same Vue single-file component.

Interactive playground ​

Change the content, color, size, visual treatment, disabled, and loading states. The preview updates immediately.

Props ​

PropTypeDefaultDescription
color"primary" | "secondary" | "info" | "success" | "warning" | "danger" | "neutral""neutral"Visual color applied to the button.
sizeOButtonSize"md"Controls the button's form-control scale.
disabledbooleanfalsePrevents interaction with the button.
loadingbooleanfalseDisables the button and shows a spinner over its content without changing its size.
outlinebooleanfalseUses the outlined button treatment.
nudebooleanfalseUses the minimal button treatment.
softbooleanfalseUses the soft treatment: a background tinted with the button color and no border.
iconComponentundefinedVue component rendered as the button icon.
iconPositionOButtonIconPosition"leading"Places the icon before or after the button content.

Events ​

EventPayloadDescription
nonenoneNo custom Vue events are emitted.

Slots ​

SlotPropsDescription
defaultnoneProvides the visible button content.
iconnoneProvides configured or custom icon markup and overrides the icon prop.
TypeDefinition
OButtonIconPositiontype OButtonIconPosition = "leading" | "trailing";
OButtonSizetype OButtonSize = "xs" | OokoFormControlSize;
OokoFormControlSizetype OokoFormControlSize = "sm" | "md";
OokoColortype OokoColor = (typeof OOKO_COLORS)[number];

CSS custom properties ​

Custom propertyDefaultDescription
--o-button-paddingvar(--o-space-1-5) var(--o-space-4)Sets the inner spacing around the button content.
--o-button-border1px solidSets the button border width and style.
--o-button-border-colortransparentSets the button border color. Outline and hovered nude buttons assign their color's border shade on the button itself.
--o-button-border-radiusvar(--o-radius-round)Sets the button corner radius.
--o-button-gapvar(--o-space-2)Sets the space between the icon and visible content.
--o-button-icon-size1.25remSets the rendered icon size.
--o-button-focus-width0.1875remSets the focus outline width.
--o-button-focus-stylesolidSets the focus outline style.
--o-button-focus-offset0.125remSets the distance between the button and outline.
--o-button-disabled-opacity0.5Sets the disabled button opacity.
--o-button-font-sizevar(--o-font-size-md)Sets the label size of xs, sm, and md buttons.

Override example ​

css
:root {
  --o-button-border-radius: var(--o-radius-round);
}

Define the same custom properties on a container instead of :root to limit an override to one part of an application.

Outline buttons and hovered nude buttons set --o-button-border-color on the button itself, so override it on .ooko-button or a more specific selector to replace their border color:

css
.toolbar .ooko-button {
  --o-button-border-color: var(--o-border-neutral-lighter);
}

Accessibility ​

  • The component renders a native button and preserves its keyboard and focus behavior.
  • The default slot must provide a meaningful accessible name, usually through visible text.
  • Button icons are decorative and hidden from assistive technologies.
  • An icon-only button must receive an accessible name through aria-label or aria-labelledby.
  • The disabled prop uses the native disabled state and prevents interaction.
  • The loading prop also disables the button and sets aria-busy="true". The content stays in the accessible name; the spinner is decorative.
  • Native attributes and event listeners are forwarded to the underlying button.
  • A visible :focus-visible outline identifies keyboard focus.

Behavior and edge cases ​

  • The button defaults to type="button" to avoid accidental form submission.
  • The icon prop accepts any Vue icon component; Ooko does not require a specific icon library.
  • The icon slot overrides the icon prop for libraries that require configured markup.
  • Providing an icon without a default slot creates a square button with an aspect ratio of 1.
  • iconPosition has no visual effect when neither the icon prop nor the icon slot is provided.
  • The md button uses --o-control-form-height-md, sm uses --o-control-form-height-sm, and the button-only xs size uses a spacing token for a 1.5rem minimum, for actions inside table rows. All sizes grow when the label wraps or text is enlarged.
  • loading draws the spinner over the content and makes the content transparent instead of removing it, so the button keeps its exact size and the layout does not shift.
  • With reduced motion, the loading spinner turns more slowly instead of stopping.
  • Filled buttons use white text (--o-color-white), at rest and on hover, except neutral in the dark theme, whose fill is the light end of the scale and gets a dark label. Light fills such as warning and success then fall below a 4.5:1 contrast ratio. Filled hover states darken the background. Outline and nude buttons keep their color's text shades.
  • outline, nude, and soft are alternative visual treatments and should not be combined. soft tints the background with the button color, without a border, for secondary actions shown in a series.
  • A secondary outline button has a translucent fill for decorated surfaces, and its discreet border takes the primary color on hover.
  • Native button attributes, such as aria-label, are forwarded to the underlying element.
  • App defaults may configure color, size, outline, nude, and iconPosition; direct props take precedence.