Skip to content

Timeline: add License Compliance event stories (Phase 2)#8075

Draft
janmaarten-a11y wants to merge 5 commits into
mainfrom
janmaarten-a11y-license-compliance-timeline-stories
Draft

Timeline: add License Compliance event stories (Phase 2)#8075
janmaarten-a11y wants to merge 5 commits into
mainfrom
janmaarten-a11y-license-compliance-timeline-stories

Conversation

@janmaarten-a11y

Copy link
Copy Markdown
Contributor

Summary

Adds Storybook Features stories that recreate GitHub's live License Compliance alert timeline events using the Primer Timeline component and its compositional slots. This is the License Compliance surface — a Security surface — of Phase 2 of the Timeline events effort (github/primer#6663). The Issues surface (#8070), Issue comment cards (#8072), the Dependabot alert surface (#8071), the Secret Scanning surface (#8073), and the Code Scanning surface (#8074) already landed; License Compliance follows here as a separate Security surface.

Like Secret Scanning (and unlike the server-rendered Dependabot and Code Scanning surfaces), License Compliance is fully React — the alert show page is a React SPA in github/github-ui (packages/license-compliance-alerts/) that already composes Primer React Timeline + Timeline.Badge variant=, so the live badges/actors map cleanly onto these stories.

All examples live in a single new file, Timeline.license-compliance.features.stories.tsx (+ a .module.css), exported under the title Components/Timeline/Events/License Compliance — one story export per event group.

The 9 event groups (19 variants total)

Group Variants Badge Actor
EventOpened 2 — opened (user) / opened (bot) shield on solid success (green) User
EventAppearedInBranch 1 — branch-name pill bare git-branch (default gray) none (system)
EventReviewRequested 3 — plain / with reason + comment / with PR link + button bare comment (default gray) User
EventReviewApproved 2 — plain / with comment bare check (default gray) User
EventReviewDenied 2 — plain / with comment bare x (default gray) User
EventReviewExpired 1 — request to close expired bare circle-slash (default gray) none (automatic)
EventExceptionAdded 2 — full (package + policy link + repo) / fallback bare law (default gray) User
EventLicensesAdded 2 — full (licenses + policy link + repo) / fallback bare law (default gray) User
EventClosed 4 — reason + comment / outdated / amendment / default shield-check on solid done (purple) User

Source of truth

These stories were recreated from the live React implementation in github/github-ui (packages/license-compliance-alerts/components/timeline/). The authoritative dispatch is the switch (event.type) in TimelineEventItem.tsx; per-event copy, badges, and actors were read from the per-event components under events/ and the two shared wrappers in events/shared.tsx (TimelineEventWithActor / TimelineEventWithoutActor). The two synthetic events (opened, appeared_in_branch) are constructed server-side, so we additionally verified them against the Rails builder, app/controllers/repos/license_compliance_alerts_controller.rb.

