Skip to content

[NO-JIRA][BpkLayout] Expand layout component API with opacity, as, dir, and Stack aliases#4505

Open
Faye (Faye-Xiao) wants to merge 13 commits into
mainfrom
layout-expand-unsupported-props
Open

[NO-JIRA][BpkLayout] Expand layout component API with opacity, as, dir, and Stack aliases#4505
Faye (Faye-Xiao) wants to merge 13 commits into
mainfrom
layout-expand-unsupported-props

Conversation

@Faye-Xiao
Copy link
Copy Markdown
Contributor

@Faye-Xiao Faye (Faye-Xiao) commented May 20, 2026

Summary

During Backpack adoption in [carhire-homepage], an audit of layout component usage revealed props that were silently passing through Chakra but were not formally declared in the Backpack layout API. This PR adds official support for those props.

Changes

BpkCommonLayoutProps (all layout components):

  • opacity?: number — CSS opacity value (0–1), used for fade/disabled effects
  • as?: ElementType — polymorphic rendering, allows changing the underlying HTML element (e.g. as="section", as="nav")
  • dir?: 'ltr' | 'rtl' | 'auto' — text direction, for embedding bidirectional content within an LTR page

BpkStack / BpkHStack / BpkVStack:

  • alignItems — semantic alias for align (maps to CSS align-items)
  • justifyContent — semantic alias for justify (maps to CSS justify-content)
  • When both alias and canonical prop are provided, canonical (align/justify) takes precedence
  • Bug fix: alias props no longer override HStack/VStack built-in defaults when not provided

forwardRef type:

  • Widened from HTMLDivElement to HTMLElement on BpkBox, BpkFlex, BpkStack, BpkHStack, and BpkVStack — necessary now that the as prop allows rendering any HTML element

Motivation

Consumer feedback from carhire-homepage: alignItems/justifyContent are more semantically clear than align/justify (which can be confused with text-align). Supporting both forms reduces friction for teams migrating to Backpack layout primitives.


  • Tests
  • README.md (If you have created a new component)
  • Component README.md
  • 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

Faye (Faye-Xiao) and others added 4 commits May 20, 2026 15:40
Exposes `opacity` (CSS opacity value), `as` (polymorphic element type),
and `dir` (text direction for RTL/LTR) as first-class props on all
Backpack layout components, unblocking microsite adoption where these
props are in active use.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ariants

Exposes `alignItems` and `justifyContent` as semantic aliases for the
Chakra shorthands `align` and `justify` on BpkStack, BpkHStack, and
BpkVStack. When both forms are provided, `align`/`justify` take
precedence. Explicit aliases have been in active use in carhire-homepage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hen not provided

Only spread resolved align/justify into processedProps when they have
a value. Previously, passing align: undefined explicitly overrode
HStack's built-in align="center" default, breaking the default layout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…kBox

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Faye-Xiao Faye (Faye-Xiao) force-pushed the layout-expand-unsupported-props branch from c129a46 to 14f11fa Compare May 20, 2026 07:40
@skyscanner-backpack-bot
Copy link
Copy Markdown

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

@skyscanner-backpack-bot
Copy link
Copy Markdown

skyscanner-backpack-bot Bot commented May 20, 2026

Warnings
⚠️

Package source files (e.g. packages/package-name/src/Component.js) were updated, but snapshots weren't. Have you checked that the tests still pass?

Browser support

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

Generated by 🚫 dangerJS against 898b4df

…ack aliases

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@skyscanner-backpack-bot
Copy link
Copy Markdown

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

…document level

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Faye-Xiao Faye (Faye-Xiao) marked this pull request as ready for review May 20, 2026 08:17
Copilot AI review requested due to automatic review settings May 20, 2026 08:17
@skyscanner-backpack-bot
Copy link
Copy Markdown

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

Copy link
Copy Markdown
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 expands Backpack’s layout component API to formally support previously pass-through Chakra props (as, opacity) and adds semantic aliases (alignItems, justifyContent) for Stack alignment props to ease adoption/migration.

Changes:

  • Adds as?: ElementType and opacity?: number to BpkCommonLayoutProps.
  • Adds alignItems/justifyContent aliases to BpkStack/BpkHStack/BpkVStack, with canonical align/justify taking precedence.
  • Updates Storybook stories and unit tests to demonstrate and validate the new props/aliases.

Reviewed changes

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

