Skip to content

Add PR card UI with Query Github Event Data#4087

Open
lucaslyl wants to merge 18 commits intomainfrom
CS-10224-pr-card
Open

Add PR card UI with Query Github Event Data#4087
lucaslyl wants to merge 18 commits intomainfrom
CS-10224-pr-card

Conversation

@lucaslyl
Copy link
Contributor

@lucaslyl lucaslyl commented Feb 28, 2026

linear: https://linear.app/cardstack/issue/CS-10224/pr-card

Summary

  • Add PrCard with live GitHub event integration
  • Introduce a new PrCard card type that displays pull request status by consuming live GithubEventCard data. The card shows PR state (open/closed/etc.),
  • CI check results and simple code review status (Only show the changes requested comments).

What's included:

  • PrCard card definition with isolated and fitted templates
    • Isolated: full PR detail view with header, CI checks list, review comments, and linked listing
    • Fitted: responsive card with donut chart CI summary, review status row, and container query breakpoints for all sizes
  • utils.ts: shared helpers for PR state rendering, CI item building/grouping, review state computation, and query builders
  • Theme support: added GitHub PR brand guide theme; all theme CSS variables (--card, --foreground, --destructive, etc.) include hardcoded fallbacks

Demo:

Isolated:
image

Fitted:
image

@lucaslyl lucaslyl self-assigned this Feb 28, 2026
@lucaslyl lucaslyl requested a review from a team February 28, 2026 12:35
@github-actions
Copy link

github-actions bot commented Feb 28, 2026

Host Test Results

    1 files  ±0      1 suites  ±0   2h 7m 47s ⏱️ + 7m 7s
1 955 tests ±0  1 940 ✅ ±0  15 💤 ±0  0 ❌ ±0 
1 970 runs  ±0  1 955 ✅ ±0  15 💤 ±0  0 ❌ ±0 

Results for commit e9e6b03. ± Comparison against base commit 070b11e.

