Feed

Vertical activity streams with icons and timestamps. Used for audit logs, change history, and notification lists.
The events are a list, as in Tailwind UI, and each event is one of its items: a screen reader announces the list with its number of events and moves through it event by event. A pressable event is a button inside its item. The label prop names the list (for example "Recent activity").
A virtualized feed with a bounded height scrolls its events in a list of its own. On the web, while those events overflow, that list is a keyboard tab stop (before the rows themselves when onItemPress makes them buttons), the keyboard can scroll it, and while it has keyboard focus the feed's card draws the theme's focus ring. Only the events near its viewport are mounted, and each says where it sits in the whole feed, so a screen reader still counts every event. Give a windowed feed a label: focused, a list with no name is named in Chromium from the text of every event it has rendered, so the kit warns in development when it has none.
  • RC
    Rachel Chen approved the request
    2 hours ago
  • AL
    Ada Lovelace merged release/4.2
    5 hours ago
  • SY
    System created the project
    3 days ago
iOS
  • RC
    Rachel Chen approved the request
    2 hours ago
  • AL
    Ada Lovelace merged release/4.2
    5 hours ago
  • SY
    System created the project
    3 days ago
Android
  • RC
    Rachel Chen approved the request
    2 hours ago
  • AL
    Ada Lovelace merged release/4.2
    5 hours ago
  • SY
    System created the project
    3 days ago
Web
tsx
<Feed
items={[
{ actor: "Rachel Chen", action: "approved the request", time: "2 hours ago" },
{ actor: "Ada Lovelace", action: "merged", target: "release/4.2", time: "5 hours ago" },
{ actor: "System", action: "created the project", time: "3 days ago" }
]}
/>

Props

Prop
Description
items
FeedItem[]
Events to render, top to bottom.
connector
boolean
Lead axis (pick one; default is the connector node + vertical line).
avatar
boolean
Lead axis (pick one; default is the connector node + vertical line).
compact
boolean
Density modifier: tightens the row padding and connector spacing.
onItemPress
(index: number) => void
When set, each event row is pressable, reporting the row index.
label
string
The feed's accessible name (e.g. "Recent activity"): a screen reader announces it with the list of events. A `virtualized` feed needs one: on the web its scroller is a keyboard stop while the events overflow, and Chromium names an unnamed stop from the text of every event it has rendered.
virtualized
boolean
Render the rows through a windowed `FlatList` instead of mounting every row up front, for large lists. Give the list a bounded height (via `style`, e.g. `{ maxHeight: 400 }`) so it can scroll; without one it warns and renders eagerly anyway. Default (omitted) mounts all rows, unchanged. On the web, while the rows overflow, the windowed list is a keyboard tab stop the keyboard can scroll, and the feed's card draws the focus ring while it has keyboard focus.
testID
string
E2E hook forwarded to the root element.
style
LayoutStyle
Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.

Do & Don’t

Connector

Don’t
RC
Rachel Chen approved the request
2 hours ago
SY
System created the project
3 days ago
Running the connector line past the final event leaves a dangling tail pointing at nothing.
Do
  • RC
    Rachel Chen approved the request
    2 hours ago
  • SY
    System created the project
    3 days ago
Drop the connector on the last item so the line terminates cleanly at the final event.

Avatar

Don’t
?
Pushed 3 commits
An anonymous avatar with no actor name and no timestamp strips the row of the who and the when.
Do
  • Ada Lovelace pushed 3 commits
    5 hours ago
Lead with the person's avatar, bold the actor, and keep the action plus a relative timestamp muted.