# Morph Label

> Words that morph in place when they change: the width eases to the new words while the old ones blur out and the new ones blur in.

- Name: `morph-label`
- Status: beta
- Categories: motion, display
- File: the install writes `morph-label.tsx` to your `ui` alias, `@/components/ui` by default.
- Other registry items: `@arbokui/motion-timing`. The install adds them.
- Gallery: https://arbokui.com/components/morph-label
- Registry item: https://arbokui.com/r/morph-label.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/morph-label
   ```

## Use it for

- Words that change where people are looking, like Follow to Following, Save to Saved, or a short status beside a value.
- Use MorphLabel explicitly when a word change needs the blur treatment. Button uses MotionSwap for its default crossfade.
- Whatever holds it grows or shrinks with it, so a button eases to its new width instead of snapping.

## Avoid it for

- Long text or a paragraph. It is for a few words on one line. Words wider than the space end in an ellipsis, so in a flex row give the box that holds it min-w-0.
- Words that change many times a second, like a timer. Use Rolling Number for numbers that count.
- Saying something only through the change. Words that matter, like an error, also need a role="alert" or role="status" so they are read out.

## Props

- `children`: `string | number`. The words. When they change, the old ones blur out as the new ones blur in.
- `className`: `string`. Extra classes on the label. Later classes win.

## Accessibility

- Screen readers read only the new words. The old words are hidden from them while they fade.
- It does not announce the change. Put it in a live region, or add a role="status" message, when the change must be heard.
- The morph follows the --motion-\* tokens. Reduced motion lands the new width at once and keeps only the fade, in place. With motion off, the words swap at once.

## Examples

### Words that change on a press

```tsx
const [following, setFollowing] = useState(false);

<Button emphasis={following ? "soft" : "solid"} onClick={() => setFollowing((on) => !on)}>
  {following ? "Following" : "Follow"}
</Button>
```

### A short status that changes in place

```tsx
<p className="text-sm text-muted-foreground" role="status">
  <MorphLabel>{saving ? "Saving…" : "Saved just now"}</MorphLabel>
</p>
```
