A NSW Government website

Menu

A menu: a row of text links, such as a footer's Contact us, Accessibility and Privacy, a gap apart and placed left, centred or right — centred on a phone. Its defaults come from menu in lib/menu.ts, and resolveMenu checks the props.

Examples

Menu on a dark footer

The menu in white on the grey, blue and red families’ darkest shades.

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

const nswGovernment = [
  { network: 'facebook', href: 'https://www.facebook.com/NSWGovernment' },
  { network: 'x', href: 'https://x.com/NSWGovernment' },
  { network: 'youtube', href: 'https://www.youtube.com/user/nswgovernment' },
  { network: 'linkedin', href: 'https://www.linkedin.com/company/nswgovernment' },
  { network: 'instagram', href: 'https://www.instagram.com/nswgov' },
] as const

const nswFooterLinks = [
  { href: 'https://www.nsw.gov.au', label: 'Contact us' },
  {
    href: 'https://www.nsw.gov.au/nsw-government/about-website/accessibility-statement',
    label: 'Accessibility',
  },
  { href: 'https://www.nsw.gov.au/nsw-government/about-website/copyright', label: 'Copyright' },
  { href: 'https://www.nsw.gov.au/nsw-government/about-website/disclaimer', label: 'Disclaimer' },
  {
    href: 'https://www.nsw.gov.au/nsw-government/about-website/privacy-statement',
    label: 'Privacy',
  },
] as const

function Footer({
  background,
  color,
  social,
  logo,
}: {
  /** The footer's fill. */
  background: ColorValue
  /** Its text and links. */
  color: ColorValue
  /** Its icons' tone. */
  social: SocialTone
  /** Its logo's tone. */
  logo: LogoTone
}) {
  const band = (
    <NswColumns background={background} padding={false}>
      <NswColumn>
        <NswSpacer height={32} />
      </NswColumn>
    </NswColumns>
  )
  return (
    <>
      {band}
      <NswColumns background={background}>
        <NswColumn>
          <NswSocial
            links={nswGovernment}
            tone={social}
            size={28}
            gap={16}
            align='left'
            mobileClass='mobile-left'
          />
          <NswSpacer height={48} />
          <NswText type='body-sm' color={color}>
            McKell Building, 2-24 Rawson Place, Sydney NSW 2000
          </NswText>
          <NswSpacer height={8} />
          <NswText type='body-sm' color={color}>
            Copyright © 2026 NSW Department of Customer Service, All rights reserved.
          </NswText>
          <NswSpacer height={48} />
          <NswMenu links={nswFooterLinks} type='body-sm' color={color} align='left' />
          <NswSpacer height={48} />
          <NswText type='body-sm' color={color}>
            This message was sent to <strong>[name@domain.com]</strong>. If you don&apos;t want to
            receive these emails from NSW Department of Customer Service in the future, you can{' '}
            <NswLink href='https://example.com' color={color}>
              unsubscribe
            </NswLink>
            .
          </NswText>
          <NswSpacer height={32} />
          <NswLogo
            tone={logo}
            width={56}
            href='https://www.digital.nsw.gov.au'
            align='left'
            mobileClass='mobile-left'
          />
        </NswColumn>
      </NswColumns>
      {band}
    </>
  )
}

