Mosmox UI
Current version
GitHubnpmjs.com
Foundations

Button

Action control for commands, navigation, forms, and asynchronous operations

The Button is the primary action primitive in the framework. It provides a consistent visual language for commands across websites, web applications, and dashboards while preserving native button and anchor semantics.

It supports visual variants, three sizes, Mosmox UI icons, icon-only layouts, links, disabled states, loading transitions, progress feedback, hover controls, platform-aware keyboard shortcut labels, and full-width layouts.

Installation

Import the component and icons from the UI packages.

import { ArrowRight, Download, Plus } from '@mosmox-ui/icons';
import { Button } from '@mosmox/ui';

Basic usage

The component renders a native <button> by default. Its content is passed through children.

<Button>Save changes</Button>

Use type explicitly when the button is inside a form.

<Button type="submit">Create account</Button>

Variants

Use variant to communicate the importance and behavior of an action.

<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="light">Light</Button>
<Button variant="outline">Outline</Button>
<Button variant="dashed">Dashed</Button>
<Button variant="text">Text button</Button>
<Button variant="link">Link button</Button>
<Button variant="danger">Delete</Button>
<Button variant="success">Complete</Button>

Variant guidance

  • primary is for the main action in a view.
  • secondary is for a supporting action with visible emphasis.
  • light is a filled, low-contrast action.
  • outline preserves a clear boundary without a filled background.
  • dashed is useful for secondary or add-new actions where a dashed boundary communicates an open slot.
  • text is a low-chrome action without a border or background.
  • link is for actions that should visually read as links.
  • danger communicates destructive actions.
  • success communicates a positive completion action.

Sizes

The size property controls the minimum height, typography, and padding. The framework intentionally provides default, sm, and xs without an extra-large size.

<Button size="default">Default</Button>
<Button size="sm">Small</Button>
<Button size="xs">Extra small</Button>

Horizontal padding is larger than vertical padding for all sizes. The extra-small size uses a reduced text size and a wider horizontal proportion to keep short controls visually balanced.

Icons

Use Mosmox UI icons through iconLeft and iconRight. The component reserves consistent spacing and icon dimensions.

<Button iconLeft={<Plus />}>Create project</Button>
<Button iconRight={<ArrowRight />}>Continue</Button>
<Button iconLeft={<Download />} variant="outline">Download</Button>

Icons can be combined with every visual variant and size.

Icon-only buttons

Set iconOnly when the control contains no visible text. Every icon-only button must have an accessible name through aria-label or an equivalent accessible label.

<Button aria-label="Add item" iconOnly iconLeft={<Plus />} />
<Button aria-label="Download file" variant="outline" iconOnly iconLeft={<Download />} />

Icon-only controls are square by default. Add circle when a circular control is required.

<Button aria-label="Add item" circle iconOnly iconLeft={<Plus />} />
<Button aria-label="Continue" circle variant="secondary" iconOnly iconLeft={<ArrowRight />} />

circle is a shape modifier and does not replace iconOnly; use both together for a circular icon button.

Loading states

Set loading when an action is in progress. The button becomes non-interactive and exposes aria-busy.

<Button loading>Saving</Button>

The default inline mode keeps the button content in place. When an icon is present, the loader transitions through the icon position.

<Button loading iconLeft={<Download />}>Downloading</Button>

Use loadingMode="replace" when the loader should replace the complete content and remain centered.

<Button loading loadingMode="replace">Publishing</Button>

loadingLabel provides the accessible label for the replacement state.

<Button loading loadingMode="replace" loadingLabel="Uploading file">Upload</Button>

When loading is active, native button interaction is disabled. Link buttons prevent navigation while busy.

Loading animation behavior

The loading transition preserves the button layout while animating its content:

  • inline loading replaces the active icon with a loader; the previous icon moves downward while the loader enters from above;
  • replacement loading moves the existing content out through the right edge and brings the centered loader in from the left;
  • the button keeps its minimum width during replacement so surrounding layout does not jump;
  • the loader is marked as decorative when the button supplies the accessible loading label.

Progress feedback

Pass a number from 0 to 100 through progress. The component displays the percentage in the content and renders a progress track along the bottom edge.

<Button progress={42}>Uploading (42%)</Button>

The displayed percentage is generated by the component. In normal usage, provide the label without manually adding the percentage.

<Button progress={42}>Uploading</Button>

Values below 0 are normalized to 0 and values above 100 are normalized to 100.

Progress can be combined with icons and variants.

<Button progress={68} variant="secondary" iconLeft={<Download />}>
  Downloading
</Button>

Providing href changes the rendered element to an anchor while preserving the Button API.

<Button href="/settings" variant="outline">Open settings</Button>
<Button href="https://example.com" target="_blank" rel="noreferrer" iconRight={<ArrowRight />}>
  Visit website
</Button>

