Skip to content

Commit 0c2db83

Browse files
japfjoshblackcolebemis
authored
Add resizable support to the <PageLayout> component (#2352)
* add resizable support to the PageLayout component * Add changeset file * update snapshot * take client left position into account when pane is not left aligned * fix resize behavior when pane is not at start position * fix resize when there are column gaps * use story debug values * decouple the resize handle from the vertical divider * update snap file * update snap file * rename canResizePane to resizable * update snap files * update resizable PageLayout story * rename paneWidthStorageKey to widthStorageKey * refactor(PageLayout): set pane with in CSS Custom Property * docs: add documentation for resizable nad widthStorageKey * Resizable pane refactor (#2481) * Update stories * Refactor resizable pane implementation * Clamp pane width resizing * Delay drag hover effect * Reset pane width on double click * Handle styles while dragging * Add resizable example to SplitPageLayout docs * Remove comment * Add comment about touch events * Update docs * Update resizable pane story * Update snapshots * Wrap localStorage in try/catch * Store pane width in px * Update snapshot * Update pagelayout snapshots Co-authored-by: Josh Black <[email protected]> Co-authored-by: Josh Black <[email protected]> Co-authored-by: Cole Bemis <[email protected]>
1 parent 6199b10 commit 0c2db83

File tree

8 files changed

+328
-8
lines changed

8 files changed

+328
-8
lines changed

.changeset/polite-ligers-repair.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@primer/react': minor
3+
---
4+
5+
Add resizable support to the PageLayout component.

docs/content/PageLayout.mdx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,25 @@ Using `aria-labelledby` along with `PageLayout.Header`, `PageLayout.Content`, or
279279
</PageLayout>
280280
```
281281

282+
### With resizable pane
283+
284+
```jsx live
285+
<PageLayout>
286+
<PageLayout.Header>
287+
<Placeholder label="Header" height={64} />
288+
</PageLayout.Header>
289+
<PageLayout.Content>
290+
<Placeholder label="Content" height={240} />
291+
</PageLayout.Content>
292+
<PageLayout.Pane resizable>
293+
<Placeholder label="Pane" height={120} />
294+
</PageLayout.Pane>
295+
<PageLayout.Footer>
296+
<Placeholder label="Footer" height={64} />
297+
</PageLayout.Footer>
298+
</PageLayout>
299+
```
300+
282301
## Accessibility
283302

284303
The `PageLayout` component uses [landmark roles](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/landmark_role) for `PageLayout.Header`, `PageLayout.Content`, and `PageLayout.Footer` in order to make it easier for screen reader users to navigate between sections of the page.
@@ -365,6 +384,7 @@ On macOS, you can open the VoiceOver rotor by pressing `VO-U`. You can navigate
365384
| 'normal'`}
366385
defaultValue="'normal'"
367386
/>
387+
368388
<PropsTableSxRow />
369389
</PropsTable>
370390

@@ -512,6 +532,18 @@ On macOS, you can open the VoiceOver rotor by pressing `VO-U`. You can navigate
512532
defaultValue="'medium'"
513533
description="The width of the pane."
514534
/>
535+
<PropsTableRow
536+
name="resizable"
537+
type="boolean"
538+
defaultValue="false"
539+
description="When true, the pane may be resized by the user."
540+
/>
541+
<PropsTableRow
542+
name="widthStorageKey"
543+
type="string"
544+
defaultValue="'paneWidth'"
545+
description="Provide a key used by localStorage to persist the size of the pane on the client."
546+
/>
515547
<PropsTableRow
516548
name="sticky"
517549
type="boolean"

docs/content/SplitPageLayout.mdx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,27 @@ If you need a more flexible layout component, consider using the [PageLayout](/P
112112
</Box>
113113
```
114114

115+
### With resizable pane
116+
117+
```jsx live drafts
118+
<Box sx={{height: 320, overflowY: 'auto', border: '1px solid', borderColor: 'border.default'}}>
119+
<SplitPageLayout>
120+
<SplitPageLayout.Header>
121+
<Placeholder label="Header" height={64} />
122+
</SplitPageLayout.Header>
123+
<SplitPageLayout.Pane resizable>
124+
<Placeholder label="Pane" height={120} />
125+
</SplitPageLayout.Pane>
126+
<SplitPageLayout.Content>
127+
<Placeholder label="Content" height={420} />
128+
</SplitPageLayout.Content>
129+
<SplitPageLayout.Footer>
130+
<Placeholder label="Footer" height={64} />
131+
</SplitPageLayout.Footer>
132+
</SplitPageLayout>
133+
</Box>
134+
```
135+
115136
### Without dividers
116137

117138
```jsx live drafts
@@ -378,6 +399,18 @@ If you need a more flexible layout component, consider using the [PageLayout](/P
378399
defaultValue="'medium'"
379400
description="The width of the pane."
380401
/>
402+
<PropsTableRow
403+
name="resizable"
404+
type="boolean"
405+
defaultValue="false"
406+
description="When true, the pane may be resized by the user."
407+
/>
408+
<PropsTableRow
409+
name="widthStorageKey"
410+
type="string"
411+
defaultValue="'paneWidth'"
412+
description="Provide a key used by localStorage to persist the size of the pane on the client."
413+
/>
381414
<PropsTableRow
382415
name="sticky"
383416
type="boolean"

src/PageLayout/PageLayout.stories.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const meta: Meta = {
4040
'Pane.position.wide': 'end',
4141
'Pane.width': 'medium',
4242
'Pane.sticky': false,
43+
'Pane.resizable': false,
4344
'Pane.padding': 'none',
4445
'Pane.divider.regular': 'none',
4546
'Pane.divider.narrow': 'none',
@@ -242,6 +243,10 @@ const meta: Meta = {
242243
type: 'boolean',
243244
table: {category: 'Pane props'}
244245
},
246+
'Pane.resizable': {
247+
type: 'boolean',
248+
table: {category: 'Pane props'}
249+
},
245250
'Pane.padding': {
246251
type: {
247252
name: 'enum',
@@ -380,6 +385,7 @@ const Template: Story = args => (
380385
}}
381386
width={args['Pane.width']}
382387
sticky={args['Pane.sticky']}
388+
resizable={args['Pane.resizable']}
383389
padding={args['Pane.padding']}
384390
divider={{
385391
narrow: args['Pane.divider.narrow'],
@@ -509,7 +515,7 @@ export const StickyPane: Story = args => (
509515
})}
510516
</Box>
511517
</PageLayout.Content>
512-
<PageLayout.Pane position="start" padding="normal" divider="line" sticky={args.sticky}>
518+
<PageLayout.Pane position="start" resizable padding="normal" divider="line" sticky={args.sticky}>
513519
<Box sx={{display: 'grid', gap: 3}}>
514520
{Array.from({length: args.numParagraphsInPane}).map((_, i) => {
515521
const testId = `paragraph${i}`
@@ -694,4 +700,21 @@ CustomStickyHeader.argTypes = {
694700
}
695701
}
696702

703+
export const ResizablePane: Story = () => (
704+
<PageLayout containerWidth="full">
705+
<PageLayout.Header>
706+
<Placeholder height={64} label="Header" />
707+
</PageLayout.Header>
708+
<PageLayout.Pane resizable position="start">
709+
<Placeholder height={320} label="Pane" />
710+
</PageLayout.Pane>
711+
<PageLayout.Content>
712+
<Placeholder height={640} label="Content" />
713+
</PageLayout.Content>
714+
<PageLayout.Footer>
715+
<Placeholder height={64} label="Footer" />
716+
</PageLayout.Footer>
717+
</PageLayout>
718+
)
719+
697720
export default meta

0 commit comments

Comments
 (0)