# CTA shader (goodtabs UI)

A closing call to action over slow contour lines drawn in WebGL on theme tokens.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/cta-shader.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/cta-shader`

## Usage

```tsx
import { CtaShader } from "@/components/cta-shader"
import { Button } from "@/components/ui/button"

<CtaShader className="h-96" title="Build the next screen" actions={<Button>Get started</Button>} />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| title | `ReactNode` |  | The closing line. |
| description | `ReactNode` |  | One or two sentences under the title. |
| actions | `ReactNode` |  | Buttons, usually one primary and one outline. |

## When to use

- The last section before the footer on a landing page
- When one calm moving background helps the ask feel final

## When not to use

- More than two or three times on a page: browsers cap live WebGL contexts
- Behind long copy or forms, where the lines compete with reading

## Notes for agents

- The section needs a height from the parent or a class such as h-96 or min-h-dvh
- Installs components/ui/shader-canvas.tsx, which pauses off screen and follows the theme
- Without WebGL a CSS line grid shows through; the canvas is aria-hidden
- Server component; no animation library involved

## The maths

- Lines sit every 16 px. fract((y + bend) / 16) gives a sawtooth, and min(f, 1 - f) × 16 is the distance to the nearest line.
- Two sines at unrelated frequencies (0.006 and 0.013 per px) bend the lines with no visible period.
- Line width is 1 CSS px × uScale, so a retina screen draws the same hairline as a 1x monitor.

Docs: https://ui.goodtabs.co/components/cta-shader