Inputs
Button
A native button whose appearance is decided by its context, not by props.
Import
import { Button } from "@loamui/core";Usage
Every example has a CSStab. That’s the real, complete stylesheet for the component: plain, static CSS, with nothing running in the browser.
Contexts
Buttons are neutral by default. Declare --loam-context on a region and the buttons inside re-answer their colour; there are no variant props. See the Contextualism guide.
A region adapts every component
--loam-context isn't a button feature: everything in the region answers it. Here the checkbox's fill, the button's tint and the loader's stroke all take the danger colour, and focus rings inside follow. Intent is declared once on the container, not as a colour prop on each control.
Size and width from context
There are no size or fullWidth props. Padding and font are fluid (container-relative tokens), so the button is sized by the space it lives in. Width is the parent's decision: a container of 16rem or less makes a button span it, a grid or stacked-flex region stretches its buttons (that is the platform's own layout at work), and a flex row shrink-wraps them to their labels.
Icons and loading, composed as children
There are no leftSection, rightSection or loading props. An svg child is detected via :has() and gets flex layout, a gap and 1em sizing. A composed Loader is detected and sized the same way. Icon-only is detected from the accessible name: add the aria-label the icon-only case requires anyway and the button becomes square.
Guidance
When to use it
- To trigger an action in the current context: submitting a form, opening a dialog, confirming a choice.
- For destructive or risky operations, inside a danger region, so the whole surrounding context signals the stakes rather than one red button.
When not to
- To navigate to another page or URL: use a link. A button that navigates breaks right-click, middle-click and "open in new tab".
- For many low-emphasis choices at once: consider a Menu or Tabs instead of a row of equal buttons.
Accessibility
- Always renders a real <button>, so keyboard focus, Enter/Space activation and the button role come from the platform for free.
- Write a specific label: the text should make sense out of context ("Save changes", not "OK"). Icon-only buttons need an aria-label.
- For a loading state, add `disabled` and compose a <Loader/> (marked aria-hidden) into the children so it isn't announced as content.
- Focus is shown with a :focus-visible ring (never removed without a replacement), and colour is never the only signal of state.
How it works
Prevent double submission on the server
Button deliberately ships no preventDoubleClick or debounce prop. A client-side debounce doesn't prevent duplicates (retries, impatient refreshes and flaky networks bypass it), while it does hide real failures by swallowing clicks that deserved a response. Make the operation safe to repeat instead: an idempotency key or server-side dedupe, with disabled + <Loader/> as visible feedback while the request is in flight, not as the safety mechanism.
One primary action per section
Emphasis is a property of the region, not the button: wrap the section's single most important action in a primary context (--loam-context: "primary") and leave every other button neutral. Two "primary" buttons side by side ask the user to make a decision the interface should have made: if everything is emphasised, nothing is.
Props
Status is not a prop: it comes from the surrounding --loam-context region. See the Contextualism guide.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The button content: label, and any composed icons/spinner. |
type | "button" | "submit" | "reset" | "button" | Unlike a native <button>, never a submit button unless you say so. |
render | RenderProp | — | Substitute the rendered element; the Button's classes and wiring merge onto yours. Not for navigation: a call-to-action that goes somewhere is a SignpostLink. |
...others | ButtonHTMLAttributes | — | All native <button> props are forwarded. |
Custom properties
| Property | Syntax | Default | Description |
|---|---|---|---|
--loam-button-color | CSS color | var(--loam-color-fg) | The button's single colour channel. Set it to recolour one instance or a wrapper component; background, border, hover and active are all derived from it. |
--loam-button-radius | CSS length | var(--loam-radius-md) | Corner rounding; set it per instance or on a wrapper component. |