Components · v0.1 · Stable

Icon

A thin wrapper around lucide-react that enforces the two rules every icon system fails at: consistent sizes across the app, and correct accessibility whenever an icon carries meaning.

Example

A decorative icon inline with text.

Installation

Install and import from Nova. Lucide is a peer dependency.

tsx
bun add lucide-react
tsx
import { Icon } from "@novix-ui/react";
import { Sparkles } from "lucide-react";

When to use

Use it for

  • Any lucide icon inside your app UI
  • Icons in menu rows, cards, and empty states

Skip it for

  • Icons already inside Button, IconButton, Input — they size for you
  • Custom SVGs — inline them directly and set aria attributes by hand

Sizes

Decorative vs. meaningful

If the icon adds meaning that text does not, it needs a label. If it's redundant with adjacent copy, it stays decorative.

Continue

API

Prop
Type
Default
Description
  • icon
    LucideIcon
    Any icon component exported by lucide-react.
  • size
    "xs" | "sm" | "md" | "lg" | "xl" | number
    "md"
    Semantic size token or a raw pixel value.
  • decorative
    boolean
    true
    When true, hides from assistive tech (aria-hidden).
  • label
    string
    Required when decorative is false. Becomes the accessible name.

Accessibility

Design guidelines

One weight per surface

Nova sets stroke-width 1.75 across all icons. Don't mix stroke variants in the same view.

Size follows text

Menu row = sm, section title = md, hero eyebrow = lg. Match the neighboring text.

Color inherits currentColor

Style the parent, not the icon. This keeps hover and state changes coherent.

Common mistakes

  • Passing a JSX element instead of the component reference — pass icon={Search}, not icon={<Search />}.
  • Setting fixed pixel color — use text-* on the parent.