diff --git a/packages/css/src/components/row/row.scss b/packages/css/src/components/row/row.scss
index 05caa045f3..2d45fbc419 100644
--- a/packages/css/src/components/row/row.scss
+++ b/packages/css/src/components/row/row.scss
@@ -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;
+}
diff --git a/packages/react/src/Row/Row.test.tsx b/packages/react/src/Row/Row.test.tsx
index a0cd46f245..a13ac09f39 100644
--- a/packages/react/src/Row/Row.test.tsx
+++ b/packages/react/src/Row/Row.test.tsx
@@ -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', () => {
@@ -64,4 +65,26 @@ describe('Row', () => {
expect(ref.current).toBe(component)
})
+
+ describe('Alignment', () => {
+ mainAlignOptions.map((align) =>
+ it(`sets the ‘${align}’ alignment`, () => {
+ const { container } = render()
+
+ 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()
+
+ const component = container.querySelector(':only-child')
+
+ expect(component).toHaveClass(`ams-row--align-vertical-${align}`)
+ }),
+ )
+ })
})
diff --git a/packages/react/src/Row/Row.tsx b/packages/react/src/Row/Row.tsx
index a8171430e3..649df27795 100644
--- a/packages/react/src/Row/Row.tsx
+++ b/packages/react/src/Row/Row.tsx
@@ -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 = ['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>
export const Row = forwardRef(
- ({ as: Tag = 'div', children, className, gap = 'medium', wrap = false, ...restProps }: RowProps, ref: any) => (
-
+ (
+ { align, alignVertical, as: Tag = 'div', children, className, gap = 'medium', wrap, ...restProps }: RowProps,
+ ref: any,
+ ) => (
+
{children}
),
diff --git a/packages/react/src/common/layout.ts b/packages/react/src/common/layout.ts
new file mode 100644
index 0000000000..737a52a031
--- /dev/null
+++ b/packages/react/src/common/layout.ts
@@ -0,0 +1,5 @@
+export const crossAlignOptions: Array = ['baseline', 'center', 'end', 'start']
+export type CrossAlign = (typeof crossAlignOptions)[number]
+
+export const mainAlignOptions: Array = ['around', 'between', 'center', 'end', 'evenly']
+export type MainAlign = (typeof mainAlignOptions)[number]
diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts
index 1aef581892..e3337119a2 100644
--- a/packages/react/src/index.ts
+++ b/packages/react/src/index.ts
@@ -4,6 +4,7 @@
*/
/* Append here */
+export * from './common/layout'
export * from './FormErrorList'
export * from './TableOfContents'
export * from './ErrorMessage'
diff --git a/storybook/src/components/Row/Row.docs.mdx b/storybook/src/components/Row/Row.docs.mdx
index 65d713bad2..e8e5f8396c 100644
--- a/storybook/src/components/Row/Row.docs.mdx
+++ b/storybook/src/components/Row/Row.docs.mdx
@@ -24,6 +24,55 @@ Wrap a Row around a set of components that need the same amount of white space b
+### 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.
+
+
+
+#### End-align a Single Child
+
+To align a single component to the right (in left-to-right languages), wrap it in a `` and set the `align` prop to `end`.
+
+
+
+#### 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.
+
+
+
+### 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.
+
+
+
### Wrapping
Items that may not fit together on a single line should be allowed to wrap onto multiple lines.
diff --git a/storybook/src/components/Row/Row.stories.tsx b/storybook/src/components/Row/Row.stories.tsx
index 7144b87006..a529e8d7da 100644
--- a/storybook/src/components/Row/Row.stories.tsx
+++ b/storybook/src/components/Row/Row.stories.tsx
@@ -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) => )
-
-const FourBoxes = Array.from(Array(4).keys()).map((i) => (
-
- Wrapping row item {i + 1}
-
-))
+const ThreeParagraphs = [
+
+ One line
+ ,
+
+ Two
+
+ lines
+ ,
+
+ One line
+ ,
+]
const meta = {
title: 'Components/Layout/Row',
@@ -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'],
@@ -34,9 +58,41 @@ type Story = StoryObj
export const Default: Story = {}
+export const HorizontalAlignment: Story = {
+ args: {
+ align: 'evenly',
+ children: ThreeParagraphs,
+ },
+}
+
+export const EndAlignASingleChild: Story = {
+ args: {
+ align: 'end',
+ children: ,
+ },
+}
+
+export const AlignOpposingTexts: Story = {
+ args: {
+ align: 'between',
+ alignVertical: 'baseline',
+ children: [An example heading, An example 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) => (
+
+ )),
wrap: true,
},
}