# Animated Buttons

Buttons with hover motion, such as a fill that sweeps in or an arrow that expands behind the label.

Fill sweep button

[Complete TSX file](/examples/animated-buttons/default.tsx)

```tsx
"use client";

import { FillSweepButton } from "@/siteplane/components/animated-buttons";

export default function Example() {
  return <FillSweepButton>Continue</FillSweepButton>;
}
```

## Installation

Complete [one-time setup](/docs/installation/) first.

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/animated-buttons
```

With npm: `npx shadcn@4.18.0 add @siteplane/animated-buttons`. [Registry JSON](/registry/animated-buttons.json) lists source files and dependencies.

## Usage

```tsx
import { FillSweepButton } from "@/siteplane/components/animated-buttons";

<FillSweepButton>Continue</FillSweepButton>;
```

## Fill variants

`FillSweepButton` keeps Button behavior and sweeps a fill in on hover. `destructive` uses the outlined destructive surface.

Fill sweep variants

[Complete TSX file](/examples/animated-buttons/variants.tsx)

```tsx
"use client";

import { FillSweepButton } from "@/siteplane/components/animated-buttons";

export default function Example() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      {(["default", "destructive", "inverse", "outline"] as const).map(
        (variant) => (
          <FillSweepButton key={variant} variant={variant}>
            {variant}
          </FillSweepButton>
        ),
      )}
    </div>
  );
}
```

## Expanding actions

`ExpandingArrowButton` expands its arrow circle behind the label on hover and can render a link. `ExpandingLogoutButton` shows its icon and reveals `label` on hover and keyboard focus; `label` is also its accessible name.

Expanding arrow link and log out button

[Complete TSX file](/examples/animated-buttons/expanding.tsx)

```tsx
"use client";

import {
  ExpandingArrowButton,
  ExpandingLogoutButton,
} from "@/siteplane/components/animated-buttons";

export default function Example() {
  return (
    <div className="flex flex-wrap items-center gap-4">
      <ExpandingArrowButton
        label="View projects"
        render={<a href="#projects" />}
      />
      <ExpandingLogoutButton />
    </div>
  );
}
```

## Sizes and states

The expanding recipes accept `sm`, `md`, `lg`, and `xl`. Disabled and loading buttons don't animate.

Sizes, disabled and loading

[Complete TSX file](/examples/animated-buttons/sizes.tsx)

```tsx
"use client";

import {
  ExpandingArrowButton,
  FillSweepButton,
} from "@/siteplane/components/animated-buttons";

const sizes = [
  { size: "sm", label: "Small" },
  { size: "md", label: "Medium" },
  { size: "lg", label: "Large" },
  { size: "xl", label: "Extra large" },
] as const;

export default function Example() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      {sizes.map(({ size, label }) => (
        <ExpandingArrowButton key={size} size={size} label={label} />
      ))}
      <FillSweepButton disabled>Continue</FillSweepButton>
      <FillSweepButton loading>Saving</FillSweepButton>
    </div>
  );
}
```

## API reference

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| FillSweepButton.variant | default \| destructive \| inverse \| outline | default | Button surface; destructive renders the outlined destructive surface. |
| FillSweepButton.children | ReactNode | unset | Visible content. |
| ExpandingArrowButton.label | ReactNode | Learn more | Label; replaces children. |
| ExpandingArrowButton.variant | text \| default | text | Surface; default sets the arrow on the default Button's fill, hairline rim and depth. |
| ExpandingLogoutButton.label | string | Log out | Label and default accessible name. |
| ExpandingLogoutButton.variant | default \| destructive \| inverse \| outline | destructive | Button surface; destructive renders the outlined destructive surface. |
| Arrow / Logout.size | sm \| md \| lg \| xl | provider / lg | Control size; follows SiteplaneUIProvider when omitted. |
| Arrow / Logout.type | button \| submit \| reset | button | Native button type; not set when render supplies a link. |
| ExpandingLogoutButton.aria-label | string | label | Accessible name override. |
`FillSweepButtonProps` extends `ButtonBaseProps` except `variant` and accepts
every Button size. `ExpandingArrowButtonProps` and `ExpandingLogoutButtonProps`
omit `children`, `size`, and `variant` and add `label`, the control `size` and
their own `variant` subset. The three Props types are exported;
`AnimatedButtonVariant` is not. `onClick`, `disabled`, `loading`, `render`,
`style`, and refs follow [Button](/docs/components/button/).

[Read the installed source](/source/animated-buttons).

## Usage notes

Keep actions understandable without motion. Reduced-motion behavior belongs to the built-in styles. Use actual links for navigation; leave space for expanding labels and avoid clipping them in narrow parents.
