Skip to content

Conversation

@gert-janvercauteren

This pull request introduces the new BpkCardV2 component to the Backpack design system, providing a modern, composable, and accessible card solution with extensive documentation, theming, and layout flexibility. The changes include the component implementation, full documentation, Storybook stories, and supporting styles.

The most important changes are:

Component Implementation and API:

  • Added the BpkCardV2 React component with explicit subcomponents (Header, Body, Footer, Primary, Secondary), supporting flexible layouts (including split layouts with configurable ratios), multiple surface color tokens, and visual variants (shadow or outlined). The component is fully accessible and mobile-first responsive. (packages/bpk-component-card-v2/src/BpkCardV2/BpkCardV2.tsx, packages/bpk-component-card-v2/index.ts) [1] [2]

Styling and Theming:

  • Introduced a new SCSS module with BEM naming, Backpack design tokens, and responsive/RTL support, enabling eight surface color variants, shadow/border variants, and split layouts with semantic dividers. (packages/bpk-component-card-v2/src/BpkCardV2/BpkCardV2.module.scss)

Documentation and Usage:

  • Added a comprehensive README with installation instructions, usage examples, prop tables, accessibility notes, browser support, and Figma references. (packages/bpk-component-card-v2/README.md)
  • Created a detailed changelog documenting the initial release, features, accessibility, testing, migration guide, and future enhancements. (packages/bpk-component-card-v2/CHANGELOG.md)

Storybook and Examples:

  • Added a new Storybook stories file demonstrating all features and variants of BpkCardV2, including basic usage, split layouts, surface color variants, outlined variant, complex product cards, and grid layouts. (examples/bpk-component-card-v2/stories.tsx)

Remember to include the following changes:

  • Ensure the PR title includes the name of the component you are changing so it's clear in the release notes for consumers of the changes in the version e.g [Clover-123][BpkButton] Updating the colour
  • README.md (If you have created a new component)
  • Component README.md
  • Tests
  • Accessibility tests
    • The following checks were performed:
      • Ability to navigate using a keyboard only
      • Zoom functionality (Deque University explanation):
        • The page SHOULD be functional AND readable when only the text is magnified to 200% of its initial size
        • Pages must reflow as zoom increases up to 400% so that content continues to be presented in only one column i.e. Content MUST NOT require scrolling in two directions (both vertically and horizontally)
      • Ability to navigate using a screen reader only
  • Storybook examples created/updated
  • For breaking changes or deprecating components/properties, migration guides added to the description of the PR. If the guide has large changes, consider creating a new Markdown page inside the component's docs folder and link it here

Add comprehensive specification, planning, and task documents for
BpkCardV2 component implementation. Includes feature specifications,
architectural planning, implementation tasks, and design token mapping.

- spec.md: Feature specifications with user stories and requirements
- plan.md: Implementation architecture and design decisions
- tasks.md: Task breakdown with dependencies
- requirements.md: Checklist of all requirements

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Define TypeScript types for BpkCardV2 component and all subcomponents.
Includes surface color variants, visual variants, and prop interfaces.

Types:
- BpkCardV2Props: Root component props
- BpkCardV2SurfaceColor: 8 surface color variants
- BpkCardV2Variant: Visual variants (default, outlined)
- Subcomponent prop types: Header, Body, Primary, Secondary, Footer

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Implement root BpkCardV2 component with forwardRef support, variant
and surface color props, and attached subcomponents pattern.

Features:
- forwardRef for DOM element access
- Variant support (default/outlined)
- Surface color via data attribute for CSS selector support
- ARIA label and labelledBy support
- Attached subcomponents (Header, Body, Primary, Secondary, Footer)

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
… Footer)

Implement composable subcomponents for BpkCardV2:
- Header: Semantic <header> element for card title
- Body: Main content area with split layout support
- Primary: Primary content in split layout (configurable width)
- Secondary: Secondary content in split layout
- Footer: Semantic <footer> element

Body component handles:
- Simple single-column layout
- Split layout with configurable ratio (default 70/30)
- Responsive mobile-first behavior
- Divider insertion between Primary/Secondary

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Implement comprehensive CSS Modules styling for BpkCardV2:
- Base card styles with flexbox container and border-radius
- 8 surface color variants using Backpack design tokens
- Visual variants: default (shadow) and outlined (border)
- Split layout responsive behavior (mobile stacked, desktop side-by-side)
- Divider styling between Primary and Secondary sections
- RTL support with logical properties
- Mobile-first design with 768px breakpoint

Uses:
- Backpack mixins: radii, shadows
- Backpack tokens for colors, borders, spacing
- CSS custom properties for dynamic split ratios

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Implement complete test coverage for BpkCardV2 component:
- BpkCardV2-test.tsx: 50+ unit tests covering props, rendering, variants
- accessibility-test.tsx: Jest-axe tests for WCAG 2.1 Level AA compliance
- snapshot-test.tsx: 8 snapshot tests for visual regression detection
- integration-test.tsx: 40+ tests for interactive content, edge cases, nesting

Coverage includes:
- All prop combinations (variants, colors, split ratios)
- Split layout functionality and responsive behavior
- ARIA attributes and accessibility compliance
- Keyboard navigation and focus management
- Interactive elements and form support
- Dynamic content updates and edge cases

Test count: 150+
Coverage target: 80%+

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Create 9 comprehensive Storybook stories for BpkCardV2 component:
- BasicCard: Header, Body, Footer composition
- SplitLayout: 70/30 responsive layout
- OutlinedVariant: Border-based styling
- ElevatedSurface: Elevated background color
- SurfaceColorVariants: Gallery of all 8 surface colors
- ComplexProductCard: Real-world product layout example
- MinimalCard: Body-only usage pattern
- CustomSplitRatio: Non-default split ratio (40/60)
- CardGrid: Multiple cards with different variants

Each story includes:
- Working examples with interactive controls
- Argtype definitions for props
- Documentation and use case context

Stories enable:
- Visual testing and design review
- Developer documentation
- Component exploration and learning

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Create user-facing documentation:
- README.md: Installation, usage examples, props documentation, browser support, accessibility notes, related components
- CHANGELOG.md: Version history, features, technical details, browser support, migration information

Documentation covers:
- Installation and import
- Basic card with sections
- Split layout examples
- Surface color usage
- Props reference for root and subcomponents
- Browser support matrix
- Accessibility compliance
- Related components
- Figma design link

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
- Add missing type="button" attribute to button in Storybook story
- Auto-format TypeScript/JavaScript files via eslint --fix
- Update import ordering and spacing per linter rules

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Fix double padding issue where Body had padding AND Primary/Secondary
had padding when using split layout. Now:
- Single-column layout: Body has padding
- Split layout: Body has no padding, only Primary/Secondary have padding

This ensures proper spacing without duplication in split layouts.

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

@gert-janvercauteren Gert-Jan Vercauteren (gert-janvercauteren) marked this pull request as ready for review January 28, 2026 06:46
Copilot AI review requested due to automatic review settings January 28, 2026 06:46
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 the new BpkCardV2 component to the Backpack design system, providing a modern, composable, and accessible card solution with extensive documentation, theming support, and layout flexibility.

