Skip to content

refactor(bpk-component-layout): migrate from Chakra UI to inline styles#4224

Open
Gert-Jan Vercauteren (gert-janvercauteren) wants to merge 26 commits intomainfrom
bpk-layout-panda-css
Open

refactor(bpk-component-layout): migrate from Chakra UI to inline styles#4224
Gert-Jan Vercauteren (gert-janvercauteren) wants to merge 26 commits intomainfrom
bpk-layout-panda-css

Conversation

@gert-janvercauteren

Summary

  • Remove Chakra UI dependency from bpk-component-layout and replace with validated inline styles that enforce Backpack design tokens
  • Components (BpkBox, BpkFlex, BpkGrid, BpkGridItem, BpkStack/HStack/VStack) now convert spacing tokens to rem values, validate size/position props, and strip disallowed className/style props with dev warnings
  • Set up Panda CSS infrastructure (config, PostCSS, Storybook webpack integration) for future CSS-based responsive breakpoint support

Test plan

  • All 61 unit tests pass
  • TypeScript compiles cleanly
  • Storybook renders all layout examples correctly
  • Manual verification of all Storybook stories (Box, Flex, Grid, Stack)
  • Verify no regressions in downstream consumers

🤖 Generated with Claude Code

Faye (Faye-Xiao) and others added 26 commits December 2, 2025 19:04
…irectory and add BpkProvider,BpkBox (#4067)

* feat(layout): add BpkProvider/BpkBox, tokens, tests and examples

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* add BpkStack

* add BpkStack-test and change Stories

* change bpkStack test

* add flex props

* add semicolumn and add more descriptions to Stack examples

* change lint and main.ts

* add accessibility test for stack
* add Grid and Flex

* update

* add GridItem

* responsive

* fix test issue

* add Grid responsive example

* responsive

* split story book

* wrap props responsive

* add basis type

---------

Co-authored-by: Faye <faye.xiao@skyscanner.net>
…dy up storybook examples (#4085)

* fix(layout): align breakpoints and remove large-desktop

- Restrict public breakpoints to 5 foundations tiers

- Align token->Chakra breakpoint mapping with theme

- Update README and tests; fix Grid test typo

* chore(storybook): regroup layout stories by component

- Use a single 'bpk-component-layout' sidebar node

- Add dedicated examples for Flex/Grid/Stack components

* chore(storybook): group layout stories by component

- Keep Provider example at bpk-component-layout root

- Move Box/Flex/Grid/Stack examples into dedicated story groups

- Add tabbed docs content on root layout page

* chore(storybook): split layout examples by component

- Make Box examples independent (no Stack in Box examples file)

- Reuse flex-examples/grid-examples/stack-examples directly

- Remove duplicate default exports from stories

* chore(storybook): move layout visual tests to root

- Put VisualTest and VisualTestWithZoom under bpk-component-layout

- Use default Storybook docs rendering for root

- Remove visual test exports from Box story

* feat(layout): add responsive support for Box layout props

- Allow Backpack breakpoint objects for BpkBox flex/grid/display props

- Keep spacing token processing unchanged

- Document component roles and responsive support

* refactor(layout): centralize responsive prop allowlists

- Add component-scoped allowlists in tokenUtils

- Introduce processBpkComponentProps to avoid duplicate breakpoint mapping

- Simplify Box/Flex/Grid/Stack prop processing

* fix(layout): align breakpoints to Backpack ranges

- Use min-width lower-bounds for Chakra breakpoints

- Clarify mobile-first semantics in README

- Update ResponsiveExample to include base defaults

* fix(layout): prevent unprocessed responsive props from leaking

- Drop allowlisted layout props from processed props before merging

- Add test to ensure Chakra array responsive values are rejected

* refactor(layout): group responsive allowlists by role

- Organize allowlisted responsive props into container vs item groups per component

- Preserve existing allowlist behavior

* chore(storybook): clarify layout example boundaries

- Add framed wrapper and item outlines for examples

- Improve Stack item visibility without using layout border props

* fix(layout): satisfy lint for tokenUtils

- Fix import order/grouping

- Add JSDoc for processBpkComponentProps

* refactor(layout): consolidate Stack types and utils

- Merge BpkStack types into types.ts

- Inline Stack prop processing and remove redundant tokenUtils file
…4060)

* Bump @skyscanner/stylelint-config-skyscanner from 13.1.0 to 14.2.0

Bumps [@skyscanner/stylelint-config-skyscanner](https://github.com/Skyscanner/stylelint-config-skyscanner) from 13.1.0 to 14.2.0.
- [Release notes](https://github.com/Skyscanner/stylelint-config-skyscanner/releases)
- [Changelog](https://github.com/Skyscanner/stylelint-config-skyscanner/blob/main/CHANGELOG.md)
- [Commits](Skyscanner/stylelint-config-skyscanner@13.1.0...14.2.0)

---
updated-dependencies:
- dependency-name: "@skyscanner/stylelint-config-skyscanner"
  dependency-version: 14.2.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix check error

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Kerrie Wu <kerrie.wu@skyscanner.net>
* Bump the storybook group across 1 directory with 5 updates

Bumps the storybook group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-a11y](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/a11y) | `9.1.13` | `10.1.2` |
| [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/docs) | `9.1.13` | `10.1.2` |
| [@storybook/addon-webpack5-compiler-babel](https://github.com/storybookjs/addon-webpack5-compiler-babel) | `3.0.6` | `4.0.0` |
| [@storybook/react-webpack5](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/react-webpack5) | `9.1.13` | `10.1.2` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/core) | `9.1.13` | `10.1.2` |



Updates `@storybook/addon-a11y` from 9.1.13 to 10.1.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.1.2/code/addons/a11y)

Updates `@storybook/addon-docs` from 9.1.13 to 10.1.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.1.2/code/addons/docs)

Updates `@storybook/addon-webpack5-compiler-babel` from 3.0.6 to 4.0.0
- [Release notes](https://github.com/storybookjs/addon-webpack5-compiler-babel/releases)
- [Changelog](https://github.com/storybookjs/addon-webpack5-compiler-babel/blob/main/CHANGELOG.md)
- [Commits](storybookjs/addon-webpack5-compiler-babel@v3.0.6...v4.0.0)

Updates `@storybook/react-webpack5` from 9.1.13 to 10.1.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.1.2/code/frameworks/react-webpack5)

Updates `storybook` from 9.1.13 to 10.1.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.1.2/code/core)

---
updated-dependencies:
- dependency-name: "@storybook/addon-a11y"
  dependency-version: 10.1.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: storybook
- dependency-name: "@storybook/addon-docs"
  dependency-version: 10.1.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: storybook
- dependency-name: "@storybook/addon-webpack5-compiler-babel"
  dependency-version: 4.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: storybook
- dependency-name: "@storybook/react-webpack5"
  dependency-version: 10.1.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: storybook
- dependency-name: storybook
  dependency-version: 10.1.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix storybook update issue

* fix conflict and issue

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: kerrie-wu <52308828+kerrie-wu@users.noreply.github.com>
Co-authored-by: Kerrie Wu <kerrie.wu@skyscanner.net>
* Bump jws from 3.2.2 to 3.2.3

Bumps [jws](https://github.com/brianloveswords/node-jws) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/brianloveswords/node-jws/releases)
- [Changelog](https://github.com/auth0/node-jws/blob/master/CHANGELOG.md)
- [Commits](auth0/node-jws@v3.2.2...v3.2.3)

---
updated-dependencies:
- dependency-name: jws
  dependency-version: 3.2.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* update package-lock.json

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: gc.zhu <gc.zhu@skyscanner.net>
…#4076)

* [CLOV-907][BpkButton] Update BpkButton link and linkOnDark type style

* add implicit to BpkPaginationNudger and BpkFloatingNotification and ExpandAccessoryContent

* adjust linkOnDark hover color

* add Links example

* update link on dark hover style

* remove full props in README

* update BpkPaginationNudger to iconOnly

* remove bpk-buttob-link-disabled

* button link aligned

* support inline display svg

* add button-link-type README

* rename bpk-button--link-icon-only-aligned

* rename bpk-button--link-icon-only
…to BpkButtonV2 (#4078)

* remove BpkButton code and alias BpkButton to BpkButtonV2

* refine themeAttributes file structure

* update readme

* correct file format

* udpate readme

* update readme

---------

Co-authored-by: Ezreal Yang <supremeyh@126.com>
Bumps [lint-staged](https://github.com/lint-staged/lint-staged) from 16.1.5 to 16.2.7.
- [Release notes](https://github.com/lint-staged/lint-staged/releases)
- [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md)
- [Commits](lint-staged/lint-staged@v16.1.5...v16.2.7)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-version: 16.2.7
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: IrinaWei <irina.wei@skyscanner.net>
Bumps [glob](https://github.com/isaacs/node-glob) from 11.1.0 to 13.0.0.
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](isaacs/node-glob@v11.1.0...v13.0.0)

---
updated-dependencies:
- dependency-name: glob
  dependency-version: 13.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: IrinaWei <irina.wei@skyscanner.net>
* Initial plan

* Initial exploration

Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>

* Migrate BpkLink component to TypeScript

Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>

* Add missing semicolon in examples.tsx

Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>

* Remove unused @ts-expect-error directives for bpk-component-link imports

Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>

* Remove duplicate JS files

Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>

* Update packages/bpk-component-link/src/BpkLink.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update examples/bpk-component-link/examples.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/bpk-component-link/src/BpkLink.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix TypeScript errors: convert null to undefined for href and rel attributes

Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>

* Make href prop required in BpkLink to match original Flow type and ensure accessibility

Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>

* Extend AnchorHTMLAttributes instead of using index signature for better Storybook docgen support

Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>

* Extend ButtonHTMLAttributes for BpkButtonLink to match BpkLink pattern and improve Storybook docgen

Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>

* omit props

* address rel

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: gert-janvercauteren <728889+gert-janvercauteren@users.noreply.github.com>
Co-authored-by: Gert-Jan Vercauteren <gert-jan.vercauteren@skyscanner.net>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ezreal Yang <supremeyh@126.com>
Co-authored-by: Flora Cheng <flora.cheng@skyscanner.net>
* feat: added variant size medium to bpkPrice

* fix: fixed spacing issues picked up in PR

* chore: run tests

---------

Co-authored-by: Gert-Jan Vercauteren <gert-jan.vercauteren@skyscanner.net>
* [NO JIRA][BpkVessel] Add BpkVessel to Bpk layout

* Update packages/bpk-component-layout/src/BpkVessel-test.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* update README.md

* add storybook  examples

* refactor with only allow className and style

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* [NO JIRA] Extend props to BpkVessel

* update examples

* remove redudant data-*
…es with token enforcement

Remove Chakra UI dependency and replace with a lightweight inline-style approach
that enforces Backpack design tokens. Components (BpkBox, BpkFlex, BpkGrid,
BpkGridItem, BpkStack) now use validated inline styles with spacing token
conversion, size/position validation, and runtime guards against className/style
prop misuse. Panda CSS infrastructure is set up for future CSS-based responsive
breakpoint support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 11, 2026 08:10
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

Refactors bpk-component-layout to remove Chakra UI usage, replacing it with inline-style layout primitives that enforce Backpack token constraints, while also introducing Panda CSS scaffolding for future responsive styling.

Changes:

  • Added token types + runtime validation/conversion utilities for spacing/size/position + responsive values.
  • Re-implemented layout primitives (BpkBox, BpkFlex, BpkGrid, BpkGridItem, BpkStack/HStack/VStack) using processed inline styles and stripped className/style props (dev warnings).
  • Added Panda CSS + PostCSS + Storybook wiring (including styled-system output integration).

Reviewed changes

Copilot reviewed 44 out of 48 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
postcss.config.cjs Adds Panda CSS PostCSS pipeline support.
panda.config.ts Defines Panda tokens/conditions and output directory for generated CSS.
packages/bpk-component-layout/src/types.ts Introduces new public prop types for layout primitives and token-based values.
packages/bpk-component-layout/src/tokens.ts Adds Backpack spacing/breakpoint tokens and runtime validators.
packages/bpk-component-layout/src/tokenUtils.ts Adds core prop filtering + token conversion + responsive flattening for inline styles.
packages/bpk-component-layout/src/tokenUtils-test.ts Adds unit tests for token conversion/filtering/responsive flattening behavior.
packages/bpk-component-layout/src/theme.ts Adds temporary spacing token mapping used by token conversion.
packages/bpk-component-layout/src/commonProps.ts Defines shared “layout-only” prop surface and excludes className/style/visual props.
packages/bpk-component-layout/src/accessibility-test.tsx Adds baseline a11y assertions for new primitives via jest-axe.
packages/bpk-component-layout/src/BpkVessel.tsx Adds migration-hatch component that forwards all HTML attributes including className/style.
packages/bpk-component-layout/src/BpkVessel-test.tsx Adds coverage for BpkVessel prop forwarding.
packages/bpk-component-layout/src/BpkStack.tsx Implements Stack primitives using processed inline styles and responsive flattening.
packages/bpk-component-layout/src/BpkStack.constant.ts Defines allowlisted responsive prop keys for Stack processing.
packages/bpk-component-layout/src/BpkStack-test.tsx Adds tests for Stack rendering and filtering forbidden props.
packages/bpk-component-layout/src/BpkProvider.tsx Adds provider wrapper (currently passthrough) to match new layout API.
packages/bpk-component-layout/src/BpkProvider-test.tsx Adds tests for provider rendering behavior.
packages/bpk-component-layout/src/BpkGridItem.tsx Implements GridItem using processed spacing props + grid placement props w/ inline styles.
packages/bpk-component-layout/src/BpkGridItem-test.tsx Adds GridItem rendering and basic prop acceptance tests.
packages/bpk-component-layout/src/BpkGrid.tsx Implements Grid using processed inline styles for grid-related props.
packages/bpk-component-layout/src/BpkGrid-test.tsx Adds Grid rendering/basic prop acceptance tests.
packages/bpk-component-layout/src/BpkFlex.tsx Implements Flex using processed inline styles for flex-related props.
packages/bpk-component-layout/src/BpkFlex-test.tsx Adds Flex rendering/basic prop acceptance tests.
packages/bpk-component-layout/src/BpkBox.tsx Implements Box using processed inline styles + HTML prop passthrough.
packages/bpk-component-layout/src/BpkBox-test.tsx Adds Box rendering + interaction + forbidden className filtering tests.
packages/bpk-component-layout/index.ts Exposes new primitives, types, and token utilities from package entrypoint.
packages/bpk-component-layout/README.md Documents new layout primitives, tokens, constraints, and responsive API.
package.json Adds Panda deps, styled-system jest mapping, and runs panda codegen in prepare.
examples/bpk-component-layout/vessel.stories.tsx Adds Storybook story for BpkVessel.
examples/bpk-component-layout/vessel-examples.tsx Adds example usage for migration hatch support.
examples/bpk-component-layout/stories.tsx Updates examples index to include new primitives + vessel showcase.
examples/bpk-component-layout/stack.stories.tsx Adds Stack stories/docs wiring.
examples/bpk-component-layout/stack-examples.tsx Adds Stack examples including responsive token usage.
examples/bpk-component-layout/layout-wrapper.tsx Wraps examples with provider and basic frame styling.
examples/bpk-component-layout/grid.stories.tsx Adds Grid stories/docs wiring.
examples/bpk-component-layout/grid-examples.tsx Adds Grid examples including responsive usage.
examples/bpk-component-layout/flex.stories.tsx Adds Flex stories/docs wiring.
examples/bpk-component-layout/flex-examples.tsx Adds Flex examples including responsive usage.
examples/bpk-component-layout/examples.module.scss Adds non-primitive visual outlines/frames for Storybook examples.
examples/bpk-component-layout/box.stories.tsx Adds Box stories/docs wiring.
examples/bpk-component-layout/box-examples.tsx Adds Box examples including spacing/size/position/responsive.
.storybook/webpack.config.js Ensures Panda generated CSS is loaded and avoids loader conflicts.
.storybook/preview.tsx Imports generated styled-system/styles.css into Storybook preview.
.storybook/main.ts Expands story glob to include *.stories.* convention.
.github/workflows/release.yml Fixes release workflow checkout ref to use the release tag.
Files not reviewed (1)
  • packages/package-lock.json: Language not supported

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

Comment on lines +61 to +76
export interface BpkBoxProps extends BpkCommonLayoutProps, BpkFlexGridProps {
children?: ReactNode;
position?: BpkResponsiveValue<CSSProperties['position']>;
onClick?: MouseEventHandler<HTMLDivElement>;
onFocus?: FocusEventHandler<HTMLDivElement>;
onBlur?: FocusEventHandler<HTMLDivElement>;
role?: string;
tabIndex?: number;
'aria-label'?: string;
'aria-labelledby'?: string;
'aria-describedby'?: string;
'aria-hidden'?: boolean | 'true' | 'false';
'aria-live'?: 'off' | 'polite' | 'assertive';
id?: string;
fontWeight?: string;
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

position and fontWeight are defined as BpkBoxProps, but they are not included in processBpkComponentProps’ style routing (and position isn’t in the Box responsive allowlist either). As a result, these props will be forwarded as invalid DOM attributes (e.g. <div position="relative" fontWeight="bold">) instead of being applied to style. Add position and fontWeight to the style key set (and include position in the Box allowlist if you want responsive flattening for it), or remove them from the public API if they’re intentionally unsupported.

Copilot uses AI. Check for mistakes.
'marginStart', 'marginEnd', 'marginInline',
'gap', 'spacing', 'rowGap', 'columnGap',
'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',
'top', 'right', 'bottom', 'left',
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

styleKeys doesn’t include position or fontWeight, so those props end up in htmlProps and get spread onto the DOM element as invalid HTML attributes. Include position and fontWeight in styleKeys (and consider validating/flattening position via the responsive pipeline if it’s meant to be responsive).

Suggested change
'top', 'right', 'bottom', 'left',
'top', 'right', 'bottom', 'left',
'position', 'fontWeight',

Copilot uses AI. Check for mistakes.
Comment on lines +73 to +76
| 'full'
| 'fit-content';

/**
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

BpkSizeValue allows 'full', but the runtime processing path (processSpacingProps) currently leaves size values “as-is” for size props, meaning the generated inline style may become width: "full", which is invalid CSS. Convert 'full' to '100%' during processing (e.g., in the size converter used by processSpacingProps) so valid inputs always produce valid CSS.

Suggested change
| 'full'
| 'fit-content';
/**
| 'fit-content';
/**
/**

Copilot uses AI. Check for mistakes.
/^-?\d+(\.\d+)?rem$/.test(value) || // rem values
isPercentage(value) || // percentage values
value === 'auto' ||
value === 'full' ||
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

BpkSizeValue allows 'full', but the runtime processing path (processSpacingProps) currently leaves size values “as-is” for size props, meaning the generated inline style may become width: "full", which is invalid CSS. Convert 'full' to '100%' during processing (e.g., in the size converter used by processSpacingProps) so valid inputs always produce valid CSS.

Suggested change
value === 'full' ||

Copilot uses AI. Check for mistakes.
Comment on lines +193 to +196
// If no base value, try the smallest breakpoint
const fallbackKey = Object.keys(value)[0];
if (fallbackKey !== undefined) {
return processResponsiveValue(value[fallbackKey], converter, validator, propName);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The “smallest breakpoint” fallback is currently Object.keys(value)[0], which depends on the caller’s object literal insertion order rather than an explicit breakpoint priority. Since you already have a canonical breakpoint set (BpkBreakpoint), consider selecting the fallback in a deterministic order (e.g. base, then small-mobile, mobile, small-tablet, tablet, desktop) so the behavior is stable and matches the documented “mobile-first” intent.

Suggested change
// If no base value, try the smallest breakpoint
const fallbackKey = Object.keys(value)[0];
if (fallbackKey !== undefined) {
return processResponsiveValue(value[fallbackKey], converter, validator, propName);
// If no base value, try the smallest breakpoint in a deterministic order
const breakpointPriority = [
'small-mobile',
'mobile',
'small-tablet',
'tablet',
'desktop',
] as const;
const prioritizedKey =
breakpointPriority.find((breakpoint) =>
Object.prototype.hasOwnProperty.call(value, breakpoint),
) ?? Object.keys(value)[0];
if (prioritizedKey !== undefined) {
return processResponsiveValue(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(value as any)[prioritizedKey],
converter,
validator,
propName,
);

Copilot uses AI. Check for mistakes.
- `BpkStack` / `BpkHStack` / `BpkVStack` – stack layout primitives with tokenised gaps.
- Typed layout tokens – spacing and size.

Under the hood, this package is implemented as a **facade over a layout system** and generates **CSS at runtime**, but the public API is Backpack‑flavoured and token‑driven. Consumers should only interact with the Backpack components and tokens described here, not with the underlying system.
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The README still describes Chakra breakpoint mapping and “generates CSS at runtime”, but this PR migrates away from Chakra and (per processResponsiveValue) currently flattens responsive objects down to a single inline style value (no media queries). Update this section to reflect the current behavior and roadmap (inline-only now; Panda-generated CSS/media queries later) to avoid misleading consumers.

Suggested change
Under the hood, this package is implemented as a **facade over a layout system** and generates **CSS at runtime**, but the public API is Backpack‑flavoured and token‑driven. Consumers should only interact with the Backpack components and tokens described here, not with the underlying system.
Under the hood, this package currently applies layout via **inline styles**. Responsive objects are flattened down to a single value (no media queries yet), but the public API is Backpack‑flavoured and token‑driven. In a future iteration, this API will be backed by Panda‑generated CSS (including media queries) rather than inline styles. Consumers should only interact with the Backpack components and tokens described here, not with the underlying implementation.

Copilot uses AI. Check for mistakes.
/>
```

Under the hood these keys are mapped to Chakra’s breakpoint keys (`base`, `sm`, `md`, `lg`, `xl`, `2xl`) before generating CSS.
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The README still describes Chakra breakpoint mapping and “generates CSS at runtime”, but this PR migrates away from Chakra and (per processResponsiveValue) currently flattens responsive objects down to a single inline style value (no media queries). Update this section to reflect the current behavior and roadmap (inline-only now; Panda-generated CSS/media queries later) to avoid misleading consumers.

Copilot uses AI. Check for mistakes.
import { BpkBox } from './BpkBox';
import { BpkSpacing } from './tokens';

describe('BpkBox', () => {
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

There are tests covering className filtering and event handlers, but no tests that assert position and fontWeight are applied via inline styles (and not forwarded as DOM attributes). Once position/fontWeight handling is fixed, add a test here to validate the rendered style contains the expected values and that the corresponding attributes are not present on the DOM node.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Non breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants