Skip to content

Commit

Permalink
Add resizable support to the <PageLayout> component (#2352)
Browse files Browse the repository at this point in the history
* 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 <josh@josh.black>
Co-authored-by: Josh Black <joshblack@github.com>
Co-authored-by: Cole Bemis <colebemis@github.com>
  • Loading branch information
4 people committed Oct 31, 2022
1 parent 6199b10 commit 0c2db83
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/polite-ligers-repair.md
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

Add resizable support to the PageLayout component.
32 changes: 32 additions & 0 deletions docs/content/PageLayout.mdx
Expand Up @@ -279,6 +279,25 @@ Using `aria-labelledby` along with `PageLayout.Header`, `PageLayout.Content`, or
</PageLayout>
```

### With resizable pane

```jsx live
<PageLayout>
<PageLayout.Header>
<Placeholder label="Header" height={64} />
</PageLayout.Header>
<PageLayout.Content>
<Placeholder label="Content" height={240} />
</PageLayout.Content>
<PageLayout.Pane resizable>
<Placeholder label="Pane" height={120} />
</PageLayout.Pane>
<PageLayout.Footer>
<Placeholder label="Footer" height={64} />
</PageLayout.Footer>
</PageLayout>
```

## Accessibility

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.
Expand Down Expand Up @@ -365,6 +384,7 @@ On macOS, you can open the VoiceOver rotor by pressing `VO-U`. You can navigate
| 'normal'`}
defaultValue="'normal'"
/>

<PropsTableSxRow />
</PropsTable>

Expand Down Expand Up @@ -512,6 +532,18 @@ On macOS, you can open the VoiceOver rotor by pressing `VO-U`. You can navigate
defaultValue="'medium'"
description="The width of the pane."
/>
<PropsTableRow
name="resizable"
type="boolean"
defaultValue="false"
description="When true, the pane may be resized by the user."
/>
<PropsTableRow
name="widthStorageKey"
type="string"
defaultValue="'paneWidth'"
description="Provide a key used by localStorage to persist the size of the pane on the client."
/>
<PropsTableRow
name="sticky"
type="boolean"
Expand Down
33 changes: 33 additions & 0 deletions docs/content/SplitPageLayout.mdx
Expand Up @@ -112,6 +112,27 @@ If you need a more flexible layout component, consider using the [PageLayout](/P
</Box>
```

### With resizable pane

```jsx live drafts
<Box sx={{height: 320, overflowY: 'auto', border: '1px solid', borderColor: 'border.default'}}>
<SplitPageLayout>
<SplitPageLayout.Header>
<Placeholder label="Header" height={64} />
</SplitPageLayout.Header>
<SplitPageLayout.Pane resizable>
<Placeholder label="Pane" height={120} />
</SplitPageLayout.Pane>
<SplitPageLayout.Content>
<Placeholder label="Content" height={420} />
</SplitPageLayout.Content>
<SplitPageLayout.Footer>
<Placeholder label="Footer" height={64} />
</SplitPageLayout.Footer>
</SplitPageLayout>
</Box>
```

### Without dividers

```jsx live drafts
Expand Down Expand Up @@ -378,6 +399,18 @@ If you need a more flexible layout component, consider using the [PageLayout](/P
defaultValue="'medium'"
description="The width of the pane."
/>
<PropsTableRow
name="resizable"
type="boolean"
defaultValue="false"
description="When true, the pane may be resized by the user."
/>
<PropsTableRow
name="widthStorageKey"
type="string"
defaultValue="'paneWidth'"
description="Provide a key used by localStorage to persist the size of the pane on the client."
/>
<PropsTableRow
name="sticky"
type="boolean"
Expand Down
25 changes: 24 additions & 1 deletion src/PageLayout/PageLayout.stories.tsx
Expand Up @@ -40,6 +40,7 @@ const meta: Meta = {
'Pane.position.wide': 'end',
'Pane.width': 'medium',
'Pane.sticky': false,
'Pane.resizable': false,
'Pane.padding': 'none',
'Pane.divider.regular': 'none',
'Pane.divider.narrow': 'none',
Expand Down Expand Up @@ -242,6 +243,10 @@ const meta: Meta = {
type: 'boolean',
table: {category: 'Pane props'}
},
'Pane.resizable': {
type: 'boolean',
table: {category: 'Pane props'}
},
'Pane.padding': {
type: {
name: 'enum',
Expand Down Expand Up @@ -380,6 +385,7 @@ const Template: Story = args => (
}}
width={args['Pane.width']}
sticky={args['Pane.sticky']}
resizable={args['Pane.resizable']}
padding={args['Pane.padding']}
divider={{
narrow: args['Pane.divider.narrow'],
Expand Down Expand Up @@ -509,7 +515,7 @@ export const StickyPane: Story = args => (
})}
</Box>
</PageLayout.Content>
<PageLayout.Pane position="start" padding="normal" divider="line" sticky={args.sticky}>
<PageLayout.Pane position="start" resizable padding="normal" divider="line" sticky={args.sticky}>
<Box sx={{display: 'grid', gap: 3}}>
{Array.from({length: args.numParagraphsInPane}).map((_, i) => {
const testId = `paragraph${i}`
Expand Down Expand Up @@ -694,4 +700,21 @@ CustomStickyHeader.argTypes = {
}
}

export const ResizablePane: Story = () => (
<PageLayout containerWidth="full">
<PageLayout.Header>
<Placeholder height={64} label="Header" />
</PageLayout.Header>
<PageLayout.Pane resizable position="start">
<Placeholder height={320} label="Pane" />
</PageLayout.Pane>
<PageLayout.Content>
<Placeholder height={640} label="Content" />
</PageLayout.Content>
<PageLayout.Footer>
<Placeholder height={64} label="Footer" />
</PageLayout.Footer>
</PageLayout>
)

export default meta

0 comments on commit 0c2db83

Please sign in to comment.