# Silk (Moonarc)

Draws a sheet of fabric drifting in slow folds, lit from one side: a warped height field on the GPU, normals from finite differences, a diffuse body in the colour and a narrow sheen in a second tone. The troughs keep a trace of the colour and let the page's ground through, so it reads on either theme. The pointer presses a soft dent into the cloth. Every constant is a custom property re-read when the element's style changes. Without WebGL2 or JavaScript a still diagonal sheen stands in. Fills its positioned parent.

- Pro block. Install: `npx shadcn@latest add @moonarc-pro/silk` (license key required)
- Tier C · category background · trigger always, pointer
- Readout: `<Silk depth={1} angle={-24}>`
- Browser support: widely (Chrome 56 · Firefox 51 · Safari 15); elsewhere: without WebGL2, a still repeating diagonal sheen in the colour at the fold angle
- Measured cost: 1.1 kB raw JS · 683 B gzip · + runtime + shader + canvas + gl, 10.6 kB raw in all (with dependencies 10.6 kB raw; CSS 5.1 kB raw)
- Page: https://moonarc.dev/components/silk/

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `color` | `string` | `'oklch(0.55 0.16 280)'` | Fabric colour; any CSS colour, theme tokens included. |
| `sheen` | `string` | `color lifted 65 % toward white` | The second tone: the highlight on the crests. |
| `scale` | `number` | `1.6` | Folds across the short side. |
| `speed` | `number` | `1` | Drift speed multiplier; accumulated, so a change never jumps. |
| `depth` | `number` | `1` | How deep the folds are: 0.5 is a flat sheet, 2 is deep drapery. |
| `angle` | `number` | `-24` | Rotation of the folds, in degrees. |
| `press` | `number` | `0.6` | How hard the pointer dents the cloth; 0 turns the pointer off. |

## Usage

```astro
<section class="relative min-h-[60vh] bg-background">
  <Silk color="var(--primary)" />
  <h1 class="relative">Silk background</h1>
</section>
```

## Reduced motion

No loop: one frame at a fixed moment, drawn once; the pointer does not dent it.

## With ClientRouter

Bound through the shared runtime: loop, observers and pointer listener are released before the swap and the WebGL context is lost on purpose after it; five round trips leave one context. Under transition:persist the canvas keeps its context and starts again on the next page.

## Craft

- Lighting, not colour cycling: the folds are a height field and the shader lights it, so the silk reads as cloth, with a body in the colour and a Blinn sheen in the second tone.
- Normals from two extra samples of the same function (finite differences) instead of derivatives, which would break into 2 × 2 blocks.
- Premultiplied with colour clamped to alpha, and a byte of noise scaled by alpha against banding in the long gradients.
- The troughs carry a sixth of the colour and let the ground through: deep on a dark page, airy on a light one, from the same tokens.
- The pointer lowers the height field under it and the lighting shades the dent, so nothing is painted on.

## Replaces

- Silk (React Bits)
- Satin / fabric shader backgrounds

## Source

Pro block. The source is served by the license-gated registry: `npx shadcn@latest add @moonarc-pro/silk` with a key in components.json (https://moonarc.dev/account/). Related free primitives: aurora.