♻️ This comment has been updated with latest results.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new PrCard UI in the catalog realm using mock PR state/review/CI data, along with a GitHub-styled Theme card and a demo card instance to showcase the design before real data integration (blocked by #4074).

Changes:

  • Added PrCard card definition with isolated/embedded/fitted templates and styling.
  • Added a GitHub PR-themed Brand Guide (Theme card) to supply design tokens/palette.
  • Added a sample PrCard instance JSON wired to a demo listing + theme.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
packages/catalog-realm/pr-card/pr-card.gts New PrCard card definition + isolated/fitted templates with mock CI/review state and extensive scoped CSS.
packages/catalog-realm/Theme/github-pr-brand-guide.json New GitHub PR brand guide Theme card (palette/typography/variables) for consistent styling.
packages/catalog-realm/PrCard/b306784c-a34b-40fb-90c8-61bba0d1e9c7.json Demo PrCard instance referencing the PrCard module, a listing, and the new theme.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +687 to +706
class FittedTemplate extends Component<typeof PrCard> {
get mockCi() {
return MOCK_CI;
}
get mockReviews() {
return MOCK_REVIEWS;
}
get stateLabel() {
return prStateLabel(MOCK_STATE);
}
get pillColor() {
return stateColor(this.stateLabel);
}

get prTitle() {
return this.args.model.prTitle ?? 'Pull Request';
}
get prUrl() {
return this.args.model.prUrl ?? '#';
}
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

IsolatedTemplate and FittedTemplate duplicate the same mock-data getters and derived computations (mockCi, mockReviews, stateLabel, pillColor, prTitle, prUrl, review aggregations). This makes future changes error-prone (easy to update one template and forget the other). Consider extracting shared logic into a helper module or a base component/mixin used by both templates.

Copilot uses AI. Check for mistakes.
Comment on lines +1393 to +1400
/* Horizontal divider between CI and reviews */
.status-divider {
height: 1px;
background: var(--border, #d0d7de);
flex-shrink: 0;
margin: 0 var(--boxel-sp-lg);
}

Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

FittedTemplate’s styles define .status-divider (and container-query tweaks for it), but the fitted template markup doesn’t render an element with class='status-divider'. This is dead CSS (or a missing divider in the layout). Either add the divider element where intended, or remove the unused styles and container-query adjustments.

Suggested change
/* Horizontal divider between CI and reviews */
.status-divider {
height: 1px;
background: var(--border, #d0d7de);
flex-shrink: 0;
margin: 0 var(--boxel-sp-lg);
}

Copilot uses AI. Check for mistakes.
// === Computed ===
@field cardTitle = contains(StringField, {
computeVia(this: PrCard) {
return this.prTitle ?? `PR #${this.prNumber}`;
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

cardTitle can become PR #undefined when both prTitle and prNumber are unset. This produces a confusing title and may leak "undefined" into UI/search. Consider falling back to a generic title when prNumber is null/undefined (or require prNumber).

Suggested change
return this.prTitle ?? `PR #${this.prNumber}`;
if (this.prTitle) {
return this.prTitle;
}
if (this.prNumber !== null && this.prNumber !== undefined) {
return `PR #${this.prNumber}`;
}
return 'Pull request';

Copilot uses AI. Check for mistakes.
}

get prUrl() {
return this.args.model.prUrl ?? '#';
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

Using '#' as a fallback for prUrl means the external-link anchors will still render and open a meaningless URL in a new tab when the field is missing. Prefer returning null/undefined and conditionally rendering the link only when a real URL is present (same applies to the fitted template’s prUrl getter).

Suggested change
return this.args.model.prUrl ?? '#';
return this.args.model.prUrl ?? null;

Copilot uses AI. Check for mistakes.
target='_blank'
rel='noopener noreferrer'
class='pr-external-link'
title='Open PR on GitHub'
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

This external-link anchor is icon-only. Add an accessible name (e.g., aria-label or visually-hidden text) so screen readers can announce the purpose. The same pattern appears on the review link(s) and in the fitted template.

Suggested change
title='Open PR on GitHub'
title='Open PR on GitHub'
aria-label='Open PR on GitHub'

Copilot uses AI. Check for mistakes.
target='_blank'
rel='noopener noreferrer'
class='review-external-link'
title='View review on GitHub'
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

The link title says "View review on GitHub" but the href points to the PR URL (this.prUrl), not a review-specific URL. This is misleading; either adjust the copy to match what the link does, or (once available) link directly to the review/comment permalink.

Suggested change
title='View review on GitHub'
title='View pull request on GitHub'

Copilot uses AI. Check for mistakes.
@lucaslyl lucaslyl changed the title Add PR card UI with mock data Add PR card UI with Query Github Event Data Mar 3, 2026
@lucaslyl
Copy link
Contributor Author

lucaslyl commented Mar 9, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 62dc32494c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +20 to +23
const isCheckRunEvent = this.payload?.check_run !== undefined;
return isCheckRunEvent
? this.payload?.check_run?.pull_requests?.[0].number
: (this.payload?.pull_request?.number ?? null);

Choose a reason for hiding this comment

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

P1 Badge Populate PR number for check_suite webhook cards

GithubEventCard.prNumber only branches on check_run and otherwise falls back to payload.pull_request.number, so check_suite events are stored with prNumber = null even when they contain PR references in payload.check_suite.pull_requests. Because PrCard issues searchEventQuery(..., <prNumber>, 'check_suite'), those suite events will never be returned for the target PR, causing CI status rendering to miss suite-level data.

Useful? React with 👍 / 👎.

Comment on lines +42 to +43
case 'closed':
return 'Closed';

Choose a reason for hiding this comment

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

P2 Badge Distinguish merged pull requests from closed ones

renderPrActionLabel unconditionally maps action === 'closed' to 'Closed', so merged PR events (which come through the closed action with merged metadata) are displayed as closed rather than merged. This misreports state in both templates and makes the 'Merged' icon/color branches effectively unreachable for real merged PRs.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants