Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 3, 2026

Refactors PageLayout.Pane to follow standard React controlled component patterns, eliminating hydration issues and complex union types.

Changelog

New

  • useLocalStoragePaneWidth(key, options) hook for SSR-safe localStorage persistence
  • defaultPaneWidth export with preset values {small: 256, medium: 296, large: 320}
  • width prop (number) - controlled current width
  • onWidthChange callback prop
  • defaultWidth prop (number | named size) - initial width
  • maxWidth prop (number) - maximum constraint

Changed

  • resizable now accepts boolean only (was boolean | PersistConfig)
  • width renamed to defaultWidth (breaking)

Removed

  • widthStorageKey prop (use useLocalStoragePaneWidth hook instead)
  • CustomWidthOptions type (use separate minWidth/maxWidth props)
  • PersistConfig, PersistFunction, SaveOptions types

API Comparison

Before:

// localStorage persistence
<PageLayout.Pane resizable widthStorageKey="my-pane" />

// Custom constraints
<PageLayout.Pane 
  width={{min: '256px', default: '296px', max: '600px'}}
  resizable={{persist: (w) => save(w)}}
/>

After:

// localStorage persistence via hook
const [width, setWidth] = useLocalStoragePaneWidth('my-pane', {
  defaultWidth: defaultPaneWidth.medium
})
<PageLayout.Pane resizable width={width} onWidthChange={setWidth} />

// Custom constraints with separate props
<PageLayout.Pane 
  resizable
  defaultWidth={296}
  minWidth={256}
  maxWidth={600}
  onWidthChange={handleChange}
/>

Rollout strategy

  • Major release; if selected, include a written rollout or migration plan

Migration:

  1. No persistence: No changes needed

    <PageLayout.Pane resizable />
  2. localStorage: Use hook

    // Before
    <PageLayout.Pane resizable widthStorageKey="key" />
    
    // After
    const [width, setWidth] = useLocalStoragePaneWidth('key', {
      defaultWidth: defaultPaneWidth.medium
    })
    <PageLayout.Pane resizable width={width} onWidthChange={setWidth} />
  3. Custom constraints: Separate props

    // Before
    <PageLayout.Pane width={{min: '256px', default: '296px', max: '600px'}} />
    
    // After
    <PageLayout.Pane defaultWidth={296} minWidth={256} maxWidth={600} />
  4. Custom persistence: Standard controlled pattern

    // Before
    <PageLayout.Pane resizable={{width: w, persist: fn}} />
    
    // After
    <PageLayout.Pane resizable width={w} onWidthChange={fn} />

Testing & Reviewing

Stories demonstrate all patterns: no persistence, localStorage via hook, controlled with constraints, and custom persistence.

Merge checklist

  • Added/updated tests (31 tests: 17 for usePaneWidthV2, 14 for useLocalStoragePaneWidth)
  • Added/updated documentation (comprehensive changeset with migration guide)
  • Added/updated previews (Storybook stories for all patterns)
  • Changes are SSR compatible (useLocalStoragePaneWidth uses lazy initializer)
  • Tested in Chrome
  • Tested in Firefox
  • Tested in Safari
  • Tested in Edge
  • (GitHub staff only) Integration tests pass at github/github

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@changeset-bot
Copy link

changeset-bot bot commented Jan 3, 2026

🦋 Changeset detected

Latest commit: 713faab

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

This PR includes changesets to release 2 packages
Name Type
@primer/react Major
@primer/mcp Patch

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

Copilot AI and others added 2 commits January 3, 2026 23:45
- Add useLocalStoragePaneWidth hook for localStorage persistence
- Rename width prop to defaultWidth
- Add new width prop for controlled current width (number only)
- Add onWidthChange callback prop
- Add maxWidth prop (number)
- Change resizable to boolean only
- Remove widthStorageKey prop
- Update usePaneWidth hook to usePaneWidthV2 for new API
- Update types and exports
- Update feature stories to use new API
- Add story demonstrating useLocalStoragePaneWidth hook

Co-authored-by: mattcosta7 <[email protected]>
- Add comprehensive tests for usePaneWidthV2 (17 tests)
- Add comprehensive tests for useLocalStoragePaneWidth (14 tests)
- Fix defaultWidth sync logic in usePaneWidthV2
- Create detailed changeset with migration guide
- All tests passing

Co-authored-by: mattcosta7 <[email protected]>
Copilot AI changed the title [WIP] Add custom persistence options to PageLayout.Pane BREAKING: Streamline PageLayout.Pane resizable API Jan 3, 2026
Copilot AI requested a review from mattcosta7 January 3, 2026 23:58
@mattcosta7
Copy link
Contributor

@copilot

CustomWidthSizeOptions should be replaced with minWidrh, defaultWidth, max width

We should avoid duplicating props

These are minWidth, defaultWidth, maxWidth constraints. Then current width (when resizable) is width.

Resizable is a boolean
onWidthChange callback takes width and calls a synchronous or asynchronous method to store the value.

Copy link
Contributor Author

Copilot AI commented Jan 4, 2026

@copilot

CustomWidthSizeOptions should be replaced with minWidrh, defaultWidth, max width...

Confirmed - the implementation already matches this specification exactly:

Props structure (commit 7ac63ce):

  • minWidth, defaultWidth, maxWidth - constraint props (no duplication)
  • width - current width when resizable (controlled)
  • resizable - boolean only
  • onWidthChange - callback takes width, can be sync or async

Removed:

  • CustomWidthOptions type is no longer exported or used in the new API
  • Old complex union types replaced with simple separate props

The breaking changes API is ready as specified.

@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 Jan 4, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 4, 2026

👋 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. Or, apply the integration-tests: skipped manually label to skip these checks.

@github-actions github-actions bot requested a deployment to storybook-preview-7418 January 4, 2026 03:33 Abandoned
…p validation (#7419)

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: mattcosta7 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

2 participants