Show a summary per file
File Description
packages/backpack-web/src/bpk-component-layout/src/types.ts Extends BpkStack prop types with alignItems/justifyContent aliases.
packages/backpack-web/src/bpk-component-layout/src/commonProps.ts Adds as and opacity to common layout props.
packages/backpack-web/src/bpk-component-layout/src/BpkStack.tsx Resolves alias props into canonical Chakra Stack props before processing.
packages/backpack-web/src/bpk-component-layout/src/BpkStack.stories.tsx Adds Storybook example demonstrating Stack alias props.
packages/backpack-web/src/bpk-component-layout/src/BpkStack-test.tsx Adds tests for alias behavior and precedence.
packages/backpack-web/src/bpk-component-layout/src/BpkBox.stories.tsx Adds Storybook examples for opacity and polymorphic as.
packages/backpack-web/src/bpk-component-layout/src/BpkBox-test.tsx Adds tests covering opacity and as rendering.
Comments suppressed due to low confidence (2)

packages/backpack-web/src/bpk-component-layout/src/BpkStack.tsx:61

  • Same ref typing issue as BpkStack: BpkHStack supports as via common props, so forwardRef<HTMLDivElement, ...> can become incorrect when consumers render e.g. as="nav". Consider widening the ref element type or using polymorphic typing.
export const BpkHStack = forwardRef<HTMLDivElement, BpkStackProps>(({ align, alignItems, backgroundColor, children, color, justify, justifyContent, ...props }, ref) => {
  const resolvedAlign = align ?? alignItems;
  const resolvedJustify = justify ?? justifyContent;

packages/backpack-web/src/bpk-component-layout/src/BpkStack.tsx:86

  • Same ref typing issue as BpkStack: BpkVStack supports as via common props, so forwardRef<HTMLDivElement, ...> can become incorrect when consumers render a different element. Consider widening the ref element type or using polymorphic typing.
export const BpkVStack = forwardRef<HTMLDivElement, BpkStackProps>(({ align, alignItems, backgroundColor, children, color, justify, justifyContent, ...props }, ref) => {
  const resolvedAlign = align ?? alignItems;
  const resolvedJustify = justify ?? justifyContent;

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

Comment thread packages/backpack-web/src/bpk-component-layout/src/commonProps.ts
Comment thread packages/backpack-web/src/bpk-component-layout/src/BpkStack.tsx
Comment thread packages/backpack-web/src/bpk-component-layout/src/BpkBox-test.tsx
…pacity tests

- Widen ref type from HTMLDivElement to HTMLElement on BpkBox, BpkFlex,
  BpkStack, BpkHStack, BpkVStack — the `as` prop allows rendering any
  HTML element so HTMLDivElement was too narrow
- Replace opacity smoke tests with class-comparison assertions that
  verify the prop is actually forwarded to Chakra (different opacity
  values produce different rendered output)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Faye-Xiao Faye (Faye-Xiao) changed the title [NO-JIRA][BpkLayout] Expand layout component API with opacity, as, dir and Stack aliases [NO-JIRA][BpkLayout] Expand layout component API with opacity, as, and Stack aliases May 20, 2026
@skyscanner-backpack-bot
Copy link
Copy Markdown

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

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@skyscanner-backpack-bot
Copy link
Copy Markdown

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

@skyscanner-backpack-bot
Copy link
Copy Markdown

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

@Faye-Xiao Faye (Faye-Xiao) changed the title [NO-JIRA][BpkLayout] Expand layout component API with opacity, as, and Stack aliases [NO-JIRA][BpkLayout] Expand layout component API with opacity, as, dir, and Stack aliases May 21, 2026
…passing to Chakra

forwardRef<HTMLElement> is correct externally (as prop can render any element)
but Chakra's Box/Flex/Stack/HStack/VStack ref props expect HTMLDivElement.
Cast internally to satisfy Chakra's types without narrowing the public API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
alignItems?: BpkStackOptions['align'];
/** Alias for `justify`. Maps to CSS `justify-content`. */
justifyContent?: BpkStackOptions['justify'];
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Chakra uses the align and justify for the alignItems and justifyContent. We support both for the development-friendly

opacity?: number;

// Text direction — for embedding bidirectional content within a page
dir?: 'ltr' | 'rtl' | 'auto';
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We have a real use case to support some number label in the Arab market.

Image Image

@skyscanner-backpack-bot
Copy link
Copy Markdown

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

…gical props

marginInline/paddingInline (horizontal) were already supported; marginBlock/
paddingBlock (vertical) were missing. Adding them completes the logical
properties set and provides a RTL-safe alternative to marginTop+marginBottom.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@skyscanner-backpack-bot
Copy link
Copy Markdown

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

@skyscanner-backpack-bot
Copy link
Copy Markdown

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

HTMLElement caused a breaking change for consumers using useRef<HTMLDivElement>().
HTMLDivElement is the correct default (components render a div by default),
matching Chakra's own typing for Box/Stack/Flex. Also removes the now-unnecessary
Ref<HTMLDivElement> casts introduced to work around the mismatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@skyscanner-backpack-bot
Copy link
Copy Markdown

Visit https://backpack.github.io/storybook-prs/4505 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

patch Patch production bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants