Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/rich-singers-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

Rename `stickyTop` prop name for the PageLayout to `offsetHeader` and improve docs
8 changes: 5 additions & 3 deletions docs/content/PageLayout.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo

### With a custom sticky header

Add `offsetHeader` prop to specify the height of the custom sticky header along with `sticky` prop

```jsx live
<Box sx={{height: 320, overflowY: 'auto', border: '1px solid', borderColor: 'border.default'}}>
<Box
Expand All @@ -190,7 +192,7 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo
<PageLayout.Content>
<Placeholder label="Content" height={320} />
</PageLayout.Content>
<PageLayout.Pane position="start" stickyTop={64} sticky>
<PageLayout.Pane position="start" sticky offsetHeader={64}>
<Placeholder label="Pane" height={120} />
</PageLayout.Pane>
<PageLayout.Footer>
Expand Down Expand Up @@ -469,10 +471,10 @@ On macOS, you can open the VoiceOver rotor by pressing `VO-U`. You can navigate
description="Whether the pane should stick to the top of the screen while the content scrolls."
/>
<PropsTableRow
name="stickyTop"
name="offsetHeader"
type="number | string"
defaultValue="0"
description="Use stickyTop to push the sticky pane down to make room for a sticky header if necessary. Use the type `string` to specify the height with a unit i.e. 5rem; otherwise the type `number` will be taken as px."
description="Use offsetHeader along with the sticky prop to push the sticky pane down to make room for a sticky header if necessary. Use the type `string` to specify the height with a unit i.e. 5rem; otherwise the type `number` will be taken as px."
/>
<PropsTableRow
name="padding"
Expand Down
6 changes: 3 additions & 3 deletions docs/content/SplitPageLayout.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ If you need a more flexible layout component, consider using the [PageLayout](/P
<SplitPageLayout.Content>
<Placeholder label="Content" height={320} />
</SplitPageLayout.Content>
<SplitPageLayout.Pane stickyTop={64}>
<SplitPageLayout.Pane sticky offsetHeader={64}>
<Placeholder label="Pane" height={120} />
</SplitPageLayout.Pane>
<SplitPageLayout.Footer>
Expand Down Expand Up @@ -383,10 +383,10 @@ If you need a more flexible layout component, consider using the [PageLayout](/P
description="Whether the pane should stick to the top of the screen while the content scrolls."
/>
<PropsTableRow
name="stickyTop"
name="offsetHeader"
type="number | string"
defaultValue="0"
description="Use stickyTop to push the sticky pane down to make room for a sticky header if necessary. Use the type `string` to specify the height with a unit i.e. 5rem; otherwise the type `number` will be taken as px."
description="Use offsetHeader along with the sticky prop to push the sticky pane down to make room for a sticky header if necessary. Use the type `string` to specify the height with a unit i.e. 5rem; otherwise the type `number` will be taken as px."
/>
<PropsTableRow
name="padding"
Expand Down
20 changes: 10 additions & 10 deletions src/PageLayout/PageLayout.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ export const CustomStickyHeader: Story = args => (
sx={{
position: 'sticky',
top: 0,
height: args.stickyTop,
height: args.offsetHeader,
display: 'grid',
placeItems: 'center',
backgroundColor: 'canvas.subtle',
Expand All @@ -624,20 +624,20 @@ export const CustomStickyHeader: Story = args => (
return (
<Box key={i} as="p" sx={{margin: 0}}>
<span data-testid={testId}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non
ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius
tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec
sit amet massa purus. Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor
auctor tellus in imperdiet. Ut blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum
auctor euismod nisi. Nullam tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut
ornare.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vitae orci et magna consectetur
ullamcorper eget ac purus. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante
quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec
pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus. Nunc sem
lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor auctor tellus in imperdiet. Ut
blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum auctor euismod nisi. Nullam
tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut ornare.
</span>
</Box>
)
})}
</Box>
</PageLayout.Content>
<PageLayout.Pane position="start" padding="normal" divider="line" sticky stickyTop={args.stickyTop}>
<PageLayout.Pane position="start" padding="normal" divider="line" sticky offsetHeader={args.offsetHeader}>
<Box sx={{display: 'grid', gap: 3}}>
{Array.from({length: args.numParagraphsInPane}).map((_, i) => {
const testId = `paragraph${i}`
Expand Down Expand Up @@ -666,7 +666,7 @@ CustomStickyHeader.argTypes = {
type: 'boolean',
defaultValue: true
},
stickyTop: {
offsetHeader: {
type: 'string',
defaultValue: '8rem'
},
Expand Down
14 changes: 7 additions & 7 deletions src/PageLayout/PageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ export type PageLayoutPaneProps = {
*/
dividerWhenNarrow?: 'inherit' | 'none' | 'line' | 'filled'
sticky?: boolean
stickyTop?: string | number
offsetHeader?: string | number
hidden?: boolean | ResponsiveValue<boolean>
} & SxProp

Expand All @@ -411,7 +411,7 @@ const Pane: React.FC<React.PropsWithChildren<PageLayoutPaneProps>> = ({
divider: responsiveDivider = 'none',
dividerWhenNarrow = 'inherit',
sticky = false,
stickyTop = 0,
offsetHeader = 0,
hidden: responsiveHidden = false,
children,
sx = {}
Expand All @@ -438,11 +438,11 @@ const Pane: React.FC<React.PropsWithChildren<PageLayoutPaneProps>> = ({

React.useEffect(() => {
if (sticky) {
enableStickyPane?.(stickyTop)
enableStickyPane?.(offsetHeader)
} else {
disableStickyPane?.()
}
}, [sticky, enableStickyPane, disableStickyPane, stickyTop])
}, [sticky, enableStickyPane, disableStickyPane, offsetHeader])

return (
<Box
Expand All @@ -466,9 +466,9 @@ const Pane: React.FC<React.PropsWithChildren<PageLayoutPaneProps>> = ({
...(sticky
? {
position: 'sticky',
// If stickyTop has value, it will stick the pane to the position where the sticky top ends
// else top will be 0 as the default value of stickyTop
top: typeof stickyTop === 'number' ? `${stickyTop}px` : stickyTop,
// If offsetHeader has value, it will stick the pane to the position where the sticky top ends
// else top will be 0 as the default value of offsetHeader
top: typeof offsetHeader === 'number' ? `${offsetHeader}px` : offsetHeader,
overflow: 'hidden',
maxHeight: 'var(--sticky-pane-height)'
}
Expand Down
2 changes: 1 addition & 1 deletion src/PageLayout/interaction.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ CustomStickyHeader.argTypes = {
type: 'boolean',
defaultValue: true
},
stickyTop: {
offsetHeader: {
type: 'string',
defaultValue: '8rem'
},
Expand Down
13 changes: 7 additions & 6 deletions src/PageLayout/useStickyPaneHeight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function useStickyPaneHeight() {

// Default the height to the viewport height
const [height, setHeight] = React.useState('100vh')
const [stickyTop, setStickyTop] = React.useState<number | string>(0)
const [offsetHeader, setOffsetHeader] = React.useState<number | string>(0)

// Create intersection observers to track the top and bottom of the content region
const [contentTopRef, contentTopInView, contentTopEntry] = useInView()
Expand All @@ -29,15 +29,16 @@ export function useStickyPaneHeight() {
const topRect = contentTopEntry?.target.getBoundingClientRect()
const bottomRect = contentBottomEntry?.target.getBoundingClientRect()

const stickyTopWithUnits = typeof stickyTop === 'number' ? `${stickyTop}px` : stickyTop
// Custom sticky header's height with units
const offsetHeaderWithUnits = typeof offsetHeader === 'number' ? `${offsetHeader}px` : offsetHeader

if (scrollContainer) {
const scrollRect = scrollContainer.getBoundingClientRect()

const topOffset = topRect ? Math.max(topRect.top - scrollRect.top, 0) : 0
const bottomOffset = bottomRect ? Math.max(scrollRect.bottom - bottomRect.bottom, 0) : 0

calculatedHeight = `calc(${scrollRect.height}px - (max(${topOffset}px, ${stickyTopWithUnits}) + ${bottomOffset}px))`
calculatedHeight = `calc(${scrollRect.height}px - (max(${topOffset}px, ${offsetHeaderWithUnits}) + ${bottomOffset}px))`
} else {
const topOffset = topRect ? Math.max(topRect.top, 0) : 0
const bottomOffset = bottomRect ? Math.max(window.innerHeight - bottomRect.bottom, 0) : 0
Expand All @@ -46,11 +47,11 @@ export function useStickyPaneHeight() {
// We need to account for this when calculating the offset.
const overflowScroll = Math.max(window.scrollY + window.innerHeight - document.body.scrollHeight, 0)

calculatedHeight = `calc(100vh - (max(${topOffset}px, ${stickyTopWithUnits}) + ${bottomOffset}px - ${overflowScroll}px))`
calculatedHeight = `calc(100vh - (max(${topOffset}px, ${offsetHeaderWithUnits}) + ${bottomOffset}px - ${overflowScroll}px))`
}

setHeight(calculatedHeight)
}, [contentTopEntry, contentBottomEntry, stickyTop])
}, [contentTopEntry, contentBottomEntry, offsetHeader])

// We only want to add scroll and resize listeners if the pane is sticky.
// Since hooks can't be called conditionally, we need to use state to track
Expand Down Expand Up @@ -92,7 +93,7 @@ export function useStickyPaneHeight() {

function enableStickyPane(top: string | number) {
setIsEnabled(true)
setStickyTop(top)
setOffsetHeader(top)
}

function disableStickyPane() {
Expand Down