From 766efbac45e8831a19f3e99bd9d0550028d8d4fd Mon Sep 17 00:00:00 2001 From: Ruben Sibon Date: Fri, 8 Nov 2024 11:39:13 +0100 Subject: [PATCH] feat!: Replace Aspect Ratio component with utility classes and prop on Image (#1593) Co-authored-by: Vincent Smedinga Co-authored-by: Aram <37216945+alimpens@users.noreply.github.com> --- .../css/src/components/aspect-ratio/README.md | 26 +++-- .../components/aspect-ratio/aspect-ratio.scss | 31 +---- packages/css/src/components/image/README.md | 7 +- packages/css/src/components/image/image.scss | 8 +- .../src/AspectRatio/AspectRatio.test.tsx | 62 ---------- .../react/src/AspectRatio/AspectRatio.tsx | 25 ---- packages/react/src/AspectRatio/README.md | 5 - packages/react/src/AspectRatio/index.ts | 2 - packages/react/src/Column/Column.test.tsx | 2 +- packages/react/src/Column/Column.tsx | 2 +- packages/react/src/Image/Image.test.tsx | 14 ++- packages/react/src/Image/Image.tsx | 14 ++- .../react/src/ImageSlider/ImageSlider.tsx | 6 +- packages/react/src/Row/Row.test.tsx | 2 +- packages/react/src/Row/Row.tsx | 2 +- packages/react/src/Switch/Switch.test.tsx | 2 +- .../react/src/common/{layout.ts => types.ts} | 6 + packages/react/src/index.ts | 1 - proprietary/tokens/README.md | 2 +- ...n.tokens.json => aspect-ratio.tokens.json} | 2 +- .../components/ams/aspect-ratio.tokens.json | 12 -- .../src/components/ams/avatar.tokens.json | 2 +- .../src/components/ams/image.tokens.json | 7 ++ .../AspectRatio/AspectRatio.docs.mdx | 45 -------- .../AspectRatio/AspectRatio.stories.tsx | 108 ------------------ .../components/Breakout/Breakout.stories.tsx | 10 +- .../src/components/Card/Card.stories.tsx | 6 +- .../src/components/Column/Column.stories.tsx | 2 +- .../components/Overlap/Overlap.stories.tsx | 19 ++- storybook/src/components/Row/Row.stories.tsx | 2 +- .../src/docs/components/color-palette.css | 2 +- .../design-tokens/aspect-ratio.docs.mdx | 32 ++++++ .../foundation/design-tokens/border.docs.mdx | 18 +-- .../amsterdam/ArticlePage/ArticleHeader.tsx | 6 +- .../src/pages/amsterdam/HomePage/HomeNews.tsx | 14 +-- storybook/src/styles/docs.css | 6 + .../utils/AspectRatio/AspectRatio.docs.mdx | 13 +++ .../utils/AspectRatio/AspectRatio.stories.tsx | 32 ++++++ .../src/utils/AspectRatio/AspectRatio.tsx | 15 +++ 39 files changed, 199 insertions(+), 373 deletions(-) delete mode 100644 packages/react/src/AspectRatio/AspectRatio.test.tsx delete mode 100644 packages/react/src/AspectRatio/AspectRatio.tsx delete mode 100644 packages/react/src/AspectRatio/README.md delete mode 100644 packages/react/src/AspectRatio/index.ts rename packages/react/src/common/{layout.ts => types.ts} (71%) rename proprietary/tokens/src/brand/ams/{proportion.tokens.json => aspect-ratio.tokens.json} (91%) delete mode 100644 proprietary/tokens/src/components/ams/aspect-ratio.tokens.json create mode 100644 proprietary/tokens/src/components/ams/image.tokens.json delete mode 100644 storybook/src/components/AspectRatio/AspectRatio.docs.mdx delete mode 100644 storybook/src/components/AspectRatio/AspectRatio.stories.tsx create mode 100644 storybook/src/foundation/design-tokens/aspect-ratio.docs.mdx create mode 100644 storybook/src/utils/AspectRatio/AspectRatio.docs.mdx create mode 100644 storybook/src/utils/AspectRatio/AspectRatio.stories.tsx create mode 100644 storybook/src/utils/AspectRatio/AspectRatio.tsx diff --git a/packages/css/src/components/aspect-ratio/README.md b/packages/css/src/components/aspect-ratio/README.md index 128e9799fb..e28f1973de 100644 --- a/packages/css/src/components/aspect-ratio/README.md +++ b/packages/css/src/components/aspect-ratio/README.md @@ -2,19 +2,23 @@ # Aspect Ratio -Aspect Ratio updates the height of an element with its width. +Constrains media content to a supported aspect ratio. -These are the proportions we use: +## Class names -| keyword | ratio | -| :-------- | ----: | -| `2x-wide` | 16:5 | -| `x-wide` | 16:9 | -| `wide` | 4:3 | -| `square` | 1:1 | -| `tall` | 3:4 | -| `x-tall` | 9:16 | +Each available aspect ratio has an associated class name. +The class can be applied to any component or element. + +| Class name | Example | +| :-------------------------- | :-------------------------------------------------------------------------- | +| `ams-aspect-ratio--x-tall` |
| +| `ams-aspect-ratio--tall` |
| +| `ams-aspect-ratio--square` |
| +| `ams-aspect-ratio--wide` |
| +| `ams-aspect-ratio--x-wide` |
| +| `ams-aspect-ratio--2x-wide` |
| ## Guidelines -- Use this component to constrain images, videos and other elements to one of the available aspect ratios. +- Apply one of these classes to an image, video or other media content to constrain its dimensions to one of the available aspect ratios. +- The default aspect ratio is 16:9. diff --git a/packages/css/src/components/aspect-ratio/aspect-ratio.scss b/packages/css/src/components/aspect-ratio/aspect-ratio.scss index 08fcab0fe0..061cf6c6a9 100644 --- a/packages/css/src/components/aspect-ratio/aspect-ratio.scss +++ b/packages/css/src/components/aspect-ratio/aspect-ratio.scss @@ -4,30 +4,9 @@ */ .ams-aspect-ratio { - overflow: hidden; - position: relative; -} - -.ams-aspect-ratio--x-tall { - aspect-ratio: var(--ams-aspect-ratio-x-tall); -} - -.ams-aspect-ratio--tall { - aspect-ratio: var(--ams-aspect-ratio-tall); -} - -.ams-aspect-ratio--square { - aspect-ratio: var(--ams-aspect-ratio-square); -} - -.ams-aspect-ratio--wide { - aspect-ratio: var(--ams-aspect-ratio-wide); -} - -.ams-aspect-ratio--x-wide { - aspect-ratio: var(--ams-aspect-ratio-x-wide); -} - -.ams-aspect-ratio--2x-wide { - aspect-ratio: var(--ams-aspect-ratio-2x-wide); + @each $name in ("x-tall", "tall", "square", "wide", "x-wide", "2x-wide") { + &--#{$name} { + aspect-ratio: var(--ams-aspect-ratio-#{$name}) !important; + } + } } diff --git a/packages/css/src/components/image/README.md b/packages/css/src/components/image/README.md index da8fbbcfff..c4a9cb7e52 100644 --- a/packages/css/src/components/image/README.md +++ b/packages/css/src/components/image/README.md @@ -4,6 +4,12 @@ Displays an image. +## Design + +Every Image should be shown in one of the [available aspect ratios](https://designsystem.amsterdam/?path=/docs/brand-design-tokens-aspect-ratio--docs). +The default is 16:9. +If the intrinsic dimensions of the source do not match an aspect ratio, the image will get cropped to cover the intended area. + ## Guidelines - Do not forget to include a description of the image in the `alt` attribute. @@ -15,7 +21,6 @@ Displays an image. For example, provide small, medium, and large variants for various screen sizes. This prevents unnecessary downloading of large files. Do this especially for the main image of a page, where the difference between sizes on a narrow and wide screen is most significant. -- Ensure that the aspect ratio of the image is supported by the [Aspect Ratio](/docs/components-layout-aspect-ratio--docs) component. ## Relevant WCAG requirements diff --git a/packages/css/src/components/image/image.scss b/packages/css/src/components/image/image.scss index 05d5a99a70..3416e50223 100644 --- a/packages/css/src/components/image/image.scss +++ b/packages/css/src/components/image/image.scss @@ -4,17 +4,17 @@ */ .ams-image { + aspect-ratio: var(--ams-image-aspect-ratio); block-size: auto; /* [1] */ font-style: italic; /* [3] */ + inline-size: fit-content; max-inline-size: 100%; /* [1] */ + object-fit: cover; /* [4] */ vertical-align: middle; /* [2] */ - - &--cover { - object-fit: cover; - } } // [1] Allow for fluid image sizing while maintaining aspect ratio governed by inline/block size attributes // [2] Remove ‘phantom’ white space // [3] Italicise alt text to visually offset it from surrounding copy // Source: https://x.com/csswizardry/status/1717841334462005661 +// [4] Crop the image to maintain a supported aspect ratio diff --git a/packages/react/src/AspectRatio/AspectRatio.test.tsx b/packages/react/src/AspectRatio/AspectRatio.test.tsx deleted file mode 100644 index bdeb5c497d..0000000000 --- a/packages/react/src/AspectRatio/AspectRatio.test.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { render } from '@testing-library/react' -import { createRef } from 'react' -import { AspectRatio } from './AspectRatio' -import '@testing-library/jest-dom' - -describe('Aspect ratio', () => { - it('renders', () => { - const { container } = render() - - const component = container.querySelector(':only-child') - - expect(component).toBeInTheDocument() - expect(component).toBeVisible() - }) - - it('renders children', () => { - const { getByText } = render(Child) - - expect(getByText(/Child/i)).toBeInTheDocument() - }) - - it('renders a design system BEM class name', () => { - const { container } = render() - - const component = container.querySelector(':only-child') - - expect(component).toHaveClass('ams-aspect-ratio') - }) - - it('renders the right size classes', () => { - const { container: xTall } = render() - const { container: tall } = render() - const { container: square } = render() - const { container: wide } = render() - const { container: xWide } = render() - - expect(xTall.firstChild).toHaveClass('ams-aspect-ratio--x-tall') - expect(tall.firstChild).toHaveClass('ams-aspect-ratio--tall') - expect(square.firstChild).toHaveClass('ams-aspect-ratio--square') - expect(wide.firstChild).toHaveClass('ams-aspect-ratio--wide') - expect(xWide.firstChild).toHaveClass('ams-aspect-ratio--x-wide') - }) - - it('renders an additional class name', () => { - const { container } = render() - - const component = container.querySelector(':only-child') - - expect(component).toHaveClass('extra') - expect(component).toHaveClass('ams-aspect-ratio') - }) - - it('supports ForwardRef in React', () => { - const ref = createRef() - - const { container } = render() - - const component = container.querySelector(':only-child') - - expect(ref.current).toBe(component) - }) -}) diff --git a/packages/react/src/AspectRatio/AspectRatio.tsx b/packages/react/src/AspectRatio/AspectRatio.tsx deleted file mode 100644 index 0bcb2aafa1..0000000000 --- a/packages/react/src/AspectRatio/AspectRatio.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @license EUPL-1.2+ - * Copyright Gemeente Amsterdam - */ - -import clsx from 'clsx' -import { forwardRef } from 'react' -import type { ForwardedRef, HTMLAttributes, PropsWithChildren } from 'react' - -export type Ratio = 'x-tall' | 'tall' | 'square' | 'wide' | 'x-wide' | '2x-wide' - -export type AspectRatioProps = { - /** The dimensions. */ - ratio?: Ratio -} & PropsWithChildren> - -export const AspectRatio = forwardRef( - ({ children, className, ratio = 'square', ...restProps }: AspectRatioProps, ref: ForwardedRef) => ( -
- {children} -
- ), -) - -AspectRatio.displayName = 'AspectRatio' diff --git a/packages/react/src/AspectRatio/README.md b/packages/react/src/AspectRatio/README.md deleted file mode 100644 index 739cdd6cc0..0000000000 --- a/packages/react/src/AspectRatio/README.md +++ /dev/null @@ -1,5 +0,0 @@ - - -# React Aspect Ratio component - -[Aspect ratio documentation](../../../css/src/components/aspect-ratio/README.md) diff --git a/packages/react/src/AspectRatio/index.ts b/packages/react/src/AspectRatio/index.ts deleted file mode 100644 index d0fbbc74a6..0000000000 --- a/packages/react/src/AspectRatio/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { AspectRatio } from './AspectRatio' -export type { AspectRatioProps, Ratio } from './AspectRatio' diff --git a/packages/react/src/Column/Column.test.tsx b/packages/react/src/Column/Column.test.tsx index f81fb12027..76a3f98c52 100644 --- a/packages/react/src/Column/Column.test.tsx +++ b/packages/react/src/Column/Column.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react' import { createRef } from 'react' import { Column, columnGapSizes } from './Column' -import { crossAlignOptionsForColumn, mainAlignOptions } from '../common/layout' +import { crossAlignOptionsForColumn, mainAlignOptions } from '../common/types' import '@testing-library/jest-dom' describe('Column', () => { diff --git a/packages/react/src/Column/Column.tsx b/packages/react/src/Column/Column.tsx index fd0e7c584b..1bceefda2e 100644 --- a/packages/react/src/Column/Column.tsx +++ b/packages/react/src/Column/Column.tsx @@ -6,7 +6,7 @@ import clsx from 'clsx' import { forwardRef } from 'react' import type { HTMLAttributes, PropsWithChildren } from 'react' -import type { CrossAlignForColumn, MainAlign } from '../common/layout' +import type { CrossAlignForColumn, MainAlign } from '../common/types' export const columnGapSizes = ['none', 'extra-small', 'small', 'large', 'extra-large'] as const diff --git a/packages/react/src/Image/Image.test.tsx b/packages/react/src/Image/Image.test.tsx index dbb18575a1..5f830066be 100644 --- a/packages/react/src/Image/Image.test.tsx +++ b/packages/react/src/Image/Image.test.tsx @@ -1,6 +1,7 @@ import { render } from '@testing-library/react' import { createRef } from 'react' import { Image } from './Image' +import { aspectRatioOptions } from '../common/types' import '@testing-library/jest-dom' describe('Image', () => { @@ -26,16 +27,17 @@ describe('Image', () => { const component = container.querySelector(':only-child') - expect(component).toHaveClass('extra') - expect(component).toHaveClass('ams-image') + expect(component).toHaveClass('ams-image extra') }) - it('renders a class name to display the image as large as its container', () => { - const { container } = render() + aspectRatioOptions.forEach((aspectRatio) => { + it(`renders class names to display the image in the ${aspectRatio} aspect ratio`, () => { + const { container } = render() - const component = container.querySelector(':only-child') + const component = container.querySelector(':only-child') - expect(component).toHaveClass('ams-image--cover') + expect(component).toHaveClass(`ams-aspect-ratio--${aspectRatio}`) + }) }) it('supports ForwardRef in React', () => { diff --git a/packages/react/src/Image/Image.tsx b/packages/react/src/Image/Image.tsx index 38a857e0dd..2ccee61fb3 100644 --- a/packages/react/src/Image/Image.tsx +++ b/packages/react/src/Image/Image.tsx @@ -6,15 +6,17 @@ import clsx from 'clsx' import { forwardRef } from 'react' import type { ForwardedRef, ImgHTMLAttributes } from 'react' +import { AspectRatioProps } from '../common/types' -export type ImageProps = { - /** Whether to display the image exactly as large as its container. This will clip the image if necessary. */ - cover?: boolean -} & ImgHTMLAttributes +export type ImageProps = AspectRatioProps & ImgHTMLAttributes export const Image = forwardRef( - ({ className, cover = false, ...restProps }: ImageProps, ref: ForwardedRef) => ( - + ({ aspectRatio, className, ...restProps }: ImageProps, ref: ForwardedRef) => ( + ), ) diff --git a/packages/react/src/ImageSlider/ImageSlider.tsx b/packages/react/src/ImageSlider/ImageSlider.tsx index a3181dfd8a..476b3921c5 100644 --- a/packages/react/src/ImageSlider/ImageSlider.tsx +++ b/packages/react/src/ImageSlider/ImageSlider.tsx @@ -11,13 +11,9 @@ import { ImageSliderControls } from './ImageSliderControls' import { ImageSliderItem } from './ImageSliderItem' import { ImageSliderScroller } from './ImageSliderScroller' import { ImageSliderThumbnails } from './ImageSliderThumbnails' -import { Ratio } from '../AspectRatio' import { Image, ImageProps } from '../Image/Image' -export type ImageSliderImageProps = ImageProps & { - /** Specify the aspect ratio to use for the images. */ - aspectRatio: Ratio -} +export type ImageSliderImageProps = ImageProps export type ImageSliderProps = { /** Display buttons to navigate to the previous or next image. */ diff --git a/packages/react/src/Row/Row.test.tsx b/packages/react/src/Row/Row.test.tsx index 4aae85a7fe..3a9082708e 100644 --- a/packages/react/src/Row/Row.test.tsx +++ b/packages/react/src/Row/Row.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react' import { createRef } from 'react' import { Row, rowGapSizes } from './Row' -import { crossAlignOptions, mainAlignOptions } from '../common/layout' +import { crossAlignOptions, mainAlignOptions } from '../common/types' import '@testing-library/jest-dom' describe('Row', () => { diff --git a/packages/react/src/Row/Row.tsx b/packages/react/src/Row/Row.tsx index 446829799a..b1f6be9e07 100644 --- a/packages/react/src/Row/Row.tsx +++ b/packages/react/src/Row/Row.tsx @@ -6,7 +6,7 @@ import clsx from 'clsx' import { forwardRef } from 'react' import type { HTMLAttributes, PropsWithChildren } from 'react' -import type { CrossAlign, MainAlign } from '../common/layout' +import type { CrossAlign, MainAlign } from '../common/types' export const rowGapSizes = ['none', 'extra-small', 'small', 'large', 'extra-large'] as const diff --git a/packages/react/src/Switch/Switch.test.tsx b/packages/react/src/Switch/Switch.test.tsx index a21b62e6df..7cef895e7f 100644 --- a/packages/react/src/Switch/Switch.test.tsx +++ b/packages/react/src/Switch/Switch.test.tsx @@ -92,7 +92,7 @@ describe('Switch', () => { const component = container.querySelector(':only-child') - expect(component).toHaveClass('ams-switch', 'extra') + expect(component).toHaveClass('ams-switch extra') }) it('is able to pass a React ref', () => { diff --git a/packages/react/src/common/layout.ts b/packages/react/src/common/types.ts similarity index 71% rename from packages/react/src/common/layout.ts rename to packages/react/src/common/types.ts index 9b7a20f4f0..d18a01116b 100644 --- a/packages/react/src/common/layout.ts +++ b/packages/react/src/common/types.ts @@ -1,3 +1,9 @@ +export const aspectRatioOptions = ['x-tall', 'tall', 'square', 'wide', 'x-wide', '2x-wide'] as const +export type AspectRatioProps = { + /** The aspect ratio to display media content in. */ + aspectRatio?: (typeof aspectRatioOptions)[number] +} + export const crossAlignOptions = ['start', 'center', 'baseline', 'end'] as const export type CrossAlign = (typeof crossAlignOptions)[number] diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 5a1b28f7a6..9b88224382 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -46,7 +46,6 @@ export * from './Switch' export * from './Spotlight' export * from './Card' export * from './Alert' -export * from './AspectRatio' export * from './Footer' export * from './PageMenu' export * from './TopTaskLink' diff --git a/proprietary/tokens/README.md b/proprietary/tokens/README.md index 9c2dada27b..6113bad794 100644 --- a/proprietary/tokens/README.md +++ b/proprietary/tokens/README.md @@ -82,7 +82,7 @@ Examples: :root { --ams-color-primary-red: #ec0000; --ams-space-md: 1rem; - --ams-proportion-wide: 4/3; + --ams-aspect-ratio-wide: 4/3; --ams-border-width-lg: 0.1875rem; } ``` diff --git a/proprietary/tokens/src/brand/ams/proportion.tokens.json b/proprietary/tokens/src/brand/ams/aspect-ratio.tokens.json similarity index 91% rename from proprietary/tokens/src/brand/ams/proportion.tokens.json rename to proprietary/tokens/src/brand/ams/aspect-ratio.tokens.json index 423a580ff5..f8c45326fa 100644 --- a/proprietary/tokens/src/brand/ams/proportion.tokens.json +++ b/proprietary/tokens/src/brand/ams/aspect-ratio.tokens.json @@ -1,6 +1,6 @@ { "ams": { - "proportion": { + "aspect-ratio": { "x-tall": { "value": "9 / 16" }, "tall": { "value": "3 / 4" }, "square": { "value": "1 / 1" }, diff --git a/proprietary/tokens/src/components/ams/aspect-ratio.tokens.json b/proprietary/tokens/src/components/ams/aspect-ratio.tokens.json deleted file mode 100644 index 57f889c840..0000000000 --- a/proprietary/tokens/src/components/ams/aspect-ratio.tokens.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "ams": { - "aspect-ratio": { - "x-tall": { "value": "{ams.proportion.x-tall}" }, - "tall": { "value": "{ams.proportion.tall}" }, - "square": { "value": "{ams.proportion.square}" }, - "wide": { "value": "{ams.proportion.wide}" }, - "x-wide": { "value": "{ams.proportion.x-wide}" }, - "2x-wide": { "value": "{ams.proportion.2x-wide}" } - } - } -} diff --git a/proprietary/tokens/src/components/ams/avatar.tokens.json b/proprietary/tokens/src/components/ams/avatar.tokens.json index 727faa1844..820b61132f 100644 --- a/proprietary/tokens/src/components/ams/avatar.tokens.json +++ b/proprietary/tokens/src/components/ams/avatar.tokens.json @@ -1,7 +1,7 @@ { "ams": { "avatar": { - "aspect-ratio": { "value": "{ams.proportion.square}" }, + "aspect-ratio": { "value": "{ams.aspect-ratio.square}" }, "font-family": { "value": "{ams.text.font-family}" }, "font-size": { "value": "{ams.text.level.6.font-size}" }, "font-weight": { "value": "{ams.text.font-weight.normal}" }, diff --git a/proprietary/tokens/src/components/ams/image.tokens.json b/proprietary/tokens/src/components/ams/image.tokens.json new file mode 100644 index 0000000000..cd7460011a --- /dev/null +++ b/proprietary/tokens/src/components/ams/image.tokens.json @@ -0,0 +1,7 @@ +{ + "ams": { + "image": { + "aspect-ratio": { "value": "{ams.aspect-ratio.x-wide}" } + } + } +} diff --git a/storybook/src/components/AspectRatio/AspectRatio.docs.mdx b/storybook/src/components/AspectRatio/AspectRatio.docs.mdx deleted file mode 100644 index 24a212a64a..0000000000 --- a/storybook/src/components/AspectRatio/AspectRatio.docs.mdx +++ /dev/null @@ -1,45 +0,0 @@ -{/* @license CC0-1.0 */} - -import { Canvas, Controls, Markdown, Meta, Primary } from "@storybook/blocks"; -import * as AspectRatioStories from "./AspectRatio.stories.tsx"; -import README from "../../../../packages/css/src/components/aspect-ratio/README.md?raw"; - - - -{README} - - - - - -## Examples - -### Double extra wide - -We only use this aspect ratio for a ‘hero’ image across the entire website width. - - - -### Extra wide - - - -### Wide - - - -### Square - - - -### Tall - - - -### Extra tall - -This variant may be suitable for telephones. -Most devices nowadays have an aspect ratio of 9:19.5. -Images of 9:16 fill approximately 80% of the screen. - - diff --git a/storybook/src/components/AspectRatio/AspectRatio.stories.tsx b/storybook/src/components/AspectRatio/AspectRatio.stories.tsx deleted file mode 100644 index d1814cc75a..0000000000 --- a/storybook/src/components/AspectRatio/AspectRatio.stories.tsx +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @license EUPL-1.2+ - * Copyright Gemeente Amsterdam - */ - -import { Image } from '@amsterdam/design-system-react' -import { AspectRatio } from '@amsterdam/design-system-react/src' -import { Meta, StoryObj } from '@storybook/react' - -const meta = { - title: 'Components/Layout/Aspect Ratio', - component: AspectRatio, - args: { - ratio: 'square', - }, - argTypes: { - ratio: { - control: 'radio', - options: ['2x-wide', 'x-wide', 'wide', 'square', 'tall', 'x-tall'], - }, - }, -} satisfies Meta - -export default meta - -type Story = StoryObj - -const storyConfig = { - '2x-wide': { - image: 'https://picsum.photos/1152/360', - }, - 'x-wide': { - image: 'https://picsum.photos/640/360', - }, - wide: { - image: 'https://picsum.photos/480/360', - }, - square: { - image: 'https://picsum.photos/360/360', - }, - tall: { - image: 'https://picsum.photos/360/480', - }, - 'x-tall': { - image: 'https://picsum.photos/360/640', - }, -} - -const StoryTemplate: Story = { - decorators: [ - (Story) => ( -
- -
- ), - ], - render: ({ ratio }) => ( - - - - ), -} - -export const Default: Story = { - ...StoryTemplate, -} - -export const DoubleExtraWide: Story = { - ...StoryTemplate, - args: { - ratio: '2x-wide', - }, -} - -export const ExtraWide: Story = { - ...StoryTemplate, - args: { - ratio: 'x-wide', - }, -} - -export const Wide: Story = { - ...StoryTemplate, - args: { - ratio: 'wide', - }, -} - -export const Square: Story = { - ...StoryTemplate, - args: { - ratio: 'square', - }, -} - -export const Tall: Story = { - ...StoryTemplate, - args: { - ratio: 'tall', - }, -} - -export const ExtraTall: Story = { - ...StoryTemplate, - args: { - ratio: 'x-tall', - }, -} diff --git a/storybook/src/components/Breakout/Breakout.stories.tsx b/storybook/src/components/Breakout/Breakout.stories.tsx index 383261a874..e45b4d0c45 100644 --- a/storybook/src/components/Breakout/Breakout.stories.tsx +++ b/storybook/src/components/Breakout/Breakout.stories.tsx @@ -3,7 +3,7 @@ * Copyright Gemeente Amsterdam */ -import { AspectRatio, Image, Paragraph, Screen, Spotlight } from '@amsterdam/design-system-react' +import { Image, Paragraph, Screen, Spotlight } from '@amsterdam/design-system-react' import { Breakout } from '@amsterdam/design-system-react/src' import { Meta, StoryObj } from '@storybook/react' @@ -45,9 +45,7 @@ export const Default: Story = { rowSpan={2} rowStart={1} > - - - + , ], }, @@ -57,9 +55,7 @@ export const VerticalLayout: Story = { args: { children: [ - - - + , diff --git a/storybook/src/components/Card/Card.stories.tsx b/storybook/src/components/Card/Card.stories.tsx index 1ce91605cb..f756b8fd8b 100644 --- a/storybook/src/components/Card/Card.stories.tsx +++ b/storybook/src/components/Card/Card.stories.tsx @@ -3,7 +3,7 @@ * Copyright Gemeente Amsterdam */ -import { AspectRatio, Heading, Image, Paragraph } from '@amsterdam/design-system-react' +import { Heading, Image, Paragraph } from '@amsterdam/design-system-react' import { Card } from '@amsterdam/design-system-react/src' import { Meta, StoryObj } from '@storybook/react' import { exampleTopTask } from '../shared/exampleContent' @@ -62,9 +62,7 @@ export const WithTagline: Story = { export const WithImage: Story = { args: { children: [ - - - , + , Nederlands eerste houten woonwijk komt in Zuidoost diff --git a/storybook/src/components/Column/Column.stories.tsx b/storybook/src/components/Column/Column.stories.tsx index 65d8c40323..d9b595291f 100644 --- a/storybook/src/components/Column/Column.stories.tsx +++ b/storybook/src/components/Column/Column.stories.tsx @@ -5,7 +5,7 @@ import { Card, Heading, Paragraph } from '@amsterdam/design-system-react' import { Column } from '@amsterdam/design-system-react/src' -import { crossAlignOptionsForColumn, mainAlignOptions } from '@amsterdam/design-system-react/src/common/layout' +import { crossAlignOptionsForColumn, mainAlignOptions } from '@amsterdam/design-system-react/src/common/types' import { Meta, StoryObj } from '@storybook/react' const ThreeItems = [ diff --git a/storybook/src/components/Overlap/Overlap.stories.tsx b/storybook/src/components/Overlap/Overlap.stories.tsx index 0db19d72ac..1783380b8d 100644 --- a/storybook/src/components/Overlap/Overlap.stories.tsx +++ b/storybook/src/components/Overlap/Overlap.stories.tsx @@ -3,7 +3,7 @@ * Copyright Gemeente Amsterdam */ -import { AspectRatio, Grid, Image, SearchField } from '@amsterdam/design-system-react' +import { Grid, Image, SearchField } from '@amsterdam/design-system-react' import { Overlap } from '@amsterdam/design-system-react/src' import { Meta, StoryObj } from '@storybook/react' @@ -19,15 +19,14 @@ type Story = StoryObj export const Default: Story = { args: { children: [ - - - , + , e.preventDefault()}> diff --git a/storybook/src/components/Row/Row.stories.tsx b/storybook/src/components/Row/Row.stories.tsx index 9296559050..2b962f4a5a 100644 --- a/storybook/src/components/Row/Row.stories.tsx +++ b/storybook/src/components/Row/Row.stories.tsx @@ -5,7 +5,7 @@ import { Avatar, Heading, Link } from '@amsterdam/design-system-react' import { Row } from '@amsterdam/design-system-react/src' -import { crossAlignOptions, mainAlignOptions } from '@amsterdam/design-system-react/src/common/layout' +import { crossAlignOptions, mainAlignOptions } from '@amsterdam/design-system-react/src/common/types' import { Meta, StoryObj } from '@storybook/react' const ThreeItems = [ diff --git a/storybook/src/docs/components/color-palette.css b/storybook/src/docs/components/color-palette.css index 6b8354b970..f35df283c8 100644 --- a/storybook/src/docs/components/color-palette.css +++ b/storybook/src/docs/components/color-palette.css @@ -18,7 +18,7 @@ } .ams-storybook-color-palette__example { - aspect-ratio: 16 / 9; + aspect-ratio: var(--ams-aspect-ratio-x-wide); border: 0.0625rem solid rgb(0 0 0 / 12.5%); grid-area: example; } diff --git a/storybook/src/foundation/design-tokens/aspect-ratio.docs.mdx b/storybook/src/foundation/design-tokens/aspect-ratio.docs.mdx new file mode 100644 index 0000000000..8d5bfc15d8 --- /dev/null +++ b/storybook/src/foundation/design-tokens/aspect-ratio.docs.mdx @@ -0,0 +1,32 @@ +{/* @license CC0-1.0 */} + +import { Meta } from "@storybook/blocks"; + + + +# Aspect Ratio + +Constrains media content to a supported aspect ratio. + +## Design + +Media content like images, videos, and maps take up sizable portions of a screen. +Displaying them in a limited set of aspect ratios keeps the visual impression of a page composed. +The default aspect ratio is 16:9. +Content with intrinsic dimensions that do not match an aspect ratio will be cropped. + +## Tokens + +| Token name | Value | Example | +| :------------------------- | -----: | ------------------------------------------------------------------------------------------------------------ | +| `ams.aspect-ratio.x-tall` | 9 / 16 |
| +| `ams.aspect-ratio.tall` | 3 / 4 |
| +| `ams.aspect-ratio.square` | 1 / 1 |
| +| `ams.aspect-ratio.wide` | 4 / 3 |
| +| `ams.aspect-ratio.x-wide` | 16 / 9 |
| +| `ams.aspect-ratio.2x-wide` | 16 / 5 |
| + +## Related components + +- The [Image](https://designsystem.amsterdam/?path=/docs/components-media-image--docs) component has an `aspectRatio` prop that sets one of these classes. +- The [Breakout](https://designsystem.amsterdam/?path=/docs/components-layout-breakout--docs) layout positions an image with a certain aspect ratio in a Spotlight. diff --git a/storybook/src/foundation/design-tokens/border.docs.mdx b/storybook/src/foundation/design-tokens/border.docs.mdx index 548e8e3831..7d048a7def 100644 --- a/storybook/src/foundation/design-tokens/border.docs.mdx +++ b/storybook/src/foundation/design-tokens/border.docs.mdx @@ -8,13 +8,15 @@ import { Meta } from "@storybook/blocks"; Elements that have a border, outline or underline use one of these widths. -## Widths +## Design -We have 4 border widths: +We use a limited set of border widths for consistency. -| Token name | px | rem | Example | -| :-------------------- | :-: | :----: | ------------------------------------------------------------------------------------------------------------------- | -| `ams.border.width.sm` | 1 | 0.0625 |
| -| `ams.border.width.md` | 2 | 0.125 |
| -| `ams.border.width.lg` | 3 | 0.1875 |
| -| `ams.border.width.xl` | 4 | 0.25 |
| +## Tokens + +| Token name | Value | Value (px) | Example | +| :-------------------- | --------: | :--------: | ------------------------------------------------------------------------------------------------------------------- | +| `ams.border.width.sm` | 0.0625rem | 1 |
| +| `ams.border.width.md` | 0.125rem | 2 |
| +| `ams.border.width.lg` | 0.1875rem | 3 |
| +| `ams.border.width.xl` | 0.25rem | 4 |
| diff --git a/storybook/src/pages/amsterdam/ArticlePage/ArticleHeader.tsx b/storybook/src/pages/amsterdam/ArticlePage/ArticleHeader.tsx index 2d009b8389..8d9b9ee151 100644 --- a/storybook/src/pages/amsterdam/ArticlePage/ArticleHeader.tsx +++ b/storybook/src/pages/amsterdam/ArticlePage/ArticleHeader.tsx @@ -1,4 +1,4 @@ -import { AspectRatio, Grid, Heading, Image, Overlap, Paragraph } from '@amsterdam/design-system-react' +import { Grid, Heading, Image, Overlap, Paragraph } from '@amsterdam/design-system-react' import type { ArticlePageProps } from './ArticlePage' type ArticleHeaderProps = Pick @@ -12,9 +12,7 @@ export const ArticleHeader = ({ heading, imageSrc }: ArticleHeaderProps) => ( - - - + ) diff --git a/storybook/src/pages/amsterdam/HomePage/HomeNews.tsx b/storybook/src/pages/amsterdam/HomePage/HomeNews.tsx index 6fcdfc09f6..5637dda59b 100644 --- a/storybook/src/pages/amsterdam/HomePage/HomeNews.tsx +++ b/storybook/src/pages/amsterdam/HomePage/HomeNews.tsx @@ -1,4 +1,4 @@ -import { AspectRatio, Card, Grid, Heading, Image } from '@amsterdam/design-system-react' +import { Card, Grid, Heading, Image } from '@amsterdam/design-system-react' export const HomeNews = () => ( @@ -7,9 +7,7 @@ export const HomeNews = () => ( - - - + Nederlands eerste houten woonwijk komt in Zuidoost @@ -19,9 +17,7 @@ export const HomeNews = () => ( - - - + Gratis openbaar vervoer voor kinderen @@ -31,9 +27,7 @@ export const HomeNews = () => ( - - - + Zonnepanelen op uw dak? Zo houdt u uw huis veilig diff --git a/storybook/src/styles/docs.css b/storybook/src/styles/docs.css index 6a346536d2..e60f4f3616 100644 --- a/storybook/src/styles/docs.css +++ b/storybook/src/styles/docs.css @@ -127,6 +127,12 @@ } } +.ams-docs-aspect-ratio { + min-block-size: initial; + padding-block: var(--ams-space-md); + padding-inline: var(--ams-space-md); +} + .ams-docs-item { background-color: var(--ams-docs-pink); border: thin dashed var(--ams-docs-grey); diff --git a/storybook/src/utils/AspectRatio/AspectRatio.docs.mdx b/storybook/src/utils/AspectRatio/AspectRatio.docs.mdx new file mode 100644 index 0000000000..e53bd653fe --- /dev/null +++ b/storybook/src/utils/AspectRatio/AspectRatio.docs.mdx @@ -0,0 +1,13 @@ +{/* @license CC0-1.0 */} + +import { Controls, Markdown, Meta, Primary } from "@storybook/blocks"; +import * as AspectRatioStories from "./AspectRatio.stories.tsx"; +import README from "../../../../packages/css/src/components/aspect-ratio/README.md?raw"; + + + +{README} + + + + diff --git a/storybook/src/utils/AspectRatio/AspectRatio.stories.tsx b/storybook/src/utils/AspectRatio/AspectRatio.stories.tsx new file mode 100644 index 0000000000..be6a976932 --- /dev/null +++ b/storybook/src/utils/AspectRatio/AspectRatio.stories.tsx @@ -0,0 +1,32 @@ +/** + * @license EUPL-1.2+ + * Copyright Gemeente Amsterdam + */ + +import { Meta, StoryObj } from '@storybook/react' +import { AspectRatio } from './AspectRatio' + +const meta = { + title: 'Utilities/CSS/Aspect Ratio', + component: AspectRatio, + args: { + aspectRatio: 'x-wide', + }, + argTypes: { + aspectRatio: { + control: 'radio', + options: ['2x-wide', 'x-wide', 'wide', 'square', 'tall', 'x-tall'], + }, + }, + render: ({ aspectRatio }) => ( +
+
+
+ ), +} satisfies Meta + +export default meta + +type Story = StoryObj + +export const Default: Story = {} diff --git a/storybook/src/utils/AspectRatio/AspectRatio.tsx b/storybook/src/utils/AspectRatio/AspectRatio.tsx new file mode 100644 index 0000000000..ec0d114fa1 --- /dev/null +++ b/storybook/src/utils/AspectRatio/AspectRatio.tsx @@ -0,0 +1,15 @@ +/** + * @license EUPL-1.2+ + * Copyright Gemeente Amsterdam + */ + +import { AspectRatioProps } from '@amsterdam/design-system-react/src/common/types' +import { HTMLAttributes, PropsWithChildren } from 'react' + +/** Renders examples in Storybook. Not for reuse. */ +export const AspectRatio = ({ + children, + aspectRatio, +}: AspectRatioProps & PropsWithChildren>) => ( + {children} +)