diff --git a/.changeset/empty-garlics-clean.md b/.changeset/empty-garlics-clean.md new file mode 100644 index 00000000000..ffb84d52778 --- /dev/null +++ b/.changeset/empty-garlics-clean.md @@ -0,0 +1,10 @@ +--- +"@primer/react": minor +--- + +Add a responsive `hidden` prop to `PageLayout.Header`, `PageLayout.Pane`, `PageLayout.Content`, and `PageLayout.Footer` that allows you to hide layout regions based on the viewport width. Example usage: + +```jsx +// Hide pane on narrow viewports + +``` diff --git a/docs/content/PageLayout.mdx b/docs/content/PageLayout.mdx index f1b65c9f184..d9ad832f9e7 100644 --- a/docs/content/PageLayout.mdx +++ b/docs/content/PageLayout.mdx @@ -76,6 +76,25 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo ``` +### With pane hidden on narrow viewports + +```jsx live + + + + + + + + + + + + +``` + ### With condensed spacing ```jsx live @@ -112,8 +131,6 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo ### PageLayout - - + @@ -181,6 +209,17 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo defaultValue="'full'" description="The maximum width of the content region." /> + @@ -222,6 +261,17 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo | 'filled'`} defaultValue="'inherit'" /> + @@ -242,6 +292,17 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo | 'filled'`} defaultValue="'inherit'" /> + diff --git a/package.json b/package.json index a5dc5940308..e955e1372f6 100644 --- a/package.json +++ b/package.json @@ -162,6 +162,7 @@ "husky": "7.0.4", "jest": "27.4.5", "jest-axe": "5.0.1", + "jest-matchmedia-mock": "1.1.0", "jest-styled-components": "6.3.4", "jest-matchmedia-mock": "1.1.0", "jscodeshift": "0.13.0", diff --git a/src/PageLayout/PageLayout.test.tsx b/src/PageLayout/PageLayout.test.tsx index fe96e6d384a..171bb6216f0 100644 --- a/src/PageLayout/PageLayout.test.tsx +++ b/src/PageLayout/PageLayout.test.tsx @@ -1,9 +1,21 @@ -import {render} from '@testing-library/react' import React from 'react' +import {act, render} from '@testing-library/react' +import MatchMediaMock from 'jest-matchmedia-mock' import {ThemeProvider} from '..' +import {viewportRanges} from '../hooks/useResponsiveValue' import {PageLayout} from './PageLayout' +let matchMedia: MatchMediaMock + describe('PageLayout', () => { + beforeAll(() => { + matchMedia = new MatchMediaMock() + }) + + afterEach(() => { + matchMedia.clear() + }) + it('renders default layout', () => { const {container} = render( @@ -63,4 +75,44 @@ describe('PageLayout', () => { ) expect(container).toMatchSnapshot() }) + + it('can hide pane when narrow', () => { + // Set narrow viewport + act(() => { + matchMedia.useMediaQuery(viewportRanges.narrow) + }) + + const {getByText} = render( + + + Header + Content + + Footer + + + ) + + expect(getByText('Pane')).not.toBeVisible() + }) + + it('shows all subcomponents by default', () => { + // Set regular viewport + act(() => { + matchMedia.useMediaQuery(viewportRanges.regular) + }) + + const {getByText} = render( + + + Header + Content + + Footer + + + ) + + expect(getByText('Pane')).toBeVisible() + }) }) diff --git a/src/PageLayout/PageLayout.tsx b/src/PageLayout/PageLayout.tsx index b013246e569..eaab7e4c4a5 100644 --- a/src/PageLayout/PageLayout.tsx +++ b/src/PageLayout/PageLayout.tsx @@ -1,6 +1,7 @@ import React from 'react' -import {BetterSystemStyleObject, merge, SxProp} from '../sx' import {Box} from '..' +import {ResponsiveValue, useResponsiveValue} from '../hooks/useResponsiveValue' +import {BetterSystemStyleObject, merge, SxProp} from '../sx' const REGION_ORDER = { header: 0, @@ -178,18 +179,22 @@ const VerticalDivider: React.FC = ({variant = 'none', variantWhenN export type PageLayoutHeaderProps = { divider?: 'none' | 'line' dividerWhenNarrow?: 'inherit' | 'none' | 'line' | 'filled' + hidden?: boolean | ResponsiveValue } & SxProp const Header: React.FC = ({ divider = 'none', dividerWhenNarrow = 'inherit', + hidden = false, children, sx = {} }) => { + const isHidden = useResponsiveValue(hidden, false) const {rowGap} = React.useContext(PageLayoutContext) return (