diff --git a/.changeset/spotty-parents-cheat.md b/.changeset/spotty-parents-cheat.md new file mode 100644 index 00000000000..54544ed8632 --- /dev/null +++ b/.changeset/spotty-parents-cheat.md @@ -0,0 +1,19 @@ +--- +"@primer/react": minor +--- + +* Updated the `divider` prop in `PageLayout.Header`, `PageLayout.Pane`, and `PageLayout.Footer` to use the new responsive prop API introduced in https://github.com/primer/react/pull/2174. +* Deprecated the `dividerWhenNarrow` prop in favor of the new responsive prop API + +**Before** + +``` +divider="line" +dividerWhenNarrow="filled" +``` + +**After** + +``` +divider={{regular: 'line', narrow: 'filled'}} +``` diff --git a/docs/content/PageLayout.mdx b/docs/content/PageLayout.mdx index d9ad832f9e7..277c0c1a255 100644 --- a/docs/content/PageLayout.mdx +++ b/docs/content/PageLayout.mdx @@ -48,7 +48,8 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo - + {/* You can change the divider based on the viewport width */} + @@ -172,25 +173,39 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo @@ -213,10 +228,10 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo name="hidden" type={`| boolean | { - narrow?: boolean - regular?: boolean - wide?: boolean -}`} + narrow?: boolean + regular?: boolean + wide?: boolean + }`} defaultValue="false" description="Whether the content is hidden." /> @@ -250,25 +265,39 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo @@ -281,25 +310,39 @@ See [storybook](https://primer.style/react/storybook?path=/story/layout-pagelayo diff --git a/src/PageLayout/PageLayout.tsx b/src/PageLayout/PageLayout.tsx index b317597f12f..ed1f9fa820a 100644 --- a/src/PageLayout/PageLayout.tsx +++ b/src/PageLayout/PageLayout.tsx @@ -1,6 +1,6 @@ import React from 'react' import {Box} from '..' -import {ResponsiveValue, useResponsiveValue} from '../hooks/useResponsiveValue' +import {isResponsiveValue, ResponsiveValue, useResponsiveValue} from '../hooks/useResponsiveValue' import {BetterSystemStyleObject, merge, SxProp} from '../sx' const REGION_ORDER = { @@ -79,8 +79,7 @@ Root.displayName = 'PageLayout' // Divider (internal) type DividerProps = { - variant?: 'none' | 'line' - variantWhenNarrow?: 'inherit' | 'none' | 'line' | 'filled' + variant?: 'none' | 'line' | 'filled' | ResponsiveValue<'none' | 'line' | 'filled'> } & SxProp const horizontalDividerVariants = { @@ -111,12 +110,9 @@ function negateSpacingValue(value: number | null | Array) { return value === null ? null : -value } -const HorizontalDivider: React.FC> = ({ - variant = 'none', - variantWhenNarrow = 'inherit', - sx = {} -}) => { +const HorizontalDivider: React.FC> = ({variant = 'none', sx = {}}) => { const {padding} = React.useContext(PageLayoutContext) + const responsiveVariant = useResponsiveValue(variant, 'none') return ( > = ({ { // Stretch divider to viewport edges on narrow screens marginX: negateSpacingValue(SPACING_MAP[padding]), - ...horizontalDividerVariants[variantWhenNarrow === 'inherit' ? variant : variantWhenNarrow], + ...horizontalDividerVariants[responsiveVariant], [`@media screen and (min-width: ${theme.breakpoints[1]})`]: { - marginX: '0 !important', - ...horizontalDividerVariants[variant] + marginX: '0 !important' } }, sx @@ -157,26 +152,17 @@ const verticalDividerVariants = { } } -const VerticalDivider: React.FC> = ({ - variant = 'none', - variantWhenNarrow = 'inherit', - sx = {} -}) => { +const VerticalDivider: React.FC> = ({variant = 'none', sx = {}}) => { + const responsiveVariant = useResponsiveValue(variant, 'none') return ( - merge( - { - height: '100%', - ...verticalDividerVariants[variantWhenNarrow === 'inherit' ? variant : variantWhenNarrow], - [`@media screen and (min-width: ${theme.breakpoints[1]})`]: { - ...verticalDividerVariants[variant] - } - }, - sx - ) - } + sx={merge( + { + height: '100%', + ...verticalDividerVariants[responsiveVariant] + }, + sx + )} /> ) } @@ -185,7 +171,21 @@ const VerticalDivider: React.FC> = ({ // PageLayout.Header export type PageLayoutHeaderProps = { - divider?: 'none' | 'line' + divider?: 'none' | 'line' | ResponsiveValue<'none' | 'line', 'none' | 'line' | 'filled'> + /** + * @deprecated Use the `divider` prop with a responsive value instead. + * + * Before: + * ``` + * divider="line" + * dividerWhenNarrow="filled" + * ``` + * + * After: + * ``` + * divider={{regular: 'line', narrow: 'filled'}} + * ``` + */ dividerWhenNarrow?: 'inherit' | 'none' | 'line' | 'filled' hidden?: boolean | ResponsiveValue } & SxProp @@ -197,6 +197,13 @@ const Header: React.FC> = ({ children, sx = {} }) => { + // Combine divider and dividerWhenNarrow for backwards compatibility + const dividerProp = + !isResponsiveValue(divider) && dividerWhenNarrow !== 'inherit' + ? {regular: divider, narrow: dividerWhenNarrow} + : divider + + const dividerVariant = useResponsiveValue(dividerProp, 'none') const isHidden = useResponsiveValue(hidden, false) const {rowGap} = React.useContext(PageLayoutContext) return ( @@ -213,11 +220,7 @@ const Header: React.FC> = ({ )} > {children} - + ) } @@ -279,7 +282,21 @@ export type PageLayoutPaneProps = { position?: keyof typeof panePositions positionWhenNarrow?: 'inherit' | keyof typeof panePositions width?: keyof typeof paneWidths - divider?: 'none' | 'line' + divider?: 'none' | 'line' | ResponsiveValue<'none' | 'line', 'none' | 'line' | 'filled'> + /** + * @deprecated Use the `divider` prop with a responsive value instead. + * + * Before: + * ``` + * divider="line" + * dividerWhenNarrow="filled" + * ``` + * + * After: + * ``` + * divider={{regular: 'line', narrow: 'filled'}} + * ``` + */ dividerWhenNarrow?: 'inherit' | 'none' | 'line' | 'filled' hidden?: boolean | ResponsiveValue } & SxProp @@ -305,10 +322,16 @@ const Pane: React.FC> = ({ children, sx = {} }) => { + // Combine divider and dividerWhenNarrow for backwards compatibility + const dividerProp = + !isResponsiveValue(divider) && dividerWhenNarrow !== 'inherit' + ? {regular: divider, narrow: dividerWhenNarrow} + : divider + + const dividerVariant = useResponsiveValue(dividerProp, 'none') const isHidden = useResponsiveValue(hidden, false) const {rowGap, columnGap} = React.useContext(PageLayoutContext) const computedPositionWhenNarrow = positionWhenNarrow === 'inherit' ? position : positionWhenNarrow - const computedDividerWhenNarrow = dividerWhenNarrow === 'inherit' ? divider : dividerWhenNarrow return ( > = ({ > {/* Show a horizontal divider when viewport is narrow. Otherwise, show a vertical divider. */} {children} @@ -357,7 +382,21 @@ Pane.displayName = 'PageLayout.Pane' // PageLayout.Footer export type PageLayoutFooterProps = { - divider?: 'none' | 'line' + divider?: 'none' | 'line' | ResponsiveValue<'none' | 'line', 'none' | 'line' | 'filled'> + /** + * @deprecated Use the `divider` prop with a responsive value instead. + * + * Before: + * ``` + * divider="line" + * dividerWhenNarrow="filled" + * ``` + * + * After: + * ``` + * divider={{regular: 'line', narrow: 'filled'}} + * ``` + */ dividerWhenNarrow?: 'inherit' | 'none' | 'line' | 'filled' hidden?: boolean | ResponsiveValue } & SxProp @@ -369,6 +408,13 @@ const Footer: React.FC> = ({ children, sx = {} }) => { + // Combine divider and dividerWhenNarrow for backwards compatibility + const dividerProp = + !isResponsiveValue(divider) && dividerWhenNarrow !== 'inherit' + ? {regular: divider, narrow: dividerWhenNarrow} + : divider + + const dividerVariant = useResponsiveValue(dividerProp, 'none') const isHidden = useResponsiveValue(hidden, false) const {rowGap} = React.useContext(PageLayoutContext) return ( @@ -384,11 +430,7 @@ const Footer: React.FC> = ({ sx )} > - + {children} ) diff --git a/src/PageLayout/__snapshots__/PageLayout.test.tsx.snap b/src/PageLayout/__snapshots__/PageLayout.test.tsx.snap index cfc3a6d898e..24f8bfb8370 100644 --- a/src/PageLayout/__snapshots__/PageLayout.test.tsx.snap +++ b/src/PageLayout/__snapshots__/PageLayout.test.tsx.snap @@ -115,7 +115,6 @@ exports[`PageLayout renders condensed layout 1`] = ` .c3 { margin-left: 0 !important; margin-right: 0 !important; - display: none; } } @@ -138,13 +137,6 @@ exports[`PageLayout renders condensed layout 1`] = ` .c7 { margin-left: 0 !important; margin-right: 0 !important; - display: none; - } -} - -@media screen and (min-width:768px) { - .c8 { - display: none; } } @@ -315,7 +307,6 @@ exports[`PageLayout renders default layout 1`] = ` .c3 { margin-left: 0 !important; margin-right: 0 !important; - display: none; } } @@ -352,7 +343,6 @@ exports[`PageLayout renders default layout 1`] = ` .c7 { margin-left: 0 !important; margin-right: 0 !important; - display: none; } } @@ -364,12 +354,6 @@ exports[`PageLayout renders default layout 1`] = ` } } -@media screen and (min-width:768px) { - .c8 { - display: none; - } -} - @media screen and (min-width:1012px) { .c8 { margin-right: 24px; @@ -561,7 +545,6 @@ exports[`PageLayout renders pane in different position when narrow 1`] = ` .c3 { margin-left: 0 !important; margin-right: 0 !important; - display: none; } } @@ -577,7 +560,6 @@ exports[`PageLayout renders pane in different position when narrow 1`] = ` .c10 { margin-left: 0 !important; margin-right: 0 !important; - display: none; } } @@ -589,12 +571,6 @@ exports[`PageLayout renders pane in different position when narrow 1`] = ` } } -@media screen and (min-width:768px) { - .c7 { - display: none; - } -} - @media screen and (min-width:1012px) { .c7 { margin-right: 24px; @@ -718,6 +694,13 @@ exports[`PageLayout renders with dividers 1`] = ` margin-bottom: 16px; } +.c3 { + margin-left: -16px; + margin-right: -16px; + display: none; + margin-top: 16px; +} + .c4 { -webkit-order: 2; -ms-flex-order: 2; @@ -742,11 +725,18 @@ exports[`PageLayout renders with dividers 1`] = ` margin-right: auto; } -.c9 { +.c10 { + margin-left: -16px; + margin-right: -16px; + display: none; + margin-bottom: 16px; +} + +.c8 { width: 100%; } -.c10 { +.c9 { -webkit-order: 4; -ms-flex-order: 4; order: 4; @@ -754,16 +744,6 @@ exports[`PageLayout renders with dividers 1`] = ` margin-top: 16px; } -.c3 { - margin-left: -16px; - margin-right: -16px; - display: block; - height: 8px; - background-color: #f6f8fa; - box-shadow: inset 0 -1px 0 0 #d0d7de,inset 0 1px 0 0 #d0d7de; - margin-top: 16px; -} - .c6 { -webkit-order: 1; -ms-flex-order: 1; @@ -782,30 +762,11 @@ exports[`PageLayout renders with dividers 1`] = ` } .c7 { - margin-left: -16px; - margin-right: -16px; - display: block; - height: 8px; - background-color: #f6f8fa; - box-shadow: inset 0 -1px 0 0 #d0d7de,inset 0 1px 0 0 #d0d7de; - margin-top: 16px; -} - -.c8 { height: 100%; display: none; margin-left: 16px; } -.c11 { - margin-left: -16px; - margin-right: -16px; - display: block; - height: 1px; - background-color: #d0d7de; - margin-bottom: 16px; -} - @media screen and (min-width:1012px) { .c0 { padding: 24px; @@ -819,37 +780,49 @@ exports[`PageLayout renders with dividers 1`] = ` } @media screen and (min-width:768px) { - .c9 { - width: 256px; - } -} - -@media screen and (min-width:1012px) { - .c9 { - width: 296px; + .c3 { + margin-left: 0 !important; + margin-right: 0 !important; } } @media screen and (min-width:1012px) { - .c10 { + .c3 { + margin-left: -24px; + margin-right: -24px; margin-top: 24px; } } @media screen and (min-width:768px) { - .c3 { + .c10 { margin-left: 0 !important; margin-right: 0 !important; - display: block; - height: 1px; - background-color: #d0d7de; } } @media screen and (min-width:1012px) { - .c3 { + .c10 { margin-left: -24px; margin-right: -24px; + margin-bottom: 24px; + } +} + +@media screen and (min-width:768px) { + .c8 { + width: 256px; + } +} + +@media screen and (min-width:1012px) { + .c8 { + width: 296px; + } +} + +@media screen and (min-width:1012px) { + .c9 { margin-top: 24px; } } @@ -875,52 +848,12 @@ exports[`PageLayout renders with dividers 1`] = ` } } -@media screen and (min-width:768px) { - .c7 { - margin-left: 0 !important; - margin-right: 0 !important; - display: none; - } -} - @media screen and (min-width:1012px) { .c7 { - margin-left: -24px; - margin-right: -24px; - margin-top: 24px; - } -} - -@media screen and (min-width:768px) { - .c8 { - display: block; - width: 1px; - background-color: #d0d7de; - } -} - -@media screen and (min-width:1012px) { - .c8 { margin-left: 24px; } } -@media screen and (min-width:768px) { - .c11 { - margin-left: 0 !important; - margin-right: 0 !important; - display: none; - } -} - -@media screen and (min-width:1012px) { - .c11 { - margin-left: -24px; - margin-right: -24px; - margin-bottom: 24px; - } -} -
Pane