Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Backgrounds

Pro

Sonar Background for React

A radar scope behind your content: a beam turns over range rings, and contacts ping as it passes them. For React with Base UI, when a dashboard, a security page or a loading state should feel like it's actively scanning.

Framework

A radar scope that covers the whole box: a bright beam turns around the centre with a fading trail, over range rings and compass spokes that reach the corners and fade as they go, and contacts ping as the beam passes them, then fade. It's CSS and SVG: the grid is a still drawing, the beam a turning conic gradient, and each contact's keyframes are timed to its bearing, so it lights exactly as the beam reaches it.

Use it for monitoring dashboards, security or "scanning" states and sci-fi heroes. For rings that pulse out from the centre without a beam, use Ripple; for arcs turning on concentric rings, Circles; for the other green-terminal look, Matrix.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { Sonar } from "@/components/ui/sonar";

The scope sits behind whatever you put inside, centred, with its outer rings past the container's corners. Give the container a height; for the whole page, className="fixed inset-0 -z-10" with no children.

<Sonar className="flex min-h-[420px] items-center justify-center">
  <h1 className="text-4xl font-semibold">Monitoring every region</h1>
</Sonar>

Demos

Classic

The phosphor green screen: a dark green container and color="#22c55e". By default the scope takes your theme's primary colour, so it fits light and dark pages.

Preview width

Active

A busier scope in a small card: speed={1.5} turns the beam half again as fast, blips={8} adds contacts (the most that speed allows) and rings={3} thins the grid.

Preview width

Accessibility

The scope is decorative: it's hidden from screen readers and never takes the pointer, and your content stays on top in normal flow. With reduced motion everything stops where it is: the beam at 12 o'clock with its trail and the contacts it has just lit, a still picture of the scope. The trail passes under text at up to a third of the colour, so keep a headline large and in your foreground colour. Contacts ping at most three times a second over the whole scope: blips is capped at 12 ÷ speed, and the beam slows if a stylesheet asks for more.

FAQ

How do I change the sweep speed?

Pass speed: 1 is one turn every 4 seconds, 0.5 is calmer, 2 is busier. The beam and the contacts share one clock, so contacts still ping exactly as the beam passes at any speed.

Why do contacts appear exactly when the beam passes?

Each contact's keyframes are delayed by its bearing ÷ 360 of a turn, and they run once a turn, so every contact pings on every sweep. The beam and the contacts are measured the same way, clockwise from 12 o'clock.

Does the scope fit a wide banner?

Yes. The scope is as wide as the container's diagonal, so the beam sweeps every corner, and each contact sits a share of the way from the centre to the container's edge along its bearing, so all of them stay in view in a card, a banner or a page.

How do I get the classic green screen?

Put it in a container with a dark green background (bg-[#052e16]) and pass color="#22c55e". By default it uses your theme's primary colour.

Can I change the rings and contacts?

rings sets the range rings out to the corners (6) and blips the number of contacts (5). Contacts are placed by a fixed sequence, so they're in the same spots on every render.

Does it run JavaScript?

No: positions are computed once at render and CSS animates the beam and the contacts, so it renders the same on the server. Only rotation, scale and opacity change, which the browser animates without repainting the page.

Does it turn the other way on right-to-left pages?

No: a radar turns clockwise everywhere, so the scope looks the same in either direction.

API Reference

Sonar

<div> data-slot="sonar"

PropType
blips?number

How many contacts the scope holds; each pings as the beam passes it. At most 12 ÷ speed, so no more than three ping a second.

Default
5
color?string

The scope's colour, any CSS colour: the beam and its trail, the grid and the contacts. By default your theme's primary colour.

rings?number

How many range rings the grid has, out to the corners. @default 6.

Default
6
speed?number

How fast the beam turns: 1 is a turn every 4 seconds, 0.5 half as fast, 2 twice as fast.

Default
1
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CSS variableType
--sonar-colorstring

The scope's colour (the theme's --primary).

--sonar-speedstring

How fast the beam turns (1: a turn every 4 s).

All 100 backgrounds