Skip to content
Tier

useThreadSeparators

Pro

Where a thread's dividers go, chosen by how long the thread runs: for each message that starts a new period, the props for its ThreadDivider. Draw <ThreadDivider {...separators.get(i)} /> before message i when the map has it.

  • A thread that runs under 14 days is divided by day, and each divider gets date, so it reads "Today", "Yesterday" or the date.
  • Under 120 days, by week: "Week of 9 Nov 2026", the week starting on the locale's first day (Monday when the browser can't say).
  • Under 730 days, by month: "November 2026". Longer, by year: "2025".

granularity fixes the period instead of choosing it. Days, weeks, months and years are counted in LocaleProvider's time zone (the browser's when it sets none, and UTC until the page hydrates, as every Candor time), and the labels are in its locale. A message whose time is missing or can't be read joins the period before it, so it never starts one.

The times are compared by what they hold, not by identity, so a times array made afresh on each render (a messages.map(…)) doesn't work the dividers out again, and the map it returns stays the same object until a time changes.

Markdown
Version 5.2.0· other versions

This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).

Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1, 2.6.2, 2.7.0, 2.8.0, 2.9.0, 2.10.0, 3.0.0, 4.0.0, 4.0.1, 4.0.2 and 4.1.0: the page came later, or had another name then.

Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.

Preview

Loading the preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/use-thread-separators

Brings in: locale, tokens

Usage

TSX · The example above
"use client"

import { ThreadDivider } from "@/components/candor/thread-divider"
import { useThreadSeparators } from "@/lib/candor/use-thread-separators"

// A thread that runs for about five months, so it is divided by month.
const messages = [
  { id: "m1", at: "2026-06-03T09:12:00Z", text: "Can you watch the refund queue for duplicates?" },
  { id: "m2", at: "2026-06-03T09:13:00Z", text: "Yes. I’ll flag any order charged twice." },
  { id: "m3", at: "2026-08-19T16:40:00Z", text: "Three duplicates this week, all from the same card reader." },
  { id: "m4", at: undefined, text: "A message whose time wasn’t recorded joins the month before it." },
  { id: "m5", at: "2026-11-02T08:05:00Z", text: "The reader was replaced; no duplicates since." },
]

export default function Example() {
  const separators = useThreadSeparators(messages.map((m) => m.at))
  return (
    <div className="flex max-w-lg flex-col gap-2">
      {messages.map((m, i) => (
        <div key={m.id} className="flex flex-col gap-2">
          {separators.has(i) && <ThreadDivider {...separators.get(i)} />}
          <p className="text-sm">{m.text}</p>
        </div>
      ))}
    </div>
  )
}

Functions

useThreadSeparators(times: (string | Date | null | undefined)[], options?: { granularity?: "auto" | "day" | "week" | "month" | "year" | undefined } | undefined)

Strings

The fixed words, in English by default. Change any of them under threadSeparators in <LocaleProvider strings={{ … }}>; the table is exported as threadSeparatorsStrings.

KeyEnglish
weekWeek of {date}