Skip to content
caliper ui docs

Components

Scroll top ring

A back-to-top button whose ring fills as you read. It springs in once you have scrolled past the threshold, stays in the corner of whatever scrolls, and returns you to the top with focus at the start of the content.

Free
pnpm dlx shadcn@latest add @caliper/scroll-top-ring

Changelog

Scroll the panel; the button appears and fills.

Week of October 28

Faster search across every workspace, clearer billing emails and a calmer notification centre that groups updates by project.

Fixed a sync delay on large boards and an export that skipped archived rows.

Week of October 21

Faster search across every workspace, clearer billing emails and a calmer notification centre that groups updates by project.

Fixed a sync delay on large boards and an export that skipped archived rows.

Week of October 14

Faster search across every workspace, clearer billing emails and a calmer notification centre that groups updates by project.

Fixed a sync delay on large boards and an export that skipped archived rows.

Week of October 7

Faster search across every workspace, clearer billing emails and a calmer notification centre that groups updates by project.

Fixed a sync delay on large boards and an export that skipped archived rows.

Week of September 30

Faster search across every workspace, clearer billing emails and a calmer notification centre that groups updates by project.

Fixed a sync delay on large boards and an export that skipped archived rows.

Week of September 23

Faster search across every workspace, clearer billing emails and a calmer notification centre that groups updates by project.

Fixed a sync delay on large boards and an export that skipped archived rows.

Week of September 16

Faster search across every workspace, clearer billing emails and a calmer notification centre that groups updates by project.

Fixed a sync delay on large boards and an export that skipped archived rows.

Installs components/ui/scroll-top-ring.tsxDepends on lucide-reactMotion honours reduced motion

When to use

Use it for

  • Long articles, documentation and changelogs.
  • Long scrolling panels and feeds.

Skip it when

  • Short pages; there is nothing to return from.
  • Infinite feeds where the top changes; use `LoadMore` or a jump to new items.

Decisions

Why it is built this way, so you know what to keep when you change your copy.

Behaviour

Focus follows
After the jump, focus moves to the first heading, so keyboard users continue from the top too.

Styling

Sticky, not fixed
It sticks to the bottom corner of its scroller, so it works in a panel as well as the page and never covers another panel.

Installation

terminal
pnpm dlx shadcn@latest add @caliper/scroll-top-ring

Adds its 3 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 { type ReactNode } from "react"
import { ScrollTopRing } from "@/components/ui/scroll-top-ring"

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 ScrollTopRingDemo() {
  return (
    <Panel title="Changelog" context="Scroll the panel; the button appears and fills." className="max-w-lg">
      <div className="h-80 overflow-y-auto rounded-control border border-border">
        <div className="grid gap-6 p-5">
          {["October 28", "October 21", "October 14", "October 7", "September 30", "September 23", "September 16"].map((week) => (
            <section key={week} className="grid gap-1.5">
              <h3 className="font-medium">Week of {week}</h3>
              <p className="text-sm leading-relaxed text-muted-foreground">Faster search across every workspace, clearer billing emails and a calmer notification centre that groups updates by project.</p>
              <p className="text-sm leading-relaxed text-muted-foreground">Fixed a sync delay on large boards and an export that skipped archived rows.</p>
            </section>
          ))}
        </div>
        <ScrollTopRing threshold={200} />
      </div>
    </Panel>
  );
}

API reference

ScrollTopRing

component

Also accepts the native props of its root element and a ref.

PropTypeDefaultDescription
thresholdnumber400Pixels scrolled before the button appears.
labelstring"Back to top"
focusTargetstring—The element that receives focus after the jump, by id; the top of the content when not given.

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 checks prefers-reduced-motion itself and settles immediately instead of travelling. Every state is still reachable.

All Compare & browse examples