A NSW Government website

Card

Cards in a row, as the legacy's blocks/cards draw them: each an <NswCard> — a picture, a heading, words and a link. A variant sets the arrangement — image-top (each picture above its text, the cards side by side, columns to a row, or a single card the row to itself), icon-top (the same with a square pictogram, 100px unless it sets its size; cardPictogram names the NSW set's in the tone and surface's shade) or horizontal (one card a row, its picture beside its text, halved or in thirds by split, on the imageSide) — and a tone and surface its colours, a step of the tone for each: the fill, the text and links, the headings (an image-top card's in the 100 on dark, as the legacy's) and the line between stacked cards. Each colour can be given instead. Its defaults come from card in lib/card.ts, and resolveCards checks the props.

Examples

Cards on a bright surface

The image-top cards on each family’s 600, the text white.

49.1 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  surface: 'bright' as const,
  cards: [
    cardOf(body.long, { size: '256x192', n: 19 }),
    cardOf(body.long, { size: '256x192', n: 5 }),
  ],
}));

<CardsPage title='Cards on a bright surface' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Cards on a dark surface

The image-top cards on each family’s 800, the text white and the headings in its 100.

49.1 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  surface: 'dark' as const,
  cards: [
    cardOf(body.long, { size: '256x192', n: 19 }),
    cardOf(body.long, { size: '256x192', n: 5 }),
  ],
}));

<CardsPage title='Cards on a dark surface' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Horizontal card

A card with its picture beside its text, the row halved, on white.

35.1 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'horizontal' as const,
  cards: [cardOf(body.horizontal, { size: '256x256', n: 19 })],
}));

<CardsPage title='Horizontal card' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Horizontal card on a bright surface

The horizontal card on each family’s 600, the text white.

34.9 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'horizontal' as const,
  surface: 'bright' as const,
  cards: [cardOf(body.horizontal, { size: '256x256', n: 19 })],
}));

<CardsPage title='Horizontal card on a bright surface' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Horizontal card on a dark surface

The horizontal card on each family’s 800, the text white.

34.9 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'horizontal' as const,
  surface: 'dark' as const,
  cards: [cardOf(body.horizontal, { size: '256x256', n: 19 })],
}));

<CardsPage title='Horizontal card on a dark surface' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Horizontal card on a pale surface

The horizontal card on each family’s 200, the text in its 800.

35.1 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'horizontal' as const,
  surface: 'pale' as const,
  cards: [cardOf(body.horizontal, { size: '256x256', n: 19 })],
}));

<CardsPage title='Horizontal card on a pale surface' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Horizontal card, picture at the right

The horizontal card with its picture at the right of its text.

35.2 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'horizontal' as const,
  imageSide: 'right' as const,
  cards: [cardOf(body.horizontal, { size: '256x256', n: 19 })],
}));

<CardsPage title='Horizontal card, picture at the right' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Horizontal card, picture in a third

The horizontal card with its picture in a third of the row.

35.1 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'horizontal' as const,
  split: '4-8' as const,
  cards: [cardOf(body.horizontal, { size: '171x171', n: 19 })],
}));

<CardsPage title='Horizontal card, picture in a third' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Horizontal card, picture in a third at the right

The horizontal card with its picture in a third of the row, at the right.

35.2 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'horizontal' as const,
  split: '4-8' as const,
  imageSide: 'right' as const,
  cards: [cardOf(body.horizontal, { size: '171x171', n: 19 })],
}));

<CardsPage title='Horizontal card, picture in a third at the right' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Cards with pictograms

Two cards side by side, each an NSW pictogram above its text, on white.

49.4 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'icon-top' as const,
  cards: ['trees', 'park'].map((name) => ({
    ...cardOf(body.long),
    image: { src: cardPictogram(tone, 'white', name), alt: '' },
  })),
}));

<CardsPage title='Cards with pictograms' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Cards with pictograms on a bright surface

The icon-top cards on each family’s 600, the pictograms in its 200 and the text white.

49.2 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'icon-top' as const,
  surface: 'bright' as const,
  cards: ['trees', 'park'].map((name) => ({
    ...cardOf(body.long),
    image: { src: cardPictogram(tone, 'bright', name), alt: '' },
  })),
}));

<CardsPage title='Cards with pictograms on a bright surface' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Cards with pictograms on a dark surface

The icon-top cards on each family’s 800, the pictograms in its 200 and the text white.

49.2 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'icon-top' as const,
  surface: 'dark' as const,
  cards: ['trees', 'park'].map((name) => ({
    ...cardOf(body.long),
    image: { src: cardPictogram(tone, 'dark', name), alt: '' },
  })),
}));

<CardsPage title='Cards with pictograms on a dark surface' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Cards with pictograms on a pale surface

The icon-top cards on each family’s 200, the pictograms and text in its 800.

49.4 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  variant: 'icon-top' as const,
  surface: 'pale' as const,
  cards: ['trees', 'park'].map((name) => ({
    ...cardOf(body.long),
    image: { src: cardPictogram(tone, 'pale', name), alt: '' },
  })),
}));

<CardsPage title='Cards with pictograms on a pale surface' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Cards

Two cards side by side, each a picture above its heading, words and link, on white, in the grey, blue and red families.

49.3 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  cards: [
    cardOf(body.long, { size: '256x192', n: 19 }),
    cardOf(body.long, { size: '256x192', n: 5 }),
  ],
}));

<CardsPage title='Cards' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Cards on a pale surface

The image-top cards on each family’s 200, the text in its 800.

