# Background Pattern (/ui/components/react/background-pattern)



<Playground component="background-pattern" />

## Usage [#usage]

```tsx
import { BackgroundPattern } from '@appica/ui-react/background-pattern'
```

```tsx
<BackgroundPattern>
  <YourContent />
</BackgroundPattern>
```

`BackgroundPattern` is a `<div>` wrapper that paints a subtle, masked pattern behind its `children`.
Pick a texture with the `variant` prop — `dots` (the default), `grid`, `dashed-grid`, or `hexagons` —
and tune its density with `cellSize`. The pattern is drawn from the `--pattern-color` CSS variable
(defaulting to the `--color-border-intense` token) via `currentColor` masks, so it stays muted against
either light or dark surfaces; override that variable to [recolor it](#custom-color).

Enable `spotlight` to add a radial highlight that follows the cursor and brightens the pattern nearby;
pass `true` for the default, a number/length to size it, or `{ persistent: true }` to keep it always
on. The decorative layers are `aria-hidden`, so they never interfere with assistive tech — your
`children` remain fully accessible, and the wrapper accepts `className`, `style`, and any native
`<div>` attributes.

## Examples [#examples]

### Variants [#variants]

Four textures cover the common cases: scattered `dots`, a ruled `grid`, a finer `dashed-grid`, and a
`hexagons` mesh. Each carries a sensible default cell size, drawn at low opacity so content stays
legible.

```tsx
import { BackgroundPattern } from '@appica/ui-react/background-pattern'

const variants = ['dots', 'grid', 'dashed-grid', 'hexagons'] as const

export default function BackgroundPatternVariants() {
  return (
    <div className="grid w-full max-w-2xl grid-cols-1 gap-4 sm:grid-cols-2">
      {variants.map((variant) => (
        <BackgroundPattern
          key={variant}
          variant={variant}
          className="bg-background-subtle flex min-h-40 items-center justify-center overflow-hidden rounded-xl"
        >
          <span className="text-foreground-intense text-sm font-medium capitalize">{variant.replace('-', ' ')}</span>
        </BackgroundPattern>
      ))}
    </div>
  )
}
```

### Spotlight [#spotlight]

Set `spotlight` to add a cursor-following highlight that brightens the pattern near the pointer and
fades out when the cursor stops. Move your cursor over the panel to see it react.

```tsx
import { BackgroundPattern } from '@appica/ui-react/background-pattern'

export default function BackgroundPatternSpotlight() {
  return (
    <BackgroundPattern
      variant="dots"
      spotlight
      className="bg-background-subtle flex min-h-56 w-full max-w-xl items-center justify-center overflow-hidden rounded-xl"
    >
      <span className="text-foreground-intense text-sm font-medium">Move your cursor over the panel</span>
    </BackgroundPattern>
  )
}
```

### Persistent / sized spotlight [#persistent--sized-spotlight]

Pass an object to keep the highlight always on with `{ persistent: true }` and size it with `size`
(a number in px, or any CSS length). A persistent spotlight skips the fade entirely.

```tsx
import { BackgroundPattern } from '@appica/ui-react/background-pattern'

export default function BackgroundPatternPersistentSpotlight() {
  return (
    <BackgroundPattern
      variant="dashed-grid"
      spotlight={{ persistent: true, size: 150 }}
      className="bg-background-subtle flex min-h-56 w-full max-w-xl items-center justify-center overflow-hidden rounded-xl"
    >
      <span className="text-foreground-intense text-sm font-medium">Always-on highlight</span>
    </BackgroundPattern>
  )
}
```

### Custom cell size [#custom-cell-size]

`cellSize` overrides the per-variant default to make the texture denser or airier. Here the same
`grid` variant is shown at two scales.

```tsx
import { BackgroundPattern } from '@appica/ui-react/background-pattern'

export default function BackgroundPatternCellSize() {
  return (
    <div className="grid w-full max-w-2xl grid-cols-1 gap-4 sm:grid-cols-2">
      <BackgroundPattern
        variant="grid"
        cellSize={16}
        className="bg-background-subtle flex min-h-48 items-center justify-center overflow-hidden rounded-xl"
      >
        <span className="text-foreground-intense text-sm font-medium">cellSize 16</span>
      </BackgroundPattern>
      <BackgroundPattern
        variant="grid"
        cellSize={40}
        className="bg-background-subtle flex min-h-48 items-center justify-center overflow-hidden rounded-xl"
      >
        <span className="text-foreground-intense text-sm font-medium">cellSize 40</span>
      </BackgroundPattern>
    </div>
  )
}
```

### Custom color [#custom-color]

The pattern reads its color from the `--pattern-color` CSS variable, which defaults to the muted
`--color-border-intense` token. Set it to recolor the texture — point it at a theme token like
`var(--primary)`, or drop in any custom value. Here a bluish-purple hex tints the pattern and its
spotlight, paired with a matching surface mixed from the same hue and `var(--background)` via
`color-mix`, so the wash stays subtle in both light and dark mode.

```tsx
import { BackgroundPattern } from '@appica/ui-react/background-pattern'

export default function BackgroundPatternCustomColor() {
  return (
    <BackgroundPattern
      variant="hexagons"
      spotlight
      className="flex min-h-56 w-full max-w-xl items-center justify-center overflow-hidden rounded-xl bg-[color-mix(in_oklab,#7c6cf6_8%,var(--background))] [--pattern-color:#7c6cf6]"
    >
      <span className="text-foreground-intense text-sm font-medium">Tinted with a custom color</span>
    </BackgroundPattern>
  )
}
```

## API reference [#api-reference]

| Prop        | <ColMinWidth width="200">Type</ColMinWidth>                            | Default  | <ColMinWidth width="220">Description</ColMinWidth>                                                                                                             |
| ----------- | ---------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `variant`   | <Code>'dots' \| 'grid' \| 'dashed-grid' \| 'hexagons'</Code>           | `'dots'` | Pattern texture painted behind the content.                                                                                                                    |
| `spotlight` | <Code>boolean \| number \| string \| {'{ size?, persistent? }'}</Code> | `false`  | Cursor-following highlight. `true` for a 200px fading highlight; a number/length sizes it; an object with `persistent: true` keeps it always on.               |
| `cellSize`  | `number`                                                               | —        | Cell size in px; overrides the per-variant default (dots 14, grid/dashed-grid 28, hexagons 40).                                                                |
| `track`     | <Code>'self' \| 'window'</Code>                                        | `'self'` | Where the spotlight reads pointer movement. `'self'` tracks over this element; `'window'` tracks anywhere — for a pattern positioned behind unrelated content. |
| `className` | `string`                                                               | —        | Extra classes, merged via `tailwind-merge`.                                                                                                                    |
| `style`     | `CSSProperties`                                                        | —        | Inline styles on the wrapper.                                                                                                                                  |

`BackgroundPattern` renders a `<div>` and forwards every remaining native `<div>` attribute. The
decorative pattern and spotlight layers are `aria-hidden`. Set the `--pattern-color` CSS variable (via
`className` or `style`) to recolor the texture — see [Custom color](#custom-color).

## Accessibility [#accessibility]

* The pattern and spotlight layers are `aria-hidden` and `pointer-events-none`, so they're skipped by
  assistive tech and never intercept clicks.
* Content is wrapped, not replaced — your `children` stay in the normal flow and fully accessible.
* The pattern is intentionally low-emphasis; ensure your foreground content keeps sufficient contrast
  against the background for it to stay readable.
* The cursor spotlight honours `prefers-reduced-motion` — it's forced persistent (fade-free) when a
  user requests reduced motion.
