Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions packages/react/src/PageLayout/PageLayout.features.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ export const PullRequestPage = () => (
</div>
</div>
</PageLayout.Pane>
<PageLayout.Sidebar position="start" aria-label="Inspector sidebar">
<div className={classes.SidebarBox}>
<p>This is the sidebar content.</p>
</div>
</PageLayout.Sidebar>
</PageLayout>
)

Expand Down Expand Up @@ -301,6 +306,23 @@ export const ResizablePane: StoryFn = () => (
</PageLayout>
)

export const ResizablePaneTwo: StoryFn = () => (
<PageLayout containerWidth="full">
<PageLayout.Header>
<Placeholder height={64} label="Header" />
</PageLayout.Header>
<PageLayout.Pane resizable position="start" aria-label="Side pane">
<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 const ScrollContainerWithinPageLayoutPane: StoryFn = () => (
<div className={classes.NestedScrollContainer}>
<div className={classes.OverflowAuto}>
Expand Down Expand Up @@ -361,6 +383,129 @@ export const WithCustomPaneHeading: StoryFn = () => (
</PageLayout>
)

export const SidebarStart: StoryFn = () => (
<PageLayout containerWidth="full">
<PageLayout.Sidebar position="start" aria-label="Navigation sidebar">
<Placeholder height={800} label="Sidebar (Start)" />
</PageLayout.Sidebar>
<PageLayout.Header>
<Placeholder height={64} label="Header" />
</PageLayout.Header>
<PageLayout.Content>
<Placeholder height={640} label="Content" />
</PageLayout.Content>
<PageLayout.Footer>
<Placeholder height={64} label="Footer" />
</PageLayout.Footer>
</PageLayout>
)

export const SidebarEnd: StoryFn = () => (
<PageLayout containerWidth="full">
<PageLayout.Sidebar position="end" aria-label="Inspector sidebar">
<Placeholder height={800} label="Sidebar (End)" />
</PageLayout.Sidebar>
<PageLayout.Header>
<Placeholder height={64} label="Header" />
</PageLayout.Header>
<PageLayout.Content>
<Placeholder height={640} label="Content" />
</PageLayout.Content>
<PageLayout.Footer>
<Placeholder height={64} label="Footer" />
</PageLayout.Footer>
</PageLayout>
)

export const ResizableSidebar: StoryFn = () => (
<PageLayout containerWidth="full">
<PageLayout.Sidebar
resizable
position="end"
aria-label="Resizable sidebar"
style={{height: '100vh'}}
width={{
min: '200px',
default: '300px',
max: '2000px',
}}
>
<Placeholder height={800} label="Resizable Sidebar" />
</PageLayout.Sidebar>
<PageLayout.Header>
<Placeholder height={64} label="Header" />
</PageLayout.Header>
<PageLayout.Pane position="start" aria-label="Side pane">
<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 const SidebarWithPaneResizable: StoryFn = () => (
<PageLayout containerWidth="full">
<PageLayout.Sidebar
style={{height: '100vh'}}
resizable
position="end"
aria-label="Navigation sidebar"
width={{min: '200px', default: '300px', max: '2000px'}}
>
<Placeholder height={800} label="Resizable Sidebar" />
</PageLayout.Sidebar>
<PageLayout.Header>
<Placeholder height={64} label="Header" />
</PageLayout.Header>
<PageLayout.Pane resizable position="start" aria-label="Side pane">
<Placeholder height={320} label="Resizable Pane" />
</PageLayout.Pane>
<PageLayout.Content>
<Placeholder height={640} label="Content" />
</PageLayout.Content>
<PageLayout.Footer>
<Placeholder height={64} label="Footer" />
</PageLayout.Footer>
</PageLayout>
)

export const StickySidebar: StoryFn = () => (
<PageLayout containerWidth="full">
<PageLayout.Sidebar sticky position="start" aria-label="Sticky sidebar">
<Placeholder height={200} label="Sticky Sidebar" />
</PageLayout.Sidebar>
<PageLayout.Header>
<Placeholder height={64} label="Header" />
</PageLayout.Header>
<PageLayout.Content>
<Placeholder height={2000} label="Tall Content (scroll to test sticky)" />
</PageLayout.Content>
<PageLayout.Footer>
<Placeholder height={64} label="Footer" />
</PageLayout.Footer>
</PageLayout>
)

export const SidebarFullscreenWhenNarrow: StoryFn = () => (
<PageLayout containerWidth="full">
<PageLayout.Sidebar position="start" whenNarrow="fullscreen" aria-label="Fullscreen sidebar">
<Placeholder height={800} label="Sidebar (fullscreen at narrow)" />
</PageLayout.Sidebar>
<PageLayout.Header>
<Placeholder height={64} label="Header" />
</PageLayout.Header>
<PageLayout.Content>
<Placeholder height={640} label="Content" />
</PageLayout.Content>
<PageLayout.Footer>
<Placeholder height={64} label="Footer" />
</PageLayout.Footer>
</PageLayout>
)
export const ResizablePaneWithoutPersistence: StoryFn = () => {
const [currentWidth, setCurrentWidth] = React.useState<number>(defaultPaneWidth.medium)

Expand Down
133 changes: 132 additions & 1 deletion packages/react/src/PageLayout/PageLayout.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@
width: 100%;

@media screen and (min-width: 768px) {
/*
/*
* --pane-max-width is set by JS on mount and updated on resize (debounced).
* JS calculates viewport - margin to avoid scrollbar discrepancy with 100vw.
*/
Expand Down Expand Up @@ -742,3 +742,134 @@
contain: layout style paint;
pointer-events: none;
}

/* Sidebar */
.PageLayoutRoot:where([data-has-sidebar]) {
/* Note: Sidebar styles are only applied when the PageLayout has a Sidebar child
via `[data-has-sidebar`]` on the root element
*/
display: flex;
/*
Current layout structure for Sidebar support:
-- [Sidebar] | [Header + Content + Footer] | [Sidebar] --
*/
flex-direction: row;
}

.SidebarWrapper {
/* Current layout structure:
-- [Sidebar] | [Resizable Divider] --
*/
display: flex;
flex-direction: row;
flex-shrink: 0;
height: 100%;

&:where([data-is-hidden='true']) {
display: none;
}

/* Position: start (left side) */
&:where([data-position='start']) {
order: -1;
}

/* Position: end (right side) */
&:where([data-position='end']) {
order: 1;
}

/* Sticky sidebar */
&:where([data-sticky]) {
position: sticky;
top: 0;
height: 100vh;
}

/* Narrow viewport */
@media (--viewportRange-narrow) {
&:where([data-is-hidden-narrow='true']) {
display: none;
}

/* Fullscreen mode at narrow viewport */
&:where([data-when-narrow='fullscreen']) {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
min-width: unset;
max-width: unset;
border-radius: 0;
/* stylelint-disable-next-line primer/spacing */
z-index: 999;
background-color: var(--bgColor-default);
}
}

/* Regular viewport */
@media (--viewportRange-regular) {
&:where([data-is-hidden-regular='true']) {
display: none;
}
}

/* Wide viewport */
@media (--viewportRange-wide) {
&:where([data-is-hidden-wide='true']) {
display: none;
}
}
}

.Sidebar {
width: var(--pane-width-size);
/* stylelint-disable-next-line primer/spacing */
padding: var(--spacing);
height: 100%;
overflow: auto;

&:where([data-resizable]) {
width: 100%;

@media screen and (min-width: 768px) {
width: clamp(var(--pane-min-width), var(--pane-width), var(--pane-max-width));
}
}

/* In fullscreen mode at narrow, sidebar takes full available space */
@media (--viewportRange-narrow) {
:where([data-when-narrow='fullscreen']) > & {
width: 100%;
height: 100%;
min-width: unset;
max-width: unset;
}
}
}

.SidebarVerticalDivider {
/* Base position (non-responsive) */
&:where([data-position='start']) {
/* stylelint-disable-next-line primer/spacing */
margin-left: var(--spacing);
}

&:where([data-position='end']) {
/* stylelint-disable-next-line primer/spacing */
margin-right: var(--spacing);
}

/* Hide divider in fullscreen mode at narrow viewport */
@media (--viewportRange-narrow) {
:where([data-when-narrow='fullscreen']) > & {
display: none;
}
}
}

.Sidebar[data-dragging='true'] {
contain: layout style paint;
pointer-events: none;
}
Loading
Loading