Skip to content

Timeline

Show an activity feed grouped by day, with space made for new events.

import { Timeline, TimelineEvent, TimelineEventType } from '@youj/react'

Installation & usage

npm i @youj/react

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use a timeline for what happened, in order: deploys, commits, comments and alerts on a project, or the history of an order or an account. Each event has a typed mark on a rail, who did it, when, and optional details that open in place. For a list of things people act on (read, archive, snooze), use Notification Center. For records people sort and filter, use a data table.

import { Timeline, type TimelineEvent } from '@youj/react'

const events: TimelineEvent[] = [
  { id: 'e1', type: 'deploy', actor: { name: 'Mira Chen' }, title: 'deployed web@4f2c91a to production', time: '2026-09-27T09:41:00Z' },
  { id: 'e2', type: 'comment', actor: { name: 'Jonas Weber' }, title: 'commented on #482', time: '2026-09-27T08:15:00Z' },
]

export function Activity() {
  return <Timeline events={events} />
}

Pass events in any order. The timeline sorts them newest first and groups them under Today, Yesterday and dated headings. Each time reads as "5 min ago" today and as a clock time on older days, and it stays true: the feed re-renders every minute. Pass now to pin the clock instead, so a demo or a test reads the same on any day.

Keep the actor out of title: the timeline shows the name, with an avatar, before it. When title is JSX, pass a plain-text summary too, for the announcement when the event arrives live.

Reference

Propsevents, types, onLoadMore… (7)

Props

Timeline props
PropType
eventsRequiredreadonly TimelineEvent[]–
typesRecord<string, TimelineEventType>

Extra or replacement event types.

–
onLoadMore() => Promise<unknown> | void

Loads older events. Shows a Load more button while hasMore.

–
hasMoreboolean

default false

false
localestring

Default: the YoujProvider locale.

–
emptyReactNode

Shown when there are no events.

–
nowDate | number

The moment "Today" and relative times count from, pinned (a demo's clock, a test). Default: the clock, read every minute once the page is live.

–
Other props pass through: extends ComponentProps<'div'>.

An event (TimelineEvent) has an id, a type, a title, a time (a Date, an ISO string or a timestamp), and optionally an actor (name, avatar), a plain-text summary, details and meta.

MotionEvent arrives, events below, event leaves… · reduced motion

Motion

Motion tokens
MomentTokens
Event arrivesfades down 6px into its slot at the top (PresenceList)
duration.baseease.enter

220ms · cubic-bezier(0.16, 1, 0.3, 1)

220mscubic-bezier(0.16, 1, 0.3, 1)
Events belowglide down to make room
spring.smooth

0.36s, bounce 0

0.36s, bounce 0
Event leaves
duration.fastease.exit

140ms · cubic-bezier(0.4, 0, 1, 1)

140mscubic-bezier(0.4, 0, 1, 1)
Markan arriving event’s icon plays once; every mark plays while its row is hovered
no token

Detailsheight and opacity (Collapse)
duration.baseease.standard

220ms · cubic-bezier(0.2, 0, 0, 1)

220mscubic-bezier(0.2, 0, 0, 1)

Reduced motion

Events appear and leave in place, details open at once and the marks stay still.

Reduced motion

New events take their place at once and the list below doesn't glide. Details open and close instantly, and the marks don't play. What's announced, and when, is unchanged.

AccessibilityARIA, announcements

Accessibility

  • Each day is a section with a heading and an ordered list of its events.
  • Every event starts with its type in words, "Deploy:", before who did it and what, because the mark is decorative.
  • Times are <time> elements with the full date and time in datetime and on hover.
  • A live arrival is announced once in a polite live region, as "Deploy: Mira Chen deployed web@4f2c91a to production". Loaded history isn't announced as news.
  • Details toggles are disclosure buttons with aria-expanded and aria-controls. Load more announces "Loading older activity" while it runs.