From 57fcfe6fa2478dbf0ecdb29a000dd32fa2e01537 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Fri, 8 Dec 2023 10:21:16 -0500 Subject: [PATCH] Adapts Blankslate to render proportionally in narrow areas (#3869) * adapts Blankslate to render proportionally in narrow areas * adds color token fallbacks * adds changeset * formats CSS with Prettier * rm dead css module style * uses smarter primitives * tweaks type scale * improves token usage * upgrades styled-components, converts Blankslate styles back to styled-components * adds comment explaining why 34rem for min-width * renders an inline style block to get around styled-component 5.x limitations around container blocks * Update src/Blankslate/Blankslate.tsx Co-authored-by: Siddharth Kshetrapal --------- Co-authored-by: Siddharth Kshetrapal --- .changeset/many-ants-pump.md | 7 ++ package-lock.json | 12 +-- src/Blankslate/Blankslate.tsx | 158 +++++++++++++++++++++++++--------- 3 files changed, 128 insertions(+), 49 deletions(-) create mode 100644 .changeset/many-ants-pump.md diff --git a/.changeset/many-ants-pump.md b/.changeset/many-ants-pump.md new file mode 100644 index 00000000000..4032eefb4bd --- /dev/null +++ b/.changeset/many-ants-pump.md @@ -0,0 +1,7 @@ +--- +'@primer/react': patch +--- + +Adapts Blankslate to render proportionally in narrow areas. + + diff --git a/package-lock.json b/package-lock.json index e8c310fee41..11454bb6a3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14126,9 +14126,9 @@ "dev": true }, "node_modules/@types/styled-components": { - "version": "5.1.27", - "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.27.tgz", - "integrity": "sha512-oY9c1SdztRRF0QDQdwXEenfAjGN4WGUkaMpx5hvdTbYYqw01qoY2GrHi+kAR6SVofynzD6KbGoF5ITP0zh5pvg==", + "version": "5.1.30", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.30.tgz", + "integrity": "sha512-xxJqw0s1myRTgrzHgG5tKHS9hK+KNhjbKMXDWlHRo9eDNVVUqf147QUGYUqwyCDkFyGr2pi1qJKFMEy0ACZb0A==", "dev": true, "dependencies": { "@types/hoist-non-react-statics": "*", @@ -18203,9 +18203,9 @@ "dev": true }, "node_modules/csstype": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", - "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, "node_modules/csv": { "version": "5.5.3", diff --git a/src/Blankslate/Blankslate.tsx b/src/Blankslate/Blankslate.tsx index 0742d8ae24b..abfad264cdf 100644 --- a/src/Blankslate/Blankslate.tsx +++ b/src/Blankslate/Blankslate.tsx @@ -1,71 +1,147 @@ import React from 'react' -import styled from 'styled-components' import Box from '../Box' import {Button} from '../Button' -import {get} from '../constants' import Link from '../Link' +import {get} from '../constants' +import styled from 'styled-components' + +export type BlankslateProps = React.PropsWithChildren<{ + /** + * Add a border around this component + */ + border?: boolean + + /** + * Constrain the maximum width of this component + */ + narrow?: boolean + + /** + * Increase the padding of this component + */ + spacious?: boolean +}> const StyledBlankslate = styled.div` - display: grid; - justify-items: center; - padding: ${get('space.5')}; + container-type: inline-size; + + .Blankslate { + --blankslate-outer-padding-block: var(--base-size-32); + --blankslate-outer-padding-inline: var(--base-size-32); + display: grid; + justify-items: center; + padding: var(--blankslate-outer-padding-block) var(--blankslate-outer-padding-inline); + } + + .Blankslate[data-spacious='true'] { + --blankslate-outer-padding-block: var(--base-size-80); + --blankslate-outer-padding-inline: var(--base-size-40); + } - &[data-border='true'] { - border: ${get('borderWidths.1')} solid ${get('colors.border.default')}; - border-radius: ${get('radii.2')}; + .Blankslate[data-border='true'] { + border: var(--borderWidth-thin) solid var(--borderColor-default, ${get('colors.border.default')}); + border-radius: var(--borderRadius-medium); } - &[data-narrow='true'] { + .Blankslate[data-narrow='true'] { margin: 0 auto; max-width: 485px; } - &[data-spacious='true'] { - padding: ${get('space.9')} ${get('space.6')}; + .Blankslate-Heading, + .Blankslate-Description { + margin: 0; + margin-bottom: var(--stack-gap-condensed); } - .BlankSlateAction { - margin-top: ${get('space.3')}; + .Blankslate-Heading { + font-size: var(--text-title-size-medium); + font-weight: var(--text-title-weight-medium); } - .BlankSlateAction:first-of-type { - margin-top: ${get('space.4')}; + .Blankslate-Description { + color: var(--fgColor-muted, ${get('colors.fg.muted')}); + font-size: var(--text-body-size-large); } - .BlankSlateAction:last-of-type { - margin-bottom: ${get('space.2')}; + .Blankslate-Action { + margin-top: var(--stack-gap-normal); + } + + .Blankslate-Action:first-of-type { + margin-top: var(--stack-gap-spacious); + } + + .Blankslate-Action:last-of-type { + margin-bottom: var(--stack-gap-condensed); } ` -export type BlankslateProps = React.PropsWithChildren<{ - /** - * Add a border around this component - */ - border?: boolean +const BlankslateContainerQuery = ` + /* At the time these styles were written, + 34rem was our "small" breakpoint width */ + @container (max-width: 34rem) { + ${StyledBlankslate} .Blankslate { + --blankslate-outer-padding-block: var(--base-size-20); + --blankslate-outer-padding-inline: var(--base-size-20); + } - /** - * Constrain the maximum width of this component - */ - narrow?: boolean + ${StyledBlankslate} .Blankslate[data-spacious='true'] { + --blankslate-outer-padding-block: var(--base-size-44); + --blankslate-outer-padding-inline: var(--base-size-28); + } - /** - * Increase the padding of this component - */ - spacious?: boolean -}> + ${StyledBlankslate} .Blankslate-Visual { + margin-bottom: var(--stack-gap-condensed); + max-width: var(--base-size-24); + } + + ${StyledBlankslate} .Blankslate-Visual svg { + width: 100%; + } + + ${StyledBlankslate} .Blankslate-Heading { + font-size: var(--text-title-size-small); + } + + ${StyledBlankslate} .Blankslate-Description { + font-size: var(--text-body-size-medium); + } + + ${StyledBlankslate} .Blankslate-Action { + margin-top: var(--stack-gap-condensed); + } + + ${StyledBlankslate} .Blankslate-Action:first-of-type { + margin-top: var(--stack-gap-normal); + } + + ${StyledBlankslate} .Blankslate-Action:last-of-type { + margin-bottom: calc(var(--stack-gap-condensed) / 2); + } +` function Blankslate({border, children, narrow, spacious}: BlankslateProps) { return ( - - {children} - + <> + {/* + This is a workaround so we can use `@container` without upgrading `styled-components` to 6.x + See [this comment](https://github.com/primer/react/pull/3869#discussion_r1392523030) for more info + */} + + +
+ {children} +
+
+ ) } export type VisualProps = React.PropsWithChildren function Visual({children}: VisualProps) { - return {children} + return {children} } export type HeadingProps = React.PropsWithChildren<{ @@ -74,7 +150,7 @@ export type HeadingProps = React.PropsWithChildren<{ function Heading({as = 'h2', children}: HeadingProps) { return ( - + {children} ) @@ -83,11 +159,7 @@ function Heading({as = 'h2', children}: HeadingProps) { export type DescriptionProps = React.PropsWithChildren function Description({children}: DescriptionProps) { - return ( - - {children} - - ) + return

{children}

} export type PrimaryActionProps = React.PropsWithChildren<{ @@ -96,7 +168,7 @@ export type PrimaryActionProps = React.PropsWithChildren<{ function PrimaryAction({children, href}: PrimaryActionProps) { return ( -
+
@@ -110,7 +182,7 @@ export type SecondaryActionProps = React.PropsWithChildren<{ function SecondaryAction({children, href}: SecondaryActionProps) { return ( -
+
{children}
)