nili/ui
All components

KeyComponents

Overview
34 exports0 variant axes69 props8 files
import { ChartLegend, ChartLegendDot, ContentCard, ContentLabel, ControlLabel, HintText } 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.

Label

The field label every input uses. The asterisk and the sublabel are hidden from assistive tech — requiredness is carried by the input's own required, and a screen reader that hears “Phone Number star optional” has been told the same thing three times, twice contradictorily.

Forgot?
import { Label, LinkButton } from "@nili/ui"

export function Example() {
  return (
    <>
      <Label htmlFor="a">Email address</Label>
      <Label htmlFor="b" required>Email address</Label>
      <Label htmlFor="c" sublabel="(optional)">Email address</Label>
      <Label htmlFor="d" information informationLabel="Why we ask">
        Email address
      </Label>
      <Label htmlFor="e" hint={<LinkButton href="#" size="sm">Forgot?</LinkButton>}>
        Password
      </Label>
      <Label htmlFor="f" disabled>Email address</Label>
    </>
  )
}

Hint Text

The line under a field. status colours it; icon adds the matching glyph. The error status is what a Text Input renders when you pass it an error.

This is a hint text to help user.

This field is unavailable.

import { HintText } from "@nili/ui"

export function Example() {
  return (
    <>
      <HintText icon>This is a hint text to help user.</HintText>
      <HintText status="error" icon>Please enter a valid email.</HintText>
      <HintText status="disabled">This field is unavailable.</HintText>
    </>
  )
}

Control Label

The label row a Checkbox, Radio or Switch builds internally — label, sublabel, badge, description and an action. Exported because a custom control should look like the built-in ones.

(recommended)FreeWe will only email you about things you asked for.Manage
import { ControlLabel, Badge, LinkButton } from "@nili/ui"

export function Example() {
  return (
    <ControlLabel
      htmlFor="notify"
      label="Email notifications"
      sublabel="(recommended)"
      badge={<Badge size="small" color="green" appearance="lighter">Free</Badge>}
      description="We will only email you about things you asked for."
      linkButton={<LinkButton href="#" size="sm">Manage</LinkButton>}
    />
  )
}

Password Strength

Four levels. The meter is decorative on its own — pass the label so the verdict is written out, not left to a colour.

Weak password
Could be stronger
Strong password
import { PasswordStrength, TextInput } from "@nili/ui"

export function Example() {
  return (
    <>
      <TextInput type="password" label="Password" />
      <PasswordStrength strength="moderate" label="Could be stronger" />
    </>
  )
}

Key Icon

The framed icon that heads a modal, an empty state or a content card. Two appearances, ten colours, five sizes.

lighter
stroke
sizes
import { KeyIcon, Icon } from "@nili/ui"
import { RiSparkling2Line } from "@remixicon/react"

export function Example() {
  return (
    <>
      <KeyIcon color="purple"><Icon icon={RiSparkling2Line} /></KeyIcon>
      <KeyIcon color="purple" appearance="stroke"><Icon icon={RiSparkling2Line} /></KeyIcon>
      <KeyIcon color="purple" size="2xl"><Icon icon={RiSparkling2Line} /></KeyIcon>
    </>
  )
}

Chart Legend

With onToggle it renders as a button with aria-pressed, because toggling a series is a control. Without it, plain text. value is pre-formatted — numerals are a locale decision, not the legend's.

toggleable (click one)
dots
import { ChartLegend, ChartLegendDot } from "@nili/ui"

export function Example() {
  const [hidden, setHidden] = useState<string[]>([])

  return (
    <>
      {series.map((item) => (
        <ChartLegend
          key={item.key}
          color={item.color}
          value={item.value}
          hidden={hidden.includes(item.key)}
          onToggle={() => toggle(item.key)}
        >
          {item.label}
        </ChartLegend>
      ))}

      {/* just the dot */}
      <ChartLegendDot color="blue" />
    </>
  )
}

Content Label and Content Card

A title with an optional leading and trailing slot. Figma draws six Types — avatar, icon, brand, company — and they are all the same startAdornment. Content Card is the selectable version.

AL
Ada LovelaceOwner · ada@nili.design
Design systemprivate24 components · updated 2 days agov0.2
import { ContentLabel, ContentCard, KeyIcon, Avatar, Icon, Badge } from "@nili/ui"
import { RiFolderLine } from "@remixicon/react"

export function Example() {
  const [selected, setSelected] = useState("a")

  return (
    <>
      <ContentLabel
        startAdornment={<Avatar size="sm" name="Ada Lovelace" tone="blue" />}
        title="Ada Lovelace"
        description="Owner · ada@nili.design"
      />

      <ContentCard
        selected={selected === "a"}
        onSelect={() => setSelected("a")}
        startAdornment={
          <KeyIcon size="md" color="blue"><Icon icon={RiFolderLine} /></KeyIcon>
        }
        title="Design system"
        description="24 components · updated 2 days ago"
        badge={<Badge size="small" color="green" appearance="lighter">v0.2</Badge>}
      />
    </>
  )
}