Skip to content
caliper ui docs

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.

Free
pnpm dlx shadcn@latest add @caliper/signal-strength

Call quality

Bars rise and fall with the connection.

  • Maya Chen
  • Dev Patel
  • Lisbon room
  • Kofi Mensah
Installs components/ui/signal-strength.tsxDepends on none beyond ReactMotion none in component source

When 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

terminal
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.

example.tsx
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.

PropTypeDefaultDescription
level *number—Bars lit, from 0 to 4.
status"connected" | "offline" | "searching""connected"Searching sweeps the bars; offline greys them out with a slash.
labelstring"Signal"What the signal is of, e.g. "Network". Pass "" when the row says it already.
size"sm" | "md""md"

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.

All Changing values examples