# Action Swap

> Cycle an action's label and icon with blur, roll, or letter-cascade transitions.

Source: https://www.honestui.com/docs/animated/action-swap

```tsx
"use client";

import { Bell, BellOff, Volume2 } from "honestui/icons";

import { ActionSwapButton } from "@/registry/default/animated/action-swap";

const items = [
  { id: "every-update", label: "Every update", icon: <Bell className="size-4" /> },
  { id: "priority-only", label: "Priority only", icon: <Volume2 className="size-4" /> },
  { id: "paused", label: "Alerts paused", icon: <BellOff className="size-4" /> },
];

export function ActionSwapDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-3 p-6">
      <ActionSwapButton items={items} animation="blur" />
      <ActionSwapButton items={items} animation="roll" variant="outline" />
      <ActionSwapButton items={items} animation="cascade" variant="primary" />
    </div>
  );
}

```

## Overview [#overview]

Use Action Swap when one compact control moves through a small, predictable set of related modes. The button can animate its label, icon, or both while preserving a stable hit target.

## Installation [#installation]

<CliBlock commands="[&#x22;action-swap&#x22;]" />

## Usage [#usage]

```tsx
import { ActionSwapButton } from "@/components/animated/action-swap"

const items = [
  { id: "digest", label: "Daily digest" },
  { id: "paused", label: "Digest paused" },
]

<ActionSwapButton items={items} animation="cascade" />
```

Use `ActionSwapText` and `ActionSwapIcon` directly when another control owns the interaction. The `action-swap-blur`, `action-swap-roll`, and `action-swap-cascade` entry points provide fixed-animation wrappers.

## Accessibility [#accessibility]

Keep every state label specific. Icon-only items need an `ariaLabel`. Reduced-motion users receive an immediate, legible state change without the full transition.

## API Reference [#api-reference]


  ### `items`

type: `ActionSwapItem[]`

Ordered states with an 

    `id`

    , visible 

    `label`

    , optional 

    `icon`

    , and optional 

    `ariaLabel`

    .

  ### `value`

type: `string`

Controlled active item id.

  ### `defaultValue`

type: `string`

Initial item id for uncontrolled use.

  ### `onValueChange`



void">
    Runs after the active item changes.

  ### `animation`

type: `&#x22;blur&#x22; | &#x22;roll&#x22; | &#x22;cascade&#x22;` · default: `&#x22;blur&#x22;`

Transition used for the label and icon.

  ### `variant`

type: `&#x22;primary&#x22; | &#x22;secondary&#x22; | &#x22;outline&#x22; | &#x22;ghost&#x22;` · default: `&#x22;secondary&#x22;`

Visual emphasis of the button.

  ### `size`

type: `&#x22;sm&#x22; | &#x22;md&#x22; | &#x22;lg&#x22; | &#x22;icon&#x22;` · default: `&#x22;md&#x22;`

Button size.

  ### `cycle`

type: `boolean` · default: `true`

Advances to the next item when clicked.
