Skip to content

Timeline: add comment event stories (Phase 2)#8072

Merged
janmaarten-a11y merged 15 commits into
mainfrom
janmaarten-a11y-timeline-comment-stories
Jul 8, 2026
Merged

Timeline: add comment event stories (Phase 2)#8072
janmaarten-a11y merged 15 commits into
mainfrom
janmaarten-a11y-timeline-comment-stories

Conversation

@janmaarten-a11y

@janmaarten-a11y janmaarten-a11y commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Part of github/primer#6663 (Phase 2).

Adds Storybook Features stories that recreate GitHub's timeline comment cards using Primer React, plus the shared internal helper module the whole Phase 2 stack builds on.

Stacked PR. This is the bottom of the Phase 2 stack — it carries the shared internal/ helpers that #8070, #8071, #8073, #8074, #8075 all import. Those five are based on this branch and should merge after it (GitHub auto-retargets them to main once this lands).

What's included

1. Comment card stories — Components/Timeline/Internal/Comment cards

packages/react/src/Timeline/Timeline.comments.features.stories.tsx (+ co-located CSS module). A single story (CommentCards, shown as "Comment cards") renders 7 labeled sections, each built from the internal CommentCard helper:

  • Standard user comment — circle avatar, Author subject-author badge, reactions row
  • Bot comment (GitHub App) — square photo avatar, bot label
  • Copilot comment — octicon avatar, AI label, name renders as "Copilot"
  • Dependabot comment — square accent octicon avatar (white DependabotIcon on brand blue), bot label
  • User comment via a GitHub App — the "– with {app}" timestamp suffix
  • User comment via an app (with app avatar badge) — the parent-child avatar (small app avatar overlapping the bottom-right of the author avatar)
  • Comment (inline avatar / compact) — the gutter-less inline-avatar form (see Responsive below)

2. Shared internal helper module — Timeline/internal/

Extracted so the six surface stories consume components instead of copy-pasting primitive clusters (resolves review feedback about baking helpers into the story):

  • internal/timelineStoryHelpers.tsx (+ .module.css) — VariantSection, RealisticTimeline, Examples, BoldLink, InlineAvatar, MutedTime. The last three reproduce live-GitHub styling Primer doesn't express natively yet and are tracked to remove upstream (github/primer#6826 bold inline link, feat(RelativeTime): remove support for sx prop #6827 inline avatar, feat: remove sx prop from Button, LinkButton, IconButton, and ButtonG… #6828 muted timestamp).
  • internal/CommentCard.tsx (+ .module.css) — the self-contained comment-card composition (header, body, reactions, caret, octicon/parent-child avatars, responsive rules). Internal only, not exported from the package index.
  • internal/timelineStoryHelpers.stories.tsx — a Components/Timeline/Internal/Helpers story documenting the six shared helpers in isolation.

Sidebar tree:

Components / Timeline / Internal
  ├─ Comment cards
  └─ Helpers

Responsive behavior (matches github.com)

The large-gutter comment cards collapse to the inline-avatar form below 768px — verified against live github-ui (ActivityHeader forceInlineAvatar / avatarHiddenOnMedium, LayoutHelpers nonLeadingElement_inlineAvatars). Implemented with a container query on a Comments-local root: ≥768px shows the 40px gutter avatar + rail + speech-bubble caret; <768px hides the gutter avatar and the caret, renders a 24px inline avatar in the header ("{author} commented {time}"), and runs the body full-width. The compact section demonstrates this form directly; it's also the responsive rendering for every comment.

Source of truth

Recreated from the live React components in github-ui packages/commenting (ActivityHeader, CommentAuthorAssociation, CommentSubjectAuthor, IssueComment). Key denotations were verified against live, not invented:

  • Actor labels are lowercase bot / AI — from LABELS.authorLabel(isBot, isCopilot) (bot for bots/Dependabot, AI for Copilot, name shown as "Copilot"). Not "Bot"/"Copilot".
  • Author badge is the subject-author badge (CommentSubjectAuthor, LABELS.commentAuthor), shown when the commenter opened the issue — distinct from association values (Member/Owner/Collaborator/Contributor).
  • via-app suffix is the literal "– with {app}" appended to the timestamp line, with the app name as an inline (underlined) link.
  • Parent-child app avatar deliberately corrects Primer's upstream .avatar-child asymmetric offset (right: -15% / bottom: -9%) + translucent #fffc ring with a symmetric offset + opaque ring (github/github#439417).

Deferred (not in this PR): threaded review replies, embedded-in-thread comments, and minimized/collapsed states. The CommentCard helper has an isReply prop wired (drops border/caret/gutter avatar) so those can be added later without reshaping it.

Accessibility

  • Decorative Timeline.Badge octicons render bare (aria-hidden) to avoid double-announcing the adjacent body text.
  • In-text links underline via a data-a11y-link-underlines="true" wrapper that reproduces GitHub's default-on "Show link underlines" setting, so inline links satisfy axe link-in-text-block (WCAG 1.4.1) without diverging from live.
  • The card click-guard uses e.target instanceof Element before closest('a') (guards against SVG/octicon click targets).

