Timeline: add License Compliance event stories (Phase 2)#8075
Timeline: add License Compliance event stories (Phase 2)#8075janmaarten-a11y wants to merge 5 commits into
Conversation
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>
|
There was a problem hiding this comment.
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 ComplianceStorybook 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
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>
- 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>
Summary
Adds Storybook Features stories that recreate GitHub's live License Compliance alert timeline events using the Primer
Timelinecomponent 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 ReactTimeline+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 titleComponents/Timeline/Events/License Compliance— one story export per event group.The 9 event groups (19 variants total)
EventOpenedshieldon solidsuccess(green)EventAppearedInBranchgit-branch(default gray)EventReviewRequestedcomment(default gray)EventReviewApprovedcheck(default gray)EventReviewDeniedx(default gray)EventReviewExpiredcircle-slash(default gray)EventExceptionAddedlaw(default gray)EventLicensesAddedlaw(default gray)EventClosedshield-checkon soliddone(purple)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 theswitch (event.type)inTimelineEventItem.tsx; per-event copy, badges, and actors were read from the per-event components underevents/and the two shared wrappers inevents/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:
appeared_in_branchPR sub-row is dormant.AppearedInBranchEventrenders aPullRequestLinkwhenever its body carriespull_request_number/pull_request_title, but the Railscreate_synthetic_branch_eventonly ever writes{branch_name}(andactor: nil) — PR enrichment is applied only toreview_requestedevents. So that sub-row is dead in production; we build only the branch-name pill and note the dormant path in-code.review_expiredis actor-less. Although the component usesTimelineEventWithActor, 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.getClosedActionText(closureReason, resolution)inClosedEvent.tsx:closed as {closureReason}(free text, e.g. "used in tests") /closed as outdated(resolutionOutdated) /closed as amendment(resolutionExceptionAddedorLicensesAdded) /closed this alert(default). All four are built.create_synthetic_opened_eventattributes the syntheticopenedevent toattribution_only_system_identity_for(:license_compliance), rendered as a normal linked actor (its login isn't[bot]-suffixed, so no "bot" Label) — distinct from theMarkGithubIcon"GitHub" system actor used on the Secret Scanning surface.Slots
TimelineEventWithActor, which renders a 20px circle avatar + login (a profile link whenactor.urlis present, otherwise bold text; bots strip the[bot]suffix and append a secondary "bot"Label).Timeline.Actions(right-controls slot, added in Add Timeline.Actions sub-component #7886) carries the "Review request" button on the latestreview_requestedevent (label confirmed fromReviewRequestedEvent.tsx, avariant="primary" size="small"button).Badge note
Gray/default events render as a bare
Timeline.Badge(no solid fill, no--timelineBadge-bgColorhook) — Appeared-in-branch, all three Review states, Review-expired, Exception-added, and Licenses-added. Only Opened (green/success) and Closed (purple/done) are solidvariant=badges — matching the live components, where only those two pass an explicitbadgeVariant.Scope & conventions
Timeline.docs.jsonorbuild.ts. Individual timeline events are not consumer-facing components.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.<section><h3 caption>scaffolding above each row so variants stay scannable like a Figma component set, without pollutingTimeline.Body.TimelineEventWithActor(note: larger than the Secret Scanning surface's 16px).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-blockrule (WCAG 1.4.1) in high-contrast themes. The stories intentionally render them with an underline (theinlineprop) 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 liveactorLinkstyle.Changelog
Stories-only change — no consumer-facing component or API change, so no changeset (the
skip changesetlabel is applied).Rollout
No rollout concerns — adds Storybook examples only; ships no runtime code.
Testing
prettier— cleaneslint— cleanstylelint— cleantsc— 0 new type errors (the only repo tsc error is pre-existing inscript/components-json/build.ts)Merge checklist
Components/Timeline/Events/License Complianceskip changeset+component: Timelinelabels applied