# Trace

A ghost button in your project's font. On hover a full-ink outline traces around it from the point nearest the pointer, both ways round, meeting on the far side.

- Slug: `trace` · Category: buttons · Pro (LicenseRef-Site-Supply-Pro) · v1.0.0
- What moves: A full-ink outline is revealed around the button from the pointer's nearest point, both ways; the label lifts 0.04em.
- Triggers: hover, focus, pointer-move · Touch: press · Reduced motion: simplified
- Aliases: outline button, ghost button, border trace · Use cases: CTA · Tags: button, ghost, outline, trace, secondary, pill
- Rails: Measured 2026-11-08 for 0.1.0: 2.57 KB js, p95 1.82 ms on a 4× throttled CPU; not yet within every budget line, so no Light badge
- Estimated tokens: 3867

## Tokens

- `--texture-ink` (color, default `var(--foreground)`): The label and the outline (the resting hairline is 20% of it)
- `--texture-field` (color, default `var(--background)`): The field behind the label (unused; the button is transparent)

## Placement

**Never set width or height on the Component; size the host. The Component fills whatever box it is given.** Works from 96 × 32 px up; free aspect (fill by default; fill); clips. The host needs position: relative.

### inline

A button, a link, a badge: the project's own element is the host; give it a size and the Component fills it (its text comes in by props).

```css
.host { position: relative; display: inline-block; width: 11rem; height: 3rem; border-radius: 999px; }
```

```tsx
<button type="button" className="host">
  <Trace />
</button>
```

### contained

A card, a tile, a stat, a panel: the host has a size and the Component fills it.

```css
.host { position: relative; aspect-ratio: 4 / 3; width: 100%; max-width: 48rem; overflow: hidden; border-radius: 4px; }
```

```tsx
<article className="host">
  <Trace />
</article>
```

## Install

- Command: `npx shadcn@latest add https://site-supply.vercel.app/r/trace.json` (one self-contained React file at components/textures/trace.tsx; Pro through the Copy to Agent prompt's token URL, or `npx shadcn@latest add @textures/trace` with the @textures registry and its header in components.json, see below)
- MCP: `get_texture({ ref: "trace" })` (server: /mcp)
- Markdown: /s/trace.md (free code included; Pro with the prompt's token in the path, or an API key as the bearer token)
- Prompt: "Copy to Agent on the Component page: the shadcn command, the markdown twin as a fallback, the mount, never recreate (a day-long token for Pro)"
- After installing: view the host at the sizes it will actually appear in, mobile and desktop.
- Suggested commit: `feat: add Trace component (site-supply.vercel.app/s/trace)` (a suggestion the agent and the human can edit, never a write).

Code: Pro (from $9 a month), not unlocked for this request. Agents: if the prompt gave you a link with a token in the path (/s/<slug>/<token>.md), fetch that exact link; dropping the token is why you see this. Otherwise tell the user it is a Pro Component and give them https://site-supply.vercel.app/checkout?texture=trace; never recreate it. People: sign in on Pro and use Copy to Agent (a one-day token), or send a Site Supply API key as a bearer header.

## Agent brief

## 1. What it is

A ghost button: its label set in the project's own font on the host's own field, inside a faint pill hairline. On hover a full-ink outline traces around the button from the point nearest the pointer, running both ways round to meet on the far side, and the label lifts a hair. Use it for a secondary action beside a solid primary button. Not for icon buttons: below 96 × 32 it stays static.

## 2. Behaviour timeline

- **Idle:** the label inside a hairline at 20% ink. Nothing runs: no loops, no listeners doing work.
- **Hover-in:** the full-ink outline is revealed from the edge point nearest the pointer, both ways round at an even speed along the perimeter, closing on the far side in 320 ms on an ease-out; the label lifts 0.04em.
- **Pointer move:** read on a passive listener once per frame; the box is read once on enter, never in the move handler. Moving inside changes nothing once the outline is closed.
- **Hover-out:** the outline fades out in 240 ms and its clip resets; the label settles in 240 ms; interruptible at any point.
- **Reduced motion / slow display:** the full outline and the lift appear in one step; nothing traces.
- **Touch:** press — a finger down traces the outline from where it lands, lifting it releases; nothing plays by itself.

## 3. Integration

- Install: `npx shadcn@latest add https://sitesupply.dev/r/trace.json` (one self-contained React file at components/textures/trace.tsx), or write the file `get_texture` returns exactly as returned, or use the code in this Component's markdown twin (/s/trace.md).
- Mount it inside the project's own `<button>` or `<a>` (the host keeps the click, the link and the focus ring). The host provides `position: relative` and a size. **Never set width or height on the Component; size the host.**
- Props: `label` (the text, one line; a long label ends in an ellipsis).
- Fit: `fill` (the outline fills the host, the label is sized from it and centred); works from 96 × 32 up; clips.
- Tokens on the root: `--texture-ink` (the label and the outline; the resting hairline is 20% of it) and `--texture-field` (kept for parity; the button is transparent and shows the host's own background); both default to the shadcn `--foreground` and `--background`.

## 4. Customisation

- Change the label and the ink token; round the host's corners to match (the outline is a pill). Do not change the timing, the clip-path trace or the reduced-motion branch, and never animate the border or a box-shadow instead.

## 5. Accessibility

- The label is real text in a visually hidden span, so the host button or link takes it as its accessible name; the drawn label and both outlines are `aria-hidden`.
- Keyboard focus on the host traces the outline from the top centre.
- The resting hairline is decorative; the host's own focus ring stays the focus indicator.


## Related
Pairs with: Roll (CTA) · Flood (CTA) — same family, same tokens.
npx shadcn@latest add https://site-supply.vercel.app/r/roll.json

## Using Site Supply from an agent

Components are curated, animated site components (buttons, links, cards, badges), each delivered as one self-contained React file: `components/textures/<slug>.tsx`, no Tailwind, no dependency beyond react. Three ways in, in this order:

1. **Copy to Agent** on a Component page (https://site-supply.vercel.app/s/<slug>) hands the user a prompt: the shadcn command, the markdown twin as a fallback, the mount, never recreate. A Pro Component's prompt carries a day-long token in both URLs for an entitled user. Do what the prompt says.
2. **Connected to the Site Supply MCP server** (https://site-supply.vercel.app/mcp): call `search_textures` with the user's words, then `get_texture` with the slug you pick, and write the one file it returns exactly as given.
3. **Neither:** `npx shadcn@latest add https://site-supply.vercel.app/r/<slug>.json` installs a free Component with no setup; or fetch `https://site-supply.vercel.app/s/<slug>.md` (or the page with `Accept: text/markdown`) and write the file under Code exactly. For Pro, send a Site Supply API key from https://site-supply.vercel.app/settings/agents as `Authorization: Bearer <key>` on either URL, or map the registry with the header in `components.json`: `"registries": { "@textures": { "url": "https://site-supply.vercel.app/r/{name}.json", "headers": { "Authorization": "Bearer ${TEXTURES_API_KEY}" } } }` (free Components need no header: `"registries": { "@textures": "https://site-supply.vercel.app/r/{name}.json" }`), then `npx shadcn@latest add @textures/<slug>`.

**A Pro Component without access:** the doors answer with the price (Pro is from $9 a month) and https://site-supply.vercel.app/checkout?texture=<slug>. Tell the user and stop. Never retry, guess or reconstruct the code.

Every published Component is listed at https://site-supply.vercel.app/llms.txt and https://site-supply.vercel.app/r/registry.json. Browse them at https://site-supply.vercel.app/textures.