Changes:

  • Added BpkCardV2 component with explicit subcomponents (Header, Body, Primary, Secondary, Footer) supporting split layouts, 8 surface color variants, and two visual styles (shadow/outlined)
  • Implemented comprehensive testing suite including unit tests, accessibility tests, integration tests, and snapshot tests
  • Created full documentation with README, CHANGELOG, Storybook stories, and specification files

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
specs/001-composable-card/*.md Component specification, implementation plan, and task breakdown documents
packages/bpk-component-card-v2/src/BpkCardV2/BpkCardV2.tsx Root component with subcomponent composition and refs support
packages/bpk-component-card-v2/src/BpkCardV2/subcomponents/*.tsx Header, Body, Footer, Primary, Secondary subcomponents
packages/bpk-component-card-v2/src/BpkCardV2/BpkCardV2.module.scss Responsive styles with BEM naming and design tokens
packages/bpk-component-card-v2/src/BpkCardV2/common-types.ts TypeScript type definitions for component props
packages/bpk-component-card-v2/src/BpkCardV2/tests/*.tsx Comprehensive test suite (unit, accessibility, integration, snapshot)
packages/bpk-component-card-v2/README.md Component documentation with usage examples
packages/bpk-component-card-v2/CHANGELOG.md Initial release changelog
examples/bpk-component-card-v2/stories.tsx Storybook stories demonstrating all features

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

@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

- Add ForwardRefExoticComponent type definition for compound component pattern
- Wrap all subcomponents (Header, Body, Primary, Secondary, Footer) with forwardRef
- Create BpkCardV2Component type that properly types the attached subcomponents
- Make children prop optional for subcomponents to support empty sections
- Remove unsupported 'padding' prop from story example
- Export BpkCardV2Component type for external use

This resolves all TS2339 "Property does not exist" errors while maintaining
the compound component API pattern used by BpkCardV2.

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

Resolves all 42 failing tests by using the cssModules utility pattern
established in existing Backpack components. This ensures SCSS class names
are properly available in both test and production environments.

Changes:
- Import cssModules utility from bpk-react-utils in all component files
- Replace direct SCSS bracket notation with getClassName() calls
- Fixes querySelector failures when looking for elements by class name
- Maintains production styling while enabling proper test selectors
- Update test selector to avoid matching subcomponent classes
- Fix import ordering to follow Backpack conventions

Test Results:
✅ Test Suites: 334 passed, 1 skipped
✅ Tests: 1711 passed, 3 skipped, 1714 total
✅ Snapshots: 816 passed
✅ Linting: 0 errors

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

@skyscanner-backpack-bot
Copy link

skyscanner-backpack-bot bot commented Jan 30, 2026

Browser support

If this is a visual change, make sure you've tested it in multiple browsers.

Generated by 🚫 dangerJS against 2b7b48e

@gert-janvercauteren
Copy link
Contributor Author

Copilot open a new pull request to apply changes based on the comments in this thread

Copy link
Contributor

Copilot AI commented Jan 30, 2026

Gert-Jan Vercauteren (@gert-janvercauteren) I've opened a new pull request, #4191, to work on those changes. Once the pull request is ready, I'll request review from you.

…consistency (#4191)

* Initial plan

* fix: Change spelling from 'colour' to 'color' for US English consistency

Co-authored-by: gert-janvercauteren <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: gert-janvercauteren <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

Fixed two layout issues with the split card layout:
1. Changed breakpoint from bpk-breakpoint-small-tablet (max-width) to
   bpk-breakpoint-above-mobile (min-width) so split layout applies on
   desktop/tablet instead of mobile
2. Added 8px margin (MD token) to divider for proper spacing on mobile

Changes:
- Body split layout now uses flex-direction: row on tablet+ (min-width: 32.0625rem)
- Primary component border-right applied on tablet+ instead of mobile
- Divider margins: 0.5rem (8px) top/bottom using Backpack MD token
- Secondary width calculation now applies on tablet+
- All media queries now correctly target larger screens

All tests passing: 1711 tests, 816 snapshots

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

Implement bpk-spacing-md() top and bottom spacing around the divider
in split layout to match Figma design. Uses ::after pseudo-element
for positioned divider with precise inset margins.

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Updated ComplexProductCard story to showcase a realistic hotel booking
card using BpkImage, BpkRating, BpkBadge, BpkButton, and BpkText
components. Includes split layout with hotel info and booking details,
price display, amenities, location, availability, and wishlist action.
Extracted to HotelProductCard component to comply with React hooks rules.

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

Redesigned the ComplexProductCard story to showcase a realistic travel
deal with split layout matching the Figma design (node-id=405-2109):
- Primary (65%): Product showcase with image, ratings, amenities
- Secondary (35%): Booking details, pricing, and call-to-action buttons
- Footer: Limited-time offers and availability badges

Uses Backpack components:
- BpkImage (16:9 aspect ratio)
- BpkRating with review count
- BpkBadge (multiple variants)
- BpkButton with state management
- BpkText with semantic text styles
- BpkCardV2 with Header, Body (split), and Footer

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Replaced ComplexProductCard with a new implementation that directly
implements the Figma design at node-id=405-2109. Features:

Split layout (70/30):
- Primary: Hero image, product title, rating, description, location, amenities
- Secondary: Pricing, guest info, dates, offers, action buttons with wishlist
- Footer: Limited availability badge

Backpack components used:
- BpkCardV2 with split layout and footer
- BpkImage (16:9 aspect)
- BpkRating with review count
- BpkBadge (multiple variants)
- BpkButton with state management
- BpkText with semantic text styles

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
Redesigned ComplexProductCard to match the screenshot of a realistic
hotel booking card (Hotel Aiguaclara). Features:

Primary section (60%):
- Hotel image (4:3 aspect)
- Hotel name and classification
- Star rating with review count
- Amenities with checkmarks (ATOL, baggage, payments, transfers)
- Flight times with airline badges (Jet2)
- Price options (Cheapest, Half board)

Secondary section (40%):
- Package type label
- Original and discounted prices
- Per-person pricing with total
- Provider badge (Love Holidays)
- Call-to-action button
- More deals link

Uses Backpack components:
- BpkCardV2 with split layout (60/30)
- BpkImage (4:3 aspect ratio)
- BpkRating with review count
- BpkBadge for airlines and providers
- BpkButton for CTA
- BpkText with semantic text styles

Co-Authored-By: Claude (Opus 4.5) <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

The BpkRating component requires `value` and `ariaLabel` props, not
`rating` and `ratedCount`. Also use built-in `title` and `subtitle`
props instead of separate text elements.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

Convert BpkCardV2 from a callable component with attached subcomponents
to a pure namespace object with BpkCardV2.Root as the root element.

This matches the Ark-UI component architecture pattern where:
- BpkCardV2 is now a namespace containing all subcomponents
- BpkCardV2.Root replaces direct BpkCardV2 usage as the root wrapper
- All subcomponents (Header, Body, Primary, Secondary, Footer) remain
  accessible via the namespace

BREAKING CHANGE: <BpkCardV2> must now be written as <BpkCardV2.Root>

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

Add a new visual variant that removes the box-shadow without adding
a border. Useful for nested cards or cards on colored backgrounds
where elevation is not desired.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

Add flexible padding configuration to card subcomponents:
- Single size: padding="lg"
- Vertical/horizontal: padding={{ vertical: 'sm', horizontal: 'lg' }}
- Individual sides (RTL-aware): padding={{ top: 'lg', start: 'md' }}

Supports all BpkSpacing tokens: none, sm, md, base, lg, xl, xxl, xxxl, xxxxl

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

- Update spec.md with namespace pattern (BpkCardV2.Root, .Header, etc.)
- Add noElevation variant and padding prop documentation
- Update acceptance scenarios for actual implementation behavior
- Mark tasks.md phases as complete with implementation notes
- Update plan.md with actual file structure and type definitions
- Update requirements checklist with implementation decisions

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

… and Footer

Using semantic <header> and <footer> elements in a reusable card component
could cause accessibility issues when cards are nested or used multiple
times on a page. Changed to <div> elements to avoid unintended landmark
pollution.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Moved test files from __tests__ subdirectory to sit alongside component
code, matching the pattern used by other Backpack components.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Updated usage examples to use BpkCardV2.Root namespace pattern
- Added noElevation variant to props documentation
- Added padding prop documentation for Header, Body, and Footer
- Added padding types reference section
- Added surface color tokens reference
- Added Primary and Secondary subcomponent props
- Updated accessibility section (removed semantic element references)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
BpkCardV2 components should not allow custom className or style props
to enforce consistent styling through the design system.

Removed className prop from:
- BpkCardV2.Root
- BpkCardV2.Header
- BpkCardV2.Body
- BpkCardV2.Footer
- BpkCardV2.Primary
- BpkCardV2.Secondary

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

Remove orphaned className argType that referenced a prop removed in
e0802c4. Add BpkPrice component to ComplexProductCard example.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4161 to see this build running in a browser.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants