Skip to content

Spotlight List Focus

A list that dims and blurs every row except the one under the pointer.

DOM + CSS0 deps1 file · 3 KB TSX

Proeditorialminimalglass
Preview

Props

32
1.4
Meta column

The source is part of Pro

$27/month or $179 once. See Pro

No runtime dependencies
"use client";

import { useState } from "react";

type Row = { id: string; title: string; meta: string; href: string };

/**
 * Gate the scheme before a caller-supplied string reaches an href.
 * A javascript: or data:text/html URL executes on click, so any link list
 * fed from a CMS, a database or user submissions is an XSS sink without this.
 */
const SAFE_HREF = /^(?:https?:|mailto:|tel:|\/|#|\.)/i;
const safeHref = (h: string) => (SAFE_HREF.test(h.trim()) ? h : "#");


export function SpotlightListFocus({
  rows,
  dim = 32,

  // ---------------------------------------------------------------
  // Full source available with a viberdy Pro subscription.
  // https://viberdy.dev/pricing
  // ---------------------------------------------------------------
}
Details

About this pattern

The instinct when highlighting a list row is to make it bigger: scale it, lift it, add a shadow. In a dense index that is exactly wrong, because every row the pointer crosses on its way down the list pops and settles, and the page appears to twitch. Inverting the treatment fixes it — leave the hovered row untouched and drop everything else in opacity with a slight blur. Nothing moves, the contrast does all the work, and the effect reads as attention rather than as animation. The blur matters more than it looks: opacity alone flattens the unfocused rows into grey text, while a fraction of a pixel of blur pushes them behind the focal plane and makes the hierarchy feel optical instead of merely faded. On the implementation side, one delegated `mouseover` on the container with a `closest` lookup identifies the row, so a list of a hundred entries still costs a single listener rather than a hundred. Focus mirrors hover, so the spotlight is not a pointer-only affordance.

Curator’s note

Built for viberdy 2.1. Dimming the siblings instead of lifting the target is the whole idea — it keeps a dense list from twitching.

Pairs well with

Pro