KQ-892 · UNREAD/LINE

Unread Line

The rule that says where you stopped. The separator draws itself with a scaleX from its left origin on glide while the pill beside it arrives 4px up on flick, and as you read it keeps its key inside one AnimatePresence so the same rule travels to its new seat under layout while the messages re-seat around it. The pill is a real button that marks everything below it read, and when the last unread goes the rule fades and lifts away on the exit ease rather than springing.

KQ-892 · UNREAD/LINE
4 new messages
  1. Ines Moreau, 01:48, read.Gate is locked. Everything is on dock two tonight.
  2. Rui Baptista, 01:55, read.Loader keys are back on the hook by the office.
  3. Ines Moreau, 02:03, read.Good. I am off at three, Marta takes the handover.
  4. Marta Ferreira, 02:14, unread.Pallet 4471 is still held. Waylight Pay has not cleared it.
  5. Marta Ferreira, 02:16, unread.I left the paperwork on the desk under the sheet.
  6. Rui Baptista, 02:31, unread.Dock three is free from nine if the yard needs it.
  7. Marta Ferreira, 02:40, unread.Coldbrook depot closes Thursday from noon. Nothing leaves after eleven.

4 unread · first from Marta Ferreira

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/unread-line

Props

messages
UnreadMessage[]
default
The thread, oldest first: id, author, text and a preformatted time.
readCount / defaultReadCount
number
default messages.length
Controlled or initial count of messages read from the top; the rule sits after them.
onReadCountChange
(count: number) => void
default
Fires when the rule's own pill advances the boundary.
onMarkAllRead
() => void
default
Fires from the pill, alongside onReadCountChange.
onAnnounce
(sentence: string) => void
default
Fires once per frozen change sentence, for a parent's own status line.
label
string
default
Names the thread for assistive technology.
dividerLabel
string
default "New messages"
The pill's word.
upToDateLabel
string
default "You are up to date"
What the header reads when nothing is unread.
maxHeight
number
default 300
Tallest the thread grows before it scrolls inside its own box.