nili/ui
All components

Icon

Overview
4 exports0 variant axes9 props3 files
import { Icon, IconComponent } from '@nili/ui';

This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.

Basic

Pass the icon component itself to icon, or an already-created element as children. Both forms exist because a call site that already holds an element should not have to unwrap it.

import { Icon } from "@nili/ui"
import { RiSearchLine } from "@remixicon/react"

export function Example() {
  return (
    <>
      {/* the component */}
      <Icon icon={RiSearchLine} />

      {/* or an element */}
      <Icon>
        <RiSearchLine />
      </Icon>
    </>
  )
}

Sizes

size takes a number of pixels or any CSS length. '1em' makes the glyph track the surrounding font size, which is what you want for an icon sitting inside a line of text.

pixel sizes
16
20
24
32
40
size="1em"

Search

Search

Search

Search

import { Icon } from "@nili/ui"
import { RiSearchLine } from "@remixicon/react"

export function Example() {
  return (
    <>
      <Icon icon={RiSearchLine} size={16} />
      <Icon icon={RiSearchLine} size={24} />
      <Icon icon={RiSearchLine} size={40} />

      {/* follows the text around it */}
      <p className="text-[20px]">
        {t('sizes.search')} <Icon icon={RiSearchLine} size="1em" />
      </p>
    </>
  )
}

Colour

An icon paints itself with currentColor, so it inherits from whatever it sits in — which is why it works inside a Button or a Badge with no colour prop at all. Prefer a text-* token class over the color escape hatch.

inherited from a token class
inside other components
Done
import { Icon, Button, Badge } from "@nili/ui"
import { RiCheckLine } from "@remixicon/react"

export function Example() {
  return (
    <>
      {/* inherits */}
      <span className="text-success-base">
        <Icon icon={RiCheckLine} />
      </span>

      {/* inside a control, with nothing to say */}
      <Button startIcon={<Icon icon={RiCheckLine} />}>
                {t('colour.approve')}
              </Button>
      <Badge color="green" startIcon={<Icon icon={RiCheckLine} />}>Done</Badge>
    </>
  )
}

Mirroring

mirrored flips the glyph horizontally under RTL. Set it on directional icons — arrows, chevrons, a send plane — and leave it off everything else: a mirrored clock or magnifying glass is simply wrong, not localised.

ltr
rtl — the first two flip, the third does not
import { Icon } from "@nili/ui"
import { RiArrowRightSLine, RiSearchLine } from "@remixicon/react"

export function Example() {
  return (
    <>
      {/* directional — flips in Persian */}
      <Icon icon={RiArrowRightSLine} mirrored />

      {/* not directional — must not flip */}
      <Icon icon={RiSearchLine} />
    </>
  )
}

Accessible names

An icon is aria-hidden by default, because almost every icon sits beside text that already says what it means — and an icon that repeats the label makes a screen reader say it twice. Pass label only when the glyph is the whole message.

Approved← named, because the glyph is the whole message
import { Icon } from "@nili/ui"
import { RiCheckLine } from "@remixicon/react"

export function Example() {
  return (
    <>
      {/* decorative: the word "Approved" is right there */}
      <span>
        <Icon icon={RiCheckLine} /> {t('names.approved')}
      </span>

      {/* meaningful: nothing else says this row passed */}
      <Icon icon={RiCheckLine} label={t('names.passed')} />
    </>
  )
}