Icon Gallery
zenit の公開アイコンを検索・プレビュー・コピーし、静的定数、動的 registry、セマンティックレイヤーの役割分担を理解します。
2 つのエントリポイント
公開ビルドには Lucide(lucide-static v1.31.0)が同梱されています。provider の完全なカタログは ui.icons にあり、2,026 個の名前を持ちます。上流の SVG 2,025 個に、互換エイリアス hand-pointing(上流の pointer.svg とバイト単位で同一)を加えたものです。ui.system_icons は provider に依存しない 45 個のセマンティックロールを提供します。zenit 自身のコンポーネントはこちらだけに依存するため、ベンダー名が公開コンポーネントの契約に漏れることはありません。
ui.system_icons45 個の安定したセマンティックロール(close、search、alert、pointer…)。どの provider でもコンパイルできる必要がある、再利用可能なフレームワーク / パッケージのコード向けui.icons2,026 個の Lucide 名。プロダクト UI と動的な設定向けui.assets.common17 個の旧互換アイコン。新しいコードでは推奨されません全 2,026 個の一覧
名前を入力すると即座に絞り込まれます。アイコンは 180 個ずつ読み込まれるので、2,000 以上の DOM ノードを一度に作ることはありません。アイコンをクリックすると、そのまま貼り付けられる ui.iconTint の呼び出しが表示されます。エスケープが必要な名前(ui.icons.@"type" など)はジェネレーターの規則どおりに処理済みです。
描画と着色
ビルド時に gen-icons が各アイコンを平坦化ジオメトリに変換します(各 Asset は icon_id とサイズ別の reps を持ちます)。実行時には ui.iconTint が論理サイズに最も近い rep を選んでノードに書き込むため、ウィンドウ内で SVG エンジンは動きません。事前平坦化ジオメトリを持たない Asset だけが svgTint のラスタライズにフォールバックします。幅 / 高さが固定ピクセルでない場合は Asset のデフォルトサイズ(Lucide は 24)が使われます。
ui.iconTint はテーマに追従する色に最適で、1 つの Asset を任意のサイズと色で使い回せます。ui.icon は tint を受け取らず白で描画するため、明るい背景では iconTint を使ってください。不透明度などの BoxStyle フィールドが必要なときは ui.iconTintStyled を使います。マウント済みアイコンの色を変える(hover、選択状態)には node.setTint(color) を呼びます。icon テーブルのストレージと svgTint フォールバックの image ストレージの両方を扱い、どちらもないノードでは false を返します。
// Follow the theme: tint with a token color.
const settings = try ui.iconTint(
cx,
ui.icons.settings,
cx.tokens.color.fg_secondary,
.{ .width = .fixed(20), .height = .fixed(20) },
);
// Dynamic lookup by kebab-case source name (config files, user data).
const configured = ui.icons.get("circle-alert") orelse
return error.UnknownIcon;
const warning = try ui.iconTint(cx, configured, cx.tokens.color.warning, .{
.width = .fixed(24),
.height = .fixed(24),
});
// Enumerate the whole registry.
for (ui.icons.all) |entry| {
std.log.debug("{s}", .{entry.name});
}セマンティックアイコンの契約
コンポーネントのコードでは、特定ベンダーの名前に縛られず ui.system_icons.close と書くべきです。Lucide プロファイルは src/ui/system_icons_lucide.zig で 45 個のロールすべてを具体的な Asset に対応付けています。-Dicon-set で provider を切り替えても、コンポーネントの API は変わりません。
ロール名と Lucide 名が異なる対応:
alertcircle-alertaudioheadphonesclosexhomehousenotificationbelltrashtrash-2editpencilmore_horizontalellipsiscursor_defaultmouse-pointer-2cursor_clickmouse-pointer-clickpointerhand-pointingnot_allowedbangrabhandresize_horizontalchevrons-left-rightresize_verticalchevrons-up-downresize_diagonalexpandwaithourglassprogressloader-circlehelpcircle-helpwarningtriangle-alert// Reusable code: depend on the role, not the provider's name.
const close = try ui.iconTint(cx, ui.system_icons.close, cx.tokens.color.fg_secondary, .{
.width = .fixed(16),
.height = .fixed(16),
});
// Icon-only button: no visible label, so set the accessible name explicitly.
const remove = try ui.widgets.Button(.{
.icon_only = true,
.icon_asset = ui.system_icons.trash,
.variant = .ghost,
}).mount(scope, cx);
remove.behavior.interaction.a11y.label = "Delete";命名・更新・ライセンス
- ✓
2 つの表記。Registry の検索には Lucide の kebab-case のソース名(
ui.icons.get("circle-alert"))を使い、Zig 定数ではハイフンをアンダースコアに置き換えます(ui.icons.circle_alert)。 - ✓
自動エスケープ。Zig のキーワードやプリミティブ型名(
iN/uNを含む)と衝突する定数、または数字で始まる定数はジェネレーターがエスケープします。例:ui.icons.@"type"。動的なgetには影響しません。 - ✓
列挙可能。
ui.icons.allは名前順に並んだ{ name, asset }の配列で、getはこれを二分探索します。 - ✓
上流と同一。SVG ファイルは上流とバイト単位で同一なので、更新やライセンス監査が容易です。更新時は古いファイルを削除してからコピーし、改名されたアイコンが残らないようにします。
- ✓
別ライセンス。Lucide は ISC License(
src/ui/icons_oss/LICENSE)で提供されており、zenit ルートの GPL-3.0-only ライセンスの対象外です。
# Verify the Lucide profile (test-headless + storybook build); the worktree is not modified
bash scripts/switch_icon_set.sh lucide
# Regenerate the committed provider module after the SVG set changes
zig build gen-icons-lucide
zig build test-ui