Scope & conventions

  • Story wrapped in a file-scoped FeatureFlags decorator enabling primer_react_timeline_list_semantics (future-state <ol>/<li> DOM; refs Timeline: Use list semantics for screen reader navigation #7910).
  • Storybook-only by designnot wired into components-json / the primer.style docs page (not added to Timeline.docs.json or build.ts). Individual timeline events are not consumer-facing components.
  • The future event-category data-* filtering taxonomy (github/primer#6663) is intentionally deferred.

Changelog

New

  • Timeline.comments.features.stories.tsx (+ CSS module) — comment-card stories (Components/Timeline/Internal/Comment cards).
  • Timeline/internal/timelineStoryHelpers.tsx (+ CSS module) — shared internal story helpers (VariantSection, RealisticTimeline, Examples, BoldLink, InlineAvatar, MutedTime), consumed by all six Phase 2 surface stories.
  • Timeline/internal/CommentCard.tsx (+ CSS module) — internal comment-card composition helper.
  • Timeline/internal/timelineStoryHelpers.stories.tsxComponents/Timeline/Internal/Helpers reference story.

Changed

  • None (new files only).

Removed

  • None.

Rollout strategy

  • None; Storybook-only stories + internal helpers — no changes to the published package, so a skip changeset label is applied.

Testing & Reviewing

  • prettier, eslint, and stylelint clean; type-check passes with 0 new errors (the pre-existing @primer/doc-gen baseline error in script/components-json/build.ts is unchanged).
  • Comment denotations verified against the live github-ui packages/commenting React components; responsive collapse measured headless at ≥768px and <768px.
  • Review in Storybook under Components → Timeline → Internal → Comment cards (and Helpers).

Merge checklist

  • Added/updated tests
  • Added/updated documentation
  • Added/updated previews (Storybook)
  • Changes are SSR compatible
  • Tested in Chrome
  • Tested in Firefox
  • Tested in Safari
  • Tested in Edge
  • (GitHub staff only) Integration tests pass at github/github-ui

@changeset-bot

changeset-bot Bot commented Jun 28, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: d41a013

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@janmaarten-a11y janmaarten-a11y added skip changeset This change does not need a changelog component: Timeline labels Jun 28, 2026
@github-actions github-actions Bot temporarily deployed to storybook-preview-8072 June 28, 2026 09:53 Inactive
@janmaarten-a11y janmaarten-a11y changed the title Add Timeline comment-card Storybook stories (Issues surface) Timeline: add comment event stories (Phase 2) Jun 28, 2026
@janmaarten-a11y janmaarten-a11y self-assigned this Jun 28, 2026
@github-actions github-actions Bot requested a deployment to storybook-preview-8072 June 28, 2026 22:06 Abandoned
@janmaarten-a11y janmaarten-a11y requested a review from Copilot June 28, 2026 22:16
@github-actions github-actions Bot temporarily deployed to storybook-preview-8072 June 28, 2026 22:16 Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Storybook-only “Features” story group that recreates GitHub Issues timeline comment cards using Timeline.Item + Timeline.Avatar plus a co-located CSS module for the card shell (header, caret, reactions).

Changes:

  • Added Timeline.comments.features.stories.tsx with a local CommentCard helper and a single EventComment export showing 5 actor variants (standard user, bot, Copilot, Dependabot, via-app).
  • Added Timeline.comments.features.stories.module.css to style the comment-card layout (card chrome, caret, avatar positioning, reactions row).
  • Wrapped stories in the primer_react_timeline_list_semantics feature-flag decorator for future <ol>/<li> semantics.
Show a summary per file
File Description
packages/react/src/Timeline/Timeline.comments.features.stories.tsx Adds the Storybook “Issues” comment-card event group and supporting local composition helpers.
packages/react/src/Timeline/Timeline.comments.features.stories.module.css Provides scoped CSS to visually compose a GitHub-like comment card (caret, header bar, reactions, octicon avatars).

Review details

  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Low

Comment thread packages/react/src/Timeline/Timeline.comments.features.stories.tsx Outdated
@github-actions github-actions Bot requested a deployment to storybook-preview-8072 June 28, 2026 22:34 Abandoned
@github-actions github-actions Bot temporarily deployed to storybook-preview-8072 June 28, 2026 22:43 Inactive
@janmaarten-a11y janmaarten-a11y marked this pull request as ready for review June 29, 2026 20:15
@janmaarten-a11y janmaarten-a11y requested a review from a team as a code owner June 29, 2026 20:15
@janmaarten-a11y janmaarten-a11y added the integration-tests: skipped manually Changes in this PR do not require an integration test label Jun 29, 2026
@github-actions github-actions Bot temporarily deployed to storybook-preview-8072 July 7, 2026 00:55 Inactive
Comment thread packages/react/src/Timeline/Timeline.comments.features.stories.tsx Outdated
janmaarten-a11y and others added 6 commits July 7, 2026 14:16
Per the Figma spec, render the Dependabot comment gutter avatar as a white
DependabotIcon on an accent-blue rounded square via the octicon-avatar mode
(new avatarIconShape/avatarIconTone props), replacing the off-brand photo URL.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Match Figma: avatar left edge ~72px left of the rail, card overlaps the rail by
16px (so the rail runs behind the card's left edge), avatar→card ~56px, with the
caret bridging the gap. Remove the divider above the reactions row to match the
live comment card.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Avoid a runtime throw when the click target is a non-Element (e.g. an SVG
octicon) by checking e.target instanceof Element before calling closest.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reconstruct GitHub's dual-avatar pattern — a small app/agent avatar overlapping
the bottom-right of the large author avatar, for app/agent co-authored comments
(e.g. "monalisa … – with GitHub Actions"). Add an appAvatar prop to CommentCard
and a new story section. Based on Primer's .avatar-parent-child but corrected:
uses a symmetric offset and an opaque ring instead of .avatar-child's
long-standing asymmetric right:-15%/bottom:-9% offset and translucent shadow
(github/github#439417).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nts to Private/ namespace

Add packages/react/src/Timeline/internal/timelineStoryHelpers.{tsx,module.css}
with six story-only helpers (VariantSection, RealisticTimeline, Examples,
BoldLink, InlineAvatar, MutedTime) for the Timeline event-story surfaces to
share. Never exported from the package index (stories don't ship), so no public
API surface. BoldLink/InlineAvatar/MutedTime shim live-GitHub styling Primer
doesn't express yet (tracked in github/primer#6826/#6827/#6828).

Retitle the Comments stories to Private/Components/Timeline/Events/Comments and
consume the shared VariantSection + RealisticTimeline. Pure refactor — Storybook
rendering unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ts story

Add a gutter-less comment form: a ~24px avatar inline in the header before the
author ('{author} commented {time}') with the body spanning full width, alongside
the existing large-gutter variants. This is both the new Issues issue_inline_avatars
rendering (github-ui ActivityHeader forceInlineAvatar) and the responsive
narrow-viewport form. Consumes the shared InlineAvatar helper; wraps the large-gutter
sections in a .GutterGroup so the inline section renders full-width.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e Comments to Internal/, add Helpers story

- Large-gutter comment cards now collapse to the compact inline form below 768px
  via a container query on the Comments root (mirrors live github.com: gutter avatar
  + 56px indent only at >=768px; small inline header avatar + full-width body below).
  Both avatars stay in the DOM, toggled by CSS.
- The always-inline (compact) card now overlaps the rail by ~16px like the large
  card, instead of sitting flush.
- Retitle Comments story to Components/Timeline/Internal/Comments (out of Private/).
- Add Components/Timeline/Internal/Helpers story documenting the six shared
  internal helpers in isolation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Comments story to Events/ (resolves #8072 review)

Move the CommentCard component + CommentCardProps + its sub-helpers
(octicon/inline avatars, parent-child app avatar, reactions) into
internal/CommentCard.tsx, and all CommentCard-specific classes + the responsive
@container collapse rules into internal/CommentCard.module.css. The story keeps
only the example data, variant catalog, and the container-establishing
.CommentsRoot. Retitle the story Components/Timeline/Internal/Comments ->
Components/Timeline/Events/Comments (code location and sidebar location are
decoupled; Internal/ is reserved for the Helpers primitive docs). Pure move —
zero visual/functional change, verified at >=768px and <768px.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ts IA to Internal/Comment cards

- The responsive large cards kept their speech-bubble caret when collapsing to
  the inline form below 768px, pointing at a gutter avatar that's no longer
  shown. Toggle the .CardResponsive caret with the same container query as the
  gutter avatar: hidden <768px, shown >=768px.
- Retitle the Comments story to Components/Timeline/Internal/Comment cards so it
  sits next to Internal/Helpers (only one comment story; it documents the
  internal CommentCard).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
janmaarten-a11y and others added 2 commits July 7, 2026 19:47
…Helpers leaves

Both internal stories now share title 'Components/Timeline/Internal' with the leaf
name coming from the export: rename EventComment -> CommentCards (leaf 'Comment
cards') and keep Helpers (leaf 'Helpers'). This removes the extra 'Event comment'
sub-leaf and the redundant 'Helpers/Helpers' nesting, so both render as siblings
directly under Internal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add CommentCards.storyName = 'Comment cards' so the Internal leaf reads in
sentence case instead of Storybook's auto-title-cased 'Comment Cards'. Story ID
stays components-timeline-internal--comment-cards.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@janmaarten-a11y janmaarten-a11y added this pull request to the merge queue Jul 8, 2026
Merged via the queue into main with commit d038d5b Jul 8, 2026
55 checks passed
@janmaarten-a11y janmaarten-a11y deleted the janmaarten-a11y-timeline-comment-stories branch July 8, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: Timeline integration-tests: skipped manually Changes in this PR do not require an integration test skip changeset This change does not need a changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants