Resume Marker

Remembers where a reader stopped in a long feed or doc and offers a jump back, without moving the page on its own.

StopsLost my place in a long feed

Team handbook

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/resume-marker.json

The files land in your project. They're yours to edit.

Usage

resume-marker-usage.tsx
import { ResumeMarker } from "@/components/ui/resume-marker"

<ResumeMarker
  key={run}
  storageKey={STORAGE}
  items={sections}
  getKey={(section) => section.id}
  aria-label="Team handbook"
  className="h-80 rounded-xl border bg-background"
  renderItem={(section) => (
    <article className="border-b px-3 py-3 last:border-b-0">
      <h3 className="text-sm font-medium">
        {section.number}. {section.title}
      </h3>
      <p className="mt-1 text-sm text-muted-foreground">
        What to know about {section.title.toLowerCase()}, who to ask, and the links you&apos;ll need.
      </p>
    </article>
  )}
/>

What it catches

  • The item the reader rested on, saved only after saveDelay so a quick flick isn't stored
  • Their place on return, shown as a marker
  • A jump to it and a jump back, never an automatic scroll
  • Stale or malformed saved positions, ignored after maxAge

Props

ResumeMarker props
PropTypeDefault
storageKey* (required)

Identifies this feed or document in localStorage, e.g. "handbook:v3".

string—
items* (required)

Everything in the feed, in reading order.

T[]—
getKey* (required)

A stable key for each item; it's what gets saved.

(item: T) => string—
renderItem* (required)

Renders one item.

(item: T, index: number) => React.ReactNode—
saveDelay

How long the reader must rest on a spot before it's saved, in ms, so a quick flick isn't saved.

number1000
maxAge

Saved positions older than this (ms) are ignored.

number30 * DAY
markerLabel

Divider label above the item the reader stopped on.

string"You were here"
jumpLabel

Pill that scrolls to the saved spot.

string"Jump to where you left off"
backLabel

Pill shown briefly after a jump, undoing it.

string"Back to where you were"
dismissLabel

Accessible label of the button that dismisses the pill.

string"Dismiss"

* required. Also accepts the native props of <div> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Marker is a role=separator with an aria-label
  • Jump and back move focus to the target item (tabIndex=-1) without an extra scroll jump
  • Smooth scrolling is skipped under reduced motion
  • Jump pill sits in a polite live region; dismiss has an aria-label

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

  • Stored in localStorage per device and browser; it does not sync
  • Needs stable item keys; reordered or removed items lose the marker

What it stops

Lost my place in a long feed

Also known as

you were here · continue reading · scroll position · unread · feed · docs · bookmark · last read

Dependencies

Pairs well with