We verified the live render path (and the Rails builder) rather than trusting the Figma audit blindly. The notable resolutions:

  • The appeared_in_branch PR sub-row is dormant. AppearedInBranchEvent renders a PullRequestLink whenever its body carries pull_request_number / pull_request_title, but the Rails create_synthetic_branch_event only ever writes {branch_name} (and actor: nil) — PR enrichment is applied only to review_requested events. So that sub-row is dead in production; we build only the branch-name pill and note the dormant path in-code.
  • review_expired is actor-less. Although the component uses TimelineEventWithActor, expiry is automatic and Rails attaches no actor (the live test fixture has none); the copy "Request to close expired" is a standalone capitalized sentence. Built without an actor.
  • The 4 closure-reason strings come from live getClosedActionText(closureReason, resolution) in ClosedEvent.tsx: closed as {closureReason} (free text, e.g. "used in tests") / closed as outdated (resolution Outdated) / closed as amendment (resolution ExceptionAdded or LicensesAdded) / closed this alert (default). All four are built.
  • The Opened actor is the license-compliance system bot. create_synthetic_opened_event attributes the synthetic opened event to attribution_only_system_identity_for(:license_compliance), rendered as a normal linked actor (its login isn't [bot]-suffixed, so no "bot" Label) — distinct from the MarkGithubIcon "GitHub" system actor used on the Secret Scanning surface.

Slots

  • No system "GitHub" actor on this surface (unlike Secret Scanning) — every actor event flows through TimelineEventWithActor, which renders a 20px circle avatar + login (a profile link when actor.url is present, otherwise bold text; bots strip the [bot] suffix and append a secondary "bot" Label).
  • Actor-less events (Appeared-in-branch, Review-expired) render body text only — no avatar or link.
  • Timeline.Actions (right-controls slot, added in Add Timeline.Actions sub-component #7886) carries the "Review request" button on the latest review_requested event (label confirmed from ReviewRequestedEvent.tsx, a variant="primary" size="small" button).

Badge note

Gray/default events render as a bare Timeline.Badge (no solid fill, no --timelineBadge-bgColor hook) — Appeared-in-branch, all three Review states, Review-expired, Exception-added, and Licenses-added. Only Opened (green/success) and Closed (purple/done) are solid variant= badges — matching the live components, where only those two pass an explicit badgeVariant.

Scope & conventions

  • Storybook-only by design — not added to Timeline.docs.json or build.ts. Individual timeline events are not consumer-facing components.
  • File-scoped future-state list-semantics decorator (primer_react_timeline_list_semantics, refs Timeline: Use list semantics for screen reader navigation #7910) so every story renders in the <ol>/<li> DOM the timeline will ship.
  • Per-variant <section><h3 caption> scaffolding above each row so variants stay scannable like a Figma component set, without polluting Timeline.Body.
  • 20px avatars, matching the live TimelineEventWithActor (note: larger than the Secret Scanning surface's 16px).
  • Deferred data-* event-category taxonomy (still open in github/primer#6663) — intentionally not baked in yet.

Accessibility

The live in-text links (the "license policy" link on Exception-added / Licenses-added, and the PR link on Review-requested) use a color-only style (no underline or bold) that would fail the axe link-in-text-block rule (WCAG 1.4.1) in high-contrast themes. The stories intentionally render them with an underline (the inline prop) so they pass and model good a11y — a small, deliberate deviation from live, noted in-code. (The live color-only links are a potential a11y gap worth flagging to the owning team.) The actor profile link is semibold, the non-color differentiator that satisfies the same rule, matching the live actorLink style.

Changelog

Stories-only change — no consumer-facing component or API change, so no changeset (the skip changeset label is applied).

Rollout

No rollout concerns — adds Storybook examples only; ships no runtime code.

Testing

  • prettier — clean
  • eslint — clean
  • stylelint — clean
  • tsc — 0 new type errors (the only repo tsc error is pre-existing in script/components-json/build.ts)

Merge checklist

  • Stories render under Components/Timeline/Events/License Compliance
  • All 9 event groups translated and verified against the live React components + Rails synthetic-event builder
  • prettier / eslint / stylelint clean, 0 new tsc errors
  • skip changeset + component: Timeline labels applied
  • Review of copy / badge / actor fidelity

janmaarten-a11y and others added 2 commits June 28, 2026 14:04
Phase 2 of github/primer#6663. Adds the Opened event group plus the
file scaffold for the License Compliance alert timeline, mirroring the
reviewed Secret Scanning stories template.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds the eight remaining event groups (appeared_in_branch, review
requested/approved/denied/expired, exception_added, licenses_added,
closed) to complete the License Compliance alert timeline stories,
verified against the live per-event components and the Rails synthetic
event builder. Documents the dormant appeared_in_branch PR sub-row and
the actor-less review_expired event.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@janmaarten-a11y janmaarten-a11y added skip changeset This change does not need a changelog component: Timeline labels Jun 28, 2026
@changeset-bot

changeset-bot Bot commented Jun 28, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: e08fd78

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

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 “Features” story set for License Compliance alert timeline events, modeled as realistic Timeline compositions (badge-row items, optional sub-rows, and right-side actions) and styled with a co-located CSS Module.

Changes:

  • Added Components/Timeline/Events/License Compliance Storybook stories covering 9 event groups (opened → closed), including actor-less and comment/PR sub-row variants.
  • Added a CSS Module to provide story-only scaffolding (variant captions, inline actor/avatar styling, sub-row layout) while keeping the core Timeline row markup faithful.
Show a summary per file
File Description
packages/react/src/Timeline/Timeline.license-compliance.features.stories.tsx New Storybook story exports for License Compliance timeline event groups, with local helpers for actor, timestamps, comments, and sub-rows.
packages/react/src/Timeline/Timeline.license-compliance.features.stories.module.css Story-only styling for realistic Timeline rendering, variant scaffolding, and inline actor/sub-row presentation.

Review details

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

Comment thread packages/react/src/Timeline/Timeline.license-compliance.features.stories.tsx Outdated
@janmaarten-a11y janmaarten-a11y self-assigned this Jun 28, 2026
janmaarten-a11y and others added 2 commits June 28, 2026 15:08
Render the inline actor as plain inline elements (a vertical-align:middle
Avatar followed by an inline Link/span) instead of an inline-flex wrapper,
matching the aligned Issues and Dependabot story rows. The inline-flex box
baseline-aligned oddly within the surrounding inline text, throwing the
badge, actor, and summary off a single line.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- UserActor derives the bot shape from the login (strips a trailing
  [bot] suffix and renders bots unlinked), matching live shared.tsx,
  instead of a separate bot prop.
- Wrap each group's examples in an Examples container that prevents
  default navigation on the story-only demo links, so clicking a
  placeholder href doesn't navigate out of Storybook (mirrors the base
  Timeline WithActions story).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot requested a deployment to storybook-preview-8075 June 28, 2026 22:16 Abandoned
@github-actions github-actions Bot temporarily deployed to storybook-preview-8075 June 28, 2026 22:26 Inactive
- All system events use the github-license-compliance[bot] actor: the
  Opened event is now a single bot variant, and Review-expired shows the
  bot actor (Rails sets it for system user_id<=0; the no-actor mock was
  misleading). Add LICENSE_BOT_AVATAR.
- Closed covers the full live closure-reason set (amendment, private
  package, inaccurate license, policy edited, fixed) plus outdated and
  the default.
- Note that the review_requested closure_reason format comes from the Go
  OLC service and needs a prod smoke-test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: Timeline skip changeset This change does not need a changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants