Spotlight
The soft, angled glow that fades in behind hero copy: one rotated ellipse under a 151-unit Gaussian blur, absolutely positioned and sized as a percentage of its container. `fill` defaults to `currentColor`, so a text-colour class on the parent tints it.
Preview
Rendered from the story the storybook (a11y) CI gate runs axe against — the preview can't show something that hasn't been verified.
Install
Two equivalent paths — the URL works in any shadcn-CLI setup; the alias works once you've registered @interlace in your components.json.
npx shadcn@latest add https://ds.interlace.tools/r/spotlight.jsonnpx shadcn@latest add @interlace/spotlightHistory
This component is at v1.2.0, first shipped in @interlace/ui 1.0.0. The version is stamped as a banner into the file the install writes, so the copy in your tree says which one you have — compare it with the number above before deciding whether to re-run the install.
No release note names this component yet. It shipped with the release above and has not changed since — see the full changelog for what moved elsewhere in the DS.
Import
Single named export.
import { Spotlight } from '@/components/ui/aceternity/spotlight';Anatomy
Extracted from the primitive's JSDoc header. The source is the only documentation that can't drift.
Spotlight (motion.svg — data-slot="spotlight",
viewBox "0 0 3787 2842")
├─ g filter=url(#spotlight-blur-…)
│ └─ ellipse (rotated by a transform matrix)
└─ defs > filter (feFlood → feBlend → feGaussianBlur 151)API reference
Parsed from the type declarations in the source — the same file the install writes into your tree, so this table can't drift from the component you get.
SpotlightProps
| Prop | Type | Description |
|---|---|---|
| fill | string | Required stable selector for E2E tests. Has no runtime default — the consumer must provide one so omissions surface instead of being masked. / "data-testid": string; /** Fill color of the glow. Accepts any CSS color *token* — a CSS custom property (`var(--brand-accent)`), a Tailwind-driven keyword, or `currentColor` to inherit the container's text color. Avoid raw hex/rgb literals so the design system stays the single source of color truth. @default "currentColor" |
| fillOpacity | number | Opacity of the glow once fully revealed, 0–1. @default 0.21 |
| duration | number | Duration of the fade-in reveal, in seconds. Ignored under `prefers-reduced-motion` (the glow renders static at full opacity). @default 1.5 |
| delay | number | Delay before the reveal starts, in seconds. Ignored under `prefers-reduced-motion`. @default 0.2 |
Accessibility
Every story for this component is rendered headlessly and checked with axe-core (wcag2aa, wcag22aa, best-practice, ACT) on every PR. That gate has no continue-on-error, so what ships has zero known violations.
What follows is what static analysis can see. Axe cannot press a key and never sees an overlay open, so the operable-without-a-mouse claim lives in Behavior instead, where the keyboard path is replayed step by step.
- Focus + keyboard behaviour
- Native element semantics — no interaction layer to get wrong.
- Focus ring (WCAG 2.2 SC 2.4.13)
- Not focusable — no focus indicator required.
- Reduced motion
- Animation is gated on prefers-reduced-motion.
- ARIA in the source
aria-hidden
Examples
3 more states from the same story file.
Dependencies
- Base UI primitive
- Native / no Base UI dependency
- Lucide icons
- none
- NPM dependencies
motion
- Registry dependencies
Source
The full implementation — components/ui/aceternity/spotlight.tsx once installed.
"use client";
import React, { forwardRef, useId } from "react";
// @interlace/spotlight v1.2.0 — Interlace design system.
// Docs, props and live preview: https://ds.interlace.tools/c/spotlight
// What changed since: https://ds.interlace.tools/c/spotlight#history
// Generated banner — keep it, the upgrade diff reads this version.
/**
* @interlace/ui — Spotlight
*
* The soft, angled glow that fades in behind hero copy: one rotated ellipse
* under a 151-unit Gaussian blur, absolutely positioned and sized as a
* percentage of its container. `fill` defaults to `currentColor`, so a
* text-colour class on the parent tints it.
*
* Decorative by contract — `aria-hidden`, `focusable="false"`,
* `pointer-events-none`, and out of flow, so CLS is zero.
*
…188 more lines…Registry JSON
The raw registry record — what the shadcn CLI fetches.