> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Button

> Trigger actions or navigate with styled buttons.

Use `Button` for an action. Supply its visible label as children, and give icon-only buttons an `aria-label`.

For recurring design defaults, use [MainButton](/ui/components/input/main-button)
or [LightButton](/ui/components/input/light-button) from `twenty-ui/components`.
Both share Button's native props, refs, state, and rendering behavior.

## State ownership

`Button` triggers an action and does not manage a selected value, so it has no controlled or uncontrolled selection mode. Its native `value` prop supplies form data, not selection state.

Your application owns `loading`, `disabled`, and `soon`, which default to `false`. Clicking a button does not change these props or automatically show loading while an asynchronous handler runs. Pass the current application state explicitly.

```tsx theme={null}
import { useState } from 'react';
import { Button } from 'twenty-ui/primitives/input';

type SaveRecordProps = { onSave: () => Promise<void> };

export const SaveRecord = ({ onSave }: SaveRecordProps) => {
  const [loading, setLoading] = useState(false);
  const [hasError, setHasError] = useState(false);

  const handleSave = async () => {
    setLoading(true);
    setHasError(false);

    try {
      await onSave();
    } catch {
      setHasError(true);
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <Button loading={loading} onClick={handleSave}>
        Save record
      </Button>
      {hasError && <p role="alert">Unable to save the record. Try again.</p>}
    </>
  );
};
```

The application starts and clears loading around the save operation. The button prevents activation while loading and becomes available again when the operation finishes, including after an error. `MainButton` and `LightButton` use the same state model.

## Appearance

```tsx theme={null}
import { Button } from 'twenty-ui/primitives/input';
import { IconPlus } from 'twenty-ui/icon';

export const CreateRecord = () => (
  <Button variant="solid" color="accent" size="sm" startIcon={<IconPlus />}>
    Create record
  </Button>
);
```

Choose `solid`, `outline`, `soft`, or `ghost` independently of the `neutral`, `accent`, `danger`, or `success` color. Sizes are `sm` and `md`; the defaults are `outline`, `neutral`, and `md`. `fullWidth` fills the available width. `startIcon` and `endIcon` accept elements and are decorative. `elevated` adds a shadow. `hotkeys` displays keyboard hints on larger screens; bind the shortcuts in your application.

`disabled`, `loading`, and `soon` prevent activation. Loading keeps the label accessible and preserves the button's width while showing a spinner. Customize the upcoming-feature label with `soonLabel`.

## Links and forms

```tsx theme={null}
import { Button } from 'twenty-ui/primitives/input';

export const DocumentationLink = () => (
  <Button href="https://twenty.com" target="_blank" rel="noreferrer">
    Read documentation
  </Button>
);
```

`href` renders an anchor with link semantics. The caller can supply its own `render` element or router link. Set `href` and preserve an anchor for navigation; without `href`, preserve a native button. Button derives its semantics without public `nativeButton` or `role` flags. Disabled links cannot activate.

Buttons default to `type="button"`. Set `type="submit"` or `type="reset"` explicitly for forms. Native props, event handlers, refs, and Base UI's `render` prop pass through to the root.

## Props

<ParamField body="className" type="string | ((state: ButtonState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="color" type="&#x22;neutral&#x22; | &#x22;accent&#x22; | &#x22;danger&#x22; | &#x22;success&#x22;" default="neutral">
  Semantic color of the button.
</ParamField>

<ParamField body="elevated" type="boolean" default="false">
  Adds a shadow to the button.
</ParamField>

<ParamField body="endIcon" type="ReactNode">
  Decorative content displayed after the label.
</ParamField>

<ParamField body="focusableWhenDisabled" type="boolean" default="false">
  Whether the button should be focusable when disabled.
</ParamField>

<ParamField body="fullWidth" type="boolean" default="false">
  Expands the button to fill its container width.
</ParamField>

<ParamField body="hotkeys" type="string[]">
  Keyboard shortcut hints displayed on non-mobile screens.
</ParamField>

<ParamField body="loading" type="boolean" default="false">
  Shows a loading indicator and disables activation while preserving the button width.
</ParamField>

<ParamField body="render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ButtonState>">
  Caller-supplied root element or renderer. Preserve a native button, or an anchor when `href` is set. Router integration belongs to the caller.
</ParamField>

<ParamField body="size" type="&#x22;sm&#x22; | &#x22;md&#x22;" default="md">
  Button height: `sm` (24px) or `md` (32px).
</ParamField>

<ParamField body="soon" type="boolean" default="false">
  Displays a coming-soon label and disables activation.
</ParamField>

<ParamField body="soonLabel" type="string">
  Text for the coming-soon label.
</ParamField>

<ParamField body="startIcon" type="ReactNode">
  Decorative content displayed before the label.
</ParamField>

<ParamField body="style" type="CSSProperties | ((state: ButtonState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

<ParamField body="variant" type="&#x22;solid&#x22; | &#x22;outline&#x22; | &#x22;ghost&#x22; | &#x22;soft&#x22;" default="outline">
  Visual treatment of the button surface.
</ParamField>
