Skip to content

Commit

Permalink
Merge branch 'develop' into feature/DES-793-add-autofocus-to-form-err…
Browse files Browse the repository at this point in the history
…or-list
  • Loading branch information
VincentSmedinga authored Jul 19, 2024
2 parents f00ad86 + 1b9c269 commit 8c6072a
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 12 deletions.
36 changes: 36 additions & 0 deletions packages/css/src/components/row/row.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,39 @@
.ams-row--wrap {
flex-wrap: wrap;
}

.ams-row--align-around {
justify-content: space-around;
}

.ams-row--align-between {
justify-content: space-between;
}

.ams-row--align-center {
justify-content: center;
}

.ams-row--align-end {
justify-content: flex-end;
}

.ams-row--align-evenly {
justify-content: space-evenly;
}

.ams-row--align-vertical-baseline {
align-items: baseline;
}

.ams-row--align-vertical-center {
align-items: center;
}

.ams-row--align-vertical-end {
align-items: flex-end;
}

.ams-row--align-vertical-start {
align-items: flex-start;
}
23 changes: 23 additions & 0 deletions packages/react/src/Row/Row.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +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 '@testing-library/jest-dom'

describe('Row', () => {
Expand Down Expand Up @@ -64,4 +65,26 @@ describe('Row', () => {

expect(ref.current).toBe(component)
})

describe('Alignment', () => {
mainAlignOptions.map((align) =>
it(`sets the ‘${align}’ alignment`, () => {
const { container } = render(<Row align={align} />)

const component = container.querySelector(':only-child')

expect(component).toHaveClass(`ams-row--align-${align}`)
}),
)

crossAlignOptions.map((align) =>
it(`sets the ‘${align}’ vertical alignment`, () => {
const { container } = render(<Row alignVertical={align} />)

const component = container.querySelector(':only-child')

expect(component).toHaveClass(`ams-row--align-vertical-${align}`)
}),
)
})
})
27 changes: 23 additions & 4 deletions packages/react/src/Row/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,43 @@
import clsx from 'clsx'
import { forwardRef } from 'react'
import type { HTMLAttributes, PropsWithChildren } from 'react'
import type { CrossAlign, MainAlign } from '../common/layout'

export const rowGapSizes: Array<string> = ['extra-small', 'small', 'medium', 'large', 'extra-large']

type RowTag = 'article' | 'div' | 'section'
type RowGap = (typeof rowGapSizes)[number]
type RowTag = 'article' | 'div' | 'section'

export type RowProps = {
/** The horizontal alignment of the items in the row. */
align?: MainAlign
/** The vertical alignment of the items in the row. */
alignVertical?: CrossAlign
/** The HTML element to use. */
as?: RowTag
/** The amount of vertical space between items. */
gap?: RowGap
/** Whether items of the row can wrap onto multiple lines. */
wrap?: Boolean
wrap?: boolean
} & PropsWithChildren<HTMLAttributes<HTMLElement>>

