ObjectUIObjectUI

Icon

Display icons from the Lucide icon library

Examples

Basic Icon

Icon Sizes

Colored Icons

Schema

interface IconSchema {
  type: 'icon';
  icon: string;              // Lucide glyph name (kebab-case), REQUIRED
  size?: number | 'sm' | 'md' | 'lg' | 'xl';
  color?: string;            // Tailwind color class
  className?: string;
}

The glyph is named by icon:

{ "type": "icon", "icon": "check" }

name is identity, not the glyph

name is the SDUI identity key every node carries, alongside id. It is not read as a glyph name on ui:icon, and writing one there renders no icon:

{ "type": "icon", "id": "save_icon", "name": "save_icon" }

That node is refused by IconSchema — with a message naming this rename — and, if it reaches the renderer unvalidated, draws a dashed-square placeholder with an accessible name saying which icon failed, rather than rendering nothing. There is deliberately no fallback from icon to name: a key that means "identity" sometimes and "glyph" other times, depending on whether a lucide lookup happened to hit, is the ambiguity this contract removes.

Migrating stored metadata

Metadata authored before this change names its glyph with name. Convert it in bulk — once, at the source — with the converter shipped for it:

import { migrateIconNodeKeys } from '@object-ui/types';

declare const storedPage: unknown;
declare function save(document: unknown): Promise<void>;

const { document, converted, warnings } = migrateIconNodeKeys(storedPage);
console.log(`converted ${converted} icon node(s)`);
if (warnings.length) console.warn(warnings.map((w) => w.message).join('\n'));
if (document !== storedPage) await save(document);

It walks the whole document, lifts name to icon on every icon node, and reports rather than guesses for the two cases it will not touch: a node that already declares both keys (icon wins; name stays the identity it is), and a node that names no glyph at all.

On this page