-
Notifications
You must be signed in to change notification settings - Fork 645
Hidden component #2301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hidden component #2301
Changes from all commits
05435c4
9590976
8af384d
02c5642
685fdb8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@primer/react": patch | ||
| --- | ||
|
|
||
| Hidden component |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| --- | ||
| title: Hidden | ||
| description: Use Hidden to responsively hide or show content in narrow, regular and wide viewports. | ||
| source: https://github.com/primer/react/blob/main/src/Hidden/index.tsx | ||
| status: Alpha | ||
| componentId: hidden | ||
| --- | ||
|
|
||
| The `Hidden` component is a utility component that will help you hide or show content/components in different viewports. | ||
| **Attention:** Use Hidden only to control behaviour in a responsive manner. It does not take any `sx` props. | ||
|
|
||
| ## Example | ||
|
|
||
| ```jsx live | ||
| <Hidden when="narrow"> | ||
| <Placeholder height="80px" label="This is not visible in narrow viewport" /> | ||
| </Hidden> | ||
| ``` | ||
|
|
||
| ## Array as `when` prop | ||
|
|
||
| ```jsx live | ||
| <Hidden when={['narrow', 'wide']}> | ||
| <Placeholder height="80px" label="This is not visible in narrow and wide viewport" /> | ||
| </Hidden> | ||
| ``` | ||
|
|
||
| ## Props | ||
|
|
||
| <PropsTable> | ||
| <PropsTableRow | ||
| name="when" | ||
| type="string or Array" | ||
| description="Can be one or more values of 'narrow', 'wide', 'regular'" | ||
| /> | ||
| </PropsTable> | ||
|
|
||
| ## Status | ||
|
|
||
| <ComponentChecklist | ||
| items={{ | ||
| propsDocumented: true, | ||
| noUnnecessaryDeps: true, | ||
| adaptsToThemes: true, | ||
| adaptsToScreenSizes: true, | ||
| fullTestCoverage: false, | ||
| usedInProduction: false, | ||
| usageExamplesDocumented: true, | ||
| designReviewed: false, | ||
| a11yReviewed: false, | ||
| stableApi: false, | ||
| addressedApiFeedback: false, | ||
| hasDesignGuidelines: false, | ||
| hasFigmaComponent: false | ||
| }} | ||
| /> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import {Meta} from '@storybook/react' | ||
| import React from 'react' | ||
| import {ThemeProvider} from '..' | ||
| import {Hidden} from './Hidden' | ||
| import BaseStyles from '../BaseStyles' | ||
| import Box from '../Box' | ||
|
|
||
| const meta: Meta = { | ||
| title: 'Layout components/Hidden', | ||
| component: Hidden, | ||
| decorators: [ | ||
| (Story: React.ComponentType<React.PropsWithChildren<unknown>>): JSX.Element => ( | ||
| <ThemeProvider> | ||
| <BaseStyles> | ||
| <Story /> | ||
| </BaseStyles> | ||
| </ThemeProvider> | ||
| ) | ||
| ], | ||
| parameters: { | ||
| controls: { | ||
| expanded: true | ||
| } | ||
| }, | ||
| argTypes: { | ||
| on: { | ||
| type: { | ||
| name: 'enum', | ||
| value: ['narrow', 'regular', 'wide'] | ||
| }, | ||
| defaultValue: 'regular', | ||
| control: {type: 'radio'} | ||
| } | ||
| } | ||
| } | ||
| 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> | ||
| ) | ||
|
|
||
| export const isHiddenInNarrowOnly = () => ( | ||
| <Box> | ||
| <Hidden on="narrow">This is hidden in narrow only</Hidden> | ||
| </Box> | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import React from 'react' | ||
| import {useMedia} from '../hooks/useMedia' | ||
| import {viewportRanges} from '../hooks/useResponsiveValue' | ||
|
|
||
| type Viewports = 'narrow' | 'regular' | 'wide' | ||
|
|
||
| type HiddenProps = { | ||
| on: Array<Viewports> | Viewports | ||
| children: React.ReactNode | ||
| } | ||
|
|
||
| export const Hidden = ({on: hiddenViewports, children}: HiddenProps) => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I loved the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept going back and forth with
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would we need to worry about providing a default value for SSR in this exploration? |
||
| const isNarrowViewport = useMedia(viewportRanges.narrow) | ||
| const isRegularViewport = useMedia(viewportRanges.regular) | ||
| const isWideViewport = useMedia(viewportRanges.wide) | ||
|
Comment on lines
+13
to
+15
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think it'd be possible to generate one media query string from the given viewports? Would be cool to do something like: function mediaQuery(rangeOrRanges: Array<Viewports> | Viewports) {
const ranges = Array.isArray(rangeOrRanges) ? rangeOrRanges : [rangeOrRanges]
return ranges.map(range => viewportRanges[range]).join(', ')
}
export const Hidden = ({on: hiddenViewports, children}: HiddenProps) => {
const matches = useMedia(mediaQuery(hiddenViewports))
if (matches) {
return null
}
return children
}Basically any time one of the media queries from
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, its a good optimisation! |
||
| 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 | ||
| } | ||
| return show ? <>{children}</> : null | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import {Hidden} from './Hidden' | ||
|
|
||
| export default Hidden |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the implementation below, will this be changing to
on?