-
Notifications
You must be signed in to change notification settings - Fork 526
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Hidden: Refactor the component to use the new `getBreakpointsDeclarat…
…ions` util function and add missing stories and tests (#2729) * Refactor Hidden component to use getBreakpointDeclarations for responsive rendering * Add missing stories and test & update docs * add changeset * check stories for axe violation * storybook fixes * wrap the hidden content in a box to display flex * breakpoints & ranges -> into consts and update global storybook parameters * use string when there is a single value for `on` Co-authored-by: Josh Black <joshblack@github.com> * code review feedbacks * utils for breakpoints * rename and update hard-coded media queries * PageHeader: Add visual ordering and `PageLayout` story example (#2763) * Add visual ordering and pageLayout example * Mock IntersectionObserver for <ThemeProvider> in story render * remove unused components * add TitleArea order * add changeset * update the snapshot Co-authored-by: Josh Black <joshblack@github.com>
- Loading branch information
1 parent
d2d4846
commit 4dcf658
Showing
22 changed files
with
555 additions
and
186 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@primer/react': patch | ||
--- | ||
|
||
PageHeader: Add visual ordering for layout enforcement |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@primer/react': patch | ||
--- | ||
|
||
Hidden: Refactor Hidden component to use `getBreakpointsDeclarations` util function to reduce layout shifts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,30 @@ | ||
import {Meta} from '@storybook/react' | ||
import React from 'react' | ||
import {ThemeProvider} from '..' | ||
import {Hidden} from './Hidden' | ||
import BaseStyles from '../BaseStyles' | ||
import Box from '../Box' | ||
import {ComponentMeta, ComponentStory} from '@storybook/react' | ||
|
||
const meta: Meta = { | ||
title: 'Layout components/Hidden', | ||
component: Hidden, | ||
decorators: [ | ||
(Story: React.ComponentType<React.PropsWithChildren<unknown>>): JSX.Element => ( | ||
<ThemeProvider> | ||
<BaseStyles> | ||
<Story /> | ||
</BaseStyles> | ||
</ThemeProvider> | ||
), | ||
], | ||
import Hidden from '.' | ||
|
||
export default { | ||
title: 'Drafts/Components/Hidden', | ||
parameters: { | ||
controls: { | ||
expanded: true, | ||
}, | ||
}, | ||
args: { | ||
on: ['regular'], | ||
}, | ||
argTypes: { | ||
on: { | ||
type: { | ||
name: 'enum', | ||
value: ['narrow', 'regular', 'wide'], | ||
}, | ||
defaultValue: 'regular', | ||
control: {type: 'radio'}, | ||
control: {type: 'multi-select'}, | ||
description: 'The viewport type to hide the content on.', | ||
}, | ||
}, | ||
} | ||
export default meta | ||
|
||
export const isVisibleInRegularOnly = () => ( | ||
<Box> | ||
<Hidden on={['narrow', 'wide']}> This value is only shown in regular viewport</Hidden> | ||
</Box> | ||
) | ||
|
||
export const isVisibleInNarrowOnly = () => ( | ||
<Box> | ||
<Hidden on={['regular', 'wide']}> This value is only shown in narrow viewport</Hidden> | ||
</Box> | ||
) | ||
} as ComponentMeta<typeof Hidden> | ||
|
||
export const isHiddenInNarrowOnly = () => ( | ||
<Box> | ||
<Hidden on="narrow">This is hidden in narrow only</Hidden> | ||
</Box> | ||
export const Playground: ComponentStory<typeof Hidden> = args => ( | ||
<Hidden {...args}>The content is hidden on {Array(args.on).join(',')}</Hidden> | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import React from 'react' | ||
import '@testing-library/jest-dom/extend-expect' | ||
import {render} from '@testing-library/react' | ||
import {Hidden} from '.' | ||
import MatchMediaMock from 'jest-matchmedia-mock' | ||
import {behavesAsComponent, checkExports, renderStyles, checkStoriesForAxeViolations} from '../utils/testing' | ||
import {mediaQueries} from '../utils/layout' | ||
|
||
let matchMedia: MatchMediaMock | ||
describe('Hidden', () => { | ||
beforeAll(() => { | ||
matchMedia = new MatchMediaMock() | ||
}) | ||
|
||
afterAll(() => { | ||
matchMedia.clear() | ||
}) | ||
|
||
behavesAsComponent({ | ||
Component: Hidden, | ||
options: {skipAs: true, skipSx: true}, | ||
toRender: () => ( | ||
<Hidden on={'narrow'}> | ||
<div>Hidden on narrow</div> | ||
</Hidden> | ||
), | ||
}) | ||
|
||
checkExports('Hidden', { | ||
default: Hidden, | ||
Hidden, | ||
}) | ||
|
||
it('renders `on` prop as expected', () => { | ||
const {container} = render( | ||
<Hidden on={'narrow'}> | ||
<div>Hidden on narrow</div> | ||
</Hidden>, | ||
) | ||
expect(container).toMatchSnapshot() | ||
}) | ||
|
||
it('renders the styles as expected when a single viewport value is provided as a string via `on` prop', () => { | ||
const expectedStyles = { | ||
// `.replace` is used because renderStyles return the JSON object without a space after the column | ||
[`${mediaQueries.regular.replace(': ', ':')}`]: { | ||
display: 'none', | ||
}, | ||
} | ||
expect( | ||
renderStyles( | ||
<Hidden on="regular"> | ||
<div>This is hidden on regular viewports</div> | ||
</Hidden>, | ||
), | ||
).toEqual(expect.objectContaining(expectedStyles)) | ||
}) | ||
|
||
it('renders the styles as expected when multiple viewport values are provided as an array via `on` prop', () => { | ||
const expectedStyles = { | ||
[`${mediaQueries.narrow.replace(': ', ':')}`]: { | ||
display: 'none', | ||
}, | ||
[`${mediaQueries.wide.replace(': ', ':')}`]: { | ||
display: 'none', | ||
}, | ||
} | ||
expect( | ||
renderStyles( | ||
<Hidden on={['narrow', 'wide']}> | ||
<div>This is hidden on regular and wide viewports</div> | ||
</Hidden>, | ||
), | ||
).toEqual(expect.objectContaining(expectedStyles)) | ||
}) | ||
}) | ||
|
||
checkStoriesForAxeViolations('features', '../Hidden/') | ||
checkStoriesForAxeViolations('examples', '../Hidden/') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,40 @@ | ||
import React from 'react' | ||
import {useMedia} from '../hooks/useMedia' | ||
import {viewportRanges} from '../hooks/useResponsiveValue' | ||
import {ResponsiveValue} from '../hooks/useResponsiveValue' | ||
import {getBreakpointDeclarations} from '../utils/getBreakpointDeclarations' | ||
import Box from '../Box' | ||
|
||
type Viewports = 'narrow' | 'regular' | 'wide' | ||
type Viewport = 'narrow' | 'regular' | 'wide' | ||
|
||
export type HiddenProps = { | ||
on: Array<Viewports> | Viewports | ||
on: Array<Viewport> | Viewport | ||
children: React.ReactNode | ||
} | ||
|
||
export const Hidden = ({on: hiddenViewports, children}: HiddenProps) => { | ||
const isNarrowViewport = useMedia(viewportRanges.narrow) | ||
const isRegularViewport = useMedia(viewportRanges.regular) | ||
const isWideViewport = useMedia(viewportRanges.wide) | ||
let show = true | ||
if (isNarrowViewport && (hiddenViewports === 'narrow' || hiddenViewports.indexOf('narrow') > -1)) { | ||
show = false | ||
} else if (isRegularViewport && (hiddenViewports === 'regular' || hiddenViewports.indexOf('regular') > -1)) { | ||
show = false | ||
} else if (isWideViewport && (hiddenViewports === 'wide' || hiddenViewports.indexOf('wide') > -1)) { | ||
show = false | ||
/* Normalize the value that is received from the prop `on`. | ||
* For array types : ['narrow', 'wide'] -> {narrow: true, wide: true} | ||
* For string types: 'narrow' -> {narrow: true} | ||
*/ | ||
function normalize(hiddenViewports: Array<Viewport> | Viewport): ResponsiveValue<boolean> | null { | ||
// For array types | ||
if (Array.isArray(hiddenViewports)) { | ||
const breakpoints: ResponsiveValue<boolean> = {} | ||
// ['narrow', 'wide'] -> {narrow: true, wide: true} | ||
for (const breakpoint of hiddenViewports) { | ||
breakpoints[breakpoint] = true | ||
} | ||
return breakpoints | ||
} | ||
// For string types | ||
// 'narrow' -> {narrow: true} | ||
return { | ||
[hiddenViewports]: true, | ||
} | ||
} | ||
|
||
return show ? <>{children}</> : null | ||
export const Hidden = ({on, children}: HiddenProps) => { | ||
// Get breakpoint declarations for the normalized ResponsiveValue object | ||
const styles = getBreakpointDeclarations(normalize(on), 'display', () => 'none') | ||
// Render the children with the styles | ||
return styles ? <Box sx={styles}>{children}</Box> : null | ||
} | ||
|
||
Hidden.displayName = 'Hidden' |
Oops, something went wrong.