---
title: "Emoji-Komponente — zenit Zig UI"
description: "Farbige Emoji, ZWJ-Sequenzen und Hautton-Modifikatoren. Farbige Glyphen bleiben farbig; ZWJ-Sequenzen werden als ein Graphem gerendert."
url: https://zenit.z.express/de/components/emoji
language: de
alternate_en: https://zenit.z.express/components/emoji.md
alternate_zh: https://zenit.z.express/zh/components/emoji.md
alternate_es: https://zenit.z.express/es/components/emoji.md
alternate_ja: https://zenit.z.express/ja/components/emoji.md
alternate_ko: https://zenit.z.express/ko/components/emoji.md
alternate_fr: https://zenit.z.express/fr/components/emoji.md
project: zenit v0.1.0-alpha (Zig 0.15.2, macOS)
source: https://github.com/version-next/zenit
---

# Emoji

`ui.text`

Farbige Emoji, ZWJ-Sequenzen und Hautton-Modifikatoren.

[Video](https://zenit.z.express/media/stories/emoji.mp4?v=5f65f98444)

**BEHAVIOR CONTRACT**

Farbige Glyphen bleiben farbig; ZWJ-Sequenzen werden als ein Graphem gerendert.

**RECORDED INTERACTION**

Durchläuft die Emoji-Beispiele.

`examples/storybook/stories.zig:3400`

```zig
// 每个 emoji 单独一个 test_id 节点，且刻意选中心区域是大面积纯色的：
//   🟥 U+1F7E5 红方块  🟩 U+1F7E9 绿方块  🟦 U+1F7E6 蓝方块
// 方块类 emoji 中心整块同色，不受字号/抗锯齿/中心点偏移影响，是最稳的
// 像素靶。文字颜色特意设成中性灰 —— 若 shader 错误地把 emoji 乘上文字色，
// 结果会退回灰度（三通道相等），此测立刻变红。
pub fn buildEmoji(scope: *ui.Scope, cx: *ui.Cx) anyerror!*ui.Node {
    _ = scope;
    const a = cx.allocator;
    const c = try col(cx, 16);

    try c.appendChild(a, try label(cx, "Color emoji (BGRA atlas page + shader color branch)"));

    const Case = struct { name: []const u8, test_id: []const u8, glyph: []const u8 };
    const cases = [_]Case{
        .{ .name = "red square", .test_id = "story.emoji.red", .glyph = "\u{1F7E5}" },
        .{ .name = "green square", .test_id = "story.emoji.green", .glyph = "\u{1F7E9}" },
        .{ .name = "blue square", .test_id = "story.emoji.blue", .glyph = "\u{1F7E6}" },
    };

    const tiles = try row(cx, 24);
    for (cases) |case| {
        const cell = try col(cx, 6);
        try cell.appendChild(a, try label(cx, case.name));
        // 中性灰文字色：emoji 若被错误地乘上它，会退化成灰度。
        const glyph_node = try ui.text(cx, case.glyph, .{
            .font_size = 64,
            .color = ui.Color.rgb(128, 128, 128),
        });
        glyph_node.meta.ownership.meta.test_id = case.test_id;
        try cell.appendChild(a, glyph_node);
        try tiles.appendChild(a, cell);
    }
    try c.appendChild(a, tiles);

    // 对照组：同一个中性灰颜色下的普通文本，必须仍然是灰度（三通道相等）。
    // 证明彩色分支没有把灰度路径一起改坏。
    try c.appendChild(a, try label(cx, "grayscale control (must stay gray)"));
    const control = try ui.text(cx, "AAAA", .{
        .font_size = 64,
        .color = ui.Color.rgb(128, 128, 128),
    });
    control.meta.ownership.meta.test_id = "story.emoji.control";
    try c.appendChild(a, control);

    // 混排：emoji 与文字同一段，验证 shaping/fallback 与彩色分流能共存于一行。
    try c.appendChild(a, try label(cx, "mixed run"));
    // 显式给 light 文本色：ui.text 的默认 color 是 comptime 求值的
    // theme.dark.color.fg_primary，不随 cx.setTheme(&light) 变化，
    // 漏写会在 storybook 的浅色底上渲染成几乎看不见的浅色字。
    const mixed = try ui.text(cx, "Hello \u{1F600} world \u{1F30D}", .{
        .font_size = 28,
        .color = light.color.fg_primary,
    });
    mixed.meta.ownership.meta.test_id = "story.emoji.mixed";
    try c.appendChild(a, mixed);

    return c;
}
```

[Quellcode auf GitHub ansehenexamples/storybook/stories.zig:3400](https://github.com/version-next/zenit/blob/HEAD/examples/storybook/stories.zig#L3400)

Der unveränderte Quellcode der Story aus dem Storybook (zenit 5f9add5+wip 2026-09-30). `W` steht für `ui.widgets`; `col` / `row` / `label` sind kleine Layout-Helfer des Storybooks.
