From c4b2c0ee499ebf7e614cf863a790189ede050002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 14 Aug 2024 21:43:37 +0200 Subject: [PATCH 01/26] Update typography tokens with new values --- packages/design-tokens/themes/shared.ts | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/design-tokens/themes/shared.ts b/packages/design-tokens/themes/shared.ts index cb524c3dc6..5a1f348705 100644 --- a/packages/design-tokens/themes/shared.ts +++ b/packages/design-tokens/themes/shared.ts @@ -173,22 +173,22 @@ export const shared = [ }, { name: '--cui-typography-headline-two-font-size', - value: '1.5rem', + value: '1.375rem', type: 'dimension', }, { name: '--cui-typography-headline-two-line-height', - value: '1.75rem', + value: '1.625rem', type: 'dimension', }, { name: '--cui-typography-headline-three-font-size', - value: '1.25rem', + value: '1.375rem', type: 'dimension', }, { name: '--cui-typography-headline-three-line-height', - value: '1.5rem', + value: '1.625rem', type: 'dimension', }, { @@ -198,57 +198,57 @@ export const shared = [ }, { name: '--cui-typography-headline-four-line-height', - value: '1.5rem', + value: '1.375rem', type: 'dimension', }, { name: '--cui-typography-title-one-font-size', - value: '7.5rem', + value: '4rem', type: 'dimension', }, { name: '--cui-typography-title-one-line-height', - value: '7.5rem', + value: '4.5rem', type: 'dimension', }, { name: '--cui-typography-title-two-font-size', - value: '6rem', + value: '3rem', type: 'dimension', }, { name: '--cui-typography-title-two-line-height', - value: '6rem', + value: '3.5rem', type: 'dimension', }, { name: '--cui-typography-title-three-font-size', - value: '4rem', + value: '3rem', type: 'dimension', }, { name: '--cui-typography-title-three-line-height', - value: '4rem', + value: '3.5rem', type: 'dimension', }, { name: '--cui-typography-title-four-font-size', - value: '3.5rem', + value: '2.5rem', type: 'dimension', }, { name: '--cui-typography-title-four-line-height', - value: '3.5rem', + value: '2.875rem', type: 'dimension', }, { name: '--cui-typography-sub-headline-font-size', - value: '0.875rem', + value: '1.125rem', type: 'dimension', }, { name: '--cui-typography-sub-headline-line-height', - value: '1.25rem', + value: '1.375rem', type: 'dimension', }, { @@ -258,7 +258,7 @@ export const shared = [ }, { name: '--cui-typography-body-one-line-height', - value: '1.5rem', + value: '1.375rem', type: 'dimension', }, { @@ -278,7 +278,7 @@ export const shared = [ }, { name: '--cui-typography-body-large-line-height', - value: '1.75rem', + value: '1.5rem', type: 'dimension', }, /* Z-indices */ From 889ea4cfb83be9b800384e1973bd7bb5bfac047c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 14 Aug 2024 21:56:36 +0200 Subject: [PATCH 02/26] Add new sizes to Body --- packages/circuit-ui/components/Body/Body.mdx | 2 +- .../components/Body/Body.module.css | 15 +++++++++ .../components/Body/Body.stories.tsx | 8 ++--- packages/circuit-ui/components/Body/Body.tsx | 32 +++++++++++++++++-- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/packages/circuit-ui/components/Body/Body.mdx b/packages/circuit-ui/components/Body/Body.mdx index d6ff462d95..9870e0913d 100644 --- a/packages/circuit-ui/components/Body/Body.mdx +++ b/packages/circuit-ui/components/Body/Body.mdx @@ -18,7 +18,7 @@ The Body component is used to present content to our users. ### Sizes -The Body component comes in two sizes. Use the default `one` size in most cases. Consider using the [BodyLarge component](Typography/BodyLarge) for large typography in specific cases. +The Body component comes in three sizes. Use the default `m` size in most cases. <Story of={Stories.Sizes} /> diff --git a/packages/circuit-ui/components/Body/Body.module.css b/packages/circuit-ui/components/Body/Body.module.css index 262306322e..b61df58219 100644 --- a/packages/circuit-ui/components/Body/Body.module.css +++ b/packages/circuit-ui/components/Body/Body.module.css @@ -4,6 +4,21 @@ /* Sizes */ +.l { + font-size: var(--cui-typography-body-large-font-size); + line-height: var(--cui-typography-body-large-line-height); +} + +.m { + font-size: var(--cui-typography-body-one-font-size); + line-height: var(--cui-typography-body-one-line-height); +} + +.s { + font-size: var(--cui-typography-body-two-font-size); + line-height: var(--cui-typography-body-two-line-height); +} + .one { font-size: var(--cui-typography-body-one-font-size); line-height: var(--cui-typography-body-one-line-height); diff --git a/packages/circuit-ui/components/Body/Body.stories.tsx b/packages/circuit-ui/components/Body/Body.stories.tsx index eda2d599e2..cf8917d0fb 100644 --- a/packages/circuit-ui/components/Body/Body.stories.tsx +++ b/packages/circuit-ui/components/Body/Body.stories.tsx @@ -30,12 +30,12 @@ export default { export const Base = (args: BodyProps) => <Body {...args}>{content}</Body>; -const sizes = ['one', 'two'] as const; +const sizes = ['l', 'm', 's'] as const; export const Sizes = (args: BodyProps) => - sizes.map((s) => ( - <Body key={s} {...args} size={s}> - This is a body {s}. {content} + sizes.map((size) => ( + <Body key={size} {...args} size={size}> + This is size {size}. {content} </Body> )); diff --git a/packages/circuit-ui/components/Body/Body.tsx b/packages/circuit-ui/components/Body/Body.tsx index af4669e4e9..b8efebe351 100644 --- a/packages/circuit-ui/components/Body/Body.tsx +++ b/packages/circuit-ui/components/Body/Body.tsx @@ -17,6 +17,7 @@ import { forwardRef, type HTMLAttributes } from 'react'; import type { AsPropType } from '../../types/prop-types.js'; import { clsx } from '../../styles/clsx.js'; +import { deprecate } from '../../util/logger.js'; import classes from './Body.module.css'; @@ -24,9 +25,20 @@ type Variant = 'highlight' | 'quote' | 'confirm' | 'alert' | 'subtle'; export interface BodyProps extends HTMLAttributes<HTMLParagraphElement> { /** - * Choose from 2 font sizes. Default `one`. + * Choose from 3 font sizes. Default `m`. */ - size?: 'one' | 'two'; + size?: + | 's' + | 'm' + | 'l' + /** + * @deprecated + */ + | 'one' + /** + * @deprecated + */ + | 'two'; /** * Choose from style variants. */ @@ -52,8 +64,22 @@ function getHTMLElement(variant?: Variant): AsPropType { * to our users. */ export const Body = forwardRef<HTMLParagraphElement, BodyProps>( - ({ className, as, size = 'one', variant, ...props }, ref) => { + ({ className, as, size = 'm', variant, ...props }, ref) => { const Element = as || getHTMLElement(variant); + + if (process.env.NODE_ENV !== 'production') { + const deprecatedSizeMap: Record<string, string> = { + 'one': 'm', + 'two': 's', + }; + if (size in deprecatedSizeMap) { + deprecate( + 'Body', + `The "${size}" size has been deprecated. Use the "${deprecatedSizeMap[size]}" size instead.`, + ); + } + } + return ( <Element {...props} From 87b03854ccb0fa5878831c56f37e21c999a28df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 14 Aug 2024 21:47:29 +0200 Subject: [PATCH 03/26] Add new sizes to Headline --- .../components/Headline/Headline.mdx | 2 +- .../components/Headline/Headline.module.css | 15 +++++++ .../components/Headline/Headline.stories.tsx | 8 ++-- .../components/Headline/Headline.tsx | 41 +++++++++++++++++-- 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/packages/circuit-ui/components/Headline/Headline.mdx b/packages/circuit-ui/components/Headline/Headline.mdx index 5a4679db2a..29b4b420d1 100644 --- a/packages/circuit-ui/components/Headline/Headline.mdx +++ b/packages/circuit-ui/components/Headline/Headline.mdx @@ -16,7 +16,7 @@ The Headline component is used for describing the contents of a page or page sec ### Sizes -The Headline component comes in four sizes. +The Headline component comes in three sizes. Use the `four` size for card headers and `three` for page titles in web applications. For specific use cases such as landing pages, consider using the [Title](Typography/Title) component. diff --git a/packages/circuit-ui/components/Headline/Headline.module.css b/packages/circuit-ui/components/Headline/Headline.module.css index 16070244a3..e5566d1d1b 100644 --- a/packages/circuit-ui/components/Headline/Headline.module.css +++ b/packages/circuit-ui/components/Headline/Headline.module.css @@ -6,6 +6,21 @@ /* Sizes */ +.l { + font-size: var(--cui-typography-headline-one-font-size); + line-height: var(--cui-typography-headline-one-line-height); +} + +.m { + font-size: var(--cui-typography-headline-two-font-size); + line-height: var(--cui-typography-headline-two-line-height); +} + +.s { + font-size: var(--cui-typography-headline-four-font-size); + line-height: var(--cui-typography-headline-four-line-height); +} + .one { font-size: var(--cui-typography-headline-one-font-size); line-height: var(--cui-typography-headline-one-line-height); diff --git a/packages/circuit-ui/components/Headline/Headline.stories.tsx b/packages/circuit-ui/components/Headline/Headline.stories.tsx index 644c1b241d..840ecf083a 100644 --- a/packages/circuit-ui/components/Headline/Headline.stories.tsx +++ b/packages/circuit-ui/components/Headline/Headline.stories.tsx @@ -28,12 +28,12 @@ Base.args = { as: 'h2', }; -const sizes = ['one', 'two', 'three', 'four'] as const; +const sizes = ['l', 'm', 's'] as const; export const Sizes = (args: HeadlineProps) => - sizes.map((s) => ( - <Headline key={s} {...args} size={s}> - This is a headline {s} + sizes.map((size) => ( + <Headline key={size} {...args} size={size}> + This is size {size} </Headline> )); diff --git a/packages/circuit-ui/components/Headline/Headline.tsx b/packages/circuit-ui/components/Headline/Headline.tsx index 204c47ed83..b58b7ef4eb 100644 --- a/packages/circuit-ui/components/Headline/Headline.tsx +++ b/packages/circuit-ui/components/Headline/Headline.tsx @@ -17,14 +17,34 @@ import { forwardRef, type HTMLAttributes } from 'react'; import { clsx } from '../../styles/clsx.js'; import { CircuitError } from '../../util/errors.js'; +import { deprecate } from '../../util/logger.js'; import classes from './Headline.module.css'; export interface HeadlineProps extends HTMLAttributes<HTMLHeadingElement> { /** - * A Circuit UI headline size. Defaults to `one`. + * Choose from 3 font sizes. Defaults to `m`. */ - size?: 'one' | 'two' | 'three' | 'four'; + size?: + | 's' + | 'm' + | 'l' + /** + * @deprecated + */ + | 'one' + /** + * @deprecated + */ + | 'two' + /** + * @deprecated + */ + | 'three' + /** + * @deprecated + */ + | 'four'; /** * The HTML heading element to render. * Headings should be nested sequentially without skipping any levels. @@ -37,7 +57,7 @@ export interface HeadlineProps extends HTMLAttributes<HTMLHeadingElement> { * A flexible headline component capable of rendering any HTML heading element. */ export const Headline = forwardRef<HTMLHeadingElement, HeadlineProps>( - ({ className, as, size = 'one', ...props }, ref) => { + ({ className, as, size = 'm', ...props }, ref) => { if ( process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test' && @@ -47,6 +67,21 @@ export const Headline = forwardRef<HTMLHeadingElement, HeadlineProps>( throw new CircuitError('Headline', 'The `as` prop is required.'); } + if (process.env.NODE_ENV !== 'production') { + const deprecatedSizeMap: Record<string, string> = { + 'one': 'l', + 'two': 'm', + 'three': 'm', + 'four': 's', + }; + if (size in deprecatedSizeMap) { + deprecate( + 'Headline', + `The "${size}" size has been deprecated. Use the "${deprecatedSizeMap[size]}" size instead.`, + ); + } + } + const Element = as || 'h2'; return ( From 3f6aa162bea335b342f7d504fa27000482e7d69f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 14 Aug 2024 21:58:32 +0200 Subject: [PATCH 04/26] Add new sizes to Title --- .../circuit-ui/components/Title/Title.mdx | 2 +- .../components/Title/Title.module.css | 15 +++++++ .../components/Title/Title.stories.tsx | 8 ++-- .../circuit-ui/components/Title/Title.tsx | 41 +++++++++++++++++-- 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/packages/circuit-ui/components/Title/Title.mdx b/packages/circuit-ui/components/Title/Title.mdx index 4f183200c3..14e4bcae69 100644 --- a/packages/circuit-ui/components/Title/Title.mdx +++ b/packages/circuit-ui/components/Title/Title.mdx @@ -16,7 +16,7 @@ The Title component is used to render headings with large typography. Typically, ### Sizes -The Title component comes in four sizes. In most cases, use the [Headline component](Typography/Headline) component instead to render headings. +The Title component comes in three sizes. In most cases, use the [Headline component](Typography/Headline) component instead to render headings. <Story of={Stories.Sizes} /> diff --git a/packages/circuit-ui/components/Title/Title.module.css b/packages/circuit-ui/components/Title/Title.module.css index e2edae4e40..5e63a768ad 100644 --- a/packages/circuit-ui/components/Title/Title.module.css +++ b/packages/circuit-ui/components/Title/Title.module.css @@ -6,6 +6,21 @@ /* Sizes */ +.l { + font-size: var(--cui-typography-title-one-font-size); + line-height: var(--cui-typography-title-one-line-height); +} + +.m { + font-size: var(--cui-typography-title-two-font-size); + line-height: var(--cui-typography-title-two-line-height); +} + +.s { + font-size: var(--cui-typography-title-four-font-size); + line-height: var(--cui-typography-title-four-line-height); +} + .one { font-size: var(--cui-typography-title-one-font-size); line-height: var(--cui-typography-title-one-line-height); diff --git a/packages/circuit-ui/components/Title/Title.stories.tsx b/packages/circuit-ui/components/Title/Title.stories.tsx index b2f433928e..0fe6a4fddd 100644 --- a/packages/circuit-ui/components/Title/Title.stories.tsx +++ b/packages/circuit-ui/components/Title/Title.stories.tsx @@ -28,12 +28,12 @@ Base.args = { as: 'h1', }; -const sizes = ['one', 'two', 'three', 'four'] as const; +const sizes = ['l', 'm', 's'] as const; export const Sizes = (args: TitleProps) => - sizes.map((s) => ( - <Title key={s} {...args} size={s}> - This is a Title {s} + sizes.map((size) => ( + <Title key={size} {...args} size={size}> + This is size {size} </Title> )); diff --git a/packages/circuit-ui/components/Title/Title.tsx b/packages/circuit-ui/components/Title/Title.tsx index 6bb00d088d..358d0bb113 100644 --- a/packages/circuit-ui/components/Title/Title.tsx +++ b/packages/circuit-ui/components/Title/Title.tsx @@ -17,14 +17,34 @@ import { forwardRef, type HTMLAttributes } from 'react'; import { clsx } from '../../styles/clsx.js'; import { CircuitError } from '../../util/errors.js'; +import { deprecate } from '../../util/logger.js'; import classes from './Title.module.css'; export interface TitleProps extends HTMLAttributes<HTMLHeadingElement> { /** - * A Circuit UI title size. Defaults to `one`. + * Choose from 3 font sizes. Defaults to `m`. */ - size?: 'one' | 'two' | 'three' | 'four'; + size?: + | 's' + | 'm' + | 'l' + /** + * @deprecated + */ + | 'one' + /** + * @deprecated + */ + | 'two' + /** + * @deprecated + */ + | 'three' + /** + * @deprecated + */ + | 'four'; /** * The HTML heading element to render. * Headings should be nested sequentially without skipping any levels. @@ -37,7 +57,7 @@ export interface TitleProps extends HTMLAttributes<HTMLHeadingElement> { * A flexible title component capable of rendering any HTML heading element. */ export const Title = forwardRef<HTMLHeadingElement, TitleProps>( - ({ className, as, size = 'one', ...props }, ref) => { + ({ className, as, size = 'm', ...props }, ref) => { if ( process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test' && @@ -47,6 +67,21 @@ export const Title = forwardRef<HTMLHeadingElement, TitleProps>( throw new CircuitError('Title', 'The `as` prop is required.'); } + if (process.env.NODE_ENV !== 'production') { + const deprecatedSizeMap: Record<string, string> = { + 'one': 'l', + 'two': 'm', + 'three': 'm', + 'four': 's', + }; + if (size in deprecatedSizeMap) { + deprecate( + 'Title', + `The "${size}" size has been deprecated. Use the "${deprecatedSizeMap[size]}" size instead.`, + ); + } + } + const Element = as || 'h1'; return ( From 2fa0351d1a118c15093248203ec66efcf0d43711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 14 Aug 2024 21:49:21 +0200 Subject: [PATCH 05/26] Deprecate the BodyLarge component --- .../circuit-ui/components/BodyLarge/BodyLarge.mdx | 4 +++- .../circuit-ui/components/BodyLarge/BodyLarge.tsx | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/circuit-ui/components/BodyLarge/BodyLarge.mdx b/packages/circuit-ui/components/BodyLarge/BodyLarge.mdx index 08b3f5d464..fa308ec5f6 100644 --- a/packages/circuit-ui/components/BodyLarge/BodyLarge.mdx +++ b/packages/circuit-ui/components/BodyLarge/BodyLarge.mdx @@ -5,7 +5,9 @@ import * as Stories from './BodyLarge.stories'; # BodyLarge -<Status variant="stable" /> +<Status variant="deprecated"> +Use the Body component in size `l` instead. +</Status> The BodyLarge component is used to render content with large typography. Typically, large typography is intended for landing pages. In most cases, the [Body](Typography/Body) should be used instead. diff --git a/packages/circuit-ui/components/BodyLarge/BodyLarge.tsx b/packages/circuit-ui/components/BodyLarge/BodyLarge.tsx index 65516f2978..476324ebd4 100644 --- a/packages/circuit-ui/components/BodyLarge/BodyLarge.tsx +++ b/packages/circuit-ui/components/BodyLarge/BodyLarge.tsx @@ -17,6 +17,7 @@ import { forwardRef, type HTMLAttributes, type Ref } from 'react'; import type { AsPropType } from '../../types/prop-types.js'; import { clsx } from '../../styles/clsx.js'; +import { deprecate } from '../../util/logger.js'; import classes from './BodyLarge.module.css'; @@ -48,11 +49,17 @@ function getHTMLElement(variant?: Variant): AsPropType { } /** - * The BodyLarge component is used to present the core textual content - * to our users. + * @deprecated Use the Body component in size `l` instead. */ export const BodyLarge = forwardRef<HTMLParagraphElement, BodyLargeProps>( ({ className, as, variant, ...props }, ref) => { + if (process.env.NODE_ENV !== 'production') { + deprecate( + 'BodyLarge', + 'The BodyLarge component has been deprecated. Use the Body component in size `l` instead.', + ); + } + const Element = as || getHTMLElement(variant); return ( <Element From 3044645d367b6567b25e87d0b9c910d0d093678d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 14 Aug 2024 21:51:26 +0200 Subject: [PATCH 06/26] Deprecate the SubHeadline component --- .../circuit-ui/components/SubHeadline/SubHeadline.mdx | 4 +++- .../circuit-ui/components/SubHeadline/SubHeadline.tsx | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/circuit-ui/components/SubHeadline/SubHeadline.mdx b/packages/circuit-ui/components/SubHeadline/SubHeadline.mdx index 0909f36672..ebf2627ab0 100644 --- a/packages/circuit-ui/components/SubHeadline/SubHeadline.mdx +++ b/packages/circuit-ui/components/SubHeadline/SubHeadline.mdx @@ -5,7 +5,9 @@ import * as Stories from './SubHeadline.stories'; # SubHeadline -<Status variant="stable" /> +<Status variant="deprecated"> +Use the Headline component in size `s` instead. +</Status> The SubHeadline component helps break up larger related chunks of content in the same section. It is typically used to separate subsections within a card. diff --git a/packages/circuit-ui/components/SubHeadline/SubHeadline.tsx b/packages/circuit-ui/components/SubHeadline/SubHeadline.tsx index a7832923d5..15840419d5 100644 --- a/packages/circuit-ui/components/SubHeadline/SubHeadline.tsx +++ b/packages/circuit-ui/components/SubHeadline/SubHeadline.tsx @@ -17,6 +17,7 @@ import { forwardRef, type HTMLAttributes } from 'react'; import { clsx } from '../../styles/clsx.js'; import { CircuitError } from '../../util/errors.js'; +import { deprecate } from '../../util/logger.js'; import classes from './SubHeadline.module.css'; @@ -30,8 +31,7 @@ export interface SubHeadlineProps extends HTMLAttributes<HTMLHeadingElement> { } /** - * A flexible SubHeadline component capable of rendering using any HTML heading - * element, except h1. + * @deprecated Use the Headline component in size `s` instead. */ export const SubHeadline = forwardRef<HTMLHeadingElement, SubHeadlineProps>( ({ className, as, ...props }, ref) => { @@ -44,6 +44,13 @@ export const SubHeadline = forwardRef<HTMLHeadingElement, SubHeadlineProps>( throw new CircuitError('SubHeadline', 'The `as` prop is required.'); } + if (process.env.NODE_ENV !== 'production') { + deprecate( + 'SubHeadline', + 'The SubHeadline component has been deprecated. Use the Headline component in size `s` instead.', + ); + } + const Element = as || 'h2'; return ( From e6fe8b41b9a47287ae704ef675916c3e70bb7053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Thu, 15 Aug 2024 11:23:29 +0200 Subject: [PATCH 07/26] Replace SubHeadline component in SideNavigation --- .../components/DesktopNavigation/DesktopNavigation.tsx | 2 +- .../components/SecondaryLinks/SecondaryLinks.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/circuit-ui/components/SideNavigation/components/DesktopNavigation/DesktopNavigation.tsx b/packages/circuit-ui/components/SideNavigation/components/DesktopNavigation/DesktopNavigation.tsx index a8ad6d7fda..9efa23c2ee 100644 --- a/packages/circuit-ui/components/SideNavigation/components/DesktopNavigation/DesktopNavigation.tsx +++ b/packages/circuit-ui/components/SideNavigation/components/DesktopNavigation/DesktopNavigation.tsx @@ -83,7 +83,7 @@ export function DesktopNavigation({ aria-label={secondaryNavigationLabel} > <Skeleton className={classes.headline} as="div"> - <Headline as="h2" size="four"> + <Headline as="h2" size="three"> {activePrimaryLink?.label} </Headline> </Skeleton> diff --git a/packages/circuit-ui/components/SideNavigation/components/SecondaryLinks/SecondaryLinks.tsx b/packages/circuit-ui/components/SideNavigation/components/SecondaryLinks/SecondaryLinks.tsx index d175413a45..442446e891 100644 --- a/packages/circuit-ui/components/SideNavigation/components/SecondaryLinks/SecondaryLinks.tsx +++ b/packages/circuit-ui/components/SideNavigation/components/SecondaryLinks/SecondaryLinks.tsx @@ -24,7 +24,7 @@ import { useFocusList, type FocusProps, } from '../../../../hooks/useFocusList/index.js'; -import { SubHeadline } from '../../../SubHeadline/index.js'; +import { Headline } from '../../../Headline/index.js'; import { Body } from '../../../Body/index.js'; import { Badge } from '../../../Badge/index.js'; import { useComponents } from '../../../ComponentsContext/index.js'; @@ -81,7 +81,9 @@ function SecondaryGroup({ <li> {label && ( <Skeleton className={classes['group-headline']} as="div"> - <SubHeadline as="h3">{label}</SubHeadline> + <Headline as="h3" size="s"> + {label} + </Headline> </Skeleton> )} <ul role="list" className={classes.list}> From e007df1870549c9b50048c03602c9b5cd70bc586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Thu, 15 Aug 2024 11:35:41 +0200 Subject: [PATCH 08/26] Add explicit color to Body component --- packages/circuit-ui/components/Body/Body.module.css | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/circuit-ui/components/Body/Body.module.css b/packages/circuit-ui/components/Body/Body.module.css index b61df58219..e0396c2eea 100644 --- a/packages/circuit-ui/components/Body/Body.module.css +++ b/packages/circuit-ui/components/Body/Body.module.css @@ -1,5 +1,6 @@ .base { font-weight: var(--cui-font-weight-regular); + color: var(--cui-fg-normal); } /* Sizes */ From d054e093995a6f8e3384b2313050d3b3c796d431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Tue, 20 Aug 2024 13:20:06 +0200 Subject: [PATCH 09/26] Rename Title component to Display --- docs/features/1-theme.mdx | 2 +- .../circuit-ui/components/Display/Display.mdx | 27 +++++++++++++++++++ .../Display.module.css} | 0 .../Display.spec.tsx} | 18 ++++++------- .../Display.stories.tsx} | 16 +++++------ .../{Title/Title.tsx => Display/Display.tsx} | 12 ++++----- .../components/{Title => Display}/index.ts | 4 +-- .../components/Headline/Headline.mdx | 2 +- .../circuit-ui/components/Title/Title.mdx | 27 ------------------- packages/circuit-ui/index.ts | 4 +-- .../no-deprecated-components/index.ts | 8 ++++++ templates/astro/src/pages/index.astro | 6 ++--- templates/nextjs/template/app/page.tsx | 6 ++--- templates/remix/app/routes/_index/route.tsx | 6 ++--- 14 files changed, 73 insertions(+), 65 deletions(-) create mode 100644 packages/circuit-ui/components/Display/Display.mdx rename packages/circuit-ui/components/{Title/Title.module.css => Display/Display.module.css} (100%) rename packages/circuit-ui/components/{Title/Title.spec.tsx => Display/Display.spec.tsx} (82%) rename packages/circuit-ui/components/{Title/Title.stories.tsx => Display/Display.stories.tsx} (71%) rename packages/circuit-ui/components/{Title/Title.tsx => Display/Display.tsx} (87%) rename packages/circuit-ui/components/{Title => Display}/index.ts (86%) delete mode 100644 packages/circuit-ui/components/Title/Title.mdx diff --git a/docs/features/1-theme.mdx b/docs/features/1-theme.mdx index bf30171a85..a4fbf5348c 100644 --- a/docs/features/1-theme.mdx +++ b/docs/features/1-theme.mdx @@ -61,7 +61,7 @@ Use spacings for gutters, margins, and paddings. Don't use it for border width, ## Typography -Avoid using the `var(--cui-typography-*)` CSS custom properties directly in your styles. Instead, use the typography components [`Title`](Typography/Title/Docs), [`Headline`](Typography/Headline/Docs), [`SubHeadline`](Typography/SubHeadline/Docs), [`Body`](Typography/Body/Docs), and [`BodyLarge`](Typography/BodyLarge/Docs). +Avoid using the `var(--cui-typography-*)` CSS custom properties directly in your styles. Instead, use the typography components [`Display`](Typography/Display/Docs), [`Headline`](Typography/Headline/Docs), [`SubHeadline`](Typography/SubHeadline/Docs), [`Body`](Typography/Body/Docs), and [`BodyLarge`](Typography/BodyLarge/Docs). ## Font stack diff --git a/packages/circuit-ui/components/Display/Display.mdx b/packages/circuit-ui/components/Display/Display.mdx new file mode 100644 index 0000000000..a3a4c4fd81 --- /dev/null +++ b/packages/circuit-ui/components/Display/Display.mdx @@ -0,0 +1,27 @@ +import { Meta, Status, Props, Story } from '../../../../.storybook/components'; +import * as Stories from './Display.stories'; + +<Meta of={Stories} /> + +# Display + +<Status variant="stable" /> + +The Display component is used to render headings with large typography. Typically, large typography is intended for landing pages. In most cases, the [Headline](Typography/Headline) should be used instead. + +<Story of={Stories.Base} /> +<Props /> + +## Component variations + +### Sizes + +The Display component comes in three sizes. In most cases, use the [Headline component](Typography/Headline) component instead to render headings. + +<Story of={Stories.Sizes} /> + +--- + +## Accessibility + +All accessibility guidelines for the [Headline component](Typography/Headline) also apply to the Display component../Display.stories diff --git a/packages/circuit-ui/components/Title/Title.module.css b/packages/circuit-ui/components/Display/Display.module.css similarity index 100% rename from packages/circuit-ui/components/Title/Title.module.css rename to packages/circuit-ui/components/Display/Display.module.css diff --git a/packages/circuit-ui/components/Title/Title.spec.tsx b/packages/circuit-ui/components/Display/Display.spec.tsx similarity index 82% rename from packages/circuit-ui/components/Title/Title.spec.tsx rename to packages/circuit-ui/components/Display/Display.spec.tsx index 984fbfd8d4..ecb2ccfbbb 100644 --- a/packages/circuit-ui/components/Title/Title.spec.tsx +++ b/packages/circuit-ui/components/Display/Display.spec.tsx @@ -18,15 +18,15 @@ import { createRef } from 'react'; import { render, axe } from '../../util/test-utils.js'; -import { Title } from './Title.js'; +import { Display } from './Display.jsx'; -describe('Title', () => { +describe('Display', () => { it('should merge a custom class name with the default ones', () => { const className = 'foo'; const { container } = render( - <Title as="h2" className={className}> - Title - </Title>, + <Display as="h2" className={className}> + Display + </Display>, ); const headline = container.querySelector('h2'); expect(headline?.className).toContain(className); @@ -35,16 +35,16 @@ describe('Title', () => { it('should forward a ref', () => { const ref = createRef<HTMLHeadingElement>(); const { container } = render( - <Title as="h2" ref={ref}> - Title - </Title>, + <Display as="h2" ref={ref}> + Display + </Display>, ); const headline = container.querySelector('h2'); expect(ref.current).toBe(headline); }); it('should meet accessibility guidelines', async () => { - const { container } = render(<Title as="h2">Title</Title>); + const { container } = render(<Display as="h2">Display</Display>); const actual = await axe(container); expect(actual).toHaveNoViolations(); }); diff --git a/packages/circuit-ui/components/Title/Title.stories.tsx b/packages/circuit-ui/components/Display/Display.stories.tsx similarity index 71% rename from packages/circuit-ui/components/Title/Title.stories.tsx rename to packages/circuit-ui/components/Display/Display.stories.tsx index 0fe6a4fddd..67fb43eb5f 100644 --- a/packages/circuit-ui/components/Title/Title.stories.tsx +++ b/packages/circuit-ui/components/Display/Display.stories.tsx @@ -13,15 +13,15 @@ * limitations under the License. */ -import { Title, type TitleProps } from './Title.js'; +import { Display, type DisplayProps } from './Display.jsx'; export default { - title: 'Typography/Title', - component: Title, + title: 'Typography/Display', + component: Display, }; -export const Base = (args: TitleProps) => ( - <Title {...args}>This is a Title</Title> +export const Base = (args: DisplayProps) => ( + <Display {...args}>This is a Display</Display> ); Base.args = { @@ -30,11 +30,11 @@ Base.args = { const sizes = ['l', 'm', 's'] as const; -export const Sizes = (args: TitleProps) => +export const Sizes = (args: DisplayProps) => sizes.map((size) => ( - <Title key={size} {...args} size={size}> + <Display key={size} {...args} size={size}> This is size {size} - </Title> + </Display> )); Sizes.args = { diff --git a/packages/circuit-ui/components/Title/Title.tsx b/packages/circuit-ui/components/Display/Display.tsx similarity index 87% rename from packages/circuit-ui/components/Title/Title.tsx rename to packages/circuit-ui/components/Display/Display.tsx index 358d0bb113..01cde9b714 100644 --- a/packages/circuit-ui/components/Title/Title.tsx +++ b/packages/circuit-ui/components/Display/Display.tsx @@ -19,9 +19,9 @@ import { clsx } from '../../styles/clsx.js'; import { CircuitError } from '../../util/errors.js'; import { deprecate } from '../../util/logger.js'; -import classes from './Title.module.css'; +import classes from './Display.module.css'; -export interface TitleProps extends HTMLAttributes<HTMLHeadingElement> { +export interface DisplayProps extends HTMLAttributes<HTMLHeadingElement> { /** * Choose from 3 font sizes. Defaults to `m`. */ @@ -56,7 +56,7 @@ export interface TitleProps extends HTMLAttributes<HTMLHeadingElement> { /** * A flexible title component capable of rendering any HTML heading element. */ -export const Title = forwardRef<HTMLHeadingElement, TitleProps>( +export const Display = forwardRef<HTMLHeadingElement, DisplayProps>( ({ className, as, size = 'm', ...props }, ref) => { if ( process.env.NODE_ENV !== 'production' && @@ -64,7 +64,7 @@ export const Title = forwardRef<HTMLHeadingElement, TitleProps>( !process?.env?.UNSAFE_DISABLE_ELEMENT_ERRORS && !as ) { - throw new CircuitError('Title', 'The `as` prop is required.'); + throw new CircuitError('Display', 'The `as` prop is required.'); } if (process.env.NODE_ENV !== 'production') { @@ -76,7 +76,7 @@ export const Title = forwardRef<HTMLHeadingElement, TitleProps>( }; if (size in deprecatedSizeMap) { deprecate( - 'Title', + 'Display', `The "${size}" size has been deprecated. Use the "${deprecatedSizeMap[size]}" size instead.`, ); } @@ -94,4 +94,4 @@ export const Title = forwardRef<HTMLHeadingElement, TitleProps>( }, ); -Title.displayName = 'Title'; +Display.displayName = 'Display'; diff --git a/packages/circuit-ui/components/Title/index.ts b/packages/circuit-ui/components/Display/index.ts similarity index 86% rename from packages/circuit-ui/components/Title/index.ts rename to packages/circuit-ui/components/Display/index.ts index 347923192c..b85c320261 100644 --- a/packages/circuit-ui/components/Title/index.ts +++ b/packages/circuit-ui/components/Display/index.ts @@ -13,6 +13,6 @@ * limitations under the License. */ -export { Title } from './Title.js'; +export { Display } from './Display.jsx'; -export type { TitleProps } from './Title.js'; +export type { DisplayProps } from './Display.jsx'; diff --git a/packages/circuit-ui/components/Headline/Headline.mdx b/packages/circuit-ui/components/Headline/Headline.mdx index 29b4b420d1..2731e7b862 100644 --- a/packages/circuit-ui/components/Headline/Headline.mdx +++ b/packages/circuit-ui/components/Headline/Headline.mdx @@ -18,7 +18,7 @@ The Headline component is used for describing the contents of a page or page sec The Headline component comes in three sizes. -Use the `four` size for card headers and `three` for page titles in web applications. For specific use cases such as landing pages, consider using the [Title](Typography/Title) component. +Use the `four` size for card headers and `three` for page titles in web applications. For specific use cases such as landing pages, consider using the [Display](Typography/Display) component. <Story of={Stories.Sizes} inline={false} /> diff --git a/packages/circuit-ui/components/Title/Title.mdx b/packages/circuit-ui/components/Title/Title.mdx deleted file mode 100644 index 14e4bcae69..0000000000 --- a/packages/circuit-ui/components/Title/Title.mdx +++ /dev/null @@ -1,27 +0,0 @@ -import { Meta, Status, Props, Story } from '../../../../.storybook/components'; -import * as Stories from './Title.stories'; - -<Meta of={Stories} /> - -# Title - -<Status variant="stable" /> - -The Title component is used to render headings with large typography. Typically, large typography is intended for landing pages. In most cases, the [Headline](Typography/Headline) should be used instead. - -<Story of={Stories.Base} /> -<Props /> - -## Component variations - -### Sizes - -The Title component comes in three sizes. In most cases, use the [Headline component](Typography/Headline) component instead to render headings. - -<Story of={Stories.Sizes} /> - ---- - -## Accessibility - -All accessibility guidelines for the [Headline component](Typography/Headline) also apply to the Title component. diff --git a/packages/circuit-ui/index.ts b/packages/circuit-ui/index.ts index 8263f8e5e1..02608c4248 100644 --- a/packages/circuit-ui/index.ts +++ b/packages/circuit-ui/index.ts @@ -21,8 +21,8 @@ export { clsx } from './styles/clsx.js'; // Typography export { Headline } from './components/Headline/index.js'; export type { HeadlineProps } from './components/Headline/index.js'; -export { Title } from './components/Title/index.js'; -export type { TitleProps } from './components/Title/index.js'; +export { Display } from './components/Display/index.js'; +export type { DisplayProps } from './components/Display/index.js'; export { SubHeadline } from './components/SubHeadline/index.js'; export type { SubHeadlineProps } from './components/SubHeadline/index.js'; export { Body } from './components/Body/index.js'; diff --git a/packages/eslint-plugin-circuit-ui/no-deprecated-components/index.ts b/packages/eslint-plugin-circuit-ui/no-deprecated-components/index.ts index 1fb4c815f1..d49163e463 100644 --- a/packages/eslint-plugin-circuit-ui/no-deprecated-components/index.ts +++ b/packages/eslint-plugin-circuit-ui/no-deprecated-components/index.ts @@ -31,6 +31,14 @@ const components = [ name: 'Selector', alternative: 'Use the SelectorGroup component instead.', }, + { + name: 'SubHeadline', + alternative: 'Use the Headline component in size `s` instead.', + }, + { + name: 'Title', + alternative: 'Use the new Display component instead.', + }, ]; export const noDeprecatedComponents = createRule({ diff --git a/templates/astro/src/pages/index.astro b/templates/astro/src/pages/index.astro index 30fd0d931c..4326b46f3d 100644 --- a/templates/astro/src/pages/index.astro +++ b/templates/astro/src/pages/index.astro @@ -1,5 +1,5 @@ --- -import { Title, BodyLarge } from '@sumup-oss/circuit-ui'; +import { Display, BodyLarge } from '@sumup-oss/circuit-ui'; import Root from '../layouts/Root.astro'; import DocCard from '../components/DocCard.astro'; @@ -7,9 +7,9 @@ const title = 'Welcome to Circuit UI + Astro'; --- <Root title={title}> - <Title as="h1" size="three"> + <Display as="h1" size="three"> {title} - </Title> + </Display> <BodyLarge className="intro"> Get started by editing <code>src/pages/index.astro</code> diff --git a/templates/nextjs/template/app/page.tsx b/templates/nextjs/template/app/page.tsx index 2654164ef6..3fe28a978d 100644 --- a/templates/nextjs/template/app/page.tsx +++ b/templates/nextjs/template/app/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next'; -import { Title, BodyLarge } from '@sumup-oss/circuit-ui'; +import { Display, BodyLarge } from '@sumup-oss/circuit-ui'; import { SumUpLogo } from '@sumup-oss/icons'; import { DocCard } from '../components/DocCard'; @@ -14,9 +14,9 @@ export default function Page() { return ( <div className={styles.grid}> <main className={styles.main}> - <Title as="h1" size="three"> + <Display as="h1" size="three"> {metadata.title as string} - </Title> + </Display> <BodyLarge className={styles.intro}> Get started by editing <code>app/page.tsx</code> diff --git a/templates/remix/app/routes/_index/route.tsx b/templates/remix/app/routes/_index/route.tsx index 6eb181a587..2399a74711 100644 --- a/templates/remix/app/routes/_index/route.tsx +++ b/templates/remix/app/routes/_index/route.tsx @@ -1,5 +1,5 @@ import type { MetaFunction } from '@remix-run/node'; -import { Title, BodyLarge } from '@sumup-oss/circuit-ui'; +import { Display, BodyLarge } from '@sumup-oss/circuit-ui'; import { DocCard } from '../../components/DocCard/index.js'; @@ -18,9 +18,9 @@ export const meta: MetaFunction = () => [ export default function Index() { return ( <> - <Title as="h1" size="three"> + <Display as="h1" size="three"> {title} - </Title> + </Display> <BodyLarge className={styles.intro}> Get started by editing <code>app/routes/_index/route.tsx</code> From 77f1b826c79cee4bf364e4bd4158abc52e333cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Tue, 20 Aug 2024 13:27:51 +0200 Subject: [PATCH 10/26] Add weight prop to Body component --- packages/circuit-ui/components/Body/Body.mdx | 6 ++++++ packages/circuit-ui/components/Body/Body.module.css | 10 ++++++++++ packages/circuit-ui/components/Body/Body.stories.tsx | 9 +++++++++ packages/circuit-ui/components/Body/Body.tsx | 10 +++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/circuit-ui/components/Body/Body.mdx b/packages/circuit-ui/components/Body/Body.mdx index 9870e0913d..acb19ee7cb 100644 --- a/packages/circuit-ui/components/Body/Body.mdx +++ b/packages/circuit-ui/components/Body/Body.mdx @@ -22,6 +22,12 @@ The Body component comes in three sizes. Use the default `m` size in most cases. <Story of={Stories.Sizes} /> +### Weights + +The Body component comes in three weights. Use the default `regular` weight in most cases. + +<Story of={Stories.Weights} /> + ### Variants The Body component accepts five different variants—`highlight`, `quote`, `confirm`, `alert` and `subtle`—to tailor it according to the content we are presenting. diff --git a/packages/circuit-ui/components/Body/Body.module.css b/packages/circuit-ui/components/Body/Body.module.css index e0396c2eea..ce006a5e95 100644 --- a/packages/circuit-ui/components/Body/Body.module.css +++ b/packages/circuit-ui/components/Body/Body.module.css @@ -30,6 +30,16 @@ line-height: var(--cui-typography-body-two-line-height); } +/* Weights */ + +.regular { + font-weight: var(--cui-font-weight-regular); +} + +.bold { + font-weight: var(--cui-font-weight-bold); +} + /* Variants */ .highlight, diff --git a/packages/circuit-ui/components/Body/Body.stories.tsx b/packages/circuit-ui/components/Body/Body.stories.tsx index cf8917d0fb..ae3a36af8e 100644 --- a/packages/circuit-ui/components/Body/Body.stories.tsx +++ b/packages/circuit-ui/components/Body/Body.stories.tsx @@ -39,6 +39,15 @@ export const Sizes = (args: BodyProps) => </Body> )); +const weights = ['regular', 'bold'] as const; + +export const Weights = (args: BodyProps) => + weights.map((weight) => ( + <Body key={weight} {...args} weight={weight}> + This is the {weight} weight. {content} + </Body> + )); + const variants = ['highlight', 'quote', 'confirm', 'alert', 'subtle'] as const; export const Variants = (args: BodyProps) => diff --git a/packages/circuit-ui/components/Body/Body.tsx b/packages/circuit-ui/components/Body/Body.tsx index b8efebe351..d1502d025d 100644 --- a/packages/circuit-ui/components/Body/Body.tsx +++ b/packages/circuit-ui/components/Body/Body.tsx @@ -39,6 +39,10 @@ export interface BodyProps extends HTMLAttributes<HTMLParagraphElement> { * @deprecated */ | 'two'; + /** + * Choose from two font weights. Default: `regular`. + */ + weight?: 'regular' | 'bold'; /** * Choose from style variants. */ @@ -64,7 +68,10 @@ function getHTMLElement(variant?: Variant): AsPropType { * to our users. */ export const Body = forwardRef<HTMLParagraphElement, BodyProps>( - ({ className, as, size = 'm', variant, ...props }, ref) => { + ( + { className, as, size = 'm', weight = 'regular', variant, ...props }, + ref, + ) => { const Element = as || getHTMLElement(variant); if (process.env.NODE_ENV !== 'production') { @@ -87,6 +94,7 @@ export const Body = forwardRef<HTMLParagraphElement, BodyProps>( className={clsx( classes.base, classes[size], + classes[weight], variant && classes[variant], className, )} From e19711a288cced32c38f30452807f017d333dd47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Tue, 20 Aug 2024 14:19:37 +0200 Subject: [PATCH 11/26] Add new typography tokens and deprecate old ones --- packages/design-tokens/themes/schema.ts | 209 +++++++++++++++++++--- packages/design-tokens/themes/shared.ts | 225 ++++++++++++++++++++++++ 2 files changed, 409 insertions(+), 25 deletions(-) diff --git a/packages/design-tokens/themes/schema.ts b/packages/design-tokens/themes/schema.ts index 2600fb99ad..f33599833d 100644 --- a/packages/design-tokens/themes/schema.ts +++ b/packages/design-tokens/themes/schema.ts @@ -205,30 +205,189 @@ export const schema = [ { name: '--cui-transitions-default', type: 'duration' }, { name: '--cui-transitions-slow', type: 'duration' }, /* Typography */ - { name: '--cui-typography-headline-one-font-size', type: 'dimension' }, - { name: '--cui-typography-headline-one-line-height', type: 'dimension' }, - { name: '--cui-typography-headline-two-font-size', type: 'dimension' }, - { name: '--cui-typography-headline-two-line-height', type: 'dimension' }, - { name: '--cui-typography-headline-three-font-size', type: 'dimension' }, - { name: '--cui-typography-headline-three-line-height', type: 'dimension' }, - { name: '--cui-typography-headline-four-font-size', type: 'dimension' }, - { name: '--cui-typography-headline-four-line-height', type: 'dimension' }, - { name: '--cui-typography-title-one-font-size', type: 'dimension' }, - { name: '--cui-typography-title-one-line-height', type: 'dimension' }, - { name: '--cui-typography-title-two-font-size', type: 'dimension' }, - { name: '--cui-typography-title-two-line-height', type: 'dimension' }, - { name: '--cui-typography-title-three-font-size', type: 'dimension' }, - { name: '--cui-typography-title-three-line-height', type: 'dimension' }, - { name: '--cui-typography-title-four-font-size', type: 'dimension' }, - { name: '--cui-typography-title-four-line-height', type: 'dimension' }, - { name: '--cui-typography-sub-headline-font-size', type: 'dimension' }, - { name: '--cui-typography-sub-headline-line-height', type: 'dimension' }, - { name: '--cui-typography-body-one-font-size', type: 'dimension' }, - { name: '--cui-typography-body-one-line-height', type: 'dimension' }, - { name: '--cui-typography-body-two-font-size', type: 'dimension' }, - { name: '--cui-typography-body-two-line-height', type: 'dimension' }, - { name: '--cui-typography-body-large-font-size', type: 'dimension' }, - { name: '--cui-typography-body-large-line-height', type: 'dimension' }, + { name: '--cui-typography-display-l-font-size', type: 'dimension' }, + { name: '--cui-typography-display-l-line-height', type: 'dimension' }, + { name: '--cui-typography-display-l-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-display-m-font-size', type: 'dimension' }, + { name: '--cui-typography-display-m-line-height', type: 'dimension' }, + { name: '--cui-typography-display-m-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-display-s-font-size', type: 'dimension' }, + { name: '--cui-typography-display-s-line-height', type: 'dimension' }, + { name: '--cui-typography-display-s-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-headline-l-font-size', type: 'dimension' }, + { name: '--cui-typography-headline-l-line-height', type: 'dimension' }, + { name: '--cui-typography-headline-l-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-headline-m-font-size', type: 'dimension' }, + { name: '--cui-typography-headline-m-line-height', type: 'dimension' }, + { name: '--cui-typography-headline-m-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-headline-s-font-size', type: 'dimension' }, + { name: '--cui-typography-headline-s-line-height', type: 'dimension' }, + { name: '--cui-typography-headline-s-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-body-l-font-size', type: 'dimension' }, + { name: '--cui-typography-body-l-line-height', type: 'dimension' }, + { name: '--cui-typography-body-l-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-body-m-font-size', type: 'dimension' }, + { name: '--cui-typography-body-m-line-height', type: 'dimension' }, + { name: '--cui-typography-body-m-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-body-s-font-size', type: 'dimension' }, + { name: '--cui-typography-body-s-line-height', type: 'dimension' }, + { name: '--cui-typography-body-s-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-compact-l-font-size', type: 'dimension' }, + { name: '--cui-typography-compact-l-line-height', type: 'dimension' }, + { name: '--cui-typography-compact-l-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-compact-m-font-size', type: 'dimension' }, + { name: '--cui-typography-compact-m-line-height', type: 'dimension' }, + { name: '--cui-typography-compact-m-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-compact-s-font-size', type: 'dimension' }, + { name: '--cui-typography-compact-s-line-height', type: 'dimension' }, + { name: '--cui-typography-compact-s-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-numeral-l-font-size', type: 'dimension' }, + { name: '--cui-typography-numeral-l-line-height', type: 'dimension' }, + { name: '--cui-typography-numeral-l-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-numeral-m-font-size', type: 'dimension' }, + { name: '--cui-typography-numeral-m-line-height', type: 'dimension' }, + { name: '--cui-typography-numeral-m-letter-spacing', type: 'dimension' }, + { name: '--cui-typography-numeral-s-font-size', type: 'dimension' }, + { name: '--cui-typography-numeral-s-line-height', type: 'dimension' }, + { name: '--cui-typography-numeral-s-letter-spacing', type: 'dimension' }, + { + name: '--cui-typography-headline-one-font-size', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-l-font-size` token instead.', + }, + { + name: '--cui-typography-headline-one-line-height', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-one-line-height` token instead.', + }, + { + name: '--cui-typography-headline-two-font-size', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-m-font-size` token instead.', + }, + { + name: '--cui-typography-headline-two-line-height', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-m-line-height` token instead.', + }, + { + name: '--cui-typography-headline-three-font-size', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-m-font-size` token instead.', + }, + { + name: '--cui-typography-headline-three-line-height', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-m-line-height` token instead.', + }, + { + name: '--cui-typography-headline-four-font-size', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-s-font-size` token instead.', + }, + { + name: '--cui-typography-headline-four-line-height', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-s-line-height` token instead.', + }, + { + name: '--cui-typography-title-one-font-size', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-display-l-font-size` token instead.', + }, + { + name: '--cui-typography-title-one-line-height', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-display-l-line-height` token instead.', + }, + { + name: '--cui-typography-title-two-font-size', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-display-m-font-size` token instead.', + }, + { + name: '--cui-typography-title-two-line-height', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-display-m-line-height` token instead.', + }, + { + name: '--cui-typography-title-three-font-size', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-display-m-font-size` token instead.', + }, + { + name: '--cui-typography-title-three-line-height', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-display-m-line-height` token instead.', + }, + { + name: '--cui-typography-title-four-font-size', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-display-s-font-size` token instead.', + }, + { + name: '--cui-typography-title-four-line-height', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-display-s-line-height` token instead.', + }, + { + name: '--cui-typography-sub-headline-font-size', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-s-font-size` token instead.', + }, + { + name: '--cui-typography-sub-headline-line-height', + type: 'dimension', + deprecation: + 'Use the `--cui-typography-headline-s-line-height` token instead.', + }, + { + name: '--cui-typography-body-one-font-size', + type: 'dimension', + deprecation: 'Use the `--cui-typography-body-m-font-size` token instead.', + }, + { + name: '--cui-typography-body-one-line-height', + type: 'dimension', + deprecation: 'Use the `--cui-typography-body-m-line-height` token instead.', + }, + { + name: '--cui-typography-body-two-font-size', + type: 'dimension', + deprecation: 'Use the `--cui-typography-body-s-font-size` token instead.', + }, + { + name: '--cui-typography-body-two-line-height', + type: 'dimension', + deprecation: 'Use the `--cui-typography-body-s-line-height` token instead.', + }, + { + name: '--cui-typography-body-large-font-size', + type: 'dimension', + deprecation: 'Use the `--cui-typography-body-l-font-size` token instead.', + }, + { + name: '--cui-typography-body-large-line-height', + type: 'dimension', + deprecation: 'Use the `--cui-typography-body-l-line-height` token instead.', + }, /* Z-indices */ { name: '--cui-z-index-default', type: 'number' }, { name: '--cui-z-index-absolute', type: 'number' }, @@ -240,4 +399,4 @@ export const schema = [ { name: '--cui-z-index-navigation', type: 'number' }, { name: '--cui-z-index-modal', type: 'number' }, { name: '--cui-z-index-toast', type: 'number' }, -] satisfies { name: TokenName; type: TokenType }[]; +] satisfies { name: TokenName; type: TokenType; deprecation?: string }[]; diff --git a/packages/design-tokens/themes/shared.ts b/packages/design-tokens/themes/shared.ts index 5a1f348705..f3eea48863 100644 --- a/packages/design-tokens/themes/shared.ts +++ b/packages/design-tokens/themes/shared.ts @@ -161,6 +161,231 @@ export const shared = [ type: 'duration', }, /* Typography */ + { + name: '--cui-typography-display-l-font-size', + value: '4rem', + type: 'dimension', + }, + { + name: '--cui-typography-display-l-line-height', + value: '4.5rem', + type: 'dimension', + }, + { + name: '--cui-typography-display-l-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-display-m-font-size', + value: '3rem', + type: 'dimension', + }, + { + name: '--cui-typography-display-m-line-height', + value: '3.5rem', + type: 'dimension', + }, + { + name: '--cui-typography-display-m-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-display-s-font-size', + value: '2.5rem', + type: 'dimension', + }, + { + name: '--cui-typography-display-s-line-height', + value: '2.875rem', + type: 'dimension', + }, + { + name: '--cui-typography-display-s-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-headline-l-font-size', + value: '2rem', + type: 'dimension', + }, + { + name: '--cui-typography-headline-l-line-height', + value: '2.25rem', + type: 'dimension', + }, + { + name: '--cui-typography-headline-l-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-headline-m-font-size', + value: '1.375rem', + type: 'dimension', + }, + { + name: '--cui-typography-headline-m-line-height', + value: '1.625rem', + type: 'dimension', + }, + { + name: '--cui-typography-headline-m-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-headline-s-font-size', + value: '1.125rem', + type: 'dimension', + }, + { + name: '--cui-typography-headline-s-line-height', + value: '1.375rem', + type: 'dimension', + }, + { + name: '--cui-typography-headline-s-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-body-l-font-size', + value: '1.25rem', + type: 'dimension', + }, + { + name: '--cui-typography-body-l-line-height', + value: '1.5rem', + type: 'dimension', + }, + { + name: '--cui-typography-body-l-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-body-m-font-size', + value: '1rem', + type: 'dimension', + }, + { + name: '--cui-typography-body-m-line-height', + value: '1.375rem', + type: 'dimension', + }, + { + name: '--cui-typography-body-m-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-body-s-font-size', + value: '0.875rem', + type: 'dimension', + }, + { + name: '--cui-typography-body-s-line-height', + value: '1.24rem', + type: 'dimension', + }, + { + name: '--cui-typography-body-s-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-compact-l-font-size', + value: '1.125rem', + type: 'dimension', + }, + { + name: '--cui-typography-compact-l-line-height', + value: '1.5rem', + type: 'dimension', + }, + { + name: '--cui-typography-compact-l-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-compact-m-font-size', + value: '0.9375rem', + type: 'dimension', + }, + { + name: '--cui-typography-compact-m-line-height', + value: '1.0625rem', + type: 'dimension', + }, + { + name: '--cui-typography-compact-m-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-compact-s-font-size', + value: '0.8125rem', + type: 'dimension', + }, + { + name: '--cui-typography-compact-s-line-height', + value: '0.9375rem', + type: 'dimension', + }, + { + name: '--cui-typography-compact-s-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-numeral-l-font-size', + value: '3rem', + type: 'dimension', + }, + { + name: '--cui-typography-numeral-l-line-height', + value: '3.375rem', + type: 'dimension', + }, + { + name: '--cui-typography-numeral-l-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-numeral-m-font-size', + value: '1.5rem', + type: 'dimension', + }, + { + name: '--cui-typography-numeral-m-line-height', + value: '1.75rem', + type: 'dimension', + }, + { + name: '--cui-typography-numeral-m-letter-spacing', + value: '0px', + type: 'dimension', + }, + { + name: '--cui-typography-numeral-s-font-size', + value: '1rem', + type: 'dimension', + }, + { + name: '--cui-typography-numeral-s-line-height', + value: '1rem', + type: 'dimension', + }, + { + name: '--cui-typography-numeral-s-letter-spacing', + value: '0px', + type: 'dimension', + }, { name: '--cui-typography-headline-one-font-size', value: '2rem', From a05cdf3665eb2e102891af156d1dc01819a66eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Tue, 20 Aug 2024 17:24:04 +0200 Subject: [PATCH 12/26] Add ESLint rule to flag deprecated custom properties --- .eslintrc.js | 1 + packages/design-tokens/themes/schema.ts | 122 ++++++++++------ packages/design-tokens/themes/shared.ts | 2 + .../component-lifecycle-imports/index.ts | 3 +- packages/eslint-plugin-circuit-ui/index.ts | 2 + .../no-deprecated-custom-properties/README.md | 36 +++++ .../index.spec.ts | 131 ++++++++++++++++++ .../no-deprecated-custom-properties/index.ts | 84 +++++++++++ .../no-invalid-custom-properties/index.ts | 5 +- .../prefer-custom-properties/index.ts | 5 +- 10 files changed, 340 insertions(+), 51 deletions(-) create mode 100644 packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/README.md create mode 100644 packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/index.spec.ts create mode 100644 packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/index.ts diff --git a/.eslintrc.js b/.eslintrc.js index 5eda0a38f8..8633d64339 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,6 +17,7 @@ module.exports = require('@sumup-oss/foundry/eslint')({ }, rules: { '@sumup-oss/circuit-ui/no-invalid-custom-properties': 'error', + '@sumup-oss/circuit-ui/no-deprecated-custom-properties': 'error', '@sumup-oss/circuit-ui/prefer-custom-properties': 'warn', 'react/no-unknown-property': ['error', { ignore: ['css'] }], }, diff --git a/packages/design-tokens/themes/schema.ts b/packages/design-tokens/themes/schema.ts index f33599833d..bf08483dac 100644 --- a/packages/design-tokens/themes/schema.ts +++ b/packages/design-tokens/themes/schema.ts @@ -250,144 +250,176 @@ export const schema = [ { name: '--cui-typography-numeral-s-font-size', type: 'dimension' }, { name: '--cui-typography-numeral-s-line-height', type: 'dimension' }, { name: '--cui-typography-numeral-s-letter-spacing', type: 'dimension' }, + /* eslint-disable @sumup-oss/circuit-ui/no-deprecated-custom-properties */ { name: '--cui-typography-headline-one-font-size', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-l-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-headline-l-font-size', + }, }, { name: '--cui-typography-headline-one-line-height', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-one-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-headline-l-line-height', + }, }, { name: '--cui-typography-headline-two-font-size', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-m-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-headline-m-font-size', + }, }, { name: '--cui-typography-headline-two-line-height', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-m-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-headline-m-line-height', + }, }, { name: '--cui-typography-headline-three-font-size', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-m-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-headline-m-font-size', + }, }, { name: '--cui-typography-headline-three-line-height', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-m-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-headline-m-line-height', + }, }, { name: '--cui-typography-headline-four-font-size', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-s-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-headline-s-font-size', + }, }, { name: '--cui-typography-headline-four-line-height', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-s-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-headline-s-line-height', + }, }, { name: '--cui-typography-title-one-font-size', type: 'dimension', - deprecation: - 'Use the `--cui-typography-display-l-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-display-l-font-size', + }, }, { name: '--cui-typography-title-one-line-height', type: 'dimension', - deprecation: - 'Use the `--cui-typography-display-l-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-display-l-line-height', + }, }, { name: '--cui-typography-title-two-font-size', type: 'dimension', - deprecation: - 'Use the `--cui-typography-display-m-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-display-m-font-size', + }, }, { name: '--cui-typography-title-two-line-height', type: 'dimension', - deprecation: - 'Use the `--cui-typography-display-m-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-display-m-line-height', + }, }, { name: '--cui-typography-title-three-font-size', type: 'dimension', - deprecation: - 'Use the `--cui-typography-display-m-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-display-m-font-size', + }, }, { name: '--cui-typography-title-three-line-height', type: 'dimension', - deprecation: - 'Use the `--cui-typography-display-m-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-display-m-line-height', + }, }, { name: '--cui-typography-title-four-font-size', type: 'dimension', - deprecation: - 'Use the `--cui-typography-display-s-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-display-s-font-size', + }, }, { name: '--cui-typography-title-four-line-height', type: 'dimension', - deprecation: - 'Use the `--cui-typography-display-s-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-display-s-line-height', + }, }, { name: '--cui-typography-sub-headline-font-size', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-s-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-headline-s-font-size', + }, }, { name: '--cui-typography-sub-headline-line-height', type: 'dimension', - deprecation: - 'Use the `--cui-typography-headline-s-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-headline-s-line-height', + }, }, { name: '--cui-typography-body-one-font-size', type: 'dimension', - deprecation: 'Use the `--cui-typography-body-m-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-body-m-font-size', + }, }, { name: '--cui-typography-body-one-line-height', type: 'dimension', - deprecation: 'Use the `--cui-typography-body-m-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-body-m-line-height', + }, }, { name: '--cui-typography-body-two-font-size', type: 'dimension', - deprecation: 'Use the `--cui-typography-body-s-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-body-s-font-size', + }, }, { name: '--cui-typography-body-two-line-height', type: 'dimension', - deprecation: 'Use the `--cui-typography-body-s-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-body-s-line-height', + }, }, { name: '--cui-typography-body-large-font-size', type: 'dimension', - deprecation: 'Use the `--cui-typography-body-l-font-size` token instead.', + deprecation: { + replacement: '--cui-typography-body-l-font-size', + }, }, { name: '--cui-typography-body-large-line-height', type: 'dimension', - deprecation: 'Use the `--cui-typography-body-l-line-height` token instead.', + deprecation: { + replacement: '--cui-typography-body-l-line-height', + }, }, + /* eslint-disable @sumup-oss/circuit-ui/no-deprecated-custom-properties */ /* Z-indices */ { name: '--cui-z-index-default', type: 'number' }, { name: '--cui-z-index-absolute', type: 'number' }, @@ -399,4 +431,8 @@ export const schema = [ { name: '--cui-z-index-navigation', type: 'number' }, { name: '--cui-z-index-modal', type: 'number' }, { name: '--cui-z-index-toast', type: 'number' }, -] satisfies { name: TokenName; type: TokenType; deprecation?: string }[]; +] satisfies { + name: TokenName; + type: TokenType; + deprecation?: { replacement: TokenName }; +}[]; diff --git a/packages/design-tokens/themes/shared.ts b/packages/design-tokens/themes/shared.ts index f3eea48863..81fe9b2fcf 100644 --- a/packages/design-tokens/themes/shared.ts +++ b/packages/design-tokens/themes/shared.ts @@ -386,6 +386,7 @@ export const shared = [ value: '0px', type: 'dimension', }, + /* eslint-disable @sumup-oss/circuit-ui/no-deprecated-custom-properties */ { name: '--cui-typography-headline-one-font-size', value: '2rem', @@ -506,6 +507,7 @@ export const shared = [ value: '1.5rem', type: 'dimension', }, + /* eslint-enable @sumup-oss/circuit-ui/no-deprecated-custom-properties */ /* Z-indices */ { name: '--cui-z-index-default', diff --git a/packages/eslint-plugin-circuit-ui/component-lifecycle-imports/index.ts b/packages/eslint-plugin-circuit-ui/component-lifecycle-imports/index.ts index 3d5fec786f..909f6f48e6 100644 --- a/packages/eslint-plugin-circuit-ui/component-lifecycle-imports/index.ts +++ b/packages/eslint-plugin-circuit-ui/component-lifecycle-imports/index.ts @@ -132,8 +132,7 @@ export const componentLifecycleImports = createRule({ fixes.push( fixer.replaceText( node, - context - .getSourceCode() + context.sourceCode .getText(node) .replace(importSpecifier, '') .replace(' ,', ''), diff --git a/packages/eslint-plugin-circuit-ui/index.ts b/packages/eslint-plugin-circuit-ui/index.ts index 9afd975cd3..15d218eac1 100644 --- a/packages/eslint-plugin-circuit-ui/index.ts +++ b/packages/eslint-plugin-circuit-ui/index.ts @@ -15,6 +15,7 @@ import { componentLifecycleImports } from './component-lifecycle-imports'; import { noInvalidCustomProperties } from './no-invalid-custom-properties'; +import { noDeprecatedCustomProperties } from './no-deprecated-custom-properties'; import { noDeprecatedComponents } from './no-deprecated-components'; import { noDeprecatedProps } from './no-deprecated-props'; import { noRenamedProps } from './no-renamed-props'; @@ -26,6 +27,7 @@ import { renamedPackageScope } from './renamed-package-scope'; export const rules = { 'component-lifecycle-imports': componentLifecycleImports, 'no-invalid-custom-properties': noInvalidCustomProperties, + 'no-deprecated-custom-properties': noDeprecatedCustomProperties, 'no-deprecated-components': noDeprecatedComponents, 'no-deprecated-props': noDeprecatedProps, 'no-renamed-props': noRenamedProps, diff --git a/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/README.md b/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/README.md new file mode 100644 index 0000000000..4383f63def --- /dev/null +++ b/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/README.md @@ -0,0 +1,36 @@ +# Replace deprecated CSS custom properties (`no-deprecated-custom-properties`) + +Occasionally, CSS custom properties are removed or renamed. This rule flags uses of deprecated custom properties. + +## Rule Details + +Examples of **incorrect** code for this rule: + +```css +.class { + font-size: var(--cui-typography-headline-one-font-size); + line-height: var(--cui-typography-headline-one-line-height); +} +``` + +Examples of **correct** code for this rule: + +```css +.class { + font-size: var(--cui-typography-headline-l-font-size); + line-height: var(--cui-typography-headline-l-line-height); +} +``` + +### Options + +n/a + +## When Not To Use It + +n/a + +## Further Reading + +- [Migration guide](https://github.com/sumup-oss/circuit-ui/blob/main/MIGRATION.md) +- [Design token release notes](https://github.com/sumup-oss/circuit-ui/blob/main/packages/design-tokens/CHANGELOG.md) diff --git a/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/index.spec.ts b/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/index.spec.ts new file mode 100644 index 0000000000..e154e65adc --- /dev/null +++ b/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/index.spec.ts @@ -0,0 +1,131 @@ +/** + * Copyright 2023, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// We disable the rule in this file because we explicitly test invalid cases +/* eslint-disable @sumup-oss/circuit-ui/no-deprecated-custom-properties */ + +import { RuleTester } from '@typescript-eslint/rule-tester'; + +import { noDeprecatedCustomProperties } from '.'; + +// eslint-disable-next-line @typescript-eslint/no-unsafe-call +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, +}); + +// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access +ruleTester.run( + 'no-deprecated-custom-properties', + noDeprecatedCustomProperties, + { + valid: [ + { + name: 'custom properties in a JS object', + code: ` + const typography = { + fontSize: "var(--cui-typography-headline-l-font-size)", + lineHeight: "var(--cui-typography-headline-l-line-height)", + } + `, + }, + { + name: 'custom properties in a tagged template literal', + code: ` + const styles = css\` + font-size: var(--cui-typography-headline-l-font-size); + line-height: var(--cui-typography-headline-l-line-height); + \`; + `, + }, + { + name: 'custom properties in inline styles', + code: ` + function Component() { + return ( + <p + style="font-size:var(--cui-typography-headline-l-font-size);line-height:var(--cui-typography-headline-l-line-height);" + > + Success + </p> + ); + } + `, + }, + ], + invalid: [ + { + name: 'custom properties in a JS object', + code: ` + const typography = { + fontSize: "var(--cui-typography-headline-one-font-size)", + lineHeight: "var(--cui-typography-headline-one-line-height)", + } + `, + errors: [ + { + messageId: 'deprecated', + }, + { + messageId: 'deprecated', + }, + ], + }, + { + name: 'custom properties in a tagged template literal', + code: ` + const styles = css\` + font-size: var(--cui-typography-headline-one-font-size); + line-height: var(--cui-typography-headline-one-line-height); + \`; + `, + errors: [ + { + messageId: 'deprecated', + }, + { + messageId: 'deprecated', + }, + ], + }, + { + name: 'custom properties in inline styles', + code: ` + function Component() { + return ( + <p + style="font-size:var(--cui-typography-headline-one-font-size);line-height:var(--cui-typography-headline-one-line-height);" + > + Success + </p> + ); + } + `, + errors: [ + { + messageId: 'deprecated', + }, + { + messageId: 'deprecated', + }, + ], + }, + ], + }, +); diff --git a/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/index.ts b/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/index.ts new file mode 100644 index 0000000000..e3a8bdc3f6 --- /dev/null +++ b/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/index.ts @@ -0,0 +1,84 @@ +/** + * Copyright 2023, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ESLintUtils } from '@typescript-eslint/utils'; +import { schema } from '@sumup-oss/design-tokens'; + +const DEPRECATED_CUSTOM_PROPERTIES = schema.filter(({ deprecation }) => + Boolean(deprecation), +); +const REGEX_STRING = DEPRECATED_CUSTOM_PROPERTIES.map(({ name }) => name).join( + '|', +); + +/* eslint-disable */ + +const createRule = ESLintUtils.RuleCreator( + (name) => + `https://github.com/sumup-oss/circuit-ui/tree/main/packages/eslint-plugin-circuit-ui/${name}`, +); + +export const noDeprecatedCustomProperties = createRule({ + name: 'no-deprecated-custom-properties', + meta: { + type: 'suggestion', + schema: [], + docs: { + description: 'Deprecated custom properties should be removed or replaced', + recommended: 'strict', + }, + messages: { + deprecated: + 'The `{{name}}` custom property has been deprecated. Use the ` {{replacement}}` custom property instead.', + }, + }, + defaultOptions: [], + create(context) { + return { + // Inspired by `no-tabs`: https://github.com/eslint/eslint/blob/b98fdd413a3b07b262bfce6f704c1c1bb8582770/lib/rules/no-tabs.js + Program(node) { + context.sourceCode.getLines().forEach((line, index) => { + const regex = new RegExp(REGEX_STRING, 'g'); + let match: RegExpExecArray | null; + // biome-ignore lint/suspicious/noAssignInExpressions: + while ((match = regex.exec(line)) !== null) { + const name = match[0]; + const { replacement } = DEPRECATED_CUSTOM_PROPERTIES.find( + (token) => token.name === name, + )!.deprecation!; + context.report({ + node, + loc: { + start: { + line: index + 1, + column: match.index, + }, + end: { + line: index + 1, + column: match.index + match[0].length, + }, + }, + messageId: 'deprecated', + data: { + name, + replacement, + }, + }); + } + }); + }, + }; + }, +}); diff --git a/packages/eslint-plugin-circuit-ui/no-invalid-custom-properties/index.ts b/packages/eslint-plugin-circuit-ui/no-invalid-custom-properties/index.ts index dcf2b0465f..81ae81152f 100644 --- a/packages/eslint-plugin-circuit-ui/no-invalid-custom-properties/index.ts +++ b/packages/eslint-plugin-circuit-ui/no-invalid-custom-properties/index.ts @@ -42,16 +42,15 @@ export const noInvalidCustomProperties = createRule({ recommended: 'recommended', }, messages: { - invalid: "'{{name}}' is not a valid Circuit UI design token.", + invalid: '`{{name}}` is not a valid Circuit UI design token.', }, }, defaultOptions: [], create(context) { - const sourceCode = context.getSourceCode(); return { // Inspired by `no-tabs`: https://github.com/eslint/eslint/blob/b98fdd413a3b07b262bfce6f704c1c1bb8582770/lib/rules/no-tabs.js Program(node) { - sourceCode.getLines().forEach((line, index) => { + context.sourceCode.getLines().forEach((line, index) => { const regex = new RegExp(REGEX_STRING, 'g'); let match: RegExpExecArray | null; // biome-ignore lint/suspicious/noAssignInExpressions: diff --git a/packages/eslint-plugin-circuit-ui/prefer-custom-properties/index.ts b/packages/eslint-plugin-circuit-ui/prefer-custom-properties/index.ts index 116d5f6267..a8c2090b0f 100644 --- a/packages/eslint-plugin-circuit-ui/prefer-custom-properties/index.ts +++ b/packages/eslint-plugin-circuit-ui/prefer-custom-properties/index.ts @@ -36,7 +36,7 @@ export const preferCustomProperties = createRule({ }, messages: { replace: - "Use CSS custom properties instead of the Emotion.js theme. Replace '{{jsToken}}' with '{{cssVariable}}'.", + 'Use CSS custom properties instead of the Emotion.js theme. Replace `{{jsToken}}` with `{{cssVariable}}`.', refactor: 'Use CSS custom properties instead of the Emotion.js theme.', }, }, @@ -120,8 +120,7 @@ export const preferCustomProperties = createRule({ const jsToken = `\${${identifiers.join('.')}}`; const cssVariable = `var(${customProperty})`; - const text = context - .getSourceCode() + const text = context.sourceCode .getText(node) .replace(jsToken, cssVariable); From 216f9d7534ae976119a558e75514d052c4a52b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 21 Aug 2024 09:24:19 +0200 Subject: [PATCH 13/26] Add Stylelint rule to flag deprecated custom properties --- packages/stylelint-plugin-circuit-ui/index.ts | 3 +- .../no-deprecated-custom-properties/README.md | 29 +++++ .../index.spec.ts | 113 ++++++++++++++++++ .../no-deprecated-custom-properties/index.ts | 75 ++++++++++++ 4 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/README.md create mode 100644 packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/index.spec.ts create mode 100644 packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/index.ts diff --git a/packages/stylelint-plugin-circuit-ui/index.ts b/packages/stylelint-plugin-circuit-ui/index.ts index 3b0547d230..b365308eca 100644 --- a/packages/stylelint-plugin-circuit-ui/index.ts +++ b/packages/stylelint-plugin-circuit-ui/index.ts @@ -14,5 +14,6 @@ */ import { noInvalidCustomProperties } from './no-invalid-custom-properties/index.js'; +import { noDeprecatedCustomProperties } from './no-deprecated-custom-properties/index.js'; -export default [noInvalidCustomProperties]; +export default [noInvalidCustomProperties, noDeprecatedCustomProperties]; diff --git a/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/README.md b/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/README.md new file mode 100644 index 0000000000..461f89987b --- /dev/null +++ b/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/README.md @@ -0,0 +1,29 @@ +# Do not use deprecated Circuit UI custom properties (`no-deprecated-custom-properties`) + +Occasionally, CSS custom properties are removed or renamed. This rule flags uses of deprecated custom properties. + +## Rule Details + +Examples of **incorrect** code for this rule: + +```css +color: var(--cui-typography-headline-one-font-size); +``` + +Examples of **correct** code for this rule: + +```css +color: var(--cui-typography-headline-l-font-size); +``` + +### Options + +n/a + +## When Not To Use It + +n/a + +## Further Reading + +- [Theme documentation](https://circuit.sumup.com/?path=/docs/features-theme--docs) on the Circuit UI docs diff --git a/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/index.spec.ts b/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/index.spec.ts new file mode 100644 index 0000000000..146bd41a8d --- /dev/null +++ b/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/index.spec.ts @@ -0,0 +1,113 @@ +/** + * Copyright 2023, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// We disable the rule in this file because we explicitly test invalid cases +/* eslint-disable @sumup-oss/circuit-ui/no-deprecated-custom-properties */ + +import { testRule } from '../setupTests.js'; + +import { noDeprecatedCustomProperties, ruleName, messages } from './index.js'; + +testRule({ + plugins: [noDeprecatedCustomProperties], + ruleName, + config: true, + fix: false, + + accept: [ + { + code: `.class { + font-size: var(--cui-typography-headline-l-font-size); + }`, + description: 'Allow valid custom properties', + }, + { + code: `.class { + margin-bottom: calc(var(--cui-spacings-bit) - var(--cui-typography-headline-l-line-height)); + }`, + description: 'Allow valid custom properties in complex style rules', + }, + ], + + reject: [ + { + code: `.class { + font-size: var(--cui-typography-headline-one-font-size); + }`, + fixed: `.class { + font-size: var(--cui-typography-headline-l-font-size); + }`, + description: 'Disallow deprecated custom properties', + message: messages.deprecated( + '--cui-typography-headline-one-font-size', + '--cui-typography-headline-l-font-size', + ), + line: 2, + column: 9, + endLine: 2, + endColumn: 65, + }, + { + code: `.class { + margin-bottom: calc(var(--cui-spacings-bit) - var(--cui-typography-headline-one-line-height)); + }`, + fixed: `.class { + margin-bottom: calc(var(--cui-spacings-bit) - var(--cui-typography-headline-l-line-height)); + }`, + description: + 'Disallow deprecated custom properties in complex style rules', + message: messages.deprecated( + '--cui-typography-headline-one-line-height', + '--cui-typography-headline-l-line-height', + ), + line: 2, + column: 9, + endLine: 2, + endColumn: 103, + }, + { + code: `.class { + margin-bottom: calc(var(--cui-spacings-bit) - var(--cui-typography-headline-one-line-height) - var(--cui-typography-headline-two-line-height)); + }`, + fixed: `.class { + margin-bottom: calc(var(--cui-spacings-bit) - var(--cui-typography-headline-l-line-height) - var(--cui-typography-headline-m-line-height)); + }`, + description: + 'Disallow multiple deprecated custom properties in complex style rules', + warnings: [ + { + message: messages.deprecated( + '--cui-typography-headline-one-line-height', + '--cui-typography-headline-l-line-height', + ), + line: 2, + column: 9, + endLine: 2, + endColumn: 152, + }, + { + message: messages.deprecated( + '--cui-typography-headline-two-line-height', + '--cui-typography-headline-m-line-height', + ), + line: 2, + column: 9, + endLine: 2, + endColumn: 152, + }, + ], + }, + ], +}); diff --git a/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/index.ts b/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/index.ts new file mode 100644 index 0000000000..39b315a6f7 --- /dev/null +++ b/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/index.ts @@ -0,0 +1,75 @@ +/** + * Copyright 2023, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import stylelint, { type Rule } from 'stylelint'; +import { schema } from '@sumup-oss/design-tokens'; + +const DEPRECATED_CUSTOM_PROPERTIES = schema.filter(({ deprecation }) => + Boolean(deprecation), +); +const REGEX_STRING = DEPRECATED_CUSTOM_PROPERTIES.map(({ name }) => name).join( + '|', +); + +export const ruleName = 'circuit-ui/no-deprecated-custom-properties'; + +export const meta = { + url: 'https://github.com/sumup-oss/circuit-ui/tree/main/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/README.md', + fixable: true, +}; + +export const messages = stylelint.utils.ruleMessages(ruleName, { + deprecated: (name: string, replacement: string) => + `The \`${name}\` custom property has been deprecated. Use the \`${replacement}\` custom property instead.`, +}); + +const rule: Rule = (enabled, _options, context) => (root, result) => { + if (!enabled || DEPRECATED_CUSTOM_PROPERTIES.length === 0) { + return; + } + + root.walkDecls((decl) => { + const regex = new RegExp(REGEX_STRING, 'g'); + let match: RegExpExecArray | null; + // biome-ignore lint/suspicious/noAssignInExpressions: + while ((match = regex.exec(decl.value)) !== null) { + const name = match[0]; + // biome-ignore lint/style/noNonNullAssertion: + const { replacement } = DEPRECATED_CUSTOM_PROPERTIES.find( + (token) => token.name === name, + )!.deprecation!; + + if (context?.fix) { + decl.value = decl.value.replace(name, replacement); + } + + stylelint.utils.report({ + message: messages.deprecated(name, replacement), + node: decl, + result, + ruleName, + }); + } + }); +}; + +rule.ruleName = ruleName; +rule.meta = meta; +rule.messages = messages; + +export const noDeprecatedCustomProperties = stylelint.createPlugin( + ruleName, + rule, +); From a3c1cc58a60606231a55794f1b7f0a1d4a4c3a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 21 Aug 2024 09:28:26 +0200 Subject: [PATCH 14/26] Migrate deprecated custom properties --- .stylelintrc.js | 6 ++++ .../components/Badge/Badge.module.css | 4 +-- .../components/Body/Body.module.css | 20 ++++++------- .../components/BodyLarge/BodyLarge.module.css | 4 +-- .../components/Button/base.module.css | 10 +++---- .../components/Calendar/Calendar.module.css | 8 +++--- .../components/Status/Status.module.css | 4 +-- .../components/Checkbox/Checkbox.module.css | 2 +- .../components/Display/Display.module.css | 28 +++++++++---------- .../components/Field/Field.module.css | 15 +++++----- .../components/Headline/Headline.module.css | 28 +++++++++---------- .../components/Input/Input.module.css | 4 +-- .../components/List/List.module.css | 8 +++--- .../components/ListItem/ListItem.module.css | 4 +-- .../NotificationBanner.module.css | 16 +++++------ .../components/Popover/Popover.module.css | 4 +-- .../ProgressBar/ProgressBar.module.css | 4 +-- .../RadioButton/RadioButton.module.css | 4 +-- .../components/Select/Select.module.css | 4 +-- .../PrimaryLink/PrimaryLink.module.css | 4 +-- .../SubHeadline/SubHeadline.module.css | 4 +-- .../components/TableCell/TableCell.module.css | 12 ++++---- .../TableHeader/TableHeader.module.css | 8 +++--- .../Tabs/components/Tab/Tab.module.css | 4 +-- .../circuit-ui/components/Tag/Tag.module.css | 4 +-- .../components/Toggle/Toggle.module.css | 4 +-- .../components/Tooltip/Tooltip.module.css | 4 +-- packages/circuit-ui/styles/base.css | 4 +-- 28 files changed, 115 insertions(+), 110 deletions(-) diff --git a/.stylelintrc.js b/.stylelintrc.js index e89ad4c673..fb0e3c24c3 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -1,6 +1,12 @@ module.exports = require('@sumup-oss/foundry/stylelint')({ extends: ['stylelint-prettier/recommended', 'stylelint-config-css-modules'], + plugins: [ + // TODO: Remove once Foundry has been updated + '@sumup-oss/stylelint-plugin-circuit-ui', + ], rules: { + 'circuit-ui/no-invalid-custom-properties': true, + 'circuit-ui/no-deprecated-custom-properties': true, 'selector-class-pattern': [ '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', { diff --git a/packages/circuit-ui/components/Badge/Badge.module.css b/packages/circuit-ui/components/Badge/Badge.module.css index de3238cf59..c33329cd2c 100644 --- a/packages/circuit-ui/components/Badge/Badge.module.css +++ b/packages/circuit-ui/components/Badge/Badge.module.css @@ -1,9 +1,9 @@ .base { display: inline-block; padding: 2px var(--cui-spacings-byte); - font-size: var(--cui-typography-body-two-font-size); + font-size: var(--cui-typography-body-s-font-size); font-weight: var(--cui-font-weight-bold); - line-height: var(--cui-typography-body-two-line-height); + line-height: var(--cui-typography-body-s-line-height); text-align: center; letter-spacing: 0.25px; border-radius: var(--cui-border-radius-pill); diff --git a/packages/circuit-ui/components/Body/Body.module.css b/packages/circuit-ui/components/Body/Body.module.css index ce006a5e95..c9f61eb0d6 100644 --- a/packages/circuit-ui/components/Body/Body.module.css +++ b/packages/circuit-ui/components/Body/Body.module.css @@ -6,28 +6,28 @@ /* Sizes */ .l { - font-size: var(--cui-typography-body-large-font-size); - line-height: var(--cui-typography-body-large-line-height); + font-size: var(--cui-typography-body-l-font-size); + line-height: var(--cui-typography-body-l-line-height); } .m { - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); } .s { - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); } .one { - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); } .two { - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); } /* Weights */ diff --git a/packages/circuit-ui/components/BodyLarge/BodyLarge.module.css b/packages/circuit-ui/components/BodyLarge/BodyLarge.module.css index aabbf9e841..e2645d1970 100644 --- a/packages/circuit-ui/components/BodyLarge/BodyLarge.module.css +++ b/packages/circuit-ui/components/BodyLarge/BodyLarge.module.css @@ -1,7 +1,7 @@ .base { - font-size: var(--cui-typography-body-large-font-size); + font-size: var(--cui-typography-body-l-font-size); font-weight: var(--cui-font-weight-regular); - line-height: var(--cui-typography-body-large-line-height); + line-height: var(--cui-typography-body-l-line-height); } /* Variants */ diff --git a/packages/circuit-ui/components/Button/base.module.css b/packages/circuit-ui/components/Button/base.module.css index 86d967eb78..4320581beb 100644 --- a/packages/circuit-ui/components/Button/base.module.css +++ b/packages/circuit-ui/components/Button/base.module.css @@ -6,7 +6,7 @@ width: auto; height: auto; margin: 0; - font-size: var(--cui-typography-body-one-font-size); + font-size: var(--cui-typography-body-m-font-size); font-weight: var(--cui-font-weight-bold); text-align: center; text-decoration: none; @@ -165,8 +165,8 @@ --loader-gap: 3px; --loader-transform: scale(150%); - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); border-radius: var(--cui-border-radius-byte); } @@ -177,8 +177,8 @@ --loader-gap: 5px; --loader-transform: scale(133%); - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); border-radius: var(--cui-border-radius-byte); } diff --git a/packages/circuit-ui/components/Calendar/Calendar.module.css b/packages/circuit-ui/components/Calendar/Calendar.module.css index 866cdcf99d..c0ab955545 100644 --- a/packages/circuit-ui/components/Calendar/Calendar.module.css +++ b/packages/circuit-ui/components/Calendar/Calendar.module.css @@ -80,9 +80,9 @@ align-items: center; justify-content: center; aspect-ratio: 1 / 1; - font-size: var(--cui-typography-body-one-font-size); + font-size: var(--cui-typography-body-m-font-size); font-weight: var(--cui-font-weight-bold); - line-height: var(--cui-typography-body-one-line-height); + line-height: var(--cui-typography-body-m-line-height); } .day { @@ -90,9 +90,9 @@ height: 100%; aspect-ratio: 1 / 1; padding: 0; - font-size: var(--cui-typography-body-one-font-size); + font-size: var(--cui-typography-body-m-font-size); font-variant-numeric: tabular-nums; - line-height: var(--cui-typography-body-one-line-height); + line-height: var(--cui-typography-body-m-line-height); color: var(--cui-fg-normal); touch-action: manipulation; cursor: pointer; diff --git a/packages/circuit-ui/components/Carousel/components/Status/Status.module.css b/packages/circuit-ui/components/Carousel/components/Status/Status.module.css index fe357465c3..d0e1b5726c 100644 --- a/packages/circuit-ui/components/Carousel/components/Status/Status.module.css +++ b/packages/circuit-ui/components/Carousel/components/Status/Status.module.css @@ -1,6 +1,6 @@ @media (max-width: 479px) { .base { - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); } } diff --git a/packages/circuit-ui/components/Checkbox/Checkbox.module.css b/packages/circuit-ui/components/Checkbox/Checkbox.module.css index 2d7231510b..1d489d1e1b 100644 --- a/packages/circuit-ui/components/Checkbox/Checkbox.module.css +++ b/packages/circuit-ui/components/Checkbox/Checkbox.module.css @@ -9,7 +9,7 @@ .base + .label::before { position: absolute; - top: calc(var(--cui-typography-body-one-line-height) / 2); + top: calc(var(--cui-typography-body-m-line-height) / 2); left: 0; box-sizing: border-box; display: block; diff --git a/packages/circuit-ui/components/Display/Display.module.css b/packages/circuit-ui/components/Display/Display.module.css index 5e63a768ad..977a06a18e 100644 --- a/packages/circuit-ui/components/Display/Display.module.css +++ b/packages/circuit-ui/components/Display/Display.module.css @@ -7,36 +7,36 @@ /* Sizes */ .l { - font-size: var(--cui-typography-title-one-font-size); - line-height: var(--cui-typography-title-one-line-height); + font-size: var(--cui-typography-display-l-font-size); + line-height: var(--cui-typography-display-l-line-height); } .m { - font-size: var(--cui-typography-title-two-font-size); - line-height: var(--cui-typography-title-two-line-height); + font-size: var(--cui-typography-display-m-font-size); + line-height: var(--cui-typography-display-m-line-height); } .s { - font-size: var(--cui-typography-title-four-font-size); - line-height: var(--cui-typography-title-four-line-height); + font-size: var(--cui-typography-display-s-font-size); + line-height: var(--cui-typography-display-s-line-height); } .one { - font-size: var(--cui-typography-title-one-font-size); - line-height: var(--cui-typography-title-one-line-height); + font-size: var(--cui-typography-display-l-font-size); + line-height: var(--cui-typography-display-l-line-height); } .two { - font-size: var(--cui-typography-title-two-font-size); - line-height: var(--cui-typography-title-two-line-height); + font-size: var(--cui-typography-display-m-font-size); + line-height: var(--cui-typography-display-m-line-height); } .three { - font-size: var(--cui-typography-title-three-font-size); - line-height: var(--cui-typography-title-three-line-height); + font-size: var(--cui-typography-display-m-font-size); + line-height: var(--cui-typography-display-m-line-height); } .four { - font-size: var(--cui-typography-title-four-font-size); - line-height: var(--cui-typography-title-four-line-height); + font-size: var(--cui-typography-display-s-font-size); + line-height: var(--cui-typography-display-s-line-height); } diff --git a/packages/circuit-ui/components/Field/Field.module.css b/packages/circuit-ui/components/Field/Field.module.css index f74aeb7e08..058cf3f34b 100644 --- a/packages/circuit-ui/components/Field/Field.module.css +++ b/packages/circuit-ui/components/Field/Field.module.css @@ -8,8 +8,8 @@ .label, .legend { display: block; - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); } .label-text { @@ -33,8 +33,8 @@ .description { display: block; - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); color: var(--cui-fg-subtle); } @@ -46,8 +46,8 @@ .validation-hint { display: flex; margin-top: var(--cui-spacings-bit); - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); color: var(--cui-fg-subtle); transition: color var(--cui-transitions-default); } @@ -91,8 +91,7 @@ width: var(--cui-icon-sizes-kilo); height: var(--cui-icon-sizes-kilo); margin-top: calc( - (var(--cui-typography-body-two-line-height) - var(--cui-icon-sizes-kilo)) / - 2 + (var(--cui-typography-body-s-line-height) - var(--cui-icon-sizes-kilo)) / 2 ); margin-right: var(--cui-spacings-bit); } diff --git a/packages/circuit-ui/components/Headline/Headline.module.css b/packages/circuit-ui/components/Headline/Headline.module.css index e5566d1d1b..f951abe1fb 100644 --- a/packages/circuit-ui/components/Headline/Headline.module.css +++ b/packages/circuit-ui/components/Headline/Headline.module.css @@ -7,36 +7,36 @@ /* Sizes */ .l { - font-size: var(--cui-typography-headline-one-font-size); - line-height: var(--cui-typography-headline-one-line-height); + font-size: var(--cui-typography-headline-l-font-size); + line-height: var(--cui-typography-headline-l-line-height); } .m { - font-size: var(--cui-typography-headline-two-font-size); - line-height: var(--cui-typography-headline-two-line-height); + font-size: var(--cui-typography-headline-m-font-size); + line-height: var(--cui-typography-headline-m-line-height); } .s { - font-size: var(--cui-typography-headline-four-font-size); - line-height: var(--cui-typography-headline-four-line-height); + font-size: var(--cui-typography-headline-s-font-size); + line-height: var(--cui-typography-headline-s-line-height); } .one { - font-size: var(--cui-typography-headline-one-font-size); - line-height: var(--cui-typography-headline-one-line-height); + font-size: var(--cui-typography-headline-l-font-size); + line-height: var(--cui-typography-headline-l-line-height); } .two { - font-size: var(--cui-typography-headline-two-font-size); - line-height: var(--cui-typography-headline-two-line-height); + font-size: var(--cui-typography-headline-m-font-size); + line-height: var(--cui-typography-headline-m-line-height); } .three { - font-size: var(--cui-typography-headline-three-font-size); - line-height: var(--cui-typography-headline-three-line-height); + font-size: var(--cui-typography-headline-m-font-size); + line-height: var(--cui-typography-headline-m-line-height); } .four { - font-size: var(--cui-typography-headline-four-font-size); - line-height: var(--cui-typography-headline-four-line-height); + font-size: var(--cui-typography-headline-s-font-size); + line-height: var(--cui-typography-headline-s-line-height); } diff --git a/packages/circuit-ui/components/Input/Input.module.css b/packages/circuit-ui/components/Input/Input.module.css index 764a660191..fe7abf9c29 100644 --- a/packages/circuit-ui/components/Input/Input.module.css +++ b/packages/circuit-ui/components/Input/Input.module.css @@ -6,8 +6,8 @@ width: 100%; padding: var(--cui-spacings-kilo) var(--cui-spacings-mega); margin: 0; - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); appearance: none; background-color: var(--cui-bg-normal); border: none; diff --git a/packages/circuit-ui/components/List/List.module.css b/packages/circuit-ui/components/List/List.module.css index c5cbb0392e..1334d18211 100644 --- a/packages/circuit-ui/components/List/List.module.css +++ b/packages/circuit-ui/components/List/List.module.css @@ -6,8 +6,8 @@ .one { padding-left: var(--cui-spacings-kilo); - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); } .one li { @@ -32,8 +32,8 @@ .two { padding-left: var(--cui-spacings-kilo); - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); } .two li { diff --git a/packages/circuit-ui/components/ListItem/ListItem.module.css b/packages/circuit-ui/components/ListItem/ListItem.module.css index 1ad76591d6..6637057a64 100644 --- a/packages/circuit-ui/components/ListItem/ListItem.module.css +++ b/packages/circuit-ui/components/ListItem/ListItem.module.css @@ -118,7 +118,7 @@ button.base:active { display: flex; align-items: center; max-width: 100%; - min-height: var(--cui-typography-body-one-line-height); + min-height: var(--cui-typography-body-m-line-height); } .trailing { @@ -150,6 +150,6 @@ button.base:active { } .navigation .trailing .details { - height: var(--cui-typography-body-one-line-height); + height: var(--cui-typography-body-m-line-height); margin-right: calc(var(--cui-spacings-mega) + var(--cui-spacings-bit)); } diff --git a/packages/circuit-ui/components/NotificationBanner/NotificationBanner.module.css b/packages/circuit-ui/components/NotificationBanner/NotificationBanner.module.css index 3c72b3a5a2..c44255cef7 100644 --- a/packages/circuit-ui/components/NotificationBanner/NotificationBanner.module.css +++ b/packages/circuit-ui/components/NotificationBanner/NotificationBanner.module.css @@ -35,27 +35,27 @@ .base .headline { margin-bottom: var(--cui-spacings-byte); - font-size: var(--cui-typography-headline-four-font-size); - line-height: var(--cui-typography-headline-four-line-height); + font-size: var(--cui-typography-headline-s-font-size); + line-height: var(--cui-typography-headline-s-line-height); } @media (min-width: 768px) { .base .headline { - font-size: var(--cui-typography-headline-three-font-size); - line-height: var(--cui-typography-headline-three-line-height); + font-size: var(--cui-typography-headline-m-font-size); + line-height: var(--cui-typography-headline-m-line-height); } } .base .body { margin-bottom: var(--cui-spacings-byte); - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); } @media (min-width: 768px) { .base .body { - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); } } diff --git a/packages/circuit-ui/components/Popover/Popover.module.css b/packages/circuit-ui/components/Popover/Popover.module.css index aa078ee289..72b7ba7ccc 100644 --- a/packages/circuit-ui/components/Popover/Popover.module.css +++ b/packages/circuit-ui/components/Popover/Popover.module.css @@ -3,8 +3,8 @@ align-items: center; justify-content: flex-start; width: 100%; - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); text-align: left; background: var(--cui-bg-elevated); } diff --git a/packages/circuit-ui/components/ProgressBar/ProgressBar.module.css b/packages/circuit-ui/components/ProgressBar/ProgressBar.module.css index 12fcdb17d5..5a81904c90 100644 --- a/packages/circuit-ui/components/ProgressBar/ProgressBar.module.css +++ b/packages/circuit-ui/components/ProgressBar/ProgressBar.module.css @@ -90,6 +90,6 @@ .label { flex-shrink: 0; margin-left: var(--cui-spacings-byte); - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); } diff --git a/packages/circuit-ui/components/RadioButton/RadioButton.module.css b/packages/circuit-ui/components/RadioButton/RadioButton.module.css index 7f73be6501..60fd3c5ef5 100644 --- a/packages/circuit-ui/components/RadioButton/RadioButton.module.css +++ b/packages/circuit-ui/components/RadioButton/RadioButton.module.css @@ -8,7 +8,7 @@ .label::before { position: absolute; - top: calc(var(--cui-typography-body-one-line-height) / 2); + top: calc(var(--cui-typography-body-m-line-height) / 2); left: 0; box-sizing: border-box; display: block; @@ -27,7 +27,7 @@ .label::after { position: absolute; - top: calc(var(--cui-typography-body-one-line-height) / 2); + top: calc(var(--cui-typography-body-m-line-height) / 2); left: var(--cui-spacings-bit); box-sizing: border-box; display: block; diff --git a/packages/circuit-ui/components/Select/Select.module.css b/packages/circuit-ui/components/Select/Select.module.css index 03df237805..59c84b6edf 100644 --- a/packages/circuit-ui/components/Select/Select.module.css +++ b/packages/circuit-ui/components/Select/Select.module.css @@ -14,8 +14,8 @@ padding-left: var(--cui-spacings-mega); margin: 0; overflow-x: hidden; - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); color: var(--cui-fg-normal); text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/circuit-ui/components/SideNavigation/components/PrimaryLink/PrimaryLink.module.css b/packages/circuit-ui/components/SideNavigation/components/PrimaryLink/PrimaryLink.module.css index 7bc44e48c7..998f552b96 100644 --- a/packages/circuit-ui/components/SideNavigation/components/PrimaryLink/PrimaryLink.module.css +++ b/packages/circuit-ui/components/SideNavigation/components/PrimaryLink/PrimaryLink.module.css @@ -84,8 +84,8 @@ @media (max-width: 1279px) { .label { - font-size: var(--cui-typography-headline-two-font-size); - line-height: var(--cui-typography-headline-two-line-height); + font-size: var(--cui-typography-headline-m-font-size); + line-height: var(--cui-typography-headline-m-line-height); } } diff --git a/packages/circuit-ui/components/SubHeadline/SubHeadline.module.css b/packages/circuit-ui/components/SubHeadline/SubHeadline.module.css index 1c11dee923..d6e3a560e8 100644 --- a/packages/circuit-ui/components/SubHeadline/SubHeadline.module.css +++ b/packages/circuit-ui/components/SubHeadline/SubHeadline.module.css @@ -1,7 +1,7 @@ .base { - font-size: var(--cui-typography-sub-headline-font-size); + font-size: var(--cui-typography-headline-s-font-size); font-weight: var(--cui-font-weight-bold); - line-height: var(--cui-typography-sub-headline-line-height); + line-height: var(--cui-typography-headline-s-line-height); color: var(--cui-fg-normal); text-transform: uppercase; } diff --git a/packages/circuit-ui/components/Table/components/TableCell/TableCell.module.css b/packages/circuit-ui/components/Table/components/TableCell/TableCell.module.css index 98328356bb..5dc46c9b08 100644 --- a/packages/circuit-ui/components/Table/components/TableCell/TableCell.module.css +++ b/packages/circuit-ui/components/Table/components/TableCell/TableCell.module.css @@ -28,8 +28,8 @@ .condensed { padding: var(--cui-spacings-kilo) var(--cui-spacings-mega) var(--cui-spacings-kilo) var(--cui-spacings-giga); - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); } .presentation { @@ -47,17 +47,17 @@ .presentation.header { padding: var(--cui-spacings-byte) var(--cui-spacings-giga); - font-size: var(--cui-typography-body-two-font-size); + font-size: var(--cui-typography-body-s-font-size); font-weight: var(--cui-font-weight-bold); - line-height: var(--cui-typography-body-two-line-height); + line-height: var(--cui-typography-body-s-line-height); white-space: nowrap; } .condensed.presentation { padding: var(--cui-spacings-kilo) var(--cui-spacings-mega) var(--cui-spacings-kilo) var(--cui-spacings-giga); - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); } .condensed.presentation.header { diff --git a/packages/circuit-ui/components/Table/components/TableHeader/TableHeader.module.css b/packages/circuit-ui/components/Table/components/TableHeader/TableHeader.module.css index 5470c2316c..6fbce52f76 100644 --- a/packages/circuit-ui/components/Table/components/TableHeader/TableHeader.module.css +++ b/packages/circuit-ui/components/Table/components/TableHeader/TableHeader.module.css @@ -9,9 +9,9 @@ .base[scope="col"] { padding: var(--cui-spacings-byte) var(--cui-spacings-giga); - font-size: var(--cui-typography-body-two-font-size); + font-size: var(--cui-typography-body-s-font-size); font-weight: var(--cui-font-weight-bold); - line-height: var(--cui-typography-body-two-line-height); + line-height: var(--cui-typography-body-s-line-height); color: var(--cui-fg-subtle); white-space: nowrap; vertical-align: middle; @@ -44,8 +44,8 @@ .condensed { padding: var(--cui-spacings-kilo) var(--cui-spacings-mega) var(--cui-spacings-kilo) var(--cui-spacings-giga); - font-size: var(--cui-typography-body-two-font-size); - line-height: var(--cui-typography-body-two-line-height); + font-size: var(--cui-typography-body-s-font-size); + line-height: var(--cui-typography-body-s-line-height); vertical-align: middle; } diff --git a/packages/circuit-ui/components/Tabs/components/Tab/Tab.module.css b/packages/circuit-ui/components/Tabs/components/Tab/Tab.module.css index 45421d83de..63406bc225 100644 --- a/packages/circuit-ui/components/Tabs/components/Tab/Tab.module.css +++ b/packages/circuit-ui/components/Tabs/components/Tab/Tab.module.css @@ -6,8 +6,8 @@ float: left; height: 100%; padding: var(--cui-spacings-kilo) var(--cui-spacings-tera); - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); color: var(--cui-fg-subtle); text-decoration: none; white-space: nowrap; diff --git a/packages/circuit-ui/components/Tag/Tag.module.css b/packages/circuit-ui/components/Tag/Tag.module.css index be2a2c1625..445fb1c225 100644 --- a/packages/circuit-ui/components/Tag/Tag.module.css +++ b/packages/circuit-ui/components/Tag/Tag.module.css @@ -10,8 +10,8 @@ align-items: center; padding: calc(var(--cui-spacings-bit) - 1px) var(--cui-spacings-kilo); margin: 0; - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); word-break: break-word; cursor: default; background-color: var(--cui-bg-normal); diff --git a/packages/circuit-ui/components/Toggle/Toggle.module.css b/packages/circuit-ui/components/Toggle/Toggle.module.css index c9c7a7e0d8..5873d1a79e 100644 --- a/packages/circuit-ui/components/Toggle/Toggle.module.css +++ b/packages/circuit-ui/components/Toggle/Toggle.module.css @@ -96,9 +96,9 @@ .label { display: block; margin-left: var(--cui-spacings-kilo); - font-size: var(--cui-typography-body-one-font-size); + font-size: var(--cui-typography-body-m-font-size); font-weight: var(--cui-font-weight-regular); - line-height: var(--cui-typography-body-one-line-height); + line-height: var(--cui-typography-body-m-line-height); cursor: pointer; } diff --git a/packages/circuit-ui/components/Tooltip/Tooltip.module.css b/packages/circuit-ui/components/Tooltip/Tooltip.module.css index b9f2ae744f..420efc0083 100644 --- a/packages/circuit-ui/components/Tooltip/Tooltip.module.css +++ b/packages/circuit-ui/components/Tooltip/Tooltip.module.css @@ -73,9 +73,9 @@ .content { padding: var(--cui-spacings-byte) var(--cui-spacings-kilo); - font-size: var(--cui-typography-body-two-font-size); + font-size: var(--cui-typography-body-s-font-size); font-weight: var(--cui-font-weight-regular); - line-height: var(--cui-typography-body-two-line-height); + line-height: var(--cui-typography-body-s-line-height); color: var(--cui-fg-normal); background-color: var(--cui-bg-elevated); border: var(--cui-border-width-kilo) solid var(--cui-border-subtle); diff --git a/packages/circuit-ui/styles/base.css b/packages/circuit-ui/styles/base.css index 21e82e8317..1a00db7611 100644 --- a/packages/circuit-ui/styles/base.css +++ b/packages/circuit-ui/styles/base.css @@ -183,8 +183,8 @@ html { } body { - font-size: var(--cui-typography-body-one-font-size); - line-height: var(--cui-typography-body-one-line-height); + font-size: var(--cui-typography-body-m-font-size); + line-height: var(--cui-typography-body-m-line-height); color: var(--cui-fg-normal); background-color: var(--cui-bg-normal); } From 7242dd85854aebb9366ae0d66cb32bc926b20772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 21 Aug 2024 09:58:33 +0200 Subject: [PATCH 15/26] Visualize typography tokens in the theme docs and show deprecation warnings --- .storybook/components/Icons.tsx | 2 +- .storybook/components/Theme.tsx | 70 +++++++++++++++++++++++++-------- .storybook/components/index.ts | 1 + docs/features/1-theme.mdx | 6 ++- 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/.storybook/components/Icons.tsx b/.storybook/components/Icons.tsx index 68d7d9d749..7ccff88ad9 100644 --- a/.storybook/components/Icons.tsx +++ b/.storybook/components/Icons.tsx @@ -191,7 +191,7 @@ export function Icons() { <Badge {...props} tabIndex={0} - variant="danger" + variant="warning" className={classes.badge} > Deprecated diff --git a/.storybook/components/Theme.tsx b/.storybook/components/Theme.tsx index 83ddce233a..d861679f37 100644 --- a/.storybook/components/Theme.tsx +++ b/.storybook/components/Theme.tsx @@ -20,32 +20,33 @@ import { light, schema } from '@sumup-oss/design-tokens'; import { SumUpLogomark } from '@sumup-oss/icons'; import { Anchor, + Badge, Table, ToastProvider, useNotificationToast, type TableHeaderCell, type TableRow, } from '../../packages/circuit-ui/index.js'; +import { Tooltip } from '../../packages/circuit-ui/experimental.js'; type CustomPropertyName = `--cui-${string}`; type CustomPropertyValue = string; -type CustomProperty = [CustomPropertyName, CustomPropertyValue]; +type CustomProperty = { + name: CustomPropertyName; + value: CustomPropertyValue; + deprecation?: { replacement: CustomPropertyName }; +}; type CustomProperties = CustomProperty[]; type PreviewProps = { name: CustomPropertyName }; type PreviewComponent = ComponentType<PreviewProps>; -function filterCustomProperties( - namespace: string, - type?: string, -): CustomPropertyName[] { - return schema - .filter((token) => { - const isNamespace = token.name.startsWith(`--cui-${namespace}`); - const isType = type ? token.type === type : true; - return isNamespace && isType; - }) - .map((token) => token.name); +function filterCustomProperties(namespace: string, type?: string) { + return schema.filter((token) => { + const isNamespace = token.name.startsWith(`--cui-${namespace}`); + const isType = type ? token.type === type : true; + return isNamespace && isType; + }); } function getCustomPropertyValue(name: CustomPropertyName): CustomPropertyValue { @@ -73,13 +74,29 @@ function getRows( customProperties: CustomProperties, Preview?: PreviewComponent, ) { - return customProperties.map(([name, value]) => { + return customProperties.map(({ name, value, deprecation }) => { const row: TableRow = [ { children: ( <div style={{ display: 'flex' }}> <code style={{ whiteSpace: 'nowrap' }}>{name}</code> <CopyButton name={name} /> + {deprecation && ( + <Tooltip + type="description" + label={`Use the \`${deprecation.replacement}\` custom property instead.`} + component={(props) => ( + <Badge + {...props} + tabIndex={0} + variant="warning" + style={{ marginLeft: '1rem' }} + > + Deprecated + </Badge> + )} + /> + )} </div> ), }, @@ -111,9 +128,12 @@ export function CustomPropertiesTable({ const [customProperties, setCustomProperties] = useState<CustomProperties>(); useEffect(() => { - const names = filterCustomProperties(namespace, type); + const tokens = filterCustomProperties(namespace, type); setCustomProperties( - names.map((name) => [name, getCustomPropertyValue(name)]), + tokens.map((token) => ({ + ...token, + value: getCustomPropertyValue(token.name), + })), ); }, [namespace, type]); @@ -194,12 +214,28 @@ export function FontStack({ name }: PreviewProps) { export function FontWeight({ name }: PreviewProps) { return ( + // @ts-expect-error A CSS custom property is a valid font weight <p style={{ fontWeight: `var(${name})`, whiteSpace: 'nowrap' }}> Lorem ipsum </p> ); } +export function Typography({ name }: PreviewProps) { + if (name.includes('font-size')) { + return ( + <p style={{ fontSize: `var(${name})`, lineHeight: 1 }}>Lorem ipsum</p> + ); + } + if (name.includes('line-height')) { + return <p style={{ lineHeight: `var(${name})` }}>Lorem ipsum</p>; + } + if (name.includes('letter-spacing')) { + return <p style={{ letterSpacing: `var(${name})` }}>Lorem ipsum</p>; + } + return null; +} + export function IconSize({ name }: PreviewProps) { return ( <SumUpLogomark @@ -263,7 +299,9 @@ function TableWrapper() { headers={HEADERS} rows={Object.keys(theme.mq).map((bp) => [ { children: <code>{`theme.mq.${bp}`}</code> }, - { children: <code>{theme.mq[bp]}</code> }, + { + children: <code>{theme.mq[bp as keyof typeof theme.mq]}</code>, + }, ])} /> </Unstyled> diff --git a/.storybook/components/index.ts b/.storybook/components/index.ts index 859a9e10ab..bb2c325cfd 100644 --- a/.storybook/components/index.ts +++ b/.storybook/components/index.ts @@ -40,6 +40,7 @@ export { BorderWidth, FontStack, FontWeight, + Typography, Transition, MediaQueriesTable, } from './Theme.js'; diff --git a/docs/features/1-theme.mdx b/docs/features/1-theme.mdx index a4fbf5348c..8b547eb900 100644 --- a/docs/features/1-theme.mdx +++ b/docs/features/1-theme.mdx @@ -11,9 +11,9 @@ import { BorderWidth, FontStack, FontWeight, + Typography, Transition, } from '../../.storybook/components'; -import { Headline, SubHeadline, Body } from '@sumup-oss/circuit-ui'; <Meta title="Features/Theme" /> @@ -43,7 +43,7 @@ Circuit UI's [ESLint plugin](Packages/eslint-plugin-circuit-ui/Docs) includes r ## Spacings -Use spacings for gutters, margins, and paddings. Don't use it for border width, border radius, icon size, font size, or line height. Use the dedicated theme properties instead. +Use spacings for gutters, margins, and paddings. Don't use it for border width, border radius, icon size, font size, or line height. Use the dedicated design tokens instead. <CustomPropertiesTable namespace="spacings" preview={Spacing} /> @@ -63,6 +63,8 @@ Use spacings for gutters, margins, and paddings. Don't use it for border width, Avoid using the `var(--cui-typography-*)` CSS custom properties directly in your styles. Instead, use the typography components [`Display`](Typography/Display/Docs), [`Headline`](Typography/Headline/Docs), [`SubHeadline`](Typography/SubHeadline/Docs), [`Body`](Typography/Body/Docs), and [`BodyLarge`](Typography/BodyLarge/Docs). +<CustomPropertiesTable namespace="typography" preview={Typography} /> + ## Font stack <CustomPropertiesTable namespace="font-stack" preview={FontStack} /> From fe3b2686638f72a61e0be223d5b2922e824b5458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 21 Aug 2024 10:10:38 +0200 Subject: [PATCH 16/26] Migrate deprecated custom properties in JS --- packages/circuit-ui/components/Checkbox/Checkbox.stories.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/circuit-ui/components/Checkbox/Checkbox.stories.tsx b/packages/circuit-ui/components/Checkbox/Checkbox.stories.tsx index 7d40dc598d..c4229427ef 100644 --- a/packages/circuit-ui/components/Checkbox/Checkbox.stories.tsx +++ b/packages/circuit-ui/components/Checkbox/Checkbox.stories.tsx @@ -107,8 +107,8 @@ export const Indeterminate = (args: { style={{ display: 'block', marginBottom: 'var(--cui-spacings-bit)', - fontSize: 'var(--cui-typography-body-two-font-size)', - lineHeight: 'var(--cui-typography-body-two-line-height)', + fontSize: 'var(--cui-typography-body-s-font-size)', + lineHeight: 'var(--cui-typography-body-s-line-height)', }} > {label} From d22fd1b2375d7e6583237c055943b2e0351da7d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <connor-baer@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:51:17 +0200 Subject: [PATCH 17/26] Apply suggestions from code review --- docs/features/1-theme.mdx | 2 +- packages/circuit-ui/components/Display/Display.mdx | 2 +- packages/circuit-ui/components/Headline/Headline.mdx | 2 +- .../no-deprecated-custom-properties/README.md | 1 + .../no-deprecated-custom-properties/README.md | 2 ++ 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/features/1-theme.mdx b/docs/features/1-theme.mdx index 8b547eb900..e693dab845 100644 --- a/docs/features/1-theme.mdx +++ b/docs/features/1-theme.mdx @@ -61,7 +61,7 @@ Use spacings for gutters, margins, and paddings. Don't use it for border width, ## Typography -Avoid using the `var(--cui-typography-*)` CSS custom properties directly in your styles. Instead, use the typography components [`Display`](Typography/Display/Docs), [`Headline`](Typography/Headline/Docs), [`SubHeadline`](Typography/SubHeadline/Docs), [`Body`](Typography/Body/Docs), and [`BodyLarge`](Typography/BodyLarge/Docs). +Avoid using the `var(--cui-typography-*)` CSS custom properties directly in your styles. Instead, use the typography components [`Display`](Typography/Display/Docs), [`Headline`](Typography/Headline/Docs), and [`Body`](Typography/Body/Docs). <CustomPropertiesTable namespace="typography" preview={Typography} /> diff --git a/packages/circuit-ui/components/Display/Display.mdx b/packages/circuit-ui/components/Display/Display.mdx index a3a4c4fd81..80723e3bfc 100644 --- a/packages/circuit-ui/components/Display/Display.mdx +++ b/packages/circuit-ui/components/Display/Display.mdx @@ -24,4 +24,4 @@ The Display component comes in three sizes. In most cases, use the [Headline com ## Accessibility -All accessibility guidelines for the [Headline component](Typography/Headline) also apply to the Display component../Display.stories +All accessibility guidelines for the [Headline component](Typography/Headline) also apply to the Display component. diff --git a/packages/circuit-ui/components/Headline/Headline.mdx b/packages/circuit-ui/components/Headline/Headline.mdx index 2731e7b862..4de1756f33 100644 --- a/packages/circuit-ui/components/Headline/Headline.mdx +++ b/packages/circuit-ui/components/Headline/Headline.mdx @@ -18,7 +18,7 @@ The Headline component is used for describing the contents of a page or page sec The Headline component comes in three sizes. -Use the `four` size for card headers and `three` for page titles in web applications. For specific use cases such as landing pages, consider using the [Display](Typography/Display) component. +Use the `m` size for card headers and `l` for page titles in web applications. Consider using the [Display](Typography/Display) component for specific use cases such as landing pages. <Story of={Stories.Sizes} inline={false} /> diff --git a/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/README.md b/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/README.md index 4383f63def..7087c49063 100644 --- a/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/README.md +++ b/packages/eslint-plugin-circuit-ui/no-deprecated-custom-properties/README.md @@ -32,5 +32,6 @@ n/a ## Further Reading +- [Theme documentation](https://circuit.sumup.com/?path=/docs/features-theme--docs) on the Circuit UI docs - [Migration guide](https://github.com/sumup-oss/circuit-ui/blob/main/MIGRATION.md) - [Design token release notes](https://github.com/sumup-oss/circuit-ui/blob/main/packages/design-tokens/CHANGELOG.md) diff --git a/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/README.md b/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/README.md index 461f89987b..8d9138c11c 100644 --- a/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/README.md +++ b/packages/stylelint-plugin-circuit-ui/no-deprecated-custom-properties/README.md @@ -27,3 +27,5 @@ n/a ## Further Reading - [Theme documentation](https://circuit.sumup.com/?path=/docs/features-theme--docs) on the Circuit UI docs +- [Migration guide](https://github.com/sumup-oss/circuit-ui/blob/main/MIGRATION.md) +- [Design token release notes](https://github.com/sumup-oss/circuit-ui/blob/main/packages/design-tokens/CHANGELOG.md) From 5a53fd93067d7a27832c2f9420ddb095cab0fdc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Wed, 21 Aug 2024 13:25:25 +0200 Subject: [PATCH 18/26] Add new typography size names to no-renamed-props ESLint rule --- .../no-renamed-props/README.md | 22 ++++++++++ .../no-renamed-props/index.ts | 42 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/packages/eslint-plugin-circuit-ui/no-renamed-props/README.md b/packages/eslint-plugin-circuit-ui/no-renamed-props/README.md index 7159438dea..c2c580d912 100644 --- a/packages/eslint-plugin-circuit-ui/no-renamed-props/README.md +++ b/packages/eslint-plugin-circuit-ui/no-renamed-props/README.md @@ -16,6 +16,17 @@ Note that the rule can only lint direct uses of a component. Wrapped instances s Examples of **incorrect** code for this rule: ```tsx +// Since Circuit UI v9 +function Component() { + return ( + <div> + <Display size="one" /> + <Headline size="three" /> + <Body size="two" /> + </div> + ); +} + // Since Circuit UI v7.5 function Component() { return ( @@ -53,6 +64,17 @@ function Component() { Examples of **correct** code for this rule: ```tsx +// Since Circuit UI v9 +function Component() { + return ( + <div> + <Display size="l" /> + <Headline size="m" /> + <Body size="s" /> + </div> + ); +} + // Since Circuit UI v7.5 function Component() { return ( diff --git a/packages/eslint-plugin-circuit-ui/no-renamed-props/index.ts b/packages/eslint-plugin-circuit-ui/no-renamed-props/index.ts index b500a6e2b7..4d03738375 100644 --- a/packages/eslint-plugin-circuit-ui/no-renamed-props/index.ts +++ b/packages/eslint-plugin-circuit-ui/no-renamed-props/index.ts @@ -292,6 +292,48 @@ const configs: Config[] = [ }); }, }, + { + type: 'values', + component: 'Title', + prop: 'size', + values: { + one: 'l', + two: 'm', + three: 'm', + four: 's', + }, + }, + { + type: 'values', + component: 'Display', + prop: 'size', + values: { + one: 'l', + two: 'm', + three: 'm', + four: 's', + }, + }, + { + type: 'values', + component: 'Headline', + prop: 'size', + values: { + one: 'l', + two: 'm', + three: 'm', + four: 's', + }, + }, + { + type: 'values', + component: 'Body', + prop: 'size', + values: { + one: 'm', + two: 's', + }, + }, ]; export const noRenamedProps = createRule({ From d211a4b89ef782f596b3c707788b474e38d862c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Thu, 22 Aug 2024 13:57:40 +0200 Subject: [PATCH 19/26] Add changesets --- .changeset/dry-cheetahs-tap.md | 32 +++++++++++++++++++++++++++++ .changeset/fluffy-lobsters-sin.md | 21 +++++++++++++++++++ .changeset/friendly-falcons-turn.md | 6 ++++++ .changeset/grumpy-coins-sip.md | 5 +++++ .changeset/plenty-chicken-deny.md | 5 +++++ .changeset/pretty-tigers-run.md | 5 +++++ .changeset/rich-phones-attend.md | 5 +++++ .changeset/shiny-dragons-sip.md | 5 +++++ 8 files changed, 84 insertions(+) create mode 100644 .changeset/dry-cheetahs-tap.md create mode 100644 .changeset/fluffy-lobsters-sin.md create mode 100644 .changeset/friendly-falcons-turn.md create mode 100644 .changeset/grumpy-coins-sip.md create mode 100644 .changeset/plenty-chicken-deny.md create mode 100644 .changeset/pretty-tigers-run.md create mode 100644 .changeset/rich-phones-attend.md create mode 100644 .changeset/shiny-dragons-sip.md diff --git a/.changeset/dry-cheetahs-tap.md b/.changeset/dry-cheetahs-tap.md new file mode 100644 index 0000000000..97e5310f19 --- /dev/null +++ b/.changeset/dry-cheetahs-tap.md @@ -0,0 +1,32 @@ +--- +'@sumup-oss/design-tokens': minor +--- + +Consolidated and renamed the `typography` tokens: + +| Old | New | +| --------------------------------------- | ----------------------------------- | +| `typography-title-one-font-size` | `typography-display-l-font-size` | +| `typography-title-one-line-height` | `typography-display-l-line-height` | +| `typography-title-two-font-size` | `typography-display-m-font-size` | +| `typography-title-two-line-height` | `typography-display-m-line-height` | +| `typography-title-three-font-size` | `typography-display-m-font-size` | +| `typography-title-three-line-height` | `typography-display-m-line-height` | +| `typography-title-four-font-size` | `typography-display-s-font-size` | +| `typography-title-four-line-height` | `typography-display-s-line-height` | +| `typography-headline-one-font-size` | `typography-headline-l-font-size` | +| `typography-headline-one-line-height` | `typography-headline-l-line-height` | +| `typography-headline-two-font-size` | `typography-headline-m-font-size` | +| `typography-headline-two-line-height` | `typography-headline-m-line-height` | +| `typography-headline-three-font-size` | `typography-headline-m-font-size` | +| `typography-headline-three-line-height` | `typography-headline-m-line-height` | +| `typography-headline-four-font-size` | `typography-headline-s-font-size` | +| `typography-headline-four-line-height` | `typography-headline-s-line-height` | +| `typography-sub-headline-font-size` | `typography-headline-s-font-size` | +| `typography-sub-headline-line-height` | `typography-headline-s-line-height` | +| `typography-body-large-font-size` | `typography-body-l-font-size` | +| `typography-body-large-line-height` | `typography-body-l-line-height` | +| `typography-body-one-font-size` | `typography-body-m-font-size` | +| `typography-body-one-line-height` | `typography-body-m-line-height` | +| `typography-body-two-font-size` | `typography-body-s-font-size` | +| `typography-body-two-line-height` | `typography-body-s-line-height` | diff --git a/.changeset/fluffy-lobsters-sin.md b/.changeset/fluffy-lobsters-sin.md new file mode 100644 index 0000000000..9ff69f1b09 --- /dev/null +++ b/.changeset/fluffy-lobsters-sin.md @@ -0,0 +1,21 @@ +--- +'@sumup-oss/circuit-ui': minor +--- + +Consolidated and renamed the sizes of the Display (formerly Title), Headline, and Body components: + +**Display & Headline** + +| Old | New | +| ----- | --- | +| one | l | +| two | m | +| three | m | +| four | s | + +**Body** + +| Old | New | +| --- | --- | +| one | m | +| two | s | diff --git a/.changeset/friendly-falcons-turn.md b/.changeset/friendly-falcons-turn.md new file mode 100644 index 0000000000..b7f4989d5f --- /dev/null +++ b/.changeset/friendly-falcons-turn.md @@ -0,0 +1,6 @@ +--- +"@sumup-oss/stylelint-plugin-circuit-ui": minor +"@sumup-oss/eslint-plugin-circuit-ui": minor +--- + +Added `circuit-ui/no-deprecated-custom-properties` rule to flag uses of deprecated custom properties. diff --git a/.changeset/grumpy-coins-sip.md b/.changeset/grumpy-coins-sip.md new file mode 100644 index 0000000000..1b533cb6dc --- /dev/null +++ b/.changeset/grumpy-coins-sip.md @@ -0,0 +1,5 @@ +--- +'@sumup-oss/circuit-ui': minor +--- + +Deprecated the BodyLarge component. Use the Body component in size `l` instead. diff --git a/.changeset/plenty-chicken-deny.md b/.changeset/plenty-chicken-deny.md new file mode 100644 index 0000000000..6d577a56b7 --- /dev/null +++ b/.changeset/plenty-chicken-deny.md @@ -0,0 +1,5 @@ +--- +'@sumup-oss/circuit-ui': minor +--- + +Added an explicit foreground color to the Body component (`fg-normal`) to better support localized dark mode. Previously, the component inherited its color from its parent. diff --git a/.changeset/pretty-tigers-run.md b/.changeset/pretty-tigers-run.md new file mode 100644 index 0000000000..614d636818 --- /dev/null +++ b/.changeset/pretty-tigers-run.md @@ -0,0 +1,5 @@ +--- +"@sumup-oss/eslint-plugin-circuit-ui": major +--- + +Added a migration for the Display (formerly Title), Headline and Body components' `size` prop to the `circuit-ui/no-renamed-props` rule. diff --git a/.changeset/rich-phones-attend.md b/.changeset/rich-phones-attend.md new file mode 100644 index 0000000000..8dffc39e71 --- /dev/null +++ b/.changeset/rich-phones-attend.md @@ -0,0 +1,5 @@ +--- +'@sumup-oss/circuit-ui': minor +--- + +Deprecated the SubHeadline component. Use the Headline component in size `s` instead. diff --git a/.changeset/shiny-dragons-sip.md b/.changeset/shiny-dragons-sip.md new file mode 100644 index 0000000000..1ddfe2a5b8 --- /dev/null +++ b/.changeset/shiny-dragons-sip.md @@ -0,0 +1,5 @@ +--- +"@sumup-oss/circuit-ui": major +--- + +Renamed the Title component to Display for consistency with other platforms. From e847c57a9c2101377df226f08d224e27739eca4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Fri, 23 Aug 2024 11:37:01 +0200 Subject: [PATCH 20/26] Deprecate Body variant prop --- .changeset/brown-cobras-invite.md | 5 ++ .changeset/soft-drinks-accept.md | 5 ++ packages/circuit-ui/components/Body/Body.mdx | 2 + .../components/Body/Body.stories.tsx | 3 ++ packages/circuit-ui/components/Body/Body.tsx | 17 ++++++- .../components/BodyLarge/BodyLarge.mdx | 31 ------------- .../components/BodyLarge/BodyLarge.module.css | 31 ------------- .../BodyLarge/BodyLarge.stories.tsx | 42 ----------------- .../components/BodyLarge/BodyLarge.tsx | 46 ++----------------- .../no-deprecated-props/index.ts | 6 +++ 10 files changed, 42 insertions(+), 146 deletions(-) create mode 100644 .changeset/brown-cobras-invite.md create mode 100644 .changeset/soft-drinks-accept.md delete mode 100644 packages/circuit-ui/components/BodyLarge/BodyLarge.mdx delete mode 100644 packages/circuit-ui/components/BodyLarge/BodyLarge.module.css delete mode 100644 packages/circuit-ui/components/BodyLarge/BodyLarge.stories.tsx diff --git a/.changeset/brown-cobras-invite.md b/.changeset/brown-cobras-invite.md new file mode 100644 index 0000000000..470f8e0731 --- /dev/null +++ b/.changeset/brown-cobras-invite.md @@ -0,0 +1,5 @@ +--- +"@sumup-oss/circuit-ui": minor +--- + +Added a new `weight` prop to the Body component. Choose between the `regular` and `bold` font weights. diff --git a/.changeset/soft-drinks-accept.md b/.changeset/soft-drinks-accept.md new file mode 100644 index 0000000000..8a74ca3489 --- /dev/null +++ b/.changeset/soft-drinks-accept.md @@ -0,0 +1,5 @@ +--- +'@sumup-oss/circuit-ui': minor +--- + +Deprecated the Body component's `variant` prop. Use the new `weight` prop instead of the `highlight` variant and use custom CSS to replace the other variants. diff --git a/packages/circuit-ui/components/Body/Body.mdx b/packages/circuit-ui/components/Body/Body.mdx index acb19ee7cb..ce74d9127e 100644 --- a/packages/circuit-ui/components/Body/Body.mdx +++ b/packages/circuit-ui/components/Body/Body.mdx @@ -30,6 +30,8 @@ The Body component comes in three weights. Use the default `regular` weight in m ### Variants +<Status variant="deprecated" /> + The Body component accepts five different variants—`highlight`, `quote`, `confirm`, `alert` and `subtle`—to tailor it according to the content we are presenting. Different variants will render different HTML elements by default: diff --git a/packages/circuit-ui/components/Body/Body.stories.tsx b/packages/circuit-ui/components/Body/Body.stories.tsx index ae3a36af8e..70b869e38c 100644 --- a/packages/circuit-ui/components/Body/Body.stories.tsx +++ b/packages/circuit-ui/components/Body/Body.stories.tsx @@ -13,6 +13,8 @@ * limitations under the License. */ +import { BodyLarge } from '../BodyLarge/BodyLarge.js'; + import type { BodyProps } from './Body.js'; import { Body } from './index.js'; @@ -23,6 +25,7 @@ const content = export default { title: 'Typography/Body', component: Body, + subcomponents: { BodyLarge }, argTypes: { as: { control: 'text' }, }, diff --git a/packages/circuit-ui/components/Body/Body.tsx b/packages/circuit-ui/components/Body/Body.tsx index d1502d025d..bac58c7b73 100644 --- a/packages/circuit-ui/components/Body/Body.tsx +++ b/packages/circuit-ui/components/Body/Body.tsx @@ -44,7 +44,8 @@ export interface BodyProps extends HTMLAttributes<HTMLParagraphElement> { */ weight?: 'regular' | 'bold'; /** - * Choose from style variants. + * @deprecated Use the `weight` prop instead of the `highlight` variant and + * use custom CSS to replace the other variants. */ variant?: Variant; /** @@ -75,6 +76,20 @@ export const Body = forwardRef<HTMLParagraphElement, BodyProps>( const Element = as || getHTMLElement(variant); if (process.env.NODE_ENV !== 'production') { + if (variant) { + if (variant === 'highlight') { + deprecate( + 'Body', + 'The "highlight" variant has been deprecated. Use the "weight" prop instead.', + ); + } else { + deprecate( + 'Body', + `The "${variant}" variant has been deprecated. Use custom CSS instead.`, + ); + } + } + const deprecatedSizeMap: Record<string, string> = { 'one': 'm', 'two': 's', diff --git a/packages/circuit-ui/components/BodyLarge/BodyLarge.mdx b/packages/circuit-ui/components/BodyLarge/BodyLarge.mdx deleted file mode 100644 index fa308ec5f6..0000000000 --- a/packages/circuit-ui/components/BodyLarge/BodyLarge.mdx +++ /dev/null @@ -1,31 +0,0 @@ -import { Meta, Status, Props, Story } from '../../../../.storybook/components'; -import * as Stories from './BodyLarge.stories'; - -<Meta of={Stories} /> - -# BodyLarge - -<Status variant="deprecated"> -Use the Body component in size `l` instead. -</Status> - -The BodyLarge component is used to render content with large typography. Typically, large typography is intended for landing pages. In most cases, the [Body](Typography/Body) should be used instead. - -<Story of={Stories.Base} /> -<Props /> - -## Component variations - -### Variants - -The BodyLarge accepts five different variants—`highlight`, `quote`, `confirm`, `alert` and `subtle`—to tailor it according to the content we are presenting. - -The `highlight` variant will render a `<strong>` element by default, while the `quote` variant will render a `blockquote`. - -<Story of={Stories.Variants} /> - ---- - -## Accessibility - -All accessibility guidelines for the [Body component](Typography/Body) also apply to the BodyLarge component. diff --git a/packages/circuit-ui/components/BodyLarge/BodyLarge.module.css b/packages/circuit-ui/components/BodyLarge/BodyLarge.module.css deleted file mode 100644 index e2645d1970..0000000000 --- a/packages/circuit-ui/components/BodyLarge/BodyLarge.module.css +++ /dev/null @@ -1,31 +0,0 @@ -.base { - font-size: var(--cui-typography-body-l-font-size); - font-weight: var(--cui-font-weight-regular); - line-height: var(--cui-typography-body-l-line-height); -} - -/* Variants */ - -.highlight, -strong { - font-weight: var(--cui-font-weight-bold); -} - -.quote, -blockquote { - padding-left: var(--cui-spacings-kilo); - font-style: italic; - border-left: var(--cui-border-width-mega) solid var(--cui-border-accent); -} - -.confirm { - color: var(--cui-fg-success); -} - -.alert { - color: var(--cui-fg-danger); -} - -.subtle { - color: var(--cui-fg-subtle); -} diff --git a/packages/circuit-ui/components/BodyLarge/BodyLarge.stories.tsx b/packages/circuit-ui/components/BodyLarge/BodyLarge.stories.tsx deleted file mode 100644 index 6106a374b5..0000000000 --- a/packages/circuit-ui/components/BodyLarge/BodyLarge.stories.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright 2021, SumUp Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { BodyLargeProps } from './BodyLarge.js'; - -import { BodyLarge } from './index.js'; - -const content = - 'An electronic circuit is composed of individual electronic components, such as resistors, transistors, capacitors, inductors and diodes, connected by conductive wires or traces through which electric current can flow.'; - -export default { - title: 'Typography/BodyLarge', - component: BodyLarge, - argTypes: { - as: { control: 'text' }, - }, -}; - -export const Base = (args: BodyLargeProps) => ( - <BodyLarge {...args}>{content}</BodyLarge> -); - -const variants = ['highlight', 'quote', 'confirm', 'alert', 'subtle'] as const; - -export const Variants = (args: BodyLargeProps) => - variants.map((variant) => ( - <BodyLarge key={variant} {...args} variant={variant}> - This is a {variant} BodyLarge - </BodyLarge> - )); diff --git a/packages/circuit-ui/components/BodyLarge/BodyLarge.tsx b/packages/circuit-ui/components/BodyLarge/BodyLarge.tsx index 476324ebd4..ec6dc6fb0a 100644 --- a/packages/circuit-ui/components/BodyLarge/BodyLarge.tsx +++ b/packages/circuit-ui/components/BodyLarge/BodyLarge.tsx @@ -13,46 +13,17 @@ * limitations under the License. */ -import { forwardRef, type HTMLAttributes, type Ref } from 'react'; +import { forwardRef } from 'react'; -import type { AsPropType } from '../../types/prop-types.js'; -import { clsx } from '../../styles/clsx.js'; import { deprecate } from '../../util/logger.js'; +import { Body, type BodyProps } from '../Body/Body.js'; -import classes from './BodyLarge.module.css'; - -type Variant = 'highlight' | 'quote' | 'confirm' | 'alert' | 'subtle'; - -export interface BodyLargeProps extends HTMLAttributes<HTMLParagraphElement> { - /** - * Choose from style variants. - */ - variant?: Variant; - /** - * Render the text using any HTML element. - */ - as?: AsPropType; - /** - * The ref to the HTML DOM element. - */ - ref?: Ref<any>; -} - -function getHTMLElement(variant?: Variant): AsPropType { - if (variant === 'highlight') { - return 'strong'; - } - if (variant === 'quote') { - return 'blockquote'; - } - return 'p'; -} - +export type BodyLargeProps = Omit<BodyProps, 'size'>; /** * @deprecated Use the Body component in size `l` instead. */ export const BodyLarge = forwardRef<HTMLParagraphElement, BodyLargeProps>( - ({ className, as, variant, ...props }, ref) => { + (props, ref) => { if (process.env.NODE_ENV !== 'production') { deprecate( 'BodyLarge', @@ -60,14 +31,7 @@ export const BodyLarge = forwardRef<HTMLParagraphElement, BodyLargeProps>( ); } - const Element = as || getHTMLElement(variant); - return ( - <Element - {...props} - ref={ref} - className={clsx(classes.base, variant && classes[variant], className)} - /> - ); + return <Body {...props} ref={ref} size="l" />; }, ); diff --git a/packages/eslint-plugin-circuit-ui/no-deprecated-props/index.ts b/packages/eslint-plugin-circuit-ui/no-deprecated-props/index.ts index 661a80551d..afde936391 100644 --- a/packages/eslint-plugin-circuit-ui/no-deprecated-props/index.ts +++ b/packages/eslint-plugin-circuit-ui/no-deprecated-props/index.ts @@ -65,6 +65,12 @@ const mappings: Config[] = [ props: ['variant'], alternative: '', }, + { + components: ['Body'], + props: ['variant'], + alternative: + 'Use the `weight` prop instead of the `highlight` variant and use custom CSS to replace the other variants.', + }, ]; export const noDeprecatedProps = createRule({ From cdbe130c88d584f2c98f60b5532a64be86629206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Fri, 23 Aug 2024 12:19:04 +0200 Subject: [PATCH 21/26] Add Compact and Numeral components --- .changeset/clever-pugs-sing.md | 5 + .changeset/five-elephants-travel.md | 5 + packages/circuit-ui/components/Body/Body.mdx | 2 +- .../components/Body/Body.module.css | 1 - .../circuit-ui/components/Compact/Compact.mdx | 116 ++++++++++++++++++ .../components/Compact/Compact.module.css | 30 +++++ .../components/Compact/Compact.spec.tsx | 52 ++++++++ .../components/Compact/Compact.stories.tsx | 51 ++++++++ .../circuit-ui/components/Compact/Compact.tsx | 55 +++++++++ .../circuit-ui/components/Compact/index.ts | 18 +++ .../circuit-ui/components/Numeral/Numeral.mdx | 29 +++++ .../components/Numeral/Numeral.module.css | 31 +++++ .../components/Numeral/Numeral.spec.tsx | 52 ++++++++ .../components/Numeral/Numeral.stories.tsx | 50 ++++++++ .../circuit-ui/components/Numeral/Numeral.tsx | 55 +++++++++ .../circuit-ui/components/Numeral/index.ts | 18 +++ packages/circuit-ui/index.ts | 4 + 17 files changed, 572 insertions(+), 2 deletions(-) create mode 100644 .changeset/clever-pugs-sing.md create mode 100644 .changeset/five-elephants-travel.md create mode 100644 packages/circuit-ui/components/Compact/Compact.mdx create mode 100644 packages/circuit-ui/components/Compact/Compact.module.css create mode 100644 packages/circuit-ui/components/Compact/Compact.spec.tsx create mode 100644 packages/circuit-ui/components/Compact/Compact.stories.tsx create mode 100644 packages/circuit-ui/components/Compact/Compact.tsx create mode 100644 packages/circuit-ui/components/Compact/index.ts create mode 100644 packages/circuit-ui/components/Numeral/Numeral.mdx create mode 100644 packages/circuit-ui/components/Numeral/Numeral.module.css create mode 100644 packages/circuit-ui/components/Numeral/Numeral.spec.tsx create mode 100644 packages/circuit-ui/components/Numeral/Numeral.stories.tsx create mode 100644 packages/circuit-ui/components/Numeral/Numeral.tsx create mode 100644 packages/circuit-ui/components/Numeral/index.ts diff --git a/.changeset/clever-pugs-sing.md b/.changeset/clever-pugs-sing.md new file mode 100644 index 0000000000..361654faa4 --- /dev/null +++ b/.changeset/clever-pugs-sing.md @@ -0,0 +1,5 @@ +--- +'@sumup-oss/circuit-ui': minor +--- + +Added a new Compact component for text in space-constraint contexts. diff --git a/.changeset/five-elephants-travel.md b/.changeset/five-elephants-travel.md new file mode 100644 index 0000000000..3173bbdd60 --- /dev/null +++ b/.changeset/five-elephants-travel.md @@ -0,0 +1,5 @@ +--- +"@sumup-oss/circuit-ui": minor +--- + +Added a new Numeral component for numeric content such as currency values. diff --git a/packages/circuit-ui/components/Body/Body.mdx b/packages/circuit-ui/components/Body/Body.mdx index ce74d9127e..67faf7eec5 100644 --- a/packages/circuit-ui/components/Body/Body.mdx +++ b/packages/circuit-ui/components/Body/Body.mdx @@ -24,7 +24,7 @@ The Body component comes in three sizes. Use the default `m` size in most cases. ### Weights -The Body component comes in three weights. Use the default `regular` weight in most cases. +The Body component comes in two weights. Use the default `regular` weight in most cases. <Story of={Stories.Weights} /> diff --git a/packages/circuit-ui/components/Body/Body.module.css b/packages/circuit-ui/components/Body/Body.module.css index c9f61eb0d6..a7b178a4f9 100644 --- a/packages/circuit-ui/components/Body/Body.module.css +++ b/packages/circuit-ui/components/Body/Body.module.css @@ -1,5 +1,4 @@ .base { - font-weight: var(--cui-font-weight-regular); color: var(--cui-fg-normal); } diff --git a/packages/circuit-ui/components/Compact/Compact.mdx b/packages/circuit-ui/components/Compact/Compact.mdx new file mode 100644 index 0000000000..4baf31d626 --- /dev/null +++ b/packages/circuit-ui/components/Compact/Compact.mdx @@ -0,0 +1,116 @@ +import { Meta, Status, Props, Story } from '../../../../.storybook/components'; +import * as Stories from './Compact.stories'; + +<Meta of={Stories} /> + +# Compact + +<Status variant="stable" /> + +The Compact component is used to present content to our users. + +<Story of={Stories.Base} /> +<Props /> + +## Usage guidelines + +## Component variations + +### Sizes + +The Compact component comes in three sizes. Use the default `m` size in most cases. + +<Story of={Stories.Sizes} /> + +### Weights + +The Compact component comes in two weights. Use the default `regular` weight in most cases. + +<Story of={Stories.Weights} /> + +--- + +## Accessibility + +### Best practices + +#### Break text up into sections + +In order to make content easier to digest (especially on content-heavy pages such as articles or landing pages), break text up into sections. + +- Use semantic HTML elements and headings (use the [Headline](Typography/Headline) component) to build sections into your markup +- Add spacing between paragraphs and sections for sighted users (use the [`spacing()` style mixin](Features/Style-Mixins/Spacing)) + +This is beneficial to everyone, but critical for users with cognitive, language or learning disabilities (such as dyslexia or ADHD). + +#### Write simple copy + +Similarly to how breaking text up into sections helps users _parse_ content, writing concise and simple copy helps users _understand_ content. + +- Avoid the figurative use of words, or specialized words ([3.1.3: Unusual Words](https://www.w3.org/WAI/WCAG21/Understanding/unusual-words)) +- Allow users to access the expanded form of abbreviations ([3.1.4: Abbreviations](https://www.w3.org/WAI/WCAG21/Understanding/abbreviations)) +- Write content as clearly and simply as possible ([3.1.5: Reading Level](https://www.w3.org/WAI/WCAG21/Understanding/reading-level)) + +_Note: the success criteria referenced above are intended for AAA conformance. Though they are not requirements, they are a best practice and following them will improve the accessibility of our content._ + +#### Complement text with images + +Images, graphs, or other illustrations can help users contextualize and/or understand a piece of content. + +Visuals should usually complement text—and not replace it—unless an excellent description is provided as alternative text. + +#### Translate content + +Translate content intended for a linguistically diverse audience, and make it easy for users to change the page's language. + +Bear in mind that machine translation is often inaccurate: prefer professional translation in order to give the best possible experience to users from diverse linguistic backgrounds. + +#### Do not rely on color alone + +Color alone is not sufficient to differentiate text from the surrounding content ([1.4.1 Use of Color](https://www.w3.org/WAI/WCAG21/Understanding/use-of-color.html)). + +This is especially relevant when using the `confirm` and `alert` variants. + +For example, imagine a list of good and bad accessibility practices. It is not enough to use the `confirm` (green) variant for good practices and the `alert` (red) variant for bad practices. Instead, use additional visual cues such as icons (with an accessible label), or break up the list into two separate ones with explicit labeling. + +#### Make status messages accessible to screen readers using live regions + +When a change in content is not given focus (typically a message being added to the DOM to reflect a status update), the change needs to be announced to screen readers using a [live region](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) ([4.1.3 Status Messages](https://www.w3.org/WAI/WCAG21/Understanding/status-messages.html), [3.3.1 Error Identification](https://www.w3.org/WAI/WCAG21/Understanding/error-identification)). + +For example, a form submission fails and a message saying "This username is already taken." using `<Compact variant="alert" />` appears. Without a live region, screen reader users would have no way of knowing that something happened and that they need to make changes to the form before submitting again. They will either have to step through the DOM to try and find the relevant error message, or they will give up and close the page. + +Live regions can be tricky to work with, therefore we recommend using existing components such as the [NotificationInline](Notifications/NotificationInline) or the [NotificationToast](Notifications/NotificationToast) instead of implementing them from scratch. + +### Resources + +#### Visualizing document structure + +Use a tool like [Wave](https://wave.webaim.org/) to extract structure from a page (in Wave, you'll find the page structure under the _Structure_ tab). Verify that your copy is accurately grouped and labeled by headings. + +#### Verify your UI without color + +Simulate vision deficiencies or desaturate your page, and verify that visual cues beyond color are helping users understand your copy. + +- [Simulate vision deficiencies using Firefox](https://developer.mozilla.org/en-US/docs/Tools/Accessibility_inspector/Simulation) +- [Simulate vision deficiencies using Chrome](https://developer.chrome.com/blog/new-in-devtools-83/#vision-deficiencies) +- Desaturate a page using [Wave](https://wave.webaim.org/) (under Contrast, "Desaturate page") + +#### Test your page using a screen reader + +[Test your page using a screen reader](https://webaim.org/articles/screenreader_testing/) like JAWS (Windows), NVDA (Windows, Linux) or VoiceOver (macOS). + +This is particularly valuable for highly dynamic content, for example using live regions. + +#### Further reading + +- [Writing for Web Accessibility](https://www.w3.org/WAI/tips/writing/) (w3.org) +- [Cognitive Disabilities](https://webaim.org/articles/cognitive/) (WebAIM) + +#### Related WCAG success criteria + +- 1.4.1: [Use of Color](https://www.w3.org/WAI/WCAG21/Understanding/use-of-color.html) +- 3.1.3: [Unusual Words](https://www.w3.org/WAI/WCAG21/Understanding/unusual-words) (AAA) +- 3.1.4: [Abbreviations](https://www.w3.org/WAI/WCAG21/Understanding/abbreviations) (AAA) +- 3.1.5: [Reading Level](https://www.w3.org/WAI/WCAG21/Understanding/reading-level) (AAA) +- 3.3.1: [Error Identification](https://www.w3.org/WAI/WCAG21/Understanding/error-identification) +- 4.1.3: [Status Messages](https://www.w3.org/WAI/WCAG21/Understanding/status-messages.html) diff --git a/packages/circuit-ui/components/Compact/Compact.module.css b/packages/circuit-ui/components/Compact/Compact.module.css new file mode 100644 index 0000000000..06afc5c3a4 --- /dev/null +++ b/packages/circuit-ui/components/Compact/Compact.module.css @@ -0,0 +1,30 @@ +.base { + color: var(--cui-fg-normal); +} + +/* Sizes */ + +.l { + font-size: var(--cui-typography-compact-l-font-size); + line-height: var(--cui-typography-compact-l-line-height); +} + +.m { + font-size: var(--cui-typography-compact-m-font-size); + line-height: var(--cui-typography-compact-m-line-height); +} + +.s { + font-size: var(--cui-typography-compact-s-font-size); + line-height: var(--cui-typography-compact-s-line-height); +} + +/* Weights */ + +.regular { + font-weight: var(--cui-font-weight-regular); +} + +.bold { + font-weight: var(--cui-font-weight-bold); +} diff --git a/packages/circuit-ui/components/Compact/Compact.spec.tsx b/packages/circuit-ui/components/Compact/Compact.spec.tsx new file mode 100644 index 0000000000..a314b02acd --- /dev/null +++ b/packages/circuit-ui/components/Compact/Compact.spec.tsx @@ -0,0 +1,52 @@ +/** + * Copyright 2019, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; +import { createRef } from 'react'; + +import { axe, render } from '../../util/test-utils.js'; + +import { Compact } from './Compact.js'; + +describe('Compact', () => { + it('should merge a custom class name with the default ones', () => { + const className = 'foo'; + const { container } = render( + <Compact className={className}>Compact</Compact>, + ); + const paragraph = container.querySelector('p'); + expect(paragraph?.className).toContain(className); + }); + + it('should forward a ref', () => { + const ref = createRef<HTMLParagraphElement>(); + const { container } = render(<Compact ref={ref}>Compact</Compact>); + const paragraph = container.querySelector('p'); + expect(ref.current).toBe(paragraph); + }); + + const elements = ['p', 'article', 'div'] as const; + it.each(elements)('should render as a "%s" element', (as) => { + const { container } = render(<Compact as={as}>{as} Compact</Compact>); + const actual = container.querySelector(as); + expect(actual).toBeVisible(); + }); + + it('should meet accessibility guidelines', async () => { + const { container } = render(<Compact>Compact</Compact>); + const actual = await axe(container); + expect(actual).toHaveNoViolations(); + }); +}); diff --git a/packages/circuit-ui/components/Compact/Compact.stories.tsx b/packages/circuit-ui/components/Compact/Compact.stories.tsx new file mode 100644 index 0000000000..4e9d02c930 --- /dev/null +++ b/packages/circuit-ui/components/Compact/Compact.stories.tsx @@ -0,0 +1,51 @@ +/** + * Copyright 2019, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { CompactProps } from './Compact.js'; + +import { Compact } from './index.js'; + +const content = + 'An electronic circuit is composed of individual electronic components, such as resistors, transistors, capacitors, inductors and diodes, connected by conductive wires or traces through which electric current can flow.'; + +export default { + title: 'Typography/Compact', + component: Compact, + argTypes: { + as: { control: 'text' }, + }, +}; + +export const Base = (args: CompactProps) => ( + <Compact {...args}>{content}</Compact> +); + +const sizes = ['l', 'm', 's'] as const; + +export const Sizes = (args: CompactProps) => + sizes.map((size) => ( + <Compact key={size} {...args} size={size}> + This is size {size}. {content} + </Compact> + )); + +const weights = ['regular', 'bold'] as const; + +export const Weights = (args: CompactProps) => + weights.map((weight) => ( + <Compact key={weight} {...args} weight={weight}> + This is the {weight} weight. {content} + </Compact> + )); diff --git a/packages/circuit-ui/components/Compact/Compact.tsx b/packages/circuit-ui/components/Compact/Compact.tsx new file mode 100644 index 0000000000..de27618980 --- /dev/null +++ b/packages/circuit-ui/components/Compact/Compact.tsx @@ -0,0 +1,55 @@ +/** + * Copyright 2019, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { forwardRef, type HTMLAttributes } from 'react'; + +import type { AsPropType } from '../../types/prop-types.js'; +import { clsx } from '../../styles/clsx.js'; + +import classes from './Compact.module.css'; + +export interface CompactProps extends HTMLAttributes<HTMLParagraphElement> { + /** + * Choose from 3 font sizes. Default `m`. + */ + size?: 's' | 'm' | 'l'; + /** + * Choose from two font weights. Default: `regular`. + */ + weight?: 'regular' | 'bold'; + /** + * Render the text using any HTML element. + */ + as?: AsPropType; +} + +/** + * The Compact component is used to present the core textual content + * to our users. + */ +export const Compact = forwardRef<HTMLParagraphElement, CompactProps>( + ( + { className, as: Element = 'p', size = 'm', weight = 'regular', ...props }, + ref, + ) => ( + <Element + {...props} + ref={ref} + className={clsx(classes.base, classes[size], classes[weight], className)} + /> + ), +); + +Compact.displayName = 'Compact'; diff --git a/packages/circuit-ui/components/Compact/index.ts b/packages/circuit-ui/components/Compact/index.ts new file mode 100644 index 0000000000..61b77bab92 --- /dev/null +++ b/packages/circuit-ui/components/Compact/index.ts @@ -0,0 +1,18 @@ +/** + * Copyright 2019, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { Compact } from './Compact.js'; + +export type { CompactProps } from './Compact.js'; diff --git a/packages/circuit-ui/components/Numeral/Numeral.mdx b/packages/circuit-ui/components/Numeral/Numeral.mdx new file mode 100644 index 0000000000..70ff21789d --- /dev/null +++ b/packages/circuit-ui/components/Numeral/Numeral.mdx @@ -0,0 +1,29 @@ +import { Meta, Status, Props, Story } from '../../../../.storybook/components'; +import * as Stories from './Numeral.stories'; + +<Meta of={Stories} /> + +# Numeral + +<Status variant="stable" /> + +The Numeral component is used to present numeric content such as currency values. + +<Story of={Stories.Base} /> +<Props /> + +## Usage guidelines + +## Component variations + +### Sizes + +The Numeral component comes in three sizes. Use the default `m` size in most cases. + +<Story of={Stories.Sizes} /> + +### Weights + +The Numeral component comes in two weights. Use the default `regular` weight in most cases. + +<Story of={Stories.Weights} /> diff --git a/packages/circuit-ui/components/Numeral/Numeral.module.css b/packages/circuit-ui/components/Numeral/Numeral.module.css new file mode 100644 index 0000000000..1e1c42e4c1 --- /dev/null +++ b/packages/circuit-ui/components/Numeral/Numeral.module.css @@ -0,0 +1,31 @@ +.base { + font-variant-numeric: tabular-nums; + color: var(--cui-fg-normal); +} + +/* Sizes */ + +.l { + font-size: var(--cui-typography-numeral-l-font-size); + line-height: var(--cui-typography-numeral-l-line-height); +} + +.m { + font-size: var(--cui-typography-numeral-m-font-size); + line-height: var(--cui-typography-numeral-m-line-height); +} + +.s { + font-size: var(--cui-typography-numeral-s-font-size); + line-height: var(--cui-typography-numeral-s-line-height); +} + +/* Weights */ + +.regular { + font-weight: var(--cui-font-weight-regular); +} + +.bold { + font-weight: var(--cui-font-weight-bold); +} diff --git a/packages/circuit-ui/components/Numeral/Numeral.spec.tsx b/packages/circuit-ui/components/Numeral/Numeral.spec.tsx new file mode 100644 index 0000000000..d27a5b906a --- /dev/null +++ b/packages/circuit-ui/components/Numeral/Numeral.spec.tsx @@ -0,0 +1,52 @@ +/** + * Copyright 2019, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it } from 'vitest'; +import { createRef } from 'react'; + +import { axe, render } from '../../util/test-utils.js'; + +import { Numeral } from './Numeral.js'; + +describe('Numeral', () => { + it('should merge a custom class name with the default ones', () => { + const className = 'foo'; + const { container } = render( + <Numeral className={className}>Numeral</Numeral>, + ); + const paragraph = container.querySelector('p'); + expect(paragraph?.className).toContain(className); + }); + + it('should forward a ref', () => { + const ref = createRef<HTMLParagraphElement>(); + const { container } = render(<Numeral ref={ref}>Numeral</Numeral>); + const paragraph = container.querySelector('p'); + expect(ref.current).toBe(paragraph); + }); + + const elements = ['p', 'article', 'div'] as const; + it.each(elements)('should render as a "%s" element', (as) => { + const { container } = render(<Numeral as={as}>{as} Numeral</Numeral>); + const actual = container.querySelector(as); + expect(actual).toBeVisible(); + }); + + it('should meet accessibility guidelines', async () => { + const { container } = render(<Numeral>Numeral</Numeral>); + const actual = await axe(container); + expect(actual).toHaveNoViolations(); + }); +}); diff --git a/packages/circuit-ui/components/Numeral/Numeral.stories.tsx b/packages/circuit-ui/components/Numeral/Numeral.stories.tsx new file mode 100644 index 0000000000..ff8972c8f6 --- /dev/null +++ b/packages/circuit-ui/components/Numeral/Numeral.stories.tsx @@ -0,0 +1,50 @@ +/** + * Copyright 2019, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { NumeralProps } from './Numeral.js'; + +import { Numeral } from './index.js'; + +const content = '$ 1,009.95'; + +export default { + title: 'Typography/Numeral', + component: Numeral, + argTypes: { + as: { control: 'text' }, + }, +}; + +export const Base = (args: NumeralProps) => ( + <Numeral {...args}>{content}</Numeral> +); + +const sizes = ['l', 'm', 's'] as const; + +export const Sizes = (args: NumeralProps) => + sizes.map((size) => ( + <Numeral key={size} {...args} size={size}> + {content} in size {size} + </Numeral> + )); + +const weights = ['regular', 'bold'] as const; + +export const Weights = (args: NumeralProps) => + weights.map((weight) => ( + <Numeral key={weight} {...args} weight={weight}> + {content} in {weight} weight + </Numeral> + )); diff --git a/packages/circuit-ui/components/Numeral/Numeral.tsx b/packages/circuit-ui/components/Numeral/Numeral.tsx new file mode 100644 index 0000000000..1cabe94c6c --- /dev/null +++ b/packages/circuit-ui/components/Numeral/Numeral.tsx @@ -0,0 +1,55 @@ +/** + * Copyright 2019, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { forwardRef, type HTMLAttributes } from 'react'; + +import type { AsPropType } from '../../types/prop-types.js'; +import { clsx } from '../../styles/clsx.js'; + +import classes from './Numeral.module.css'; + +export interface NumeralProps extends HTMLAttributes<HTMLParagraphElement> { + /** + * Choose from 3 font sizes. Default `m`. + */ + size?: 's' | 'm' | 'l'; + /** + * Choose from two font weights. Default: `regular`. + */ + weight?: 'regular' | 'bold'; + /** + * Render the text using any HTML element. + */ + as?: AsPropType; +} + +/** + * The Numeral component is used to present the core textual content + * to our users. + */ +export const Numeral = forwardRef<HTMLParagraphElement, NumeralProps>( + ( + { className, as: Element = 'p', size = 'm', weight = 'regular', ...props }, + ref, + ) => ( + <Element + {...props} + ref={ref} + className={clsx(classes.base, classes[size], classes[weight], className)} + /> + ), +); + +Numeral.displayName = 'Numeral'; diff --git a/packages/circuit-ui/components/Numeral/index.ts b/packages/circuit-ui/components/Numeral/index.ts new file mode 100644 index 0000000000..ded8652bfd --- /dev/null +++ b/packages/circuit-ui/components/Numeral/index.ts @@ -0,0 +1,18 @@ +/** + * Copyright 2019, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { Numeral } from './Numeral.js'; + +export type { NumeralProps } from './Numeral.js'; diff --git a/packages/circuit-ui/index.ts b/packages/circuit-ui/index.ts index 02608c4248..be4c7a7e41 100644 --- a/packages/circuit-ui/index.ts +++ b/packages/circuit-ui/index.ts @@ -29,6 +29,10 @@ export { Body } from './components/Body/index.js'; export type { BodyProps } from './components/Body/index.js'; export { BodyLarge } from './components/BodyLarge/index.js'; export type { BodyLargeProps } from './components/BodyLarge/index.js'; +export { Compact } from './components/Compact/index.js'; +export type { CompactProps } from './components/Compact/index.js'; +export { Numeral } from './components/Numeral/index.js'; +export type { NumeralProps } from './components/Numeral/index.js'; export { Anchor } from './components/Anchor/index.js'; export type { AnchorProps } from './components/Anchor/index.js'; export { List } from './components/List/index.js'; From 03c1ed0db3edbeaa43194efee84297120018e20c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Fri, 23 Aug 2024 12:27:07 +0200 Subject: [PATCH 22/26] Add letter-spacing to typography components --- .../components/Body/Body.module.css | 13 +++------ packages/circuit-ui/components/Body/Body.tsx | 27 ++++++++++++++----- .../components/Compact/Compact.module.css | 3 +++ .../components/Display/Display.module.css | 23 +++------------- .../circuit-ui/components/Display/Display.tsx | 24 ++++++++++------- .../components/Headline/Headline.module.css | 23 +++------------- .../components/Headline/Headline.tsx | 24 ++++++++++------- .../components/Numeral/Numeral.module.css | 3 +++ 8 files changed, 65 insertions(+), 75 deletions(-) diff --git a/packages/circuit-ui/components/Body/Body.module.css b/packages/circuit-ui/components/Body/Body.module.css index a7b178a4f9..681312186b 100644 --- a/packages/circuit-ui/components/Body/Body.module.css +++ b/packages/circuit-ui/components/Body/Body.module.css @@ -7,26 +7,19 @@ .l { font-size: var(--cui-typography-body-l-font-size); line-height: var(--cui-typography-body-l-line-height); + letter-spacing: var(--cui-typography-body-l-letter-spacing); } .m { font-size: var(--cui-typography-body-m-font-size); line-height: var(--cui-typography-body-m-line-height); + letter-spacing: var(--cui-typography-body-m-letter-spacing); } .s { font-size: var(--cui-typography-body-s-font-size); line-height: var(--cui-typography-body-s-line-height); -} - -.one { - font-size: var(--cui-typography-body-m-font-size); - line-height: var(--cui-typography-body-m-line-height); -} - -.two { - font-size: var(--cui-typography-body-s-font-size); - line-height: var(--cui-typography-body-s-line-height); + letter-spacing: var(--cui-typography-body-s-letter-spacing); } /* Weights */ diff --git a/packages/circuit-ui/components/Body/Body.tsx b/packages/circuit-ui/components/Body/Body.tsx index bac58c7b73..7021038c13 100644 --- a/packages/circuit-ui/components/Body/Body.tsx +++ b/packages/circuit-ui/components/Body/Body.tsx @@ -64,13 +64,25 @@ function getHTMLElement(variant?: Variant): AsPropType { return 'p'; } +const deprecatedSizeMap: Record<string, string> = { + 'one': 'm', + 'two': 's', +}; + /** * The Body component is used to present the core textual content * to our users. */ export const Body = forwardRef<HTMLParagraphElement, BodyProps>( ( - { className, as, size = 'm', weight = 'regular', variant, ...props }, + { + className, + as, + size: legacySize = 'm', + weight = 'regular', + variant, + ...props + }, ref, ) => { const Element = as || getHTMLElement(variant); @@ -90,18 +102,19 @@ export const Body = forwardRef<HTMLParagraphElement, BodyProps>( } } - const deprecatedSizeMap: Record<string, string> = { - 'one': 'm', - 'two': 's', - }; - if (size in deprecatedSizeMap) { + if (legacySize in deprecatedSizeMap) { deprecate( 'Body', - `The "${size}" size has been deprecated. Use the "${deprecatedSizeMap[size]}" size instead.`, + `The "${legacySize}" size has been deprecated. Use the "${deprecatedSizeMap[legacySize]}" size instead.`, ); } } + const size = (deprecatedSizeMap[legacySize] || legacySize) as + | 'l' + | 'm' + | 's'; + return ( <Element {...props} diff --git a/packages/circuit-ui/components/Compact/Compact.module.css b/packages/circuit-ui/components/Compact/Compact.module.css index 06afc5c3a4..1131140c60 100644 --- a/packages/circuit-ui/components/Compact/Compact.module.css +++ b/packages/circuit-ui/components/Compact/Compact.module.css @@ -7,16 +7,19 @@ .l { font-size: var(--cui-typography-compact-l-font-size); line-height: var(--cui-typography-compact-l-line-height); + letter-spacing: var(--cui-typography-compact-l-letter-spacing); } .m { font-size: var(--cui-typography-compact-m-font-size); line-height: var(--cui-typography-compact-m-line-height); + letter-spacing: var(--cui-typography-compact-m-letter-spacing); } .s { font-size: var(--cui-typography-compact-s-font-size); line-height: var(--cui-typography-compact-s-line-height); + letter-spacing: var(--cui-typography-compact-s-letter-spacing); } /* Weights */ diff --git a/packages/circuit-ui/components/Display/Display.module.css b/packages/circuit-ui/components/Display/Display.module.css index 977a06a18e..2e589a0762 100644 --- a/packages/circuit-ui/components/Display/Display.module.css +++ b/packages/circuit-ui/components/Display/Display.module.css @@ -9,34 +9,17 @@ .l { font-size: var(--cui-typography-display-l-font-size); line-height: var(--cui-typography-display-l-line-height); + letter-spacing: var(--cui-typography-display-l-letter-spacing); } .m { font-size: var(--cui-typography-display-m-font-size); line-height: var(--cui-typography-display-m-line-height); + letter-spacing: var(--cui-typography-display-m-letter-spacing); } .s { font-size: var(--cui-typography-display-s-font-size); line-height: var(--cui-typography-display-s-line-height); -} - -.one { - font-size: var(--cui-typography-display-l-font-size); - line-height: var(--cui-typography-display-l-line-height); -} - -.two { - font-size: var(--cui-typography-display-m-font-size); - line-height: var(--cui-typography-display-m-line-height); -} - -.three { - font-size: var(--cui-typography-display-m-font-size); - line-height: var(--cui-typography-display-m-line-height); -} - -.four { - font-size: var(--cui-typography-display-s-font-size); - line-height: var(--cui-typography-display-s-line-height); + letter-spacing: var(--cui-typography-display-s-letter-spacing); } diff --git a/packages/circuit-ui/components/Display/Display.tsx b/packages/circuit-ui/components/Display/Display.tsx index 01cde9b714..7b31f8527f 100644 --- a/packages/circuit-ui/components/Display/Display.tsx +++ b/packages/circuit-ui/components/Display/Display.tsx @@ -53,11 +53,18 @@ export interface DisplayProps extends HTMLAttributes<HTMLHeadingElement> { as: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; } +const deprecatedSizeMap: Record<string, string> = { + 'one': 'l', + 'two': 'm', + 'three': 'm', + 'four': 's', +}; + /** * A flexible title component capable of rendering any HTML heading element. */ export const Display = forwardRef<HTMLHeadingElement, DisplayProps>( - ({ className, as, size = 'm', ...props }, ref) => { + ({ className, as, size: legacySize = 'm', ...props }, ref) => { if ( process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test' && @@ -68,22 +75,21 @@ export const Display = forwardRef<HTMLHeadingElement, DisplayProps>( } if (process.env.NODE_ENV !== 'production') { - const deprecatedSizeMap: Record<string, string> = { - 'one': 'l', - 'two': 'm', - 'three': 'm', - 'four': 's', - }; - if (size in deprecatedSizeMap) { + if (legacySize in deprecatedSizeMap) { deprecate( 'Display', - `The "${size}" size has been deprecated. Use the "${deprecatedSizeMap[size]}" size instead.`, + `The "${legacySize}" size has been deprecated. Use the "${deprecatedSizeMap[legacySize]}" size instead.`, ); } } const Element = as || 'h1'; + const size = (deprecatedSizeMap[legacySize] || legacySize) as + | 'l' + | 'm' + | 's'; + return ( <Element {...props} diff --git a/packages/circuit-ui/components/Headline/Headline.module.css b/packages/circuit-ui/components/Headline/Headline.module.css index f951abe1fb..a890f773bc 100644 --- a/packages/circuit-ui/components/Headline/Headline.module.css +++ b/packages/circuit-ui/components/Headline/Headline.module.css @@ -9,34 +9,17 @@ .l { font-size: var(--cui-typography-headline-l-font-size); line-height: var(--cui-typography-headline-l-line-height); + letter-spacing: var(--cui-typography-headline-l-letter-spacing); } .m { font-size: var(--cui-typography-headline-m-font-size); line-height: var(--cui-typography-headline-m-line-height); + letter-spacing: var(--cui-typography-headline-m-letter-spacing); } .s { font-size: var(--cui-typography-headline-s-font-size); line-height: var(--cui-typography-headline-s-line-height); -} - -.one { - font-size: var(--cui-typography-headline-l-font-size); - line-height: var(--cui-typography-headline-l-line-height); -} - -.two { - font-size: var(--cui-typography-headline-m-font-size); - line-height: var(--cui-typography-headline-m-line-height); -} - -.three { - font-size: var(--cui-typography-headline-m-font-size); - line-height: var(--cui-typography-headline-m-line-height); -} - -.four { - font-size: var(--cui-typography-headline-s-font-size); - line-height: var(--cui-typography-headline-s-line-height); + letter-spacing: var(--cui-typography-headline-s-letter-spacing); } diff --git a/packages/circuit-ui/components/Headline/Headline.tsx b/packages/circuit-ui/components/Headline/Headline.tsx index b58b7ef4eb..a4b0e04064 100644 --- a/packages/circuit-ui/components/Headline/Headline.tsx +++ b/packages/circuit-ui/components/Headline/Headline.tsx @@ -53,11 +53,18 @@ export interface HeadlineProps extends HTMLAttributes<HTMLHeadingElement> { as: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; } +const deprecatedSizeMap: Record<string, string> = { + 'one': 'l', + 'two': 'm', + 'three': 'm', + 'four': 's', +}; + /** * A flexible headline component capable of rendering any HTML heading element. */ export const Headline = forwardRef<HTMLHeadingElement, HeadlineProps>( - ({ className, as, size = 'm', ...props }, ref) => { + ({ className, as, size: legacySize = 'm', ...props }, ref) => { if ( process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test' && @@ -68,22 +75,21 @@ export const Headline = forwardRef<HTMLHeadingElement, HeadlineProps>( } if (process.env.NODE_ENV !== 'production') { - const deprecatedSizeMap: Record<string, string> = { - 'one': 'l', - 'two': 'm', - 'three': 'm', - 'four': 's', - }; - if (size in deprecatedSizeMap) { + if (legacySize in deprecatedSizeMap) { deprecate( 'Headline', - `The "${size}" size has been deprecated. Use the "${deprecatedSizeMap[size]}" size instead.`, + `The "${legacySize}" size has been deprecated. Use the "${deprecatedSizeMap[legacySize]}" size instead.`, ); } } const Element = as || 'h2'; + const size = (deprecatedSizeMap[legacySize] || legacySize) as + | 'l' + | 'm' + | 's'; + return ( <Element {...props} diff --git a/packages/circuit-ui/components/Numeral/Numeral.module.css b/packages/circuit-ui/components/Numeral/Numeral.module.css index 1e1c42e4c1..6c2bb82f79 100644 --- a/packages/circuit-ui/components/Numeral/Numeral.module.css +++ b/packages/circuit-ui/components/Numeral/Numeral.module.css @@ -8,16 +8,19 @@ .l { font-size: var(--cui-typography-numeral-l-font-size); line-height: var(--cui-typography-numeral-l-line-height); + letter-spacing: var(--cui-typography-numeral-l-letter-spacing); } .m { font-size: var(--cui-typography-numeral-m-font-size); line-height: var(--cui-typography-numeral-m-line-height); + letter-spacing: var(--cui-typography-numeral-m-letter-spacing); } .s { font-size: var(--cui-typography-numeral-s-font-size); line-height: var(--cui-typography-numeral-s-line-height); + letter-spacing: var(--cui-typography-numeral-s-letter-spacing); } /* Weights */ From b3ea78759b45c7479aeb68b19ffa936a2a8ef36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Fri, 23 Aug 2024 12:27:39 +0200 Subject: [PATCH 23/26] Map SubHeadline to Headline component --- .../SubHeadline/SubHeadline.module.css | 7 ------ .../components/SubHeadline/SubHeadline.tsx | 22 +++---------------- 2 files changed, 3 insertions(+), 26 deletions(-) delete mode 100644 packages/circuit-ui/components/SubHeadline/SubHeadline.module.css diff --git a/packages/circuit-ui/components/SubHeadline/SubHeadline.module.css b/packages/circuit-ui/components/SubHeadline/SubHeadline.module.css deleted file mode 100644 index d6e3a560e8..0000000000 --- a/packages/circuit-ui/components/SubHeadline/SubHeadline.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.base { - font-size: var(--cui-typography-headline-s-font-size); - font-weight: var(--cui-font-weight-bold); - line-height: var(--cui-typography-headline-s-line-height); - color: var(--cui-fg-normal); - text-transform: uppercase; -} diff --git a/packages/circuit-ui/components/SubHeadline/SubHeadline.tsx b/packages/circuit-ui/components/SubHeadline/SubHeadline.tsx index 15840419d5..fc5ebeeef8 100644 --- a/packages/circuit-ui/components/SubHeadline/SubHeadline.tsx +++ b/packages/circuit-ui/components/SubHeadline/SubHeadline.tsx @@ -15,11 +15,8 @@ import { forwardRef, type HTMLAttributes } from 'react'; -import { clsx } from '../../styles/clsx.js'; -import { CircuitError } from '../../util/errors.js'; import { deprecate } from '../../util/logger.js'; - -import classes from './SubHeadline.module.css'; +import { Headline } from '../Headline/Headline.js'; export interface SubHeadlineProps extends HTMLAttributes<HTMLHeadingElement> { /** @@ -34,16 +31,7 @@ export interface SubHeadlineProps extends HTMLAttributes<HTMLHeadingElement> { * @deprecated Use the Headline component in size `s` instead. */ export const SubHeadline = forwardRef<HTMLHeadingElement, SubHeadlineProps>( - ({ className, as, ...props }, ref) => { - if ( - process.env.NODE_ENV !== 'production' && - process.env.NODE_ENV !== 'test' && - !process?.env?.UNSAFE_DISABLE_ELEMENT_ERRORS && - !as - ) { - throw new CircuitError('SubHeadline', 'The `as` prop is required.'); - } - + (props, ref) => { if (process.env.NODE_ENV !== 'production') { deprecate( 'SubHeadline', @@ -51,11 +39,7 @@ export const SubHeadline = forwardRef<HTMLHeadingElement, SubHeadlineProps>( ); } - const Element = as || 'h2'; - - return ( - <Element {...props} ref={ref} className={clsx(classes.base, className)} /> - ); + return <Headline {...props} ref={ref} size="s" />; }, ); From cfdaa8617559178bcd12bb0dfb3a1f57db755ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Fri, 23 Aug 2024 13:00:15 +0200 Subject: [PATCH 24/26] Add color prop to Body, Compact and Numeral components --- .changeset/soft-drinks-accept.md | 2 +- .changeset/tiny-suits-smile.md | 5 ++ packages/circuit-ui/components/Body/Body.mdx | 6 +++ .../components/Body/Body.module.css | 50 ++++++++++++++++--- .../components/Body/Body.stories.tsx | 29 +++++++++++ packages/circuit-ui/components/Body/Body.tsx | 31 ++++++++++-- .../circuit-ui/components/Compact/Compact.mdx | 7 +++ .../components/Compact/Compact.module.css | 46 +++++++++++++++-- .../components/Compact/Compact.stories.tsx | 29 +++++++++++ .../circuit-ui/components/Compact/Compact.tsx | 30 ++++++++++- .../circuit-ui/components/Numeral/Numeral.mdx | 6 +++ .../components/Numeral/Numeral.module.css | 43 +++++++++++++++- .../components/Numeral/Numeral.stories.tsx | 29 +++++++++++ .../circuit-ui/components/Numeral/Numeral.tsx | 31 +++++++++++- .../no-deprecated-props/index.ts | 2 +- 15 files changed, 322 insertions(+), 24 deletions(-) create mode 100644 .changeset/tiny-suits-smile.md diff --git a/.changeset/soft-drinks-accept.md b/.changeset/soft-drinks-accept.md index 8a74ca3489..894a64a7dc 100644 --- a/.changeset/soft-drinks-accept.md +++ b/.changeset/soft-drinks-accept.md @@ -2,4 +2,4 @@ '@sumup-oss/circuit-ui': minor --- -Deprecated the Body component's `variant` prop. Use the new `weight` prop instead of the `highlight` variant and use custom CSS to replace the other variants. +Deprecated the Body component's `variant` prop. Use the new `color` prop instead of the `alert`, `confirm` and `subtle` variants. Use the new `weight` prop instead of the `highlight` variant. Use custom CSS for the `quote` variant. diff --git a/.changeset/tiny-suits-smile.md b/.changeset/tiny-suits-smile.md new file mode 100644 index 0000000000..68e9856668 --- /dev/null +++ b/.changeset/tiny-suits-smile.md @@ -0,0 +1,5 @@ +--- +'@sumup-oss/circuit-ui': minor +--- + +Added a new `color` prop to the Body component. Choose any foreground color. diff --git a/packages/circuit-ui/components/Body/Body.mdx b/packages/circuit-ui/components/Body/Body.mdx index 67faf7eec5..d16219d2aa 100644 --- a/packages/circuit-ui/components/Body/Body.mdx +++ b/packages/circuit-ui/components/Body/Body.mdx @@ -28,6 +28,12 @@ The Body component comes in two weights. Use the default `regular` weight in mos <Story of={Stories.Weights} /> +### Colors + +The Body component accepts any foreground color. Use the default `normal` color in most cases. + +<Story of={Stories.Colors} /> + ### Variants <Status variant="deprecated" /> diff --git a/packages/circuit-ui/components/Body/Body.module.css b/packages/circuit-ui/components/Body/Body.module.css index 681312186b..c6a2f30a30 100644 --- a/packages/circuit-ui/components/Body/Body.module.css +++ b/packages/circuit-ui/components/Body/Body.module.css @@ -1,7 +1,3 @@ -.base { - color: var(--cui-fg-normal); -} - /* Sizes */ .l { @@ -32,6 +28,48 @@ font-weight: var(--cui-font-weight-bold); } +/* Colors */ + +.normal { + color: var(--cui-fg-normal); +} + +.subtle { + color: var(--cui-fg-subtle); +} + +.placeholder { + color: var(--cui-fg-placeholder); +} + +.on-strong { + color: var(--cui-fg-on-strong); +} + +.on-strong-subtle { + color: var(--cui-fg-on-strong-subtle); +} + +.accent { + color: var(--cui-fg-accent); +} + +.success { + color: var(--cui-fg-success); +} + +.warning { + color: var(--cui-fg-warning); +} + +.danger { + color: var(--cui-fg-danger); +} + +.promo { + color: var(--cui-fg-promo); +} + /* Variants */ .highlight, @@ -53,7 +91,3 @@ blockquote { .alert { color: var(--cui-fg-danger); } - -.subtle { - color: var(--cui-fg-subtle); -} diff --git a/packages/circuit-ui/components/Body/Body.stories.tsx b/packages/circuit-ui/components/Body/Body.stories.tsx index 70b869e38c..f090c924b9 100644 --- a/packages/circuit-ui/components/Body/Body.stories.tsx +++ b/packages/circuit-ui/components/Body/Body.stories.tsx @@ -51,6 +51,35 @@ export const Weights = (args: BodyProps) => </Body> )); +const colors = [ + 'normal', + 'subtle', + 'placeholder', + 'on-strong', + 'on-strong-subtle', + 'accent', + 'success', + 'warning', + 'danger', + 'promo', +] as const; + +export const Colors = (args: BodyProps) => + colors.map((color) => ( + <Body + key={color} + {...args} + color={color} + style={ + color.includes('on-strong') + ? { background: 'var(--cui-bg-strong)' } + : {} + } + > + This is the {color} color. {content} + </Body> + )); + const variants = ['highlight', 'quote', 'confirm', 'alert', 'subtle'] as const; export const Variants = (args: BodyProps) => diff --git a/packages/circuit-ui/components/Body/Body.tsx b/packages/circuit-ui/components/Body/Body.tsx index 7021038c13..02f9af185f 100644 --- a/packages/circuit-ui/components/Body/Body.tsx +++ b/packages/circuit-ui/components/Body/Body.tsx @@ -44,8 +44,23 @@ export interface BodyProps extends HTMLAttributes<HTMLParagraphElement> { */ weight?: 'regular' | 'bold'; /** - * @deprecated Use the `weight` prop instead of the `highlight` variant and - * use custom CSS to replace the other variants. + * Choose a foreground color. Default: `normal`. + */ + color?: + | 'normal' + | 'subtle' + | 'placeholder' + | 'on-strong' + | 'on-strong-subtle' + | 'accent' + | 'success' + | 'warning' + | 'danger' + | 'promo'; + /** + * @deprecated Use the new `color` prop instead of the `alert`, `confirm` and + * `subtle` variants. Use the new `weight` prop instead of the `highlight` + * variant. Use custom CSS for the `quote` variant. */ variant?: Variant; /** @@ -80,6 +95,7 @@ export const Body = forwardRef<HTMLParagraphElement, BodyProps>( as, size: legacySize = 'm', weight = 'regular', + color = 'normal', variant, ...props }, @@ -92,12 +108,17 @@ export const Body = forwardRef<HTMLParagraphElement, BodyProps>( if (variant === 'highlight') { deprecate( 'Body', - 'The "highlight" variant has been deprecated. Use the "weight" prop instead.', + 'The "highlight" variant has been deprecated. Use the new `weight` prop instead.', + ); + } else if (variant === 'quote') { + deprecate( + 'Body', + 'The "quote" variant has been deprecated. Use custom CSS instead.', ); } else { deprecate( 'Body', - `The "${variant}" variant has been deprecated. Use custom CSS instead.`, + `The "${variant}" variant has been deprecated. Use the new \`color\` prop instead.`, ); } } @@ -120,9 +141,9 @@ export const Body = forwardRef<HTMLParagraphElement, BodyProps>( {...props} ref={ref} className={clsx( - classes.base, classes[size], classes[weight], + classes[color], variant && classes[variant], className, )} diff --git a/packages/circuit-ui/components/Compact/Compact.mdx b/packages/circuit-ui/components/Compact/Compact.mdx index 4baf31d626..062bb652a2 100644 --- a/packages/circuit-ui/components/Compact/Compact.mdx +++ b/packages/circuit-ui/components/Compact/Compact.mdx @@ -28,6 +28,13 @@ The Compact component comes in two weights. Use the default `regular` weight in <Story of={Stories.Weights} /> +### Colors + +The Compact component accepts any foreground color. Use the default `normal` color in most cases. + +<Story of={Stories.Colors} /> + + --- ## Accessibility diff --git a/packages/circuit-ui/components/Compact/Compact.module.css b/packages/circuit-ui/components/Compact/Compact.module.css index 1131140c60..02ccf82f40 100644 --- a/packages/circuit-ui/components/Compact/Compact.module.css +++ b/packages/circuit-ui/components/Compact/Compact.module.css @@ -1,7 +1,3 @@ -.base { - color: var(--cui-fg-normal); -} - /* Sizes */ .l { @@ -31,3 +27,45 @@ .bold { font-weight: var(--cui-font-weight-bold); } + +/* Colors */ + +.normal { + color: var(--cui-fg-normal); +} + +.subtle { + color: var(--cui-fg-subtle); +} + +.placeholder { + color: var(--cui-fg-placeholder); +} + +.on-strong { + color: var(--cui-fg-on-strong); +} + +.on-strong-subtle { + color: var(--cui-fg-on-strong-subtle); +} + +.accent { + color: var(--cui-fg-accent); +} + +.success { + color: var(--cui-fg-success); +} + +.warning { + color: var(--cui-fg-warning); +} + +.danger { + color: var(--cui-fg-danger); +} + +.promo { + color: var(--cui-fg-promo); +} diff --git a/packages/circuit-ui/components/Compact/Compact.stories.tsx b/packages/circuit-ui/components/Compact/Compact.stories.tsx index 4e9d02c930..5755b9d877 100644 --- a/packages/circuit-ui/components/Compact/Compact.stories.tsx +++ b/packages/circuit-ui/components/Compact/Compact.stories.tsx @@ -49,3 +49,32 @@ export const Weights = (args: CompactProps) => This is the {weight} weight. {content} </Compact> )); + +const colors = [ + 'normal', + 'subtle', + 'placeholder', + 'on-strong', + 'on-strong-subtle', + 'accent', + 'success', + 'warning', + 'danger', + 'promo', +] as const; + +export const Colors = (args: CompactProps) => + colors.map((color) => ( + <Compact + key={color} + {...args} + color={color} + style={ + color.includes('on-strong') + ? { background: 'var(--cui-bg-strong)' } + : {} + } + > + This is the {color} color. {content} + </Compact> + )); diff --git a/packages/circuit-ui/components/Compact/Compact.tsx b/packages/circuit-ui/components/Compact/Compact.tsx index de27618980..d2a1ea8bdc 100644 --- a/packages/circuit-ui/components/Compact/Compact.tsx +++ b/packages/circuit-ui/components/Compact/Compact.tsx @@ -29,6 +29,20 @@ export interface CompactProps extends HTMLAttributes<HTMLParagraphElement> { * Choose from two font weights. Default: `regular`. */ weight?: 'regular' | 'bold'; + /** + * Choose a foreground color. Default: `normal`. + */ + color?: + | 'normal' + | 'subtle' + | 'placeholder' + | 'on-strong' + | 'on-strong-subtle' + | 'accent' + | 'success' + | 'warning' + | 'danger' + | 'promo'; /** * Render the text using any HTML element. */ @@ -41,13 +55,25 @@ export interface CompactProps extends HTMLAttributes<HTMLParagraphElement> { */ export const Compact = forwardRef<HTMLParagraphElement, CompactProps>( ( - { className, as: Element = 'p', size = 'm', weight = 'regular', ...props }, + { + className, + as: Element = 'p', + size = 'm', + weight = 'regular', + color = 'normal', + ...props + }, ref, ) => ( <Element {...props} ref={ref} - className={clsx(classes.base, classes[size], classes[weight], className)} + className={clsx( + classes[size], + classes[weight], + classes[color], + className, + )} /> ), ); diff --git a/packages/circuit-ui/components/Numeral/Numeral.mdx b/packages/circuit-ui/components/Numeral/Numeral.mdx index 70ff21789d..fea8b6f0f5 100644 --- a/packages/circuit-ui/components/Numeral/Numeral.mdx +++ b/packages/circuit-ui/components/Numeral/Numeral.mdx @@ -27,3 +27,9 @@ The Numeral component comes in three sizes. Use the default `m` size in most cas The Numeral component comes in two weights. Use the default `regular` weight in most cases. <Story of={Stories.Weights} /> + +### Colors + +The Numeral component accepts any foreground color. Use the default `normal` color in most cases. + +<Story of={Stories.Colors} /> diff --git a/packages/circuit-ui/components/Numeral/Numeral.module.css b/packages/circuit-ui/components/Numeral/Numeral.module.css index 6c2bb82f79..7f4b54a4f0 100644 --- a/packages/circuit-ui/components/Numeral/Numeral.module.css +++ b/packages/circuit-ui/components/Numeral/Numeral.module.css @@ -1,6 +1,5 @@ .base { font-variant-numeric: tabular-nums; - color: var(--cui-fg-normal); } /* Sizes */ @@ -32,3 +31,45 @@ .bold { font-weight: var(--cui-font-weight-bold); } + +/* Colors */ + +.normal { + color: var(--cui-fg-normal); +} + +.subtle { + color: var(--cui-fg-subtle); +} + +.placeholder { + color: var(--cui-fg-placeholder); +} + +.on-strong { + color: var(--cui-fg-on-strong); +} + +.on-strong-subtle { + color: var(--cui-fg-on-strong-subtle); +} + +.accent { + color: var(--cui-fg-accent); +} + +.success { + color: var(--cui-fg-success); +} + +.warning { + color: var(--cui-fg-warning); +} + +.danger { + color: var(--cui-fg-danger); +} + +.promo { + color: var(--cui-fg-promo); +} diff --git a/packages/circuit-ui/components/Numeral/Numeral.stories.tsx b/packages/circuit-ui/components/Numeral/Numeral.stories.tsx index ff8972c8f6..3e2772a06f 100644 --- a/packages/circuit-ui/components/Numeral/Numeral.stories.tsx +++ b/packages/circuit-ui/components/Numeral/Numeral.stories.tsx @@ -48,3 +48,32 @@ export const Weights = (args: NumeralProps) => {content} in {weight} weight </Numeral> )); + +const colors = [ + 'normal', + 'subtle', + 'placeholder', + 'on-strong', + 'on-strong-subtle', + 'accent', + 'success', + 'warning', + 'danger', + 'promo', +] as const; + +export const Colors = (args: NumeralProps) => + colors.map((color) => ( + <Numeral + key={color} + {...args} + color={color} + style={ + color.includes('on-strong') + ? { background: 'var(--cui-bg-strong)' } + : {} + } + > + {content} in the {color} color. + </Numeral> + )); diff --git a/packages/circuit-ui/components/Numeral/Numeral.tsx b/packages/circuit-ui/components/Numeral/Numeral.tsx index 1cabe94c6c..8096c0a2f8 100644 --- a/packages/circuit-ui/components/Numeral/Numeral.tsx +++ b/packages/circuit-ui/components/Numeral/Numeral.tsx @@ -29,6 +29,20 @@ export interface NumeralProps extends HTMLAttributes<HTMLParagraphElement> { * Choose from two font weights. Default: `regular`. */ weight?: 'regular' | 'bold'; + /** + * Choose a foreground color. Default: `normal`. + */ + color?: + | 'normal' + | 'subtle' + | 'placeholder' + | 'on-strong' + | 'on-strong-subtle' + | 'accent' + | 'success' + | 'warning' + | 'danger' + | 'promo'; /** * Render the text using any HTML element. */ @@ -41,13 +55,26 @@ export interface NumeralProps extends HTMLAttributes<HTMLParagraphElement> { */ export const Numeral = forwardRef<HTMLParagraphElement, NumeralProps>( ( - { className, as: Element = 'p', size = 'm', weight = 'regular', ...props }, + { + className, + as: Element = 'p', + size = 'm', + weight = 'regular', + color = 'normal', + ...props + }, ref, ) => ( <Element {...props} ref={ref} - className={clsx(classes.base, classes[size], classes[weight], className)} + className={clsx( + classes.base, + classes[size], + classes[weight], + classes[color], + className, + )} /> ), ); diff --git a/packages/eslint-plugin-circuit-ui/no-deprecated-props/index.ts b/packages/eslint-plugin-circuit-ui/no-deprecated-props/index.ts index afde936391..793ce6b7ae 100644 --- a/packages/eslint-plugin-circuit-ui/no-deprecated-props/index.ts +++ b/packages/eslint-plugin-circuit-ui/no-deprecated-props/index.ts @@ -69,7 +69,7 @@ const mappings: Config[] = [ components: ['Body'], props: ['variant'], alternative: - 'Use the `weight` prop instead of the `highlight` variant and use custom CSS to replace the other variants.', + 'Use the new `color` prop instead of the `alert`, `confirm` and `subtle` variants. Use the new `weight` prop instead of the `highlight` variant. Use custom CSS for the `quote` variant.', }, ]; From ee5b417c168bf96494c63a77bbb5fc034d0d706b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Fri, 23 Aug 2024 13:57:05 +0200 Subject: [PATCH 25/26] Add migration for Body variants --- .../no-renamed-props/index.spec.ts | 48 ++++++++++++++ .../no-renamed-props/index.ts | 63 ++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin-circuit-ui/no-renamed-props/index.spec.ts b/packages/eslint-plugin-circuit-ui/no-renamed-props/index.spec.ts index 6e28b59127..33247a1ac8 100644 --- a/packages/eslint-plugin-circuit-ui/no-renamed-props/index.spec.ts +++ b/packages/eslint-plugin-circuit-ui/no-renamed-props/index.spec.ts @@ -77,6 +77,24 @@ ruleTester.run('no-renamed-props', noRenamedProps, { } `, }, + { + name: 'matched Body component without the variant prop', + code: ` + function Component() { + return <Body>Lorem ipsum</Body> + } + `, + }, + { + name: 'matched Body component with variant="quote"', + code: ` + function Component() { + return ( + <Body variant="quote">Lorem ipsum</Body> + ) + } + `, + }, ], invalid: [ { @@ -312,5 +330,35 @@ ruleTester.run('no-renamed-props', noRenamedProps, { { messageId: 'propName' }, ], }, + { + name: 'matched Body component with the old prop value', + code: ` + function ComponentA() { + return ( + <Body variant="highlight">Lorem ipsum</Body> + ) + } + + function ComponentB() { + return ( + <Body variant="alert">Lorem ipsum</Body> + ) + } + `, + output: ` + function ComponentA() { + return ( + <Body weight="bold">Lorem ipsum</Body> + ) + } + + function ComponentB() { + return ( + <Body color="danger">Lorem ipsum</Body> + ) + } + `, + errors: [{ messageId: 'bodyVariant' }, { messageId: 'bodyVariant' }], + }, ], }); diff --git a/packages/eslint-plugin-circuit-ui/no-renamed-props/index.ts b/packages/eslint-plugin-circuit-ui/no-renamed-props/index.ts index 4d03738375..b36978bcc3 100644 --- a/packages/eslint-plugin-circuit-ui/no-renamed-props/index.ts +++ b/packages/eslint-plugin-circuit-ui/no-renamed-props/index.ts @@ -55,7 +55,10 @@ type CustomConfig = { hook?: string; transform: ( node: TSESTree.JSXElement, - context: TSESLint.RuleContext<'propName' | 'propValue', never[]>, + context: TSESLint.RuleContext< + 'propName' | 'propValue' | 'bodyVariant', + never[] + >, ) => void; }; @@ -334,6 +337,62 @@ const configs: Config[] = [ two: 's', }, }, + { + type: 'custom', + component: 'Body', + // variant → weight or color + transform: (node, context) => { + const component = 'IconButton'; + + node.openingElement.attributes.forEach((attribute) => { + if ( + attribute.type !== 'JSXAttribute' || + attribute.name.type !== 'JSXIdentifier' || + attribute.name.name !== 'variant' + ) { + return; + } + + const current = getAttributeValue(attribute); + + if (current === 'highlight') { + const replacement = `weight="bold"`; + const weightAttribute = findAttribute(node, 'weight'); + context.report({ + node: attribute, + messageId: 'bodyVariant', + data: { component, current, replacement }, + fix: weightAttribute + ? undefined + : (fixer) => { + return fixer.replaceText(attribute, replacement); + }, + }); + return; + } + + if (current && ['alert', 'confirm', 'subtle'].includes(current)) { + const replacementMap: Record<string, string> = { + 'alert': `color="danger"`, + 'confirm': `color="success"`, + 'subtle': `color="subtle"`, + }; + const replacement = replacementMap[current]; + const colorAttribute = findAttribute(node, 'color'); + context.report({ + node: attribute, + messageId: 'bodyVariant', + data: { component, current, replacement }, + fix: colorAttribute + ? undefined + : (fixer) => { + return fixer.replaceText(attribute, replacement); + }, + }); + } + }); + }, + }, ]; export const noRenamedProps = createRule({ @@ -351,6 +410,8 @@ export const noRenamedProps = createRule({ "The {{component}}'s `{{current}}` prop has been renamed to `{{replacement}}`.", propValue: "The {{component}}'s `{{prop}}` prop values have been renamed. Replace `{{current}}` with `{{replacement}}`.", + bodyVariant: + 'The {{component}}\'s `variant` prop has been deprecated. Replace `variant="{{current}}"` with `{{replacement}}`.', }, }, defaultOptions: [], From f89f14d3d2863f2ca6c07cfcb983d6b0fc66d100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= <github@connorbaer.com> Date: Fri, 23 Aug 2024 15:57:04 +0200 Subject: [PATCH 26/26] Fix copyright year --- packages/circuit-ui/components/Compact/Compact.spec.tsx | 2 +- packages/circuit-ui/components/Compact/Compact.stories.tsx | 2 +- packages/circuit-ui/components/Compact/Compact.tsx | 2 +- packages/circuit-ui/components/Compact/index.ts | 2 +- packages/circuit-ui/components/Numeral/Numeral.spec.tsx | 2 +- packages/circuit-ui/components/Numeral/Numeral.stories.tsx | 2 +- packages/circuit-ui/components/Numeral/Numeral.tsx | 2 +- packages/circuit-ui/components/Numeral/index.ts | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/circuit-ui/components/Compact/Compact.spec.tsx b/packages/circuit-ui/components/Compact/Compact.spec.tsx index a314b02acd..e0c42e8aaf 100644 --- a/packages/circuit-ui/components/Compact/Compact.spec.tsx +++ b/packages/circuit-ui/components/Compact/Compact.spec.tsx @@ -1,5 +1,5 @@ /** - * Copyright 2019, SumUp Ltd. + * Copyright 2024, SumUp Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/circuit-ui/components/Compact/Compact.stories.tsx b/packages/circuit-ui/components/Compact/Compact.stories.tsx index 5755b9d877..10b58260d0 100644 --- a/packages/circuit-ui/components/Compact/Compact.stories.tsx +++ b/packages/circuit-ui/components/Compact/Compact.stories.tsx @@ -1,5 +1,5 @@ /** - * Copyright 2019, SumUp Ltd. + * Copyright 2024, SumUp Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/circuit-ui/components/Compact/Compact.tsx b/packages/circuit-ui/components/Compact/Compact.tsx index d2a1ea8bdc..c78a997a5e 100644 --- a/packages/circuit-ui/components/Compact/Compact.tsx +++ b/packages/circuit-ui/components/Compact/Compact.tsx @@ -1,5 +1,5 @@ /** - * Copyright 2019, SumUp Ltd. + * Copyright 2024, SumUp Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/circuit-ui/components/Compact/index.ts b/packages/circuit-ui/components/Compact/index.ts index 61b77bab92..53a03cc617 100644 --- a/packages/circuit-ui/components/Compact/index.ts +++ b/packages/circuit-ui/components/Compact/index.ts @@ -1,5 +1,5 @@ /** - * Copyright 2019, SumUp Ltd. + * Copyright 2024, SumUp Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/circuit-ui/components/Numeral/Numeral.spec.tsx b/packages/circuit-ui/components/Numeral/Numeral.spec.tsx index d27a5b906a..4398eedfb7 100644 --- a/packages/circuit-ui/components/Numeral/Numeral.spec.tsx +++ b/packages/circuit-ui/components/Numeral/Numeral.spec.tsx @@ -1,5 +1,5 @@ /** - * Copyright 2019, SumUp Ltd. + * Copyright 2024, SumUp Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/circuit-ui/components/Numeral/Numeral.stories.tsx b/packages/circuit-ui/components/Numeral/Numeral.stories.tsx index 3e2772a06f..7bb74c488f 100644 --- a/packages/circuit-ui/components/Numeral/Numeral.stories.tsx +++ b/packages/circuit-ui/components/Numeral/Numeral.stories.tsx @@ -1,5 +1,5 @@ /** - * Copyright 2019, SumUp Ltd. + * Copyright 2024, SumUp Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/circuit-ui/components/Numeral/Numeral.tsx b/packages/circuit-ui/components/Numeral/Numeral.tsx index 8096c0a2f8..e986c5b626 100644 --- a/packages/circuit-ui/components/Numeral/Numeral.tsx +++ b/packages/circuit-ui/components/Numeral/Numeral.tsx @@ -1,5 +1,5 @@ /** - * Copyright 2019, SumUp Ltd. + * Copyright 2024, SumUp Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/circuit-ui/components/Numeral/index.ts b/packages/circuit-ui/components/Numeral/index.ts index ded8652bfd..6dd12b8c67 100644 --- a/packages/circuit-ui/components/Numeral/index.ts +++ b/packages/circuit-ui/components/Numeral/index.ts @@ -1,5 +1,5 @@ /** - * Copyright 2019, SumUp Ltd. + * Copyright 2024, SumUp Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at