# Aurora text

> Northern lights drift inside the letters.

- Type: Component (light)
- Page: https://textlab.dev/components/aurora-text
- Markdown: https://textlab.dev/components/aurora-text.md
- Registry item: https://textlab.dev/r/aurora-text.json
- Source file: `registry/textlab/aurora-text/aurora-text.tsx`
- Dependencies: none
- Variants: polar, ember, mint
- Keywords: aurora, northern lights, gradient, mesh gradient, ambient

## When to use

- Large display headlines on dark or very light pages.
- Atmospheric brand moments.

## When not to use

- Small text; the bands need room to read.
- Next to another gradient effect.

## Installation

### CLI

```bash
npx shadcn@latest add @textlab/aurora-text
pnpm dlx shadcn@latest add @textlab/aurora-text
```

The `@textlab` name needs `"registries": { "@textlab": "https://textlab.dev/r/{name}.json" }` in `components.json`. Without it, use the full URL:

```bash
npx shadcn@latest add https://textlab.dev/r/aurora-text.json
```

Import the tokens once in your root layout: `import "@/components/textlab/tokens.css";`

### Manual

1. Install the dependencies: `npm install motion@12`
2. Copy `text-fx` (https://textlab.dev/r/text-fx.json) and this component into `components/textlab/`.

## Usage

```tsx
import { AuroraText } from "@/components/textlab/aurora-text/aurora-text";

export function Example() {
  return <AuroraText as="h1" text="Northern lights" />;
}
```

## API reference

### AuroraText

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `text` (required) | `string` | – | The copy. |
| `variant` | `"polar" \| "ember" \| "mint"` | `"polar"` | Palette. |
| `colors` | `string[]` | – | Three or four custom colors; overrides the variant. |
| `speed` | `number` | `14` | Seconds for one drift cycle. |
| `as` | `ElementType` | `"span"` | Rendered element. |
| `reducedMotion` | `"user" \| "always" \| "never"` | `"user"` | user follows the OS setting; always shows the still version. |
| `className` | `string` | – | Merged onto the root. |

## Accessibility

- Plain text clipped to color. Check contrast of the darkest band against the background.

## Motion

- A 14 s ease-in-out drift; slow enough to feel like weather, not an animation.

## Reduced motion

A still aurora frame.

## Performance

- Four background layers moved by one CSS animation.

## Notes for AI

- Use only the props documented above. Do not invent props.
- Keep the screen-reader text and the reduced-motion branch when editing the source.
- Pick a variant from: polar, ember, mint.

## Related

- [Gradient text](https://textlab.dev/components/gradient-text.md): Color flows slowly through the letters.
- [Holographic text](https://textlab.dev/components/holo-text.md): Foil that shifts color as you move across it.
- [Neon sign](https://textlab.dev/components/neon-text.md): A neon sign that hums and flickers on.

## Also in light

- [Shimmer text](https://textlab.dev/components/shimmer-text.md): A calm light passes across the words.
- [Spotlight text](https://textlab.dev/components/spotlight-text.md): A light follows the cursor and reveals the copy.
- [Glass text](https://textlab.dev/components/glass-text.md): Glass letters that bend the scene behind them.
- [Ember text](https://textlab.dev/components/ember-text.md): Letters land hot and cool down to the text color.

## Source

### components/textlab/aurora-text/aurora-text.tsx

```tsx
"use client";

import type { CSSProperties, ElementType } from "react";
import { useReduced, type ReducedMotion } from "../lib/use-reduced";

export type AuroraTextVariant = "polar" | "ember" | "mint";

export interface AuroraTextProps {
  text: string;
  /** Palette: polar greens and violets, ember oranges and pinks, mint teals and limes. */
  variant?: AuroraTextVariant;
  /** Custom colors, three or four. Overrides the variant. */
  colors?: string[];
  /** Seconds for the slowest band to drift. */
  speed?: number;
  as?: ElementType;
  reducedMotion?: ReducedMotion;
  className?: string;
  style?: CSSProperties;
}

const PALETTES: Record<AuroraTextVariant, string[]> = {
  polar: ["oklch(0.78 0.17 160)", "oklch(0.7 0.15 200)", "oklch(0.62 0.2 290)", "oklch(0.8 0.14 130)"],
  ember: ["oklch(0.72 0.19 40)", "oklch(0.66 0.22 15)", "oklch(0.7 0.2 350)", "oklch(0.82 0.15 75)"],
  mint: ["oklch(0.82 0.13 175)", "oklch(0.86 0.17 130)", "oklch(0.74 0.12 210)", "oklch(0.9 0.1 100)"],
};

// Each band drifts on its own period, so the pattern never visibly repeats.
const CSS = `
@keyframes tl-aurora-a { 0%, 100% { background-position: 0% 50%, 100% 50%, 50% 0%, 50% 100%; } 50% { background-position: 100% 40%, 0% 60%, 40% 100%, 60% 0%; } }
.tl-aurora { background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-size: 180% 180%, 160% 160%, 200% 200%, 170% 170%; box-decoration-break: clone; -webkit-box-decoration-break: clone; }
@media (prefers-reduced-motion: reduce) { .tl-aurora[data-motion="user"] { animation: none !important; } }
`;

/** Northern lights drift inside the letters: four soft bands, each moving on its own clock. */
export function AuroraText({ text, variant = "polar", colors, speed = 14, as: Tag = "span", reducedMotion = "user", className, style }: AuroraTextProps) {
  const reduced = useReduced(reducedMotion);
  const [a, b, c, d = a] = colors ?? PALETTES[variant];
  const image = [
    `radial-gradient(ellipse at 20% 30%, ${a}, transparent 60%)`,
    `radial-gradient(ellipse at 80% 70%, ${b}, transparent 55%)`,
    `radial-gradient(ellipse at 50% 10%, ${c}, transparent 60%)`,
    `linear-gradient(120deg, ${d}, ${a})`,
  ].join(", ");
  return (
    <Tag
      className={["tl-aurora", className].filter(Boolean).join(" ")}
      data-motion={reducedMotion === "user" ? "user" : undefined}
      style={{ backgroundImage: image, animation: reduced ? "none" : `tl-aurora-a ${speed}s ease-in-out infinite`, ...style }}
    >
      <style href="tl-aurora-text" precedence="default">{CSS}</style>
      {text}
    </Tag>
  );
}

export default AuroraText;
```

Full library index: https://textlab.dev/llms.txt
