# <motion-ring>

An ellipse or a box that draws itself around a word or a short phrase, like
a pen circling something important. It keeps its text on one line.

**Use it for:** one word or a short phrase to circle or box, such as a key
result, a price or a label.

**Avoid it for:** long phrases, because the ring keeps its text on one line
and can overflow a narrow screen. Use `motion-marker` or `motion-underline`
for text that wraps.

**Accessibility:** the drawing is an SVG hidden from screen readers. The
text stays in the page, selectable, and read unchanged. The ring takes room
on its left and right, so it never covers the neighbouring words. It takes
no room above and below, so it can overlap the lines above and below in a
tight paragraph.

**Reduced motion:** the ring appears fully drawn at once on the same
trigger, with no animation. With `loop` it stays drawn and never cycles.

**Common mistakes:** a large `padding` in a paragraph with a small line
height, which makes the ring cover the neighbouring lines; raise the line
height or lower `padding`.

Docs: https://www.motion-components.dev/docs/text/motion-ring/

## Install

```js
import 'motion-components/motion-ring'
```

Or without a build step:

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/motion-components@1/dist/motion-ring.js/+esm"></script>
```

## Example

```html
<p>Every change is <motion-ring>reversible</motion-ring>.</p>
```

## Attributes

| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `shape` | `'ellipse' \| 'box'` | `'ellipse'` | `'ellipse'`, or `'box'` for a rectangle with slightly rounded corners. |
| `padding` | `number` | `6` | Gap in pixels between the text and the stroke. |
| `trigger` | `'view' \| 'hover' \| 'mount'` | `'view'` | What draws the mark: `'view'` (scrolled into view), `'hover'` (pointer enter, undraws on leave) or `'mount'`. |
| `duration` | `number` | `0.6` | Spring duration of the drawing, in seconds. |
| `delay` | `number` | `0` | Seconds to wait before drawing. |
| `bounce` | `number` | `0` | Spring bounciness. `0` keeps the stroke from overshooting the text. |
| `loop` | `boolean` | `false` | Draw, hold, undraw, draw again on repeat. With `trigger="view"` the cycle runs while the mark is on screen. |
| `hold` | `number` | `1.6` | With `loop`, seconds the mark stays drawn before it undraws. |
| `gap` | `number` | `0.5` | With `loop`, seconds the mark stays undrawn before it draws again. |
| `pause-on-hover` | `boolean` | `false` | Pause the loop while the pointer is over the mark, resuming on leave. |
| `once` | `boolean` | `true` | With `trigger="view"`, draw only the first time. Set `once="false"` to undraw on leave and draw again on every entry. Ignored with `loop`. |
| `threshold` | `number` | `0.6` | Share of the element, from 0 to 1, that must be visible before it draws. |

## Properties

| Property | Type | Description |
| --- | --- | --- |
| `playState` | `'idle' \| 'running' \| 'paused' \| 'finished'` | Current state: `'idle'`, `'running'`, `'paused'` or `'finished'`. |
| `finished` | `Promise<void>` | Resolves when the current run settles. A new run replaces the promise. |

## Methods

| Method | Description |
| --- | --- |
| `play()` | Starts the animation, or resumes it when paused. Resolves once the run settles. Under `prefers-reduced-motion: reduce` the final state is applied immediately without animating. |
| `pause()` | Holds the animation at its current position. No-op unless running. |
| `finish()` | Jumps to the final state and settles. Fires `motion-finish`. |
| `cancel()` | Reverts to the initial state and returns to idle. Fires `motion-cancel`. |
| `replay()` | Draws the mark again from the start. |
| `sweep()` | Sweeps a drawn mark across: it erases from its start, so it leaves at its end, then draws in again from the start. Calls while a sweep runs, before the mark is drawn, or under reduced motion do nothing. |

## Events

The `motion-*` events bubble and are composed.

| Event | Description |
| --- | --- |
| `motion-start` | When a run starts. |
| `motion-finish` | When a run finishes, or `finish()` jumps to the end. |
| `motion-cancel` | When `cancel()` stops a run and resets it. |

## Slots

| Slot | Description |
| --- | --- |
| (default) | The word or short phrase to circle. It stays on one line. |

## CSS custom properties

| Property | Description |
| --- | --- |
| `--mc-mark-color` | Color of the stroke. Default `var(--mc-color-accent, #2563eb)`. |
| `--mc-mark-thickness` | Thickness of the stroke. Default `2px`. |