function FooterPage({
  title,
  themes,
}: {
  title: string
  themes: ReadonlyArray<{
    key: string
    background: ColorValue
    color: ColorValue
    social: SocialTone
    logo: LogoTone
  }>
}) {
  return (
    <NswLayout title={title}>
      {themes.map((theme) => (
        <Fragment key={theme.key}>
          <Footer
            background={theme.background}
            color={theme.color}
            social={theme.social}
            logo={theme.logo}
          />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const themes = [
  {
    key: 'grey',
    background: 'grey-800',
    color: 'white',
    social: 'white',
    logo: 'reversed',
  },
  {
    key: 'primary',
    background: 'primary-800',
    color: 'white',
    social: 'white',
    logo: 'reversed',
  },
  {
    key: 'accent',
    background: 'accent-800',
    color: 'white',
    social: 'white',
    logo: 'reversed',
  },
] as const;

<FooterPage title='Menu on a dark footer' themes={themes} />

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

Menu on a bright footer

The menu in white on the grey, blue and red families’ 600 shades.

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

const nswGovernment = [
  { network: 'facebook', href: 'https://www.facebook.com/NSWGovernment' },
  { network: 'x', href: 'https://x.com/NSWGovernment' },
  { network: 'youtube', href: 'https://www.youtube.com/user/nswgovernment' },
  { network: 'linkedin', href: 'https://www.linkedin.com/company/nswgovernment' },
  { network: 'instagram', href: 'https://www.instagram.com/nswgov' },
] as const

const nswFooterLinks = [
  { href: 'https://www.nsw.gov.au', label: 'Contact us' },
  {
    href: 'https://www.nsw.gov.au/nsw-government/about-website/accessibility-statement',
    label: 'Accessibility',
  },
  { href: 'https://www.nsw.gov.au/nsw-government/about-website/copyright', label: 'Copyright' },
  { href: 'https://www.nsw.gov.au/nsw-government/about-website/disclaimer', label: 'Disclaimer' },
  {
    href: 'https://www.nsw.gov.au/nsw-government/about-website/privacy-statement',
    label: 'Privacy',
  },
] as const

function Footer({
  background,
  color,
  social,
  logo,
}: {
  /** The footer's fill. */
  background: ColorValue
  /** Its text and links. */
  color: ColorValue
  /** Its icons' tone. */
  social: SocialTone
  /** Its logo's tone. */
  logo: LogoTone
}) {
  const band = (
    <NswColumns background={background} padding={false}>
      <NswColumn>
        <NswSpacer height={32} />
      </NswColumn>
    </NswColumns>
  )
  return (
    <>
      {band}
      <NswColumns background={background}>
        <NswColumn>
          <NswSocial
            links={nswGovernment}
            tone={social}
            size={28}
            gap={16}
            align='left'
            mobileClass='mobile-left'
          />
          <NswSpacer height={48} />
          <NswText type='body-sm' color={color}>
            McKell Building, 2-24 Rawson Place, Sydney NSW 2000
          </NswText>
          <NswSpacer height={8} />
          <NswText type='body-sm' color={color}>
            Copyright © 2026 NSW Department of Customer Service, All rights reserved.
          </NswText>
          <NswSpacer height={48} />
          <NswMenu links={nswFooterLinks} type='body-sm' color={color} align='left' />
          <NswSpacer height={48} />
          <NswText type='body-sm' color={color}>
            This message was sent to <strong>[name@domain.com]</strong>. If you don&apos;t want to
            receive these emails from NSW Department of Customer Service in the future, you can{' '}
            <NswLink href='https://example.com' color={color}>
              unsubscribe
            </NswLink>
            .
          </NswText>
          <NswSpacer height={32} />
          <NswLogo
            tone={logo}
            width={56}
            href='https://www.digital.nsw.gov.au'
            align='left'
            mobileClass='mobile-left'
          />
        </NswColumn>
      </NswColumns>
      {band}
    </>
  )
}

function FooterPage({
  title,
  themes,
}: {
  title: string
  themes: ReadonlyArray<{
    key: string
    background: ColorValue
    color: ColorValue
    social: SocialTone
    logo: LogoTone
  }>
}) {
  return (
    <NswLayout title={title}>
      {themes.map((theme) => (
        <Fragment key={theme.key}>
          <Footer
            background={theme.background}
            color={theme.color}
            social={theme.social}
            logo={theme.logo}
          />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const themes = [
  {
    key: 'grey',
    background: 'grey-600',
    color: 'white',
    social: 'white',
    logo: 'reversed',
  },
  {
    key: 'primary',
    background: 'primary-600',
    color: 'white',
    social: 'white',
    logo: 'reversed',
  },
  {
    key: 'accent',
    background: 'accent-600',
    color: 'white',
    social: 'white',
    logo: 'reversed',
  },
] as const;

<FooterPage title='Menu on a bright footer' themes={themes} />

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

Menu on a pale footer

The menu on the grey, blue and red families’ palest shades, in each family’s darkest.

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

const nswGovernment = [
  { network: 'facebook', href: 'https://www.facebook.com/NSWGovernment' },
  { network: 'x', href: 'https://x.com/NSWGovernment' },
  { network: 'youtube', href: 'https://www.youtube.com/user/nswgovernment' },
  { network: 'linkedin', href: 'https://www.linkedin.com/company/nswgovernment' },
  { network: 'instagram', href: 'https://www.instagram.com/nswgov' },
] as const

const nswFooterLinks = [
  { href: 'https://www.nsw.gov.au', label: 'Contact us' },
  {
    href: 'https://www.nsw.gov.au/nsw-government/about-website/accessibility-statement',
    label: 'Accessibility',
  },
  { href: 'https://www.nsw.gov.au/nsw-government/about-website/copyright', label: 'Copyright' },
  { href: 'https://www.nsw.gov.au/nsw-government/about-website/disclaimer', label: 'Disclaimer' },
  {
    href: 'https://www.nsw.gov.au/nsw-government/about-website/privacy-statement',
    label: 'Privacy',
  },
] as const

function Footer({
  background,
  color,
  social,
  logo,
}: {
  /** The footer's fill. */
  background: ColorValue
  /** Its text and links. */
  color: ColorValue
  /** Its icons' tone. */
  social: SocialTone
  /** Its logo's tone. */
  logo: LogoTone
}) {
  const band = (
    <NswColumns background={background} padding={false}>
      <NswColumn>
        <NswSpacer height={32} />
      </NswColumn>
    </NswColumns>
  )
  return (
    <>
      {band}
      <NswColumns background={background}>
        <NswColumn>
          <NswSocial
            links={nswGovernment}
            tone={social}
            size={28}
            gap={16}
            align='left'
            mobileClass='mobile-left'
          />
          <NswSpacer height={48} />
          <NswText type='body-sm' color={color}>
            McKell Building, 2-24 Rawson Place, Sydney NSW 2000
          </NswText>
          <NswSpacer height={8} />
          <NswText type='body-sm' color={color}>
            Copyright © 2026 NSW Department of Customer Service, All rights reserved.
          </NswText>
          <NswSpacer height={48} />
          <NswMenu links={nswFooterLinks} type='body-sm' color={color} align='left' />
          <NswSpacer height={48} />
          <NswText type='body-sm' color={color}>
            This message was sent to <strong>[name@domain.com]</strong>. If you don&apos;t want to
            receive these emails from NSW Department of Customer Service in the future, you can{' '}
            <NswLink href='https://example.com' color={color}>
              unsubscribe
            </NswLink>
            .
          </NswText>
          <NswSpacer height={32} />
          <NswLogo
            tone={logo}
            width={56}
            href='https://www.digital.nsw.gov.au'
            align='left'
            mobileClass='mobile-left'
          />
        </NswColumn>
      </NswColumns>
      {band}
    </>
  )
}

function FooterPage({
  title,
  themes,
}: {
  title: string
  themes: ReadonlyArray<{
    key: string
    background: ColorValue
    color: ColorValue
    social: SocialTone
    logo: LogoTone
  }>
}) {
  return (
    <NswLayout title={title}>
      {themes.map((theme) => (
        <Fragment key={theme.key}>
          <Footer
            background={theme.background}
            color={theme.color}
            social={theme.social}
            logo={theme.logo}
          />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const themes = [
  {
    key: 'grey',
    background: 'grey-200',
    color: 'grey-800',
    social: 'nsw-grey-800',
    logo: 'primary',
  },
  {
    key: 'primary',
    background: 'primary-200',
    color: 'primary-800',
    social: 'nsw-blue-800',
    logo: 'primary',
  },
  {
    key: 'accent',
    background: 'accent-200',
    color: 'accent-800',
    social: 'nsw-red-800',
    logo: 'primary',
  },
] as const;

<FooterPage title='Menu on a pale footer' themes={themes} />

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

Menu

The footer links as a menu, in a grey, a blue and a red footer on white.

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

const nswGovernment = [
  { network: 'facebook', href: 'https://www.facebook.com/NSWGovernment' },
  { network: 'x', href: 'https://x.com/NSWGovernment' },
  { network: 'youtube', href: 'https://www.youtube.com/user/nswgovernment' },
  { network: 'linkedin', href: 'https://www.linkedin.com/company/nswgovernment' },
  { network: 'instagram', href: 'https://www.instagram.com/nswgov' },
] as const

const nswFooterLinks = [
  { href: 'https://www.nsw.gov.au', label: 'Contact us' },
  {
    href: 'https://www.nsw.gov.au/nsw-government/about-website/accessibility-statement',
    label: 'Accessibility',
  },
  { href: 'https://www.nsw.gov.au/nsw-government/about-website/copyright', label: 'Copyright' },
  { href: 'https://www.nsw.gov.au/nsw-government/about-website/disclaimer', label: 'Disclaimer' },
  {
    href: 'https://www.nsw.gov.au/nsw-government/about-website/privacy-statement',
    label: 'Privacy',
  },
] as const

function Footer({
  background,
  color,
  social,
  logo,
}: {
  /** The footer's fill. */
  background: ColorValue
  /** Its text and links. */
  color: ColorValue
  /** Its icons' tone. */
  social: SocialTone
  /** Its logo's tone. */
  logo: LogoTone
}) {
  const band = (
    <NswColumns background={background} padding={false}>
      <NswColumn>
        <NswSpacer height={32} />
      </NswColumn>
    </NswColumns>
  )
  return (
    <>
      {band}
      <NswColumns background={background}>
        <NswColumn>
          <NswSocial
            links={nswGovernment}
            tone={social}
            size={28}
            gap={16}
            align='left'
            mobileClass='mobile-left'
          />
          <NswSpacer height={48} />
          <NswText type='body-sm' color={color}>
            McKell Building, 2-24 Rawson Place, Sydney NSW 2000
          </NswText>
          <NswSpacer height={8} />
          <NswText type='body-sm' color={color}>
            Copyright © 2026 NSW Department of Customer Service, All rights reserved.
          </NswText>
          <NswSpacer height={48} />
          <NswMenu links={nswFooterLinks} type='body-sm' color={color} align='left' />
          <NswSpacer height={48} />
          <NswText type='body-sm' color={color}>
            This message was sent to <strong>[name@domain.com]</strong>. If you don&apos;t want to
            receive these emails from NSW Department of Customer Service in the future, you can{' '}
            <NswLink href='https://example.com' color={color}>
              unsubscribe
            </NswLink>
            .
          </NswText>
          <NswSpacer height={32} />
          <NswLogo
            tone={logo}
            width={56}
            href='https://www.digital.nsw.gov.au'
            align='left'
            mobileClass='mobile-left'
          />
        </NswColumn>
      </NswColumns>
      {band}
    </>
  )
}

function FooterPage({
  title,
  themes,
}: {
  title: string
  themes: ReadonlyArray<{
    key: string
    background: ColorValue
    color: ColorValue
    social: SocialTone
    logo: LogoTone
  }>
}) {
  return (
    <NswLayout title={title}>
      {themes.map((theme) => (
        <Fragment key={theme.key}>
          <Footer
            background={theme.background}
            color={theme.color}
            social={theme.social}
            logo={theme.logo}
          />
          <NswColumns background='grey-100' padding={false}>
            <NswColumn>
              <NswSpacer height={24} />
            </NswColumn>
          </NswColumns>
        </Fragment>
      ))}
    </NswLayout>
  )
}

const themes = [
  {
    key: 'grey',
    background: 'white',
    color: 'grey-800',
    social: 'nsw-grey-800',
    logo: 'primary',
  },
  {
    key: 'primary',
    background: 'white',
    color: 'primary-800',
    social: 'nsw-blue-800',
    logo: 'primary',
  },
  {
    key: 'accent',
    background: 'white',
    color: 'accent-800',
    social: 'nsw-red-800',
    logo: 'primary',
  },
] as const;

<FooterPage title='Menu' themes={themes} />

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

Props

Props of NswMenu, read from the component
PropTypeDefaultDescription
mobileClassstringmobile-center, as the legacy's; give '' to keep the row's own alignmentMobile utility class(es) on the links' table, for a document's own @media rule: mobile-center centres the links on a phone, mobile-left keeps them at the left, and a row the phone wraps lines up the same way. Default mobile-center, as the legacy's; give '' to keep the row's own alignment.
devicesDevices—Which devices show the menu: left out, every device; desktop hides it on a phone (hide-on-mobile); mobile shows it on a phone only — hidden inline everywhere else, shown by the document's .show-on-mobile rule, and kept from Windows Outlook by mso-hide: all and the <!--[if !mso]> comments around it (see src/lib/devices.ts), as <NswSocial devices> is.
classNamestring—Class(es) added to every link, beside its hover tint, for a document's own stylesheet.
hoverstringthe colour'sThe hover class each link draws in place of the tint its colour takes, or '' for none; a callout hands its links its own tint through it. Default the colour's.
defaultsTextDefaults—The email's text settings (<NswLayout text>), handed down by the layout to every text-bearing primitive beneath it; the menu's own props win. Its links take the email's link colour and face from it, as a link does.
links (required)readonly MenuLink[]—The links, in the order they are drawn, each { href, label }: the address it goes to and the text it shows. At least one is required.
typeTypeScaleNamebodyThe links' step of the type scale, which sets their size and line height (body, body-sm, …); the links are bold, as every link is. Default body.
colorColorValuethe email's link colour (<NswLayout text>), else the link's primary blueThe links' colour: a theme colour name or a hex literal; their hover tint follows it, as every link's does (a colour family's 800 its own at 10%, white white at 10%). Default the email's link colour (<NswLayout text>), else the link's primary blue.
gapnumber16The space between two links in whole px. Default 16.
alignAligncenterWhere the links sit in their row: left, center or right. Default center.