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

# Button Toggle - Web

> Button Toggles let users alternate between two states with a single click.

> [!NOTE]
>
> For development, import `ButtonToggle` from
> `@servicetitan/anvil2`. For design, find it in the
> [Anvil2 file](https://www.figma.com/design/xaNQsvRKczoxu7pj0M6QT8/Anvil2-v3?node-id=157-546).

![](https://mintcdn.com/servicetitan/uz2PQSvO75TRhQ38/images/docs/web/components/shared/main-image-for-button-toggle.png?fit=max\&auto=format\&n=uz2PQSvO75TRhQ38\&q=85\&s=5f94957b6e5937f8db5402930771c05a)

## Anatomy

The Button Toggle consists of three primary elements that work together to let users alternate between two states with a single click.

![Button Toggle
anatomy](https://mintcdn.com/servicetitan/Ni0bXIw9diilEZPZ/images/docs/web/components/button-toggle/design/button-toggle-anatomy.png?fit=max\&auto=format\&n=Ni0bXIw9diilEZPZ\&q=85\&s=a531a54e58e2b21f0d57e69a0a64faa9)

1. Container
2. Text label
3. Icon

## Options

The Button Toggle supports multiple size configurations to accommodate various toggle scenarios.

#### Sizes

![Button options
sizes](https://mintcdn.com/servicetitan/Ni0bXIw9diilEZPZ/images/docs/web/components/button-toggle/design/button-options-sizes.png?fit=max\&auto=format\&n=Ni0bXIw9diilEZPZ\&q=85\&s=d76b3ce68435fc230c0432a399f9424b)

| Size | Height |
| - | - |
| Large | 48px |
| Medium | 40px |
| Small | 32px |

## Behavior

The Button Toggle responds to user interaction with distinct visual states and flexible layout behaviors.

### Visual States

#### Default

![Default Button
Toggle](https://mintcdn.com/servicetitan/Ni0bXIw9diilEZPZ/images/docs/web/components/button-toggle/design/default-button-toggle.png?fit=max\&auto=format\&n=Ni0bXIw9diilEZPZ\&q=85\&s=a44e50fd2bc1201cad8c47ec4f7a7c4c)

#### Checked

![Checked Button
Toggle](https://mintcdn.com/servicetitan/Ni0bXIw9diilEZPZ/images/docs/web/components/button-toggle/design/checked-button-toggle.png?fit=max\&auto=format\&n=Ni0bXIw9diilEZPZ\&q=85\&s=dd734c85ecee4de13f8b92edfd1f12c6)

#### Text wrap

Button Toggles fill all available space, wrapping only when no space remains. Text is center-aligned when wrapping.

#### Widths

In general, Button Toggles should match the width of their text. Container width works well when aligning with specific layout elements. Button Toggle Icon width always equals its height.

## Usage Guidelines

| Standard | Requirement |
| - | - |
| DoControl binary state | Button Toggles control the binary state of a Button. They can contain text, text with an icon, or just an icon. |
| DoSelect multiple options from a set | Button Toggles work well when selecting multiple options from a set of available options; see [How to Use](#how-to-use). |

### How to Use

Button Toggles work well when selecting multiple options from a set of available options.

buttontoggle-playground

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/buttontoggle-playground?file=src/App.tsx)

```tsx lines theme={null}
import { ButtonToggle, Flex } from "@servicetitan/anvil2";
import Star from "@servicetitan/anvil2/assets/icons/material/round/star.svg";
import Favorite from "@servicetitan/anvil2/assets/icons/material/round/favorite.svg";
import Bookmark from "@servicetitan/anvil2/assets/icons/material/round/bookmark.svg";

function App() {
  return (
    <Flex gap="2">
      <ButtonToggle icon={{ before: Star }}>Star</ButtonToggle>
      <ButtonToggle icon={{ before: Favorite }}>Heart</ButtonToggle>
      <ButtonToggle icon={{ before: Bookmark }}>Bookmark</ButtonToggle>
    </Flex>
  );
}

export default App;
```

> [!TIP]
>
> **Do**

## Content

Content within the Button Toggle should clearly communicate the toggle state through labels and optional icons.

## Keyboard Interaction

Users can navigate the Button Toggle using standard keyboard controls.

| Key | Interaction |
| - | - |
| Space or Enter | Toggles checked state |

Button Toggles using an href will also use this keyboard combination.

### Accessibility

Anvil provides most of the accessibility needs for Button Toggle out of the box, and only need some additional considerations for library users.

#### Provide labels for Icon Buttons

Regardless of whether or not a label is visible on the page, a label should be provided to describe the action for both screen readers and for users who focus on the element.

For more guidance on button labels and accessibility, see [button accessibility best practices](https://anvil.servicetitan.com/docs/accessibility/labels-and-ctas.md#buttons-and-links).

## Code

**Implementation**

buttontoggle-playground

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/buttontoggle-playground?file=src/App.tsx)

```tsx lines expandable theme={null}
import { ButtonToggle, Flex } from "@servicetitan/anvil2";
import Star from "@servicetitan/anvil2/assets/icons/material/round/star.svg";
import Favorite from "@servicetitan/anvil2/assets/icons/material/round/favorite.svg";
import Bookmark from "@servicetitan/anvil2/assets/icons/material/round/bookmark.svg";

function App() {
  return (
    <Flex gap="2">
      <ButtonToggle icon={{ before: Star }}>Star</ButtonToggle>
      <ButtonToggle icon={{ before: Favorite }}>Heart</ButtonToggle>
      <ButtonToggle icon={{ before: Bookmark }}>Bookmark</ButtonToggle>
    </Flex>
  );
}

export default App;
```

## Common Examples

```tsx theme={null}
import { ButtonToggle } from "@servicetitan/anvil2";

function ExampleComponent() {
  return <ButtonToggle>Click to toggle</ButtonToggle>;
}
```

### Button toggle sizes

Use the `size` prop to adjust the text size and padding of the button.

buttontoggle-size

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/buttontoggle-size?file=src/App.tsx)

```tsx lines expandable theme={null}
import { ButtonToggle, Flex } from "@servicetitan/anvil2";

function App() {
  return (
    <Flex gap="3">
      <ButtonToggle size="large">Large</ButtonToggle>
      <ButtonToggle size="medium">Medium(Default)</ButtonToggle>
      <ButtonToggle size="small">Small</ButtonToggle>
    </Flex>
  );
}

export default App;
```

### Controlling button toggles

buttontoggle-controlled

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/buttontoggle-controlled?file=src/App.tsx)

```tsx lines expandable theme={null}
import { ButtonToggle } from "@servicetitan/anvil2";
import { useState } from "react";

function App() {
  const [isChecked, setIsChecked] = useState(true);

  return (
    <ButtonToggle
      checked={isChecked}
      onClick={() => setIsChecked((prev) => !prev)}
    >
      Click to Toggle
    </ButtonToggle>
  );
}

export default App;
```

#### Uncontrolled button toggles

By default, button toggles are uncontrolled. The checked state changes when the button is clicked. To make the button toggle checked by default, use the `defaultChecked` prop.

buttontoggle-uncontrolled

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/buttontoggle-uncontrolled?file=src/App.tsx)

```tsx lines expandable theme={null}
import { ButtonToggle } from "@servicetitan/anvil2";

function App() {
  return <ButtonToggle defaultChecked>Click to Toggle</ButtonToggle>;
}

export default App;
```

#### Controlled button toggles

To programmatically set the checked state of a button toggle, use the `checked` prop.

### Handling state changes

The `onChange` prop accepts a function that passes the change event and current state object. This can be used to trigger other actions depending on the changed state.

```tsx theme={null}
() => {
  doSomething(state: ButtonToggleState) {
    console.log(`${state.value} is pressed: ${state.pressed}`)
  }
  return (
    <ButtonToggle onChange={(e, state) => doSomething(state)}>
      Toggle
    </ButtonToggle>
  )
}
```

## React Accessibility

### Icon-only button toggles

```tsx theme={null}
<ButtonToggle icon={Star} aria-label="Favorite" />
```

> [!TIP]
>
> **Do**

Use aria-label or aria-labelledby for a button without any text.

```tsx theme={null}
<ButtonToggle icon={Star} />
```

> [!CAUTION]
>
> **Don't**

Provide only an icon for screen readers to read.

For more guidance on button labels and accessibility, see [button accessibility best practices](https://anvil.servicetitan.com/docs/accessibility/labels-and-ctas.md#buttons-and-links).

**ButtonToggle Props**

```tsx theme={null}
<ButtonToggle
  checked={true}
  defaultChecked={false}
  disabled={false}
  icon={StarIcon}
  size="medium"
  value="toggle-1"
  onChange={(e, state) => console.log(state)}
>
  Click to toggle
</ButtonToggle>
```

## `ButtonToggle` Props

**checked** `boolean`

**children** `ReactNode`

**defaultChecked** `boolean` (default: false)

**disabled** `boolean` (default: false)

**icon** `Svg \{ before: Svg, after: Svg \}`

The SVGR library imports `*.svg` files as React components, so `icon` can
accept either a React component, or an object with `before` and/or `after`
keys to specify the placement of the icon.

**onChange** `(event, \{ pressed, value \}) =\> void`

**size** `"small" | "medium" | "large"` (default: medium)

**value** `string`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.