Components
Signal strength
Four bars for the quality of a connection. The bars rise and fall one after another as the level changes and take a colour for how good it is; while searching a light sweeps across them, and offline they grey out under a slash.
pnpm dlx shadcn@latest add @caliper/signal-strengthWhen to use
Use it for
- Call, meeting and streaming quality.
- Device lists, sync status and field apps where connectivity varies.
Skip it when
- Exact measurements; show the number in a tooltip or detail view.
- Decoration; it should reflect a real measurement.
Decisions
Why it is built this way, so you know what to keep when you change your copy.
Behaviour
- Bars in turn
- Each bar changes a moment after the one before, so a change reads as rising or falling.
Styling
- Colour follows quality
- Red for poor, amber for fair, green for good; the number of bars says the same without colour.
Usage
- Named by quality
- It is an image named "Signal: Good, 3 of 4 bars"; pass
label=""when the row says it already.
Installation
pnpm dlx shadcn@latest add @caliper/signal-strength
Adds its 2 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage
This is the code behind the preview above.
import { useState, type ReactNode } from "react" import { Button } from "@/components/ui/button" import { SignalStrength } from "@/components/ui/signal-strength" function Panel({ title, context, className = "max-w-md", children }: { title: string; context: string; className?: string; children: ReactNode }) { return ( <section className={`grid w-full gap-5 rounded-overlay border border-border bg-background p-6 shadow-resting max-sm:p-4 ${className}`}> <div className="grid gap-1"> <p className="font-medium">{title}</p> <p className="text-sm text-muted-foreground">{context}</p> </div> {children} </section> ); } export function SignalStrengthDemo() { const [level, setLevel] = useState(3); return ( <Panel title="Call quality" context="Bars rise and fall with the connection."> <ul className="grid gap-3 text-sm"> {[ ["Maya Chen", <SignalStrength key="a" level={level} />], ["Dev Patel", <SignalStrength key="b" level={1} />], ["Lisbon room", <SignalStrength key="c" level={0} status="searching" />], ["Kofi Mensah", <SignalStrength key="d" level={0} status="offline" />], ].map(([name, signal]) => ( <li key={String(name)} className="flex items-center justify-between gap-3"> <span>{name}</span> {signal} </li> ))} </ul> <div className="flex flex-wrap gap-2"> {[1, 2, 3, 4].map((value) => ( <Button key={value} size="sm" variant={value === level ? "default" : "secondary"} onClick={() => setLevel(value)}> {value} {value === 1 ? "bar" : "bars"} </Button> ))} </div> </Panel> ); }
API reference
SignalStrength
component
Also accepts the native props of its root element and a ref.
Accessibility
It is built on native elements and keeps aria-label and aria-hidden in step with state.
No custom key handling; Tab and the native activation keys do the work.
Motion
It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.
Related
- Sync statusWhether the work on screen is safe, in one pill that changes in place: saving, saved, offline with changes waiting, failed with a retry, or edited elsewhere.
- Live indicatorWhether a feed is live, in words and a dot. The dot sends out a soft ring only while live, blinks while reconnecting and rests otherwise, and gives one extra ring for each update you tell it about.
- Connection bannerSays when the app lost its connection and what that means, counts down to the next try, and confirms when it is back.