Skip to content

Add Card component#7723

Open
liuliu-dev wants to merge 17 commits intomainfrom
liuliu/add-card-component
Open

Add Card component#7723
liuliu-dev wants to merge 17 commits intomainfrom
liuliu/add-card-component

Conversation

@liuliu-dev
Copy link
Copy Markdown
Contributor

@liuliu-dev liuliu-dev commented Apr 1, 2026

Upstream the Card component from Pacer into @primer/react.

Issue: https://github.com/github/primer/issues/6467

Changelog

New

  • Card — A styled container component with border, box-shadow, and border-radius; also supports custom content without subcomponents (plain container mode)
  • Card.Icon — Renders a decorative icon in the card header (defaults to aria-hidden, supports aria-label for meaningful icons)
  • Card.Image — Renders an edge-to-edge image in the card header
  • Card.Heading — Renders a heading (defaults to h3, configurable via as prop)
  • Card.Description — Renders a description below the heading
  • Card.Menu — Slot for overlay menu (positioned absolute top-right)
  • Card.Metadata — Renders metadata content below the description

Changed

  • Playground Storybook story updated with boolean toggle controls for Card.Icon and Card.Metadata
  • CustomContent Storybook story added to demonstrate using Card as a plain styled container with arbitrary children (no subcomponents)

Rollout strategy

  • Patch release
  • Minor release
  • Major release; if selected, include a written rollout or migration plan
  • None; if selected, include a brief description as to why

Testing & Reviewing

Merge checklist

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 1, 2026

🦋 Changeset detected

Latest commit: 375b519

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Minor

Not sure what this means? Click here to learn what changesets are.

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

@liuliu-dev liuliu-dev changed the title card from pacer Add Card component Apr 1, 2026
@github-actions github-actions bot added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Apr 1, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

⚠️ Action required

👋 Hi, this pull request contains changes to the source code that github/github-ui depends on. If you are GitHub staff, test these changes with github/github-ui using the integration workflow. Check the integration testing docs for step-by-step instructions. Or, apply the integration-tests: skipped manually label to skip these checks.

To publish a canary release for integration testing, apply the Canary Release label to this PR.

@liuliu-dev liuliu-dev added the update snapshots 🤖 Command that updates VRT snapshots on the pull request label Apr 1, 2026
@github-actions github-actions bot temporarily deployed to storybook-preview-7723 April 1, 2026 21:41 Inactive
@github-actions github-actions bot removed the update snapshots 🤖 Command that updates VRT snapshots on the pull request label Apr 1, 2026
@github-actions github-actions bot temporarily deployed to storybook-preview-7723 April 1, 2026 21:54 Inactive
@github-actions github-actions bot temporarily deployed to storybook-preview-7723 April 1, 2026 22:05 Inactive
@primer
Copy link
Copy Markdown
Contributor

primer bot commented Apr 2, 2026

🤖 Lint issues have been automatically fixed and committed to this PR.

@primer
Copy link
Copy Markdown
Contributor

primer bot commented Apr 2, 2026

🤖 Lint issues have been automatically fixed and committed to this PR.

@liuliu-dev
Copy link
Copy Markdown
Contributor Author

Hey @lukasoppermann @ericwbailey 👋
Would love a design and a11y review for this Card component. Storybook preview is available on the PR deployment. Happy to iterate on feedback!

@ericwbailey
Copy link
Copy Markdown
Contributor

Can't speak to the code or overall plan, but some high-level considerations that we'll have to contend with at some point:

Card.Heading — Renders a heading (h3) with truncation

  • We'll want to make h3 able to accept multiple heading levels, in order to better integrate with the existing view heading structure. We can default to h3.
  • Truncation is an accessibility antipattern that represents non-trivial MAS risk and we'll want to remove.

Card.Icon — Renders an icon in the card header

  • We'll want to make this default to a decorative icon, with the option to add an alternate description if needed.

Card.Description — Renders a description with 2-line clamp

  • Like the heading, truncation is an accessibility antipattern that represents non-trivial MAS risk and we'll want to remove.