export const Row = forwardRef(
({ as: Tag = 'div', children, className, gap = 'medium', wrap = false, ...restProps }: RowProps, ref: any) => (
<Tag {...restProps} ref={ref} className={clsx('ams-row', `ams-row--${gap}`, wrap && 'ams-row--wrap', className)}>
(
{ align, alignVertical, as: Tag = 'div', children, className, gap = 'medium', wrap, ...restProps }: RowProps,
ref: any,
) => (
<Tag
{...restProps}
ref={ref}
className={clsx(
'ams-row',
`ams-row--${gap}`,
align && `ams-row--align-${align}`,
alignVertical && `ams-row--align-vertical-${alignVertical}`,
wrap && 'ams-row--wrap',
className,
)}
>
{children}
</Tag>
),
Expand Down
5 changes: 5 additions & 0 deletions packages/react/src/common/layout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const crossAlignOptions: Array<string> = ['baseline', 'center', 'end', 'start']
export type CrossAlign = (typeof crossAlignOptions)[number]

export const mainAlignOptions: Array<string> = ['around', 'between', 'center', 'end', 'evenly']
export type MainAlign = (typeof mainAlignOptions)[number]
1 change: 1 addition & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

/* Append here */
export * from './common/layout'
export * from './FormErrorList'
export * from './TableOfContents'
export * from './ErrorMessage'
Expand Down
49 changes: 49 additions & 0 deletions storybook/src/components/Row/Row.docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,55 @@ Wrap a Row around a set of components that need the same amount of white space b

<Controls />

### Horizontal Alignment

Items in the row can be aligned horizontally in several ways:

- **Center**: center items within the row.
- **End**: align items to the end of the row. This is the right side in left-to-right languages.
- **Space Between**: distribute whitespace between items.
- **Space Around**: distribute whitespace around items.
- **Space Evenly**: distribute whitespace evenly around items.

By default, items align to the **start** of the row – the left side in right-to-left languages.
This options has no class name or prop.

We left out the word ‘space’ from the values for the alignment prop, e.g. `align="around"`.

This example ensures that the spaces between and around all items are equally wide.

<Canvas of={RowStories.HorizontalAlignment} />

#### End-align a Single Child

To align a single component to the right (in left-to-right languages), wrap it in a `<Row>` and set the `align` prop to `end`.

<Canvas of={RowStories.EndAlignASingleChild} />

#### Align Opposing Texts

This example shows a right-aligned link next to a heading.
Use `align="between"` to position them at opposing ends of the row.
Add `alignVertical="baseline"` to align them vertically to their common baseline.
Include `wrap` to allow the link to wrap to a new line if both components don’t fit on the same line.

<Canvas of={RowStories.AlignOpposingTexts} />

### Vertical Alignment

Items in the row can be aligned vertically in several ways:

- **Start**: align items to the top of the row.
- **Center**: align items to the middle of the row.
- **End**: align items to the bottom of the row.
- **Baseline**: align items to their common text baseline.

By default, items **stretch** to the height of the row. This options has no class name or prop.

This example centers three items vertically.

<Canvas of={RowStories.VerticalAlignment} />

### Wrapping

Items that may not fit together on a single line should be allowed to wrap onto multiple lines.
Expand Down
72 changes: 64 additions & 8 deletions storybook/src/components/Row/Row.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,32 @@
* Copyright Gemeente Amsterdam
*/

import { Button, Paragraph, Row } from '@amsterdam/design-system-react/src'
import {
Avatar,
Button,
crossAlignOptions,
Heading,
Link,
mainAlignOptions,
Paragraph,
Row,
} from '@amsterdam/design-system-react/src'
import { Meta, StoryObj } from '@storybook/react'

const ThreeButtons = Array.from(Array(3).keys()).map((i) => <Button key={i}>Button {i + 1}</Button>)

const FourBoxes = Array.from(Array(4).keys()).map((i) => (
<Paragraph className="ams-docs-pink-box" key={i}>
Wrapping row item {i + 1}
</Paragraph>
))
const ThreeParagraphs = [
<Paragraph className="ams-docs-pink-box" key={1} style={{ inlineSize: '8rem' }}>
One line
</Paragraph>,
<Paragraph className="ams-docs-pink-box" key={2} style={{ inlineSize: '8rem' }}>
Two
<br />
lines
</Paragraph>,
<Paragraph className="ams-docs-pink-box" key={3} style={{ inlineSize: '8rem' }}>
One line
</Paragraph>,
]

const meta = {
title: 'Components/Layout/Row',
Expand All @@ -21,6 +37,14 @@ const meta = {
children: ThreeButtons,
},
argTypes: {
align: {
control: 'radio',
options: mainAlignOptions,
},
alignVertical: {
control: 'radio',
options: crossAlignOptions,
},
gap: {
control: 'radio',
options: ['extra-small', 'small', 'medium', 'large', 'extra-large'],
Expand All @@ -34,9 +58,41 @@ type Story = StoryObj<typeof meta>

export const Default: Story = {}

export const HorizontalAlignment: Story = {
args: {
align: 'evenly',
children: ThreeParagraphs,
},
}

export const EndAlignASingleChild: Story = {
args: {
align: 'end',
children: <Avatar label="AB" />,
},
}

export const AlignOpposingTexts: Story = {
args: {
align: 'between',
alignVertical: 'baseline',
children: [<Heading level={3}>An example heading</Heading>, <Link href="#">An example link</Link>],
wrap: true,
},
}

export const VerticalAlignment: Story = {
args: {
alignVertical: 'center',
children: ThreeParagraphs,
},
}

export const Wrapping: Story = {
args: {
children: FourBoxes,
children: Array.from(Array(4).keys()).map((i) => (
<span className="ams-docs-pink-box" key={i} style={{ inlineSize: '16rem' }} />
)),
wrap: true,
},
}

0 comments on commit 8c6072a

Please sign in to comment.