|Kit

ThemeIcon

Polymorphic

Square, non-interactive icon-display box. A muted, low-saturation surface that reads as decoration, not as a control.

ThemeIcon is a decorative, non-interactive icon glyph — the same size/radius scales as ActionIcon, but a deliberately different look. It renders a plain div (no disabled, loading, or click handling), and every variant is a muted surface: just enough contrast to sit above the page, never a vivid CTA-style fill. Reach for it wherever a themed icon glyph decorates content: feature callouts, list-item glyphs, empty states.

import { ThemeIcon } from "@42-central/ui-react/theme-icon";
import { Search } from "lucide-react";

<ThemeIcon color="neutral" variant="filled" radius="lg">
  <Search />
</ThemeIcon>;

The icon is auto-sized by the parent's size variant — drop in a bare lucide-react icon and you'll never need to set size={n} on it.

Playground

Component

Loading preview

Props

Code

<Component variant="default" size="md" />

Variants

Five muted surfaces — none of them read as a button. filled is a tinted surface with a border a shade darker, for a raised card feel; light is the same tint without the border; outline and subtle stay progressively quieter.

Code

import { Star } from 'lucide-react';

<ThemeIcon variant="filled"><Star /></ThemeIcon>
<ThemeIcon variant="light"><Star /></ThemeIcon>
<ThemeIcon variant="outline"><Star /></ThemeIcon>
<ThemeIcon variant="subtle"><Star /></ThemeIcon>
<ThemeIcon variant="default"><Star /></ThemeIcon>

Colors

Every variant (except default) accepts any color from the shared palette.

Code

<ThemeIcon variant="filled" color="neutral" radius="lg"><Search /></ThemeIcon>
<ThemeIcon variant="filled" color="brand"><Heart /></ThemeIcon>
<ThemeIcon variant="light"  color="blue"><Star /></ThemeIcon>
<ThemeIcon variant="outline" color="teal"><Settings /></ThemeIcon>
<ThemeIcon variant="filled" color="red"><Trash2 /></ThemeIcon>

Sizes

Five sizes from xs to xl — identical footprint to ActionIcon at the same size, so the two drop into the same layouts without a visual mismatch.

Code

<ThemeIcon size="xs"><Star /></ThemeIcon>
<ThemeIcon size="sm"><Star /></ThemeIcon>
<ThemeIcon size="md"><Star /></ThemeIcon>
<ThemeIcon size="lg"><Star /></ThemeIcon>
<ThemeIcon size="xl"><Star /></ThemeIcon>

Radius

Independent radius scale, including full for circular glyphs.

Code

<ThemeIcon radius="xs"><Star /></ThemeIcon>
<ThemeIcon radius="sm"><Star /></ThemeIcon>
<ThemeIcon radius="md"><Star /></ThemeIcon>
<ThemeIcon radius="lg"><Star /></ThemeIcon>
<ThemeIcon radius="xl"><Star /></ThemeIcon>
<ThemeIcon radius="full"><Star /></ThemeIcon>

Polymorphic with asChild

Same Ark UI polymorphism as ActionIcon. Wrap a link when the icon itself needs to be clickable — the kit's focus ring comes along, so the composed element is keyboard-visible. For the common "icon-only trigger" case, reach for ActionIcon instead, which adds the rest of the wiring (aria-label requirements, disabled and loading states) that a real trigger needs.

import Link from "next/link";
import { User } from "lucide-react";

<ThemeIcon asChild variant="subtle" color="neutral">
  <Link href="/profile" aria-label="Open profile">
    <User />
  </Link>
</ThemeIcon>;

API

Prop

Type

All other props are forwarded to the underlying div (or asChild element).

When to use which

  • Reach for ThemeIcon for a decorative themed icon glyph — nothing to click. Composed onto a link with asChild it still focuses correctly.
  • Reach for ActionIcon when the icon is an interactive trigger — it adds aria-label requirements, disabled states, and loading support that ThemeIcon intentionally omits.
  • Reach for Badge for an inline status chip or counter — ThemeIcon is a square, icon-first display, not a text label.

Changelog

v0.19.0
  • The default ThemeIcon and the filled Tabs and SegmentGroup tray use the kit's hairline border and quiet fill instead of the gray scale

    #316
v0.9.2
  • Carry the kit's focus ring, so composing one onto a real control with asChild is keyboard-visible

    #142
v0.1.0
  • New ThemeIcon: a square, non-interactive icon box

    #11

On this page