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

# Button

> A core interactive element, empowering users to take action effortlessly in your app.

## Examples

<Tabs>
  <Tab title="Variants">
    <Frame caption="Different button styles for varying emphasis levels.">
      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/buttons/button/button_variants_light.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=09908c3cc497fb7904d0b049e65bd56b" alt="Button variants example" noZoom className="block dark:hidden" width="1536" height="384" data-path="images/widgets/buttons/button/button_variants_light.png" />

      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/buttons/button/button_variants_dark.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=d42056e2cd482641d59ac59591148eaf" alt="Button variants example" noZoom className="hidden dark:block" width="1536" height="384" data-path="images/widgets/buttons/button/button_variants_dark.png" />
    </Frame>

    <CodeGroup>
      ```dart Primary lines theme={null}
      NeoButton(
        variant: .primary,
        label: "Primary",
        onPressed: () {},
      ),
      ```

      ```dart Secondary lines theme={null}
      NeoButton(
        variant: .secondary,
        label: "Secondary",
        onPressed: () {},
      ),
      ```

      ```dart Tertiary lines theme={null}
      NeoButton(
        variant: .tertiary,
        label: "Tertiary",
        onPressed: () {},
      ),
      ```

      ```dart Link lines theme={null}
      NeoButton(
        variant: .link,
        label: "Link",
        onPressed: () {},
      ),
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Icons">
    <Frame caption="Button icons with different positioning options.">
      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/buttons/button/button_icons_light.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=4b7d0adb61b9d53d9a1cfa75a83b7526" alt="Button with icon example" noZoom className="block dark:hidden" width="1536" height="384" data-path="images/widgets/buttons/button/button_icons_light.png" />

      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/buttons/button/button_icons_dark.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=266ae0799015a7330d9f3c660978b742" alt="Button with icon example" noZoom className="hidden dark:block" width="1536" height="384" data-path="images/widgets/buttons/button/button_icons_dark.png" />
    </Frame>

    <CodeGroup>
      ```dart Leading Icon lines theme={null}
      NeoButton(
        variant: .primary,
        label: "Create",
        icon: PhosphorIconsRegular.plus,
        onPressed: () {},
      ),
      ```

      ```dart Trailing Icon lines theme={null}
      NeoButton(
        variant: .secondary,
        label: "Open",
        icon: PhosphorIconsRegular.arrowUpRight,
        iconPosition: .trailing,
        onPressed: () {},
      ),
      ```

      ```dart Icon Only lines theme={null}
      NeoButton(
        variant: .primary,
        icon: PhosphorIconsRegular.trash,
        isDanger: true,
        onPressed: () {},
      ),
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Sizes">
    <Frame caption="Different button sizes and alignment options.">
      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/buttons/button/button_sizes_light.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=f3adb39db02107f0c5816758e8e3b532" alt="Button sizes example" noZoom className="block dark:hidden" width="1536" height="512" data-path="images/widgets/buttons/button/button_sizes_light.png" />

      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/buttons/button/button_sizes_dark.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=022335969ae6dc4f10ad05faf446bda0" alt="Button sizes example" noZoom className="hidden dark:block" width="1536" height="512" data-path="images/widgets/buttons/button/button_sizes_dark.png" />
    </Frame>

    <CodeGroup>
      ```dart Medium lines theme={null}
      NeoButton(
        variant: .primary,
        size: .medium,
        label: "Medium",
        onPressed: () {},
      ),
      ```

      ```dart Small lines theme={null}
      NeoButton(
        variant: .primary,
        size: .small,
        label: "Small",
        onPressed: () {},
      ),
      ```

      ```dart Expanded lines theme={null}
      NeoButton(
        variant: .primary,
        isExpanded: true,
        label: "Expanded",
        onPressed: () {},
      ),
      ```

      ```dart Aligned Left lines theme={null}
      NeoButton(
        variant: .primary,
        isExpanded: true,
        alignment: .start,
        label: "Aligned",
        icon: PhosphorIconsRegular.alignLeft,
        onPressed: () {},
      ),
      ```
    </CodeGroup>
  </Tab>

  <Tab title="States">
    <Frame caption="Button states for different interaction scenarios.">
      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/buttons/button/button_states_light.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=2b842c6f0d36d77e7250e5d3a2624123" noZoom className="block dark:hidden" width="1536" height="384" data-path="images/widgets/buttons/button/button_states_light.png" />

      <img src="https://mintcdn.com/tvk/xOcwrKRVA4J0vbxn/images/widgets/buttons/button/button_states_dark.png?fit=max&auto=format&n=xOcwrKRVA4J0vbxn&q=85&s=5064ac81681ae0b199c573b068e4c416" noZoom className="hidden dark:block" width="1536" height="384" data-path="images/widgets/buttons/button/button_states_dark.png" />
    </Frame>

    <CodeGroup>
      ```dart Loading State lines theme={null}
      NeoButton(
        variant: .primary,
        label: "Save Changes",
        isLoading: true,
        onPressed: () {},
      ),
      ```

      ```dart Danger State lines theme={null}
      NeoButton(
        variant: .primary,
        label: "Delete Account",
        isDanger: true,
        onPressed: () {},
      ),
      ```

      ```dart Disabled State lines theme={null}
      NeoButton(
        variant: .filled,
        label: "Submit",
        isEnabled: false,
        onPressed: () {},
      ),
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Properties

### Required

<ParamField path="variant" type="NeoButtonVariant" required>
  The variant/style of the button.
</ParamField>

<ParamField path="onPressed" type="VoidCallback" required>
  The callback to call when the button is pressed.
</ParamField>

### Content

<ParamField path="label" type="String">
  The text label to display on the button.
</ParamField>

<ParamField path="icon" type="PhosphorIconData">
  The icon to display on the button. (e.g. `PhosphorIconsRegular.plus`)
</ParamField>

<ParamField path="iconPosition" type="NeoButtonIconPosition" default=".leading">
  The position of the icon. Only applies when `icon` is provided.
</ParamField>

<ParamField path="tooltip" type="String">
  The tooltip text to display when <Tooltip tip="Long press on mobile">hovering</Tooltip> over the button.
</ParamField>

<ParamField path="isCaretRotated" type="bool">
  Adds a caret icon to the button and rotates it based on this boolean value. Useful for dropdown toggles.
</ParamField>

### Layout

<ParamField path="size" type="NeoButtonSize" default=".medium">
  The size of the button.
</ParamField>

<ParamField path="isExpanded" type="bool" default="false">
  Whether the button should fill the available width.
</ParamField>

<ParamField path="alignment" type="NeoButtonAlignment" default=".center">
  The alignment of the content inside the button. Only applies when `isExpanded` is `true`.
</ParamField>

### State

<ParamField path="isLoading" type="bool" default="false">
  Shows a spinning indicator and disables interaction. Useful for async operations.
</ParamField>

<ParamField path="isDanger" type="bool" default="false">
  Applies danger styling (typically red colors) to indicate destructive actions like deletion.
</ParamField>

<ParamField path="isEnabled" type="bool" default="true">
  Controls whether the button responds to user interaction. Disabled buttons have reduced opacity and show a forbidden cursor.
</ParamField>

<ParamField path="requireHold" type="bool" default="false">
  When enabled, users must hold the button for a specified duration before the action is triggered. Only supported for `NeoButtonVariant.secondary` buttons.
</ParamField>

<ParamField path="holdDuration" type="Duration" default="Duration(seconds: 1)">
  The duration users must hold the button when `requireHold` is `true`.
</ParamField>

### Styling

<ParamField path="bgColor" type="Color">
  The background color of the button. Only valid on the `primary` variant — use `fgColor` and `fgInteractionColor` for other variants.
</ParamField>

<ParamField path="bgInteractionColor" type="Color">
  The background color for both hover and pressed states. Overrides the theme-derived interaction color.
</ParamField>

<ParamField path="fgColor" type="Color">
  The foreground color of all content inside the button (label, icon, caret). Essential when using custom background colors.
</ParamField>

<ParamField path="fgInteractionColor" type="Color">
  The foreground color for both hover and pressed states.
</ParamField>

## Enums

### NeoButtonVariant

Different variants/styles of buttons.

* `primary`: Solid fill for high emphasis.
* `secondary`: Border-only for medium emphasis.
* `tertiary`: No fill or border initially; fills on hover for low emphasis.
* `link`: Underlined text style for low-emphasis actions and navigation.

### NeoButtonSize

* `small`: Compact size for dense UIs.
* `medium`: Standard size for most cases.

### NeoButtonAlignment

* `start`: Aligns content to the left.
* `center`: Default centering.

### NeoButtonIconPosition

* `leading`: Icon before label.
* `trailing`: Icon after label.

## Best Practices

* **Width Constraints**: When using `isExpanded: true`, always provide width constraints to prevent layout issues by wrapping in `Expanded`, `ConstrainedBox`, `SizedBox`, etc.
* **Loading States**: Use `isLoading: true` for async operations to provide visual feedback and prevent double-taps
* **Danger Actions**: Always use `isDanger: true` for destructive actions like deletion or data loss
* Combine with [`NeoHaptics`](/utilities/haptics) in the `onPressed` callback for enhanced user experience on supported devices
* Limit the number of primary (filled) buttons per screen to avoid decision paralysis
* `tooltip` is essential for accessibility when using icon-only buttons, and helpful for providing additional context on any button
* Edge case: If no `label` or `icon` is provided, the button renders as empty—always provide at least one