Anchor attributes such as target, rel, download, and href are forwarded to the rendered link. A loading or progress state prevents navigation until the operation completes.

Disabled state

Use disabled when the action is unavailable. The native button is disabled and the component applies its disabled visual state.

<Button disabled>Unavailable</Button>

Anchor elements do not have a native disabled attribute. For a link-style action that must be unavailable, use the loading or progress state, or prevent the action in the parent state before rendering the link.

Hover behavior

The default hover interaction gently lifts the button by 2 pixels without changing its shadow or adding a hover background effect. Use disableHover when no hover movement should occur.

<Button disableHover>Static interaction</Button>

Use hoverScale to scale the text and icons while keeping the button itself in place.

<Button hoverScale iconLeft={<Sparkles />}>Scale content</Button>

disableHover takes precedence over the hover-scale behavior.

Pressed state

When the pointer or keyboard activates an enabled button, it immediately returns to its resting baseline with no press animation and no additional shadow. This creates a quick press-down response while preserving the default hover lift between interactions.

Focus state

Keyboard focus uses a visible focus ring derived from the global focus token. Focus styling is separate from hover styling and remains available when hover is disabled.

Reduced motion

When the user prefers reduced motion, button transitions are removed and the loader animation is slowed. The component remains usable without relying on motion to communicate state.

Full width

Set fullWidth when the action should fill the width of its container.

<Button fullWidth>Continue</Button>

Full-width buttons are useful in forms, narrow panels, mobile layouts, and stacked action groups.

Platform keyboard shortcuts

Use win and mac to provide platform-specific shortcut labels. The component detects macOS from the browser environment and displays mac there; Windows, Linux, and other platforms display win. If only one value is provided, it is used as a fallback on both platforms.

<Button win="Ctrl+K" mac="⌘K" onClick={openSearch}>
  Search
</Button>

The shortcut is a visible kbd label on the button and is also exposed through aria-keyshortcuts. These props describe and display the shortcut; the application should register the actual keyboard handler when the shortcut needs to trigger the action.

Events and native attributes

Button-specific props are combined with native ButtonHTMLAttributes or AnchorHTMLAttributes. Event handlers are passed to the rendered element.

<Button onClick={() => saveChanges()} aria-describedby="save-help">
  Save
</Button>

Common native attributes include id, name, value, form, formAction, formMethod, tabIndex, title, keyboard handlers, focus handlers, and pointer handlers.

Accessibility

The component preserves native semantics and adds state information where needed:

  • native buttons use disabled for disabled and busy interaction;
  • busy controls expose aria-busy;
  • replacement loading content receives an accessible loading label;
  • icon-only buttons require an accessible name;
  • visible keyboard focus uses :focus-visible styling;
  • reduced-motion preferences reduce transition and spinner intensity.

Do not use an icon-only button without an accessible label.

Styling model

Button styles are split into shared theme tokens and component styles. Shared values such as colors, typography, radius, and icon size come from the theme token layer. Button-only behavior, such as progress tracks, loading transitions, and icon-only geometry, remains in Button.css.

Global values can be changed through ConfigProvider.

import { Button, ConfigProvider } from '@mosmox/ui';

<ConfigProvider
  theme={{
    colors: { primary: '#003231', text: '#0C1518' },
    radius: '5px',
  }}
>
  <Button>Uses the configured theme</Button>
</ConfigProvider>

Button-only settings can be scoped through the components.button configuration.

<ConfigProvider
  components={{
    button: { gap: '10px', iconSize: '16px', radius: '5px' },
  }}
>
  <Button iconLeft={<Plus />}>Create</Button>
</ConfigProvider>

API Reference

PropertyTypeDefaultDescription
childrenReactNode—Visible button content.
variantButtonVariantprimaryVisual variant.
sizeButtonSizedefaultdefault, sm, or xs.
iconLeftReactNode—Content before the label.
iconRightReactNode—Content after the label.
iconOnlybooleanfalseUses an icon-only square layout.
circlebooleanfalseMakes an icon-only control circular.
loadingbooleanfalseMarks the control as busy and disables interaction.
loadingModeinline | replaceinlineLoader presentation mode.
loadingLabelstringLoadingAccessible replacement-state label.
progressnumber—Progress value normalized to 0–100.
winstring—Shortcut label for Windows, Linux, and other non-macOS platforms.
macstring—Shortcut label for macOS.
disableHoverbooleanfalseDisables hover movement and scaling.
hoverScalebooleanfalseScales text and icons on hover.
fullWidthbooleanfalseExpands the control to the available width.
classNamestring—Additional class name.
styleCSSProperties—Inline styles and CSS custom-property overrides.
hrefstring—Renders an anchor instead of a button.
aria-labelstring—Accessible name, required for icon-only controls.
disabledbooleanfalseDisables a native button.
onClickfunction—Native button or anchor click handler.