@primer
Copy link
Copy Markdown
Contributor

primer bot commented Apr 6, 2026

🤖 Lint issues have been automatically fixed and committed to this PR.

@github-actions github-actions bot requested a deployment to storybook-preview-7723 April 6, 2026 18:09 Abandoned
@primer
Copy link
Copy Markdown
Contributor

primer bot commented Apr 6, 2026

🤖 Lint issues have been automatically fixed and committed to this PR.

@liuliu-dev
Copy link
Copy Markdown
Contributor Author

Thanks for the review @ericwbailey! Addressed:

  • Heading: supported via as prop (defaults to h3)
  • Truncation: removed from both heading and description, long heading/ description will wrap
  • Icon: now defaults to decorative (aria-hidden), with optional aria-label

@lukasoppermann
Copy link
Copy Markdown
Contributor

@copilot in the Playground storybook story, add toggles for the icon <Card.Icon> and the <Card.Metadata>.

Also add a story that does not use any of the internal components and just adds some custom content to the card

Copy link
Copy Markdown
Contributor

@lukasoppermann lukasoppermann left a comment

Choose a reason for hiding this comment

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

@liuliu-dev design wise:

I think we can remove the fallback values, they are not needed and don't exist anymore.

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

@copilot in the Playground storybook story, add toggles for the icon <Card.Icon> and the <Card.Metadata>.

Also add a story that does not use any of the internal components and just adds some cu...

Done in 375b519.

  • Playground: Added boolean toggle controls (showIcon and showMetadata) via argTypes, both defaulting to true. Toggling them off removes the respective Card.Icon / Card.Metadata from the rendered story.
  • CustomContent: Added a new story that places a custom <div> with a heading, paragraph and list directly inside <Card> — no Card.* subcomponents used at all.
  • Component: Updated Card to detect when no slot children are present and render children directly, so the CustomContent story (and any consumer using Card as a plain styled container) works correctly.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • example.com
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1194/chrome-linux/headless_shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1194/chrome-linux/headless_shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1194/chrome-linux/headless_shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1194/chrome-linux/headless_shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD -main/dist/gh-gpgsign/gh-gpgsign-linux-x86_64 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@lukasoppermann
Copy link
Copy Markdown
Contributor

@liuliu-dev should we tie the padding to the content-top, instead of icon bottom?

CleanShot 2026-04-07 at 09 23 53@2x

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

Uh oh! @lukasoppermann, at least one image you shared is missing helpful alt text. Check #7723 (comment) to fix the following violations:

  • Images should have meaningful alternative text (alt text) at line 3

Alt text is an invisible description that helps screen readers describe images to blind or low-vision users. If you are using markdown to display images, add your alt text inside the brackets of the markdown image.

Learn more about alt text at Basic writing and formatting syntax: images on GitHub Docs.

🤖 Beep boop! This comment was added automatically by github/accessibility-alt-text-bot.

@lukasoppermann
Copy link
Copy Markdown
Contributor

This is also a use case: https://primer-1b76de82d9-13348165.drafts.github.io/storybook/?path=/story/components-card--custom-content

CleanShot 2026-04-07 at 09 25 01@2x

I am wondering if we should expect users to "bring their own padding" or if we should have a padding inside the card by default and a prop or a way to easily remove the default padding? CC: @siddharthkp ?

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

Uh oh! @lukasoppermann, at least one image you shared is missing helpful alt text. Check #7723 (comment) to fix the following violations:

  • Images should have meaningful alternative text (alt text) at line 3

Alt text is an invisible description that helps screen readers describe images to blind or low-vision users. If you are using markdown to display images, add your alt text inside the brackets of the markdown image.

Learn more about alt text at Basic writing and formatting syntax: images on GitHub Docs.

🤖 Beep boop! This comment was added automatically by github/accessibility-alt-text-bot.

@ericwbailey
Copy link
Copy Markdown
Contributor

Thanks for the review @ericwbailey! Addressed:

Amazing! Thank you so much!

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

Labels

Canary Release Apply this label when you want CI to create a canary release of the current PR integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants