Skip to content
Get started

Components

ShaderSurface

Unstable: a moving background drawn by a WebGL shader, the design's Shader Surface in its nine types, for CtaBand, BentoTile, ProfileCard or a page section. Import it from @nizivo/react/unstable/shader-surface.

Tier: clientUnstable

Examples

Basic

Aurora as ProfileCard's cover (it follows the theme) and as CtaBand's background (aurora-dark, dark on any page, as the band is).

Alex Rivera

Product designer · Lisbon

Ship your next screen with Nizivo

One library, two themes, every state designed.

import type { JSX } from 'react';
import { CtaBand } from '@nizivo/react/unstable/cta-band';
import { ProfileCard } from '@nizivo/react/unstable/profile-card';
import { ShaderSurface } from '@nizivo/react/unstable/shader-surface';

export function ShaderSurfaceExample(): JSX.Element {
  return (
    <div style={{ display: 'grid', gap: 24, inlineSize: 640, maxInlineSize: '100%' }}>
      <ProfileCard
        style={{ inlineSize: 320 }}
        name="Alex Rivera"
        description="Product designer · Lisbon"
        cover={<ShaderSurface />}
      />
      <CtaBand
        title="Ship your next screen with Nizivo"
        description="One library, two themes, every state designed."
        background={<ShaderSurface variant="aurora-dark" />}
      />
    </div>
  );
}

Variants

Every variant, as the design's Shader Surface types name them.

Aurora
Aurora Dark
Contour
Contour Dark
Dot Matrix
Glow Orb
Glow Orb Dark
Rays
Mesh
import type { JSX } from 'react';
import { ShaderSurface, type ShaderSurfaceVariant } from '@nizivo/react/unstable/shader-surface';

const VARIANTS: readonly [ShaderSurfaceVariant, string][] = [
  ['aurora', 'Aurora'],
  ['aurora-dark', 'Aurora Dark'],
  ['contour', 'Contour'],
  ['contour-dark', 'Contour Dark'],
  ['dot-matrix', 'Dot Matrix'],
  ['glow-orb', 'Glow Orb'],
  ['glow-orb-dark', 'Glow Orb Dark'],
  ['rays', 'Rays'],
  ['mesh', 'Mesh'],
];

export function ShaderSurfaceVariantsExample(): JSX.Element {
  return (
    <div
      style={{
        display: 'grid',
        gridTemplateColumns: 'repeat(auto-fill, minmax(12rem, 1fr))',
        gap: 16,
        inlineSize: 640,
        maxInlineSize: '100%',
      }}
    >
      {VARIANTS.map(([variant, name]) => (
        <figure key={variant} style={{ display: 'grid', gap: 8, margin: 0 }}>
          <div style={{ blockSize: 120, borderRadius: 12, overflow: 'hidden' }}>
            <ShaderSurface variant={variant} />
          </div>
          <figcaption>{name}</figcaption>
        </figure>
      ))}
    </div>
  );
}

Import

import { ShaderSurface } from '@nizivo/react/unstable/shader-surface';

// Once per app (Getting started), after
// @nizivo/tokens/tokens.css and @nizivo/react/css/base.css
import '@nizivo/react/css/shader-surface.css';

Static or interactive

Client. The server renders a poster in the same colours, drawn with CSS; once the page hydrates, a canvas draws the shader over it from its first frame. A browser without WebGL keeps the poster. How to choose.

Variants

variant is the design's Shader Surface type, and each follows the theme:

  • Aurora (aurora, the default): soft curtains of light that sway, lime over a pale ground with mint below.
  • Contour (contour): the contour lines of a slowly drifting landscape, pale, with one level in six drawn bold.
  • Dot Matrix (dot-matrix): a grid of dots in slow waves, lime where it is brightest. Always dark, as the design draws it.
  • Glow Orb (glow-orb): GlowOrb's sphere in a glow that spreads over the box.
  • Rays (rays): fine strands of green, lime and warm light, some soft, leaning and waving.
  • Mesh (mesh): a soft field of mint, lime, green and the page's ground, drifting.

aurora-dark, contour-dark and glow-orb-dark keep their dark colours on a light page, for a band that is always dark. The design's Rays use an amber that is not in the palette; here the warm strands take icon/warning. Each variant's shader loads when the first surface of that variant mounts, so a page downloads only the ones it shows.

In a component

It fills its box. Pass it to the components the design draws with it: CtaBand's background (<ShaderSurface variant="aurora-dark" />), BentoTile's background (Aurora for a wide tile, Glow Orb for a square one, Contour for a tall one, as the design draws them) and ProfileCard's cover. Each drops its CSS background behind it, and CtaBand keeps a soft dark scrim behind its text, so the text stays readable whatever drifts behind.

Light on a phone

No library: one fragment shader on WebGL 1, on the same small runtime as GlowOrb. It draws only while it is on screen and the page is visible, at a pixel ratio of at most 2, and gives its WebGL context back when it unmounts (a page holds about sixteen at once). Under Reduced motion it draws one still frame. In forced colours the canvas is hidden and the system's colours show.

Colours

Each variant reads four of Nizivo's colours, chosen to match the design's. Set --nz-shader-surface-ground and --nz-shader-surface-tone-1 to -tone-3 to recolour any variant; the stylesheet says which tone is which in each. It is decoration, hidden from assistive technology; never set text on it without a surface of its own.

Props

Client component Renders data-slot="shader-surface" with the class nz-shader-surface. Props: ShaderSurfaceProps. Source: src/unstable/shader-surface/shader-surface.client.tsx.

NameTypeDefaultDescription
variantShaderSurfaceVariant
"aurora""aurora-dark""contour""contour-dark""dot-matrix""glow-orb""glow-orb-dark""mesh""rays"
'aurora'

Figma's Shader Surface type: aurora (soft curtains of light), contour (topographic lines), dot-matrix (a grid of dots in slow waves, always dark), glow-orb (GlowOrb's sphere in a glow), rays (strands of light) or mesh (a soft four-colour field). They follow the theme; a -dark one keeps its dark colours on a light page (CtaBand's band).

  • Also takes every attribute of <span> except children. (Omit<ComponentPropsWithRef<"span">, "children">)

Other exports

ShaderSurfaceProps type

import type { ShaderSurfaceProps } from '@nizivo/react/unstable/shader-surface'

The props of ShaderSurface, listed above.

ShaderSurfaceVariant type

import type { ShaderSurfaceVariant } from '@nizivo/react/unstable/shader-surface'

Figma's Shader Surface types; a -dark one keeps its dark colours on a light page.

type ShaderSurfaceVariant = "aurora" | "aurora-dark" | "contour" | "contour-dark" | "dot-matrix" | "glow-orb" | "glow-orb-dark" | "mesh" | "rays"

Data attributes and slots

Style parts by class (.nz-<slot>) and state by data attribute. Attribute meanings come from contracts/vocabulary.json.

SlotRendered byData attributes
shader-surface
.nz-shader-surface
ShaderSurface
root (no render)
  • data-variant: "aurora""aurora-dark""contour""contour-dark""dot-matrix""glow-orb""glow-orb-dark""mesh""rays" ← variant
    The variant prop; values in each component manifest

CSS hooks

Set a hook on the component's class or any ancestor to restyle it without specificity games; leave it unset for the default shown.

HookDefaultRead as
--nz-shader-surface-ground
  • default: var(--nz-bg-accent-subtle)
  • default: var(--nz-bg-canvas)
  • border-block-start-color on .nz-shader-surface
  • background on .nz-shader-surface-poster
--nz-shader-surface-tone-1
  • default: var(--nz-bg-brand-muted)
  • default: color-mix(in oklab, var(--nz-bg-brand) 25%, var(--nz-bg-canvas))
  • default: color-mix(in oklab, var(--nz-bg-accent) 35%, var(--nz-bg-brand-muted))
  • data-variant="rays": var(--nz-icon-warning)
  • border-inline-end-color on .nz-shader-surface
  • background on .nz-shader-surface-poster
--nz-shader-surface-tone-2
  • default: var(--nz-bg-accent)
  • default: var(--nz-bg-brand-subtle)
  • border-block-end-color on .nz-shader-surface
--nz-shader-surface-tone-3
  • default: var(--nz-bg-brand)
  • border-inline-start-color on .nz-shader-surface

Layers: nz.components. Classes: .nz-shader-surface, .nz-shader-surface-canvas, .nz-shader-surface-poster.

Tokens this stylesheet reads (7)

--nz-bg-accent, --nz-bg-accent-subtle, --nz-bg-brand, --nz-bg-brand-muted, --nz-bg-brand-subtle, --nz-bg-canvas, --nz-icon-warning

Accessibility

Nothing in this component takes focus or keyboard input.

Keyboard

None.

On this page