49.3 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  surface: 'pale' as const,
  cards: [
    cardOf(body.long, { size: '256x192', n: 19 }),
    cardOf(body.long, { size: '256x192', n: 5 }),
  ],
}));

<CardsPage title='Cards on a pale surface' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Cards in three columns

Three image-top cards side by side, each a 160 × 120 picture above its text.

64.5 KB built. Open the built email (opens in a new tab)

function CardsPage({ title, blocks }: { title: string; blocks: readonly CardsProps[] }) {
  return (
    <NswLayout title={title}>
      {blocks.map((block, i) => (
        <Fragment key={i}>
          <NswCards {...block} />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const tones = ['grey', 'primary', 'accent'] as const

function cardOf(words: string, picture?: { size: string; n: number }): CardContent {
  return {
    heading: 'Heading feature',
    body: words,
    link: { href: 'https://www.nsw.gov.au', label: 'Learn more' },
    ...(picture === undefined
      ? {}
      : {
          image: {
            src:
              'https://digitalnsw.github.io/images/placeholder/' +
              picture.size +
              '/' +
              String(picture.n) +
              '.jpg',
            alt: '',
          },
        }),
  }
}

const body = {
  long: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus. Nullam et ligula sodales, blandit arcu sit amet, varius felis.',
  short: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi.',
  horizontal:
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec nisi sed diam ultricies tempus.',
} as const

const blocks = tones.map((tone) => ({
  tone,
  columns: 3,
  cards: [1, 12, 9].map((n) => cardOf(body.short, { size: '160x120', n })),
}));

<CardsPage title='Cards in three columns' blocks={blocks} />

<CardsPage> is a demo helper shown inline above, not part of the package: copy it with the example, or swap in your own.

Props

NswCards

Props of NswCards, read from the component
PropTypeDefaultDescription
widthnumber—The block's width in px. Default, in a column, that column's content width, handed on by <NswColumns>; otherwise the document's row width. Set it yourself only for a block outside a column of the package's own.
layoutLayout—The layout its rows and spacers are drawn from: the document's (handed on by <NswLayout layout>) unless given one of its own.
devicesDevices—Which devices show the block: left out, every device; desktop hides it on a phone; mobile shows it on a phone only, and never in Windows Outlook (see src/lib/devices.ts), as <NswColumns devices> is.
defaultsTextDefaults—The email's text settings, handed on by <NswLayout text>: the cards' text is drawn in its face. Its sizes and colours are the cards' own.
cards (required)readonly CardContent[]—The cards, in the order they are drawn, each { heading, body?, link?, image? }. At least one.
variantCardVariantimage-topThe arrangement: image-top (each card's picture above its text, side by side), icon-top (a square pictogram above the text, 100px by default) or horizontal (one card a row, its picture beside its text). On a phone the cards stack, an image-top or icon-top card with a line below it, and a horizontal card's picture above its text. Default image-top.
toneCardToneprimaryThe colour family: grey, primary or accent. Each colour the surface sets is a step of it. Default primary.
surfaceCardSurfacewhiteThe colours: white (a white fill, the text in the tone's 800), dark (the 800, the text white, an image-top card's heading in the 100), bright (the 600, the text white) or pale (the 200, the text in the 800). Default white.
backgroundColorValuethe surface'sThe fill: a theme colour name or a hex literal, or 'transparent' for none. Default the surface's.
colorColorValuethe surface'sThe text's colour, and the links': a theme colour name or a hex literal. Default the surface's.
headingColorColorValuethe surface'sThe headings' colour: a theme colour name or a hex literal. Default the surface's.
dividerColorColorValuethe surface'sThe line between cards stacked on a phone: a theme colour name or a hex literal, or 'transparent' for none (the gap is kept). Default the surface's.
headingAsTextElementh2The headings' element (see <NswText as>). Default h2.
columnsnumber2, or 1 for a single card, which then takes the row's widthHow many image-top or icon-top cards sit side by side, 1 to 3; more cards make another row. Not for horizontal, one card a row. Default 2, or 1 for a single card, which then takes the row's width.
splitCardSplit6-6A horizontal card's split of the row between its picture and its text: 6-6 (halves) or 4-8 (a third and two). Only for horizontal. Default 6-6.
imageSideCardImageSideleftThe side of a horizontal card its picture is on: left or right. Only for horizontal. Default left.
paddingYnumber32The band of the fill above and below the cards, in whole px. 0 for none. Default 32.

NswCard

Props of NswCard, read from the component
PropTypeDefaultDescription
columnWidthnumber—The content width of the column the card sits in, handed on by <NswColumns>: an image without a width of its own is drawn this wide. Outside a column, the layout's content width.
layoutLayout—The layout its spacers are drawn from: the document's (handed on by <NswLayout layout>) unless given one of its own.
defaultsTextDefaults—The email's text settings, handed on by <NswLayout text>: the heading, body and link are drawn in its face. Their sizes and colours are the card's.
headingTypeTypeScaleNameheadline-smThe heading's step of the type scale. Default headline-sm.
headingAsTextElementh2The heading's element: div, p or a heading, h1 to h6 (see <NswText as>). Default h2.
colorColorValueprimary-800The text's colour, and the link's: a theme colour name or a hex literal. Default primary-800.
headingColorColorValuethe text'sThe heading's colour: a theme colour name or a hex literal. Default the text's.
heading (required)ReactNode—The heading: text, which may hold bold or a link. Required.
bodyReactNode—The words under the heading: text, which may hold links or bold.
linkCardLink—A link under the body, in bold, in the card's colour.
imageCardImage—A picture above the heading, or, in a horizontal row of cards, beside the text.