Sign in

    sumi

    A UI component library for MoonBit web apps — dark & light themes, overlay motion, zero config

    ui
    components
    web
    theming
    dark-mode
    Download zip
    Version
    0.3.0
    License
    Apache-2.0
    Last updated
    24 days ago
    Downloads
    20

    howtomakeaname/sumi does not have a README file

    AttachmentItem

    One attachment in the strip.

    AttachmentKind

    The kind of attachment a tile renders: a cover-fit image thumbnail, or a gradient placeholder with a document glyph for everything else.

    CheckboxMenuGroup

    A titled section of a checkbox_menu. Passing clear_label renders the small text action at the title row's right edge (meant to clear the group's selection); without a title it is ignored. A hairline divider is inserted between consecutive groups, never after the last one.

    CheckboxMenuItem

    One row in a checkbox_menu group: a label with an optional leading icon that toggles independently of the other rows.

    HitlItem

    One generation option of a hitl_card: a label, optional reference thumbnails (one per modality), a credit cost, and whether it is checked for the confirm run.

    MdTextKind

    The block kinds of a markdown answer body, matching the MD 基础组件 type scale: H2 is 16/24 Medium, H3 and H4 are 14/22 Medium (headings carry 12px vertical padding), and Body is 14/22 Regular.

    MediaTagKind

    What an inline reference points at. Image and Video can carry a thumbnail; every kind falls back to its own glyph when no thumbnail is given (or the state is Empty).

    MediaTagState

    Lifecycle of the referenced content: Candidate is a half-transparent suggestion, Uploading dims the thumbnail under a spinner, Generating swaps the visual for a spinner, Failed shows the warning disc, and Empty forces the placeholder glyph even when a thumbnail exists.

    MediaTagVariant

    Block is the filled chip used inside conversation bubbles; Inline is the transparent variant that sits inside the composer input.

    The content of a menu: a list of selectable items with optional separators and section labels between groups.

    One entry in a dropdown_menu. Rendered as a rich row (thumbnail + title + description + check mark) when description is present, otherwise as a compact icon-label row. shortcut renders a muted right-aligned key hint (e.g. "⌘E").

    ResultChipSize

    The two label treatments of a result_chip.

    • Small — 13/19.5 tertiary label over a 6px backdrop blur; floats on generated imagery
    • Medium — 14/24 secondary label; sits in a chat result row

    SegmentedItem

    One option in a segmented control.

    SelectVariant

    SessionStatus

    The generation state shown next to session titles and task cards.

    • Generating — a spinner while a run is in flight
    • Count(n) — a white square with the number of queued/finished tasks
    • Done — a brand-blue tick circle
    • Dot — a small brand-blue unread dot
    • Pending(label) — an orange pill while a run awaits review
    • Partial — an orange info circle for partial failures

    ShortcutItem

    One shortcut row: an action label and its key combination.

    ShortcutSection

    A titled cluster of shortcuts. The title carries a hairline underline; sections are separated by an 8px gap.

    SkillMark

    The small corner tag of a skill_chip highlighting a skill's freshness.

    • New — brand blue on the translucent brand block
    • Hot — orange on the translucent orange block

    StatusBadgeState

    The four looks of an async job's status badge. Running carries a progress percentage (clamped to 0–100); Count carries a queue depth (displayed capped at 99, matching the design's two-digit circle).

    TabEntry

    One tab in a tabs control.

    ToolCallState

    Whether the work is still streaming (shimmering label) or settled (static tertiary label). Failure copy is written into the label itself, e.g. "(1/1) Image generation completed, 1 item failed".

    ThemeMode

    pub(all) enum ThemeMode {
    Dark
    Light
    System
    }

    Color mode for theme. Dark and Light pin the palette; System follows the viewer's prefers-color-scheme and updates live with it.

    action_chip

    fn action_chip(label~ : String, on_click? :
    Cmd
    , disabled? : Bool, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    One quick-action button of the "more actions" sheet: a 36px radius-8 block-fill button with a centered 13/22 Regular label and an 80px minimum width, wrapping alongside its siblings inside a chip_panel.

    action_chip(label="Storyboard", on_click=emit.map(Run("storyboard")))

    add_tile

    fn add_tile(on_click? :
    Cmd
    , disabled? : Bool, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The 48px "add" tile: a quiet bordered square with a centered plus that opens an upload/picker menu (compose with dropdown_menu as the trigger). Hover raises the fill to the primary block; disabled fades the plus to the disabled text shade.

    dropdown_menu(
    trigger=add_tile(aria_label="Add image"),
    items=[...],
    open=menu_open,
    on_open_change=set_menu_open.map(v => _ => v),
    )

    agent_input

    fn agent_input(value? : String, placeholder? : String, rows? : Int, on_input? :
    Emit
    [String], on_send? :
    Cmd
    , on_stop? :
    Cmd
    , send_disabled? : Bool, send_loading? : Bool, generating? : Bool, disabled? : Bool, autofocus? : Bool, actions? : Array[
    Html
    ], children? : Array[
    Html
    ], aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The agent chat dock: a frosted 24px-radius container holding an input region and a toolbar row (left action atoms + circular send button). Controlled: the caller owns value.

    By default the input region is an auto-clamped textarea (86px min, 252px max, thin scrollbar). Pass children instead to compose rich content — inline media tags and text spans share the same baseline flow; the caller then owns the editing surface.

    generating=true swaps the send arrow for the stop square and routes the click to on_stop; send_disabled only gates the send state.

    agent_input(
    value=prompt,
    placeholder="Describe your idea, or type / to use a skill",
    on_input=emit.map(PromptChanged),
    on_send=emit(Submit),
    send_disabled=prompt.is_empty(),
    actions=[
    icon_button(icon_plus_fill(size=14), aria_label="Add attachment"),
    agent_tool_button(icon=icon_skill(), label="Use Skill"),
    icon_button(icon_at(), aria_label="Mention a reference"),
    ],
    )

    agent_tool_button

    fn agent_tool_button(icon :
    Html
    , label~ : String, disabled? : Bool, on_click? :
    Cmd
    , id? : String, class? : String, title? : String, aria_label? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The icon-leading pill of the agent input toolbar (e.g. "Use Skill") — a 32px-high ghost button with a 16px icon and a 12/20 label. Square icon-only toolbar atoms are plain icon_button instead.

    agent_tool_button(icon=icon_skill(), label="Use Skill", on_click=pick_skill)

    alert

    An inline note for validation and status messages inside a panel or a node — an icon followed by wrapping copy. Solid sits on the canvas, Subtle on an already-filled surface. The default icon is icon_important; pass icon= to replace it.

    attachment_strip

    fn attachment_strip(items~ : Array[
    AttachmentItem
    ], on_add? :
    Cmd
    , on_remove? :
    Emit
    [Int], max_visible? : Int, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The attachment strip from the design: a row of 48px tiles — image thumbnails and document placeholders — followed by the add tile. Each tile can carry an 8px remove badge that fades in on tile hover or keyboard focus. Past max_visible attachments the row clips, a right-edge fade appears, and the add tile pins itself over the fade.

    attachment_strip(
    items=[
    AttachmentItem::image("cover.png", label="Cover"),
    AttachmentItem::document("Brief.pdf"),
    ],
    on_add=pick_files,
    on_remove=set_items.map(i => items => items.filteri(fn(j, _) { j != i })),
    )

    avatar

    fn avatar(src? : String, fallback? : String, size? : Int, alt? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A round avatar. Shows the image at src when given, otherwise the first character of fallback on a spotlight fill.

    badge

    fn badge(value? : Int, dot? : Bool, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A numeric notification badge. Values above 99 render as 99+; pass dot=true for a plain dot.

    button

    fn[C :
    IsChildren
    ] button(variant? :
    ButtonVariant
    , size? :
    ButtonSize
    , disabled? : Bool, pressed? : Bool, loading? : Bool, type_? : String, id? : String, class? : String, title? : String, name? : String, value? : String, autofocus? : Bool, on_click? :
    Cmd
    , attrs? :
    Attrs
    , style? : Array[String], children : C) ->
    Html

    Render a button in one of the design's three variants.

    • Primary — solid light fill with dark text, the main call to action.
    • Secondary — translucent white fill.
    • Ghost — transparent, fills on hover; the toolbar/menu-button look.

    pressed marks a toggle-style button as the currently active tool: it adds aria-pressed and the design's selected fill (same tone as hover).

    loading=true keeps the default fill and the button's width: the content stays rendered but invisible while a 16px spinner overlays its center, and aria-busy is set; pass a title describing the busy action for screen readers.

    User styles are appended last and therefore override the built-in recipe.

    card

    fn[C :
    IsChildren
    ] card(id? : String, class? : String, title? : String, attrs? :
    Attrs
    , style? : Array[String], children : C) ->
    Html

    A surface container for grouping content on the canvas.

    card_section

    A card with the design's header/content split.

    chat_bubble

    fn chat_bubble(text? : String, children? : Array[
    Html
    ], collapsible? : Bool, collapsed? : Bool, on_toggle? :
    Cmd
    , collapse_lines? : Int, on_copy? :
    Cmd
    , aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The right-aligned bubble of a sent message. Plain text by default; pass children to compose rich content (inline media tags and text spans share the same baseline flow). Long messages can be clamped to collapse_lines behind a fade with an Expand/Collapse toggle — the caller owns collapsed. on_copy reveals a copy action below the bubble on hover.

    chat_bubble(text="Continue")
    chat_bubble(children=[
    media_tag(kind=Image, variant=Inline, thumbnail=thumb),
    @html.text("Add more detail"),
    ])
    chat_bubble(text=long, collapsible=true, collapsed=c, on_toggle=set_c.map(v => _ => !v))

    checkbox

    fn checkbox(checked~ : Bool, label? : String, indeterminate? : Bool, on_change? :
    Emit
    [Bool], disabled? : Bool, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A checkbox with an optional text label. Controlled: the caller owns checked. indeterminate=true renders the mixed dash state and reports aria-checked="mixed"; clicking it resolves to checked.

    checkbox_menu

    fn checkbox_menu(groups~ : Array[
    CheckboxMenuGroup
    ], on_toggle? :
    Emit
    [String], width? : Int, max_height? : Int, footer_label? : String, footer_icon? :
    Html
    , on_footer? :
    Cmd
    , id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A multi-select menu panel: grouped rows with an outline checkbox on the right edge, toggled independently, so picking a row never closes anything. Fully controlled — the caller owns each row's checked flag; on_toggle emits the value of the row that was clicked. Unchecked rows reveal an empty box on hover/press; checked rows always show the ticked box.

    width follows the design's size steps (160 / 200 / 240 / 320, default 200); the body scrolls once the content exceeds max_height (default 480). footer_label pins a plain row (optional footer_icon, activated through on_footer) below the scroll area, under a hairline.

    The panel is unpositioned: wrap it in a dropdown/popover container to anchor it to a trigger.

    checkbox_menu(
    groups=[
    CheckboxMenuGroup::new(
    [
    CheckboxMenuItem::new("text", "Text", checked=true),
    CheckboxMenuItem::new("date", "Date"),
    ],
    title="Fields",
    clear_label="Clear",
    on_clear=clear_fields,
    ),
    ],
    on_toggle=toggle_field.map(v => _ => v),
    )

    chip

    fn chip(label : String, selected? : Bool, on_click? :
    Cmd
    , disabled? : Bool, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A single selectable pill — the resolution/quality option in the design. Text stays full-white in both states; selection shows only through the block fill. Fully controlled — the caller owns selected; group several chips under one value to build a radio-like row.

    chip("720P", selected=quality == "720p", on_click=set_quality.map(v => _ => "720p"))

    chip_panel

    fn chip_panel(children~ : Array[
    Html
    ], width? : Int, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The "more actions" sheet of the agent input: a frosted top-rounded panel (24px backdrop blur) whose children — skill_chip or action_chip — wrap with 8px gaps around centered rows.

    chip_panel(children=[
    skill_chip(label="Storyboard", mark=Hot),
    skill_chip(label="Quick Cut"),
    ])

    context_menu

    fn[C :
    IsChildren
    ] context_menu(entries~ : Array[
    MenuEntry
    ], open~ : Bool, on_open_change? :
    Emit
    [Bool], selected? : String, on_select? :
    Emit
    [String], id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String], menu_style? : Array[String], children : C) ->
    Html

    A right-click menu wrapping any target. Fully controlled: the caller owns open; right-clicking the target emits on_open_change(true) while the theme's static event layer suppresses the native menu and records the pointer position into the --sumi-ctx-x/y variables the panel reads. Closes on outside click, Escape, and selection; arrow keys move focus.

    context_menu(
    entries=[
    Item(MenuItem::new("rename", "Rename", shortcut="R")),
    Separator,
    Item(MenuItem::new("delete", "Delete", shortcut="⌫")),
    ],
    open=ctx_open,
    on_open_change=set_ctx_open.map(v => _ => v),
    on_select=set_action.map(v => _ => v),
    [canvas_card],
    )

    credits

    fn credits(value~ : Int, original_value? : Int, muted? : Bool, on_click? :
    Cmd
    , id? : String, class? : String, title? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The credit-cost indicator shown inline in toolbars before the primary submit. original_value renders a struck-through pre-discount price. muted=true drops the tone to placeholder strength for frosted input docks, where the indicator is secondary to the composer itself.

    dialog

    fn[C :
    IsChildren
    ] dialog(id~ : String, title_text? : String, description? : String, show_close? : Bool, spacious? : Bool, closedby? : String, on_close? :
    Emit
    [String], on_cancel? :
    Cmd
    , class? : String, attrs? :
    Attrs
    , style? : Array[String], children : C) ->
    Html

    Render a styled native dialog without component state.

    The browser owns visibility and focus: open it with the host framework's dialog command (or the open attribute for SSR), and close it with a <form method="dialog"> submit button. closedby controls native dismissal: "any" allows outside clicks and Escape, "closerequest" allows Escape, and "none" requires an explicit close.

    spacious=true widens the panel from the default 480px to 616px.

    divider

    fn divider(id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A thin horizontal rule for separating stacked content.
    fn dropdown_menu(items~ : Array[
    MenuEntry
    ], trigger~ :
    Html
    , open~ : Bool, on_open_change? :
    Emit
    [Bool], selected? : String, on_select? :
    Emit
    [String], align? :
    MenuAlign
    , side? :
    MenuSide
    , id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String], trigger_style? : Array[String], menu_style? : Array[String]) ->
    Html

    A dropdown menu with a caller-supplied trigger. Fully controlled: the caller owns both the open flag (open + on_open_change) and the selected value (selected + on_select). Closes on outside click and Escape; when open, Arrow/Home/End keys move focus between items and Enter activates the focused item (handled by the theme's static event layer, so callers wire nothing extra).

    side=Top opens the panel above the trigger (input docks at the bottom of the page); the enter animation's transform origin follows side and align. menu_style appends overrides to the panel (e.g. a width).

    dropdown_menu(
    trigger=button(variant=Ghost, [text(model_label), menu_chevron()]),
    open=menu_open,
    on_open_change=set_menu_open.map(v => _ => v),
    items=MenuEntry::items([MenuItem::new("sd", "Sketch Diffusion")]),
    selected=model,
    on_select=set_model.map(v => _ => v),
    )

    editable_text

    fn editable_text(value~ : String, placeholder? : String, on_change? :
    Emit
    [String], read_only? : Bool, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A title that reads as plain text and turns into an input on click. Focus selects the whole value so typing replaces it (interaction sheet handles select-all, Enter, and Escape); the parent only sees commits — Enter or blur emits on_change, Escape restores the last value. The placeholder shows when the value is empty.

    empty_state

    fn empty_state(title_text~ : String, description? : String, icon? :
    Html
    , action? :
    Html
    , id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A placeholder for empty regions of the canvas or a result list. Pass an optional action (usually a button) below the copy.

    favorite_toggle

    fn favorite_toggle(checked~ : Bool, on_change? :
    Emit
    [Bool], disabled? : Bool, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A bare star button that toggles a favorite on/off: outline star at rest, filled amber star when on. Fully controlled — the caller owns checked. Unlike icon_button it carries no hover plate, matching the design's chrome-less affordance.

    favorite_toggle(
    checked=starred,
    on_change=set_starred.map(v => _ => v),
    )

    generation_meta

    fn generation_meta(text~ : String, on_copy? :
    Cmd
    , copy_label? : String, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The info-and-actions block under a generation result: a 14/22 tertiary disclaimer line (e.g. the content notice and the credits spent) with a bare copy action below it. Render the action by passing on_copy.

    generation_meta(
    text="AI-generated content | 0 credits used",
    on_copy=emit(CopyResult),
    )

    hitl_card

    fn hitl_card(title~ : String, items~ : Array[
    HitlItem
    ], on_toggle? :
    Emit
    [Int], confirmed? : Bool, on_cancel? :
    Cmd
    , on_confirm? :
    Cmd
    , cancel_label? : String, confirm_label? : String, max_height? : Int, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A human-in-the-loop confirm card: a titled list of generation options with per-row checkboxes and credit costs, plus a Cancel / confirm footer whose primary button carries the total cost of the checked rows. Controlled: the caller owns each item's checked and receives row clicks via on_toggle(index).

    confirmed=true renders the read-only receipt state — checkboxes and the footer drop out, leaving the settled list.

    hitl_card(
    title="Generate the following 4 videos",
    items=plan,
    on_toggle=emit.map(ToggleRow),
    on_cancel=emit(Dismiss),
    on_confirm=emit(ConfirmAll),
    )

    icon

    fn icon(path : String, size? : Int, stroke_width? : Int, style? : Array[String]) ->
    Html

    A 24x24 stroke icon rendered as inline SVG. The surrounding span owns accessibility hiding and a stable layout box; color inherits from the parent via currentColor.

    icon_adjust

    fn icon_adjust(size? : Int) ->
    Html

    icon_adjust_fill

    fn icon_adjust_fill(size? : Int) ->
    Html

    Filled adjustment sliders on a 14 grid — the settings affordance of input toolbars. (The stroked icon_adjust reads too thin at 14px.)

    icon_align_left

    fn icon_align_left(size? : Int) ->
    Html

    Three left-aligned bars, the bottom one short — the generic document placeholder glyph of the attachment tile.

    icon_arrow_down

    fn icon_arrow_down(size? : Int) ->
    Html

    icon_arrow_up

    fn icon_arrow_up(size? : Int) ->
    Html

    icon_arrow_up_fill

    fn icon_arrow_up_fill(size? : Int) ->
    Html

    Filled up-arrow on a 16 grid — the send button's glyph. (The stroked icon_arrow_up reads too thin on the solid circular fill.)

    icon_at

    fn icon_at(size? : Int) ->
    Html

    At-sign on a 14 grid — the reference-mention affordance of input toolbars.

    icon_button

    fn icon_button(icon :
    Html
    , variant? :
    ButtonVariant
    , size? :
    ButtonSize
    , disabled? : Bool, pressed? : Bool, id? : String, class? : String, title? : String, aria_label? : String, on_click? :
    Cmd
    , attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A square button for a single icon. Convenience wrapper over button with size=Icon/IconSm and variant=Ghost by default.

    icon_caret_down

    fn icon_caret_down(size? : Int) ->
    Html

    Filled rounded caret marking a filter trigger, on a 16 design grid.

    icon_chat_history

    fn icon_chat_history(size? : Int) ->
    Html

    List lines with a clock on a 16 grid — the session-history affordance of session headers.

    icon_check

    fn icon_check(size? : Int) ->
    Html

    icon_check_fill

    fn icon_check_fill(size? : Int) ->
    Html

    Filled check mark for the outline checkboxes of menu rows. The glyph grid is 12 inside the 16 viewBox (path coordinates scaled by 4/3), so at the default size 12 it reproduces the design's checkbox tick exactly.

    icon_check_fill_large

    fn icon_check_fill_large(size? : Int) ->
    Html

    Large filled check on a 16 grid — the selected-row indicator of session lists. (icon_check_fill is the smaller 12-grid checkbox tick.)

    icon_chevron_down

    fn icon_chevron_down(size? : Int) ->
    Html

    icon_chevron_down_fill

    fn icon_chevron_down_fill(size? : Int) ->
    Html

    Chunky filled chevron-down on a 14 grid — the expanded status row's affordance.

    icon_chevron_left

    fn icon_chevron_left(size? : Int) ->
    Html

    icon_chevron_right

    fn icon_chevron_right(size? : Int) ->
    Html

    icon_chevron_right_fill

    fn icon_chevron_right_fill(size? : Int) ->
    Html

    Chunky filled chevron-right on a 14 grid — the collapsed status row's affordance.

    icon_chevron_up

    fn icon_chevron_up(size? : Int) ->
    Html

    icon_chevron_up_fill

    fn icon_chevron_up_fill(size? : Int) ->
    Html

    Chunky filled chevron-up on a 14 grid — the collapse toggle's glyph. (The stroked icon_chevron_up reads too thin at this size.)

    icon_clock

    fn icon_clock(size? : Int) ->
    Html

    icon_close_circle

    fn icon_close_circle(size? : Int) ->
    Html

    Filled circle with a times cutout — the clear affordance of a filtered trigger. The glyph grid is 13.333 inside the 16 viewBox, which reproduces the design's 8.33% inset exactly at size 16.

    icon_copy

    fn icon_copy(size? : Int) ->
    Html

    Two overlapping rounded frames — the copy-to-clipboard action glyph.

    icon_crop

    fn icon_crop(size? : Int) ->
    Html

    icon_delete

    fn icon_delete(size? : Int) ->
    Html

    Trash can on a 16 grid — the delete affordance of hoverable list rows.

    icon_download

    fn icon_download(size? : Int) ->
    Html

    icon_draw

    fn icon_draw(size? : Int) ->
    Html

    Pencil with a stroke trail on a 16 grid — the canvas-work glyph of tool rows.

    icon_edit

    fn icon_edit(size? : Int) ->
    Html

    Pencil with an underline on a 16 grid — the rename affordance of hoverable list rows.

    icon_element

    fn icon_element(size? : Int) ->
    Html

    Figure inside a frame — the single-element reference glyph.

    icon_expand

    fn icon_expand(size? : Int) ->
    Html

    icon_folder

    fn icon_folder(size? : Int) ->
    Html

    Folder outline — the pick-from-library menu row's glyph.

    icon_fullscreen_alt

    fn icon_fullscreen_alt(size? : Int) ->
    Html

    Diagonal corner arrows on a 16 grid — the collapse/expand affordance of session headers.

    icon_grid

    fn icon_grid(size? : Int) ->
    Html

    icon_group

    fn icon_group(size? : Int) ->
    Html

    Shape nodes pinned to a selection frame — the grouped-reference glyph.

    icon_image

    fn icon_image(size? : Int) ->
    Html

    icon_image_fill

    fn icon_image_fill(size? : Int) ->
    Html

    Filled landscape with a sun — the placeholder glyph of an image reference that has no thumbnail yet.

    icon_important

    fn icon_important(size? : Int) ->
    Html

    Exclamation in a circle, used for inline validation and status notes.

    icon_info_circle_fill

    fn icon_info_circle_fill(size? : Int, style? : Array[String]) ->
    Html

    Filled disc with an "i" cutout — the partial-failure state of async work.

    icon_layers

    fn icon_layers(size? : Int) ->
    Html

    icon_minus

    fn icon_minus(size? : Int) ->
    Html

    icon_more

    fn icon_more(size? : Int) ->
    Html

    icon_new_conversation

    fn icon_new_conversation(size? : Int) ->
    Html

    Speech bubble with a plus on a 16 grid — the new-conversation affordance of session headers.

    icon_play

    fn icon_play(size? : Int) ->
    Html

    icon_plus

    fn icon_plus(size? : Int) ->
    Html

    icon_plus_fill

    fn icon_plus_fill(size? : Int) ->
    Html

    Rounded filled plus on the 16 grid — the add tile's glyph.

    icon_ratio

    fn icon_ratio(width~ : Int, height~ : Int, size? : Int) ->
    Html

    An aspect-ratio artwork icon: a centered rectangle outline drawn at the given ratio inside the icon box (ratio pickers in size panels).

    icon_reset

    fn icon_reset(size? : Int) ->
    Html

    icon_scissors

    fn icon_scissors(size? : Int) ->
    Html

    fn icon_search(size? : Int) ->
    Html

    icon_skill

    fn icon_skill(size? : Int) ->
    Html

    Magic wand with a sparkle on a 16 grid — the skill affordance of input toolbars and skill chips.

    icon_slash

    fn icon_slash(size? : Int) ->
    Html

    Slanted bar separating pagination numbers — a filled glyph on a 9.333x14 design grid, sized by height (the width follows the glyph's ratio).

    icon_sound

    fn icon_sound(size? : Int) ->
    Html

    Four waveform bars — the audio reference glyph.

    icon_sparkle

    fn icon_sparkle(size? : Int) ->
    Html

    icon_sparkle_fill

    fn icon_sparkle_fill(size? : Int) ->
    Html

    Filled four-point star on a 16 grid — the credit-cost glyph of generation rows and confirm buttons. Color inherits via currentColor.

    icon_star

    fn icon_star(size? : Int) ->
    Html

    Star outline on the 16 grid — the favorite toggle's off state.

    icon_star_fill

    fn icon_star_fill(size? : Int) ->
    Html

    Filled star — the favorite toggle's on state.

    icon_stop_fill

    fn icon_stop_fill(size? : Int) ->
    Html

    Filled rounded square on a 16 grid — the stop-generating glyph that replaces the send arrow while a run is in flight.

    icon_target

    fn icon_target(size? : Int) ->
    Html

    Crosshair — the pick-from-canvas menu row's glyph.

    icon_text

    fn icon_text(size? : Int) ->
    Html

    Serif-like capital T — the text reference glyph.

    icon_tick_circle_fill

    fn icon_tick_circle_fill(size? : Int, style? : Array[String]) ->
    Html

    Filled disc with a tick cutout — the completion state of async work.

    icon_timeline

    fn icon_timeline(size? : Int) ->
    Html

    Frame split into a header strip and column cells — the timeline reference glyph.

    icon_upload

    fn icon_upload(size? : Int) ->
    Html

    icon_upload_fill

    fn icon_upload_fill(size? : Int) ->
    Html

    Filled upload arrow over a baseline — the upload menu row's glyph.

    icon_video

    fn icon_video(size? : Int) ->
    Html

    Rounded frame with a play triangle — the video reference glyph.

    icon_x

    icon_x_fill

    fn icon_x_fill(size? : Int) ->
    Html

    Filled times mark, weighted to stay legible at 4px — the glyph of the attachment tile's remove badge. (The stroked icon_x renders too thin at that size.)

    input

    fn input(value~ : String, placeholder? : String, input_type? :
    InputType
    , on_input? :
    Emit
    [String], on_change? :
    Emit
    [String], on_clear? :
    Cmd
    , clearable? : Bool, prefix? :
    Html
    , suffix? :
    Html
    , error? : Bool, error_text? : String, disabled? : Bool, read_only? : Bool, name? : String, maxlength? : Int, autofocus? : Bool, id? : String, class? : String, title? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A single-line text field. Controlled: the caller owns the value.

    prefix/suffix slot icons or text inside the field; clearable=true shows a small ✕ while the value is non-empty (clears through on_input or the explicit on_clear). error/error_text render the design's error border and an optional hint line below the field.

    kbd

    fn kbd(key : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A keyboard key hint, e.g. for shortcut labels in menus and tooltips.

    md_text

    fn md_text(text~ : String, kind? :
    MdTextKind
    , id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    One block of a markdown answer: a semantic heading (H2–H4) or body paragraph in the design's type scale. All kinds read at the primary text tone; headings pad 12px above and below, the body pads none.

    md_text(kind=H2, text="Story beats")
    md_text(kind=Body, text="The opening shot drifts over the quiet bay.")

    media_tag

    A compact inline reference to a piece of content — the "Image" / "Video" chip that prefixes a conversation bubble or sits inside the composer input. Purely presentational unless on_click is given, in which case it renders as a button and brightens on hover.

    media_tag(kind=Image, thumbnail=thumb_url)
    media_tag(kind=Video, state=Generating)
    media_tag(kind=Audio, variant=Inline, state=Candidate)
    fn menu_chevron(size? : Int) ->
    Html

    The chevron for menu triggers. It carries the menu-chevron slot, so the interaction sheet rotates it 180° while the parent dropdown is open.
    fn pagination(page~ : Int, total~ : Int, on_change? :
    Emit
    [Int], id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A minimal ‹ page / total › pager for stepping through a small result set. Controlled: the parent owns page and applies on_change. The arrow buttons clamp at the range ends and disable there.

    popover

    A generic anchored floating panel with a caller-supplied trigger — the base for composite pickers that are not plain option lists (sliders, forms, previews). Same overlay/motion model as dropdown_menu: fully controlled (open + on_open_change), closes on outside click, enters with the scale animation whose origin follows side and align.

    popover(
    trigger=button(variant=Ghost, [text("16:9 · 2K"), menu_chevron()]),
    open=panel_open,
    on_open_change=set_panel_open.map(v => _ => v),
    [my_panel_content],
    )

    progress

    fn progress(value~ : Int, max? : Int, show_value? : Bool, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A determinate linear progress bar.

    prompt_box

    fn prompt_box(value~ : String, placeholder? : String, rows? : Int, on_input? :
    Emit
    [String], on_send? :
    Cmd
    , send_disabled? : Bool, send_loading? : Bool, disabled? : Bool, maxlength? : Int, show_count? : Bool, autofocus? : Bool, actions? :
    Html
    , id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The composite prompt input: a frosted, rounded container holding an auto-sized textarea and a footer row (action slot + circular send button). Controlled: the caller owns value.

    show_count=true renders a n / max counter next to the send button; it turns error-red once the value exceeds maxlength. The textarea carries the library's thin-scrollbar styling.

    prompt_box(
    value=prompt,
    placeholder="Describe what to create",
    on_input=emit.map(PromptChanged),
    on_send=emit(Submit),
    send_disabled=prompt.is_empty(),
    maxlength=800,
    show_count=true,
    )

    result_chip

    fn result_chip(label~ : String, thumbnail? : String, size? :
    ResultChipSize
    , aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A 24px rich-text reference tag of generation results: a rounded block fill holding a 16px rounded thumbnail and a short label. Small blurs the backdrop (6px) for floating over imagery; Medium drops the blur and steps the label up to 14/24 secondary for inline chat rows.

    result_chip(label="Harbor Dusk", thumbnail=ref_url)
    result_chip(label="Image", thumbnail=ref_url, size=Medium)

    segmented

    fn segmented(items~ : Array[
    SegmentedItem
    ], selected~ : String, stacked? : Bool, on_select? :
    Emit
    [String], id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A segmented single-choice control (aspect-ratio / resolution pickers in the design). Controlled: the caller owns the selected value.

    stacked=true renders tall items with the icon above the label — the ratio-picker look (16px artwork icons over 12px labels, 56px tall).

    select

    fn select(options~ : Array[
    MenuItem
    ], value~ : String, placeholder? : String, open~ : Bool, on_open_change? :
    Emit
    [Bool], on_select? :
    Emit
    [String], variant? :
    SelectVariant
    , on_clear? :
    Cmd
    , disabled? : Bool, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A form-style single select: an input-look trigger opening the compact menu. Fully controlled — the caller owns open and value. Built on dropdown_menu, so outside click, Escape, and arrow-key navigation all behave the same.

    variant=Filter swaps in the compact toolbar trigger: the label is the filter name (placeholder) until a value is selected, then the selected label with a clear affordance that emits on_clear (without opening the menu). The caller resets value in response.

    select(
    options=[@overlays.MenuItem::new("png", "PNG"), @overlays.MenuItem::new("webp", "WebP")],
    value=format,
    placeholder="Export format",
    open=select_open,
    on_open_change=set_select_open.map(v => _ => v),
    on_select=set_format.map(v => _ => v),
    )

    send_button

    fn send_button(disabled? : Bool, loading? : Bool, stop? : Bool, on_click? :
    Cmd
    , id? : String, class? : String, title? : String, aria_label? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The circular submit button used by prompt_box and agent_input. Disabled state uses the design's exact muted fill rather than opacity. loading=true keeps the muted fill, swaps the glyph for a 20px spinner in the disabled tone, and blocks clicks while a submission is in flight. stop=true swaps the arrow for the stop square — the affordance for halting an in-flight generation; pair it with an enabled click.

    session_divider

    fn session_divider(id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The hairline separator of a session list: a 0.5px rule inset 12px on both sides inside a 4px-tall cell.

    session_header

    fn session_header(title~ : String, status? :
    SessionStatus
    , on_title? :
    Cmd
    , on_new? :
    Cmd
    , on_collapse? :
    Cmd
    , new_label? : String, collapse_label? : String, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The header row of a chat window: the current-session session_title on the left and new-conversation / collapse icon buttons on the right (gap 4).

    session_header(
    title="Desert Mirage Expedition",
    status=Done,
    on_title=emit(ToggleSessionMenu),
    on_new=emit(NewConversation),
    on_collapse=emit(CollapsePanel),
    )

    session_item

    fn session_item(label~ : String, active? : Bool, disabled? : Bool, status? :
    SessionStatus
    , on_click? :
    Cmd
    , on_edit? :
    Cmd
    , on_delete? :
    Cmd
    , edit_label? : String, delete_label? : String, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    One row of a session list: a 13/22 label with an optional trailing generation status (or a check mark while active), revealing rename / delete actions on hover. The status cell hides while hovered so the actions take its place.

    session_item(
    label="Desert Mirage Expedition",
    active=current == id,
    status=Done,
    on_click=emit.map(Open(id)),
    on_edit=emit.map(Rename(id)),
    on_delete=emit.map(Remove(id)),
    )

    session_list

    fn session_list(children~ : Array[
    Html
    ], width? : Int, max_height? : Int, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The session-list panel: a floating menu surface (--sumi-menu, 12px radius, 4px padding) holding session_item rows and session_divider separators. With max_height the panel scrolls with the library's thin scrollbar, tinted to the design's blue.

    session_list(max_height=320, [
    session_item(label="Neon Harbor Nights", active=true),
    session_item(label="Alpine Sunrise Timelapse", status=Generating),
    session_divider(),
    session_item(label="Archived Storyboards", disabled=true),
    ])

    session_status

    The 20px generation-status indicator of session rows, titles, and task cards. Pending sizes to its label; every other kind is a fixed 20px cell.

    session_status(kind=Generating)
    session_status(kind=Count(5))
    session_status(kind=Pending("Review"))

    session_title

    fn session_title(label~ : String, status? :
    SessionStatus
    , on_click? :
    Cmd
    , disabled? : Bool, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The current-session pill of a chat window header: a 14/22 label, an optional generation status, and a 12px chevron, with the design's ghost hover/press fills. Typically the trigger of a session_list dropdown.

    shimmer_text

    fn shimmer_text(text : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The agent status line's in-progress look: a dim band sweeping endlessly across otherwise readable text. The gradient is clipped to the glyphs (background-clip:text), so the sweep rides on the letterforms rather than the box. The sumi-shimmer-text keyframes live in the interaction sheet; reduced motion freezes the sweep.

    shimmer_text("Working on it…")

    shortcuts_panel

    fn shortcuts_panel(sections~ : Array[
    ShortcutSection
    ], title? : String, on_close? :
    Cmd
    , width? : Int, max_height? : Int, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The keyboard-shortcuts reference panel from the design: an elevated 264px sheet with a titled header and close button, then titled sections of label + key-chip rows. Long lists scroll inside the body with the library's standard scrollbar.

    shortcuts_panel(
    title="Shortcuts",
    sections=[
    ShortcutSection::new(
    "General",
    [
    ShortcutItem::new("Toggle sidebar", "Cmd /"),
    ShortcutItem::new("Send message", "Enter"),
    ],
    ),
    ],
    on_close=close_panel,
    )

    skeleton

    fn skeleton(width? : String, height? : String, radius? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A shimmering placeholder block for loading layouts. The shimmer runs in the interaction sheet and pauses under prefers-reduced-motion.

    skeleton_lines

    fn skeleton_lines(count? : Int, style? : Array[String]) ->
    Html

    Two lines of text-shaped skeletons with the design's line metrics.

    skeleton_tile

    fn skeleton_tile(width? : String, height? : String, style? : Array[String]) ->
    Html

    The card-shaped skeleton used for image/video tiles on a canvas.

    skill_chip

    fn skill_chip(label~ : String, icon? :
    Html
    , mark? :
    SkillMark
    , mark_label? : String, more? : Bool, on_click? :
    Cmd
    , disabled? : Bool, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    One skill pill of the agent's skill picker: a 36px radius-40 chip with a hairline border and a translucent fill, holding an optional 16px leading icon, a 12/20 label, and an optional New/Hot mark. With more=true the chip becomes the "More" trigger: tighter gap, asymmetric padding, and a trailing 12px right chevron.

    skill_chip(label="Storyboard", icon=@sumi.icon_draw(size=16), mark=New)
    skill_chip(label="More", more=true, on_click=emit(OpenSkillPanel))

    slider

    fn slider(value~ : Int, min? : Int, max? : Int, step? : Int, on_input? :
    Emit
    [Int], on_commit? :
    Emit
    [Int], disabled? : Bool, show_value? : Bool, value_tooltip? : Bool, suffix? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A single-value slider built on the native range input; track fill and thumb styling live in the interaction sheet emitted by theme.

    value_tooltip=true adds the design's value bubble above the thumb, visible while hovering, dragging, or keyboard-focusing the slider. on_input fires per tick (keep it cheap); on_commit fires once on release for expensive reactions.

    slider(
    value=35,
    value_tooltip=true,
    on_input=set_strength.map(v => _ => v),
    on_commit=emit(CommitStrength),
    suffix="°",
    )

    slider_field

    fn slider_field(value~ : Int, min? : Int, max? : Int, step? : Int, label? : String, unit? : String, ticks? : Array[Int], auto? : Bool, auto_label? : String, on_auto_change? :
    Emit
    [Bool], on_input? :
    Emit
    [Int], on_commit? :
    Emit
    [Int], disabled? : Bool, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A labelled numeric field composing the slider with tick marks, tick labels, and a number box carrying the unit suffix — the duration-field pattern. Fully controlled: the parent owns value (and auto when the optional auto row is shown by passing it). The slider fires on_input per tick and on_commit on release; the number box commits on Enter or blur (Escape reverts), firing both.

    ticks lists the values that get a track mark and a label below; the first and last marks stay invisible like the design's end caps.

    slider_field(
    value=duration,
    min=0, max=180,
    label="Total duration",
    unit="s",
    ticks=[0, 30, 60, 90, 120, 150, 180],
    on_input=set_duration.map(v => _ => v),
    )

    spinner

    fn spinner(size? : Int, id? : String, class? : String, style? : Array[String]) ->
    Html

    An indeterminate loading spinner. Rotation comes from the interaction sheet emitted by theme and respects prefers-reduced-motion.

    status_badge

    fn status_badge(state~ :
    StatusBadgeState
    , aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A 20px badge reporting an async job's state, per the design: a frosted determinate ring while running, a white circle with the queue depth, a blue tick disc on completion, an amber info disc for partial failure. Rendered on dark imagery, so the palette is pinned to the dark values.

    status_badge(state=Running(45))
    status_badge(state=Count(3))
    status_badge(state=Complete)
    status_badge(state=Warning)

    stepper

    fn stepper(value~ : Int, min? : Int, max? : Int, step? : Int, on_change? :
    Emit
    [Int], disabled? : Bool, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A numeric stepper (e.g. the batch-count picker). Controlled: the caller owns value; the buttons clamp to min/max and disable at the bounds.

    switch

    fn switch(checked~ : Bool, on_change? :
    Emit
    [Bool], disabled? : Bool, id? : String, class? : String, title? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A toggle switch. Controlled: the caller owns checked.

    tabs

    fn tabs(items~ : Array[
    TabEntry
    ], selected~ : String, on_select? :
    Emit
    [String], id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A tab strip. Controlled: the caller owns the selected value; render the matching panel content next to the returned strip.

    tabs(
    items=[TabEntry::new("all", "All"), TabEntry::new("mine", "Mine")],
    selected=tab,
    on_select=set_tab.map(v => _ => v),
    )

    tag

    A small status/category label. Pass on_remove to render a removable tag with a trailing close icon.

    task_card

    fn task_card(title~ : String, status? :
    SessionStatus
    , summary? : String, children? : Array[
    Html
    ], on_click? :
    Cmd
    , aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A submitted-task bubble of the task list: a frosted 16px-radius card with a 14/24 Medium title, an optional generation status, and a two-line summary. Pass children instead of summary for a rich body (e.g. a tool_call_row).

    task_card(
    title="Neon Harbor Nights",
    status=Generating,
    summary="I will first break down the brief into its core elements.",
    )

    task_list

    fn task_list(children~ : Array[
    Html
    ], height? : Int, fade? : Int, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    The scrollable task-card feed ("bubble list"): 8px padding and gaps, a bottom fade mask (fade px, default 44), and the blue-tinted thin scrollbar. Children are usually task_card bubbles.

    task_list(height=400, children=cards)

    textarea

    fn textarea(value~ : String, placeholder? : String, rows? : Int, on_input? :
    Emit
    [String], on_change? :
    Emit
    [String], disabled? : Bool, read_only? : Bool, name? : String, maxlength? : Int, autofocus? : Bool, id? : String, class? : String, title? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A multi-line text field. Controlled: the caller owns the value.

    theme

    fn[C :
    IsChildren
    ] theme(mode? : ThemeMode, id? : String, class? : String, title? : String, attrs? :
    Attrs
    , style? : Array[String], children : C) ->
    Html

    Provide the design tokens to a subtree and emit the library's static pseudo-class interaction sheet plus the event-layer script. Wrap the app root once:

    theme(mode=Dark, [my_app_content])

    mode picks the token palette (see tokens.mbt): Dark (default), Light, or System to follow the viewer's OS setting. Tokens ride on the emitted sheet keyed by [data-sumi-theme], so nested themes with different modes compose. Override any token by appending custom CSS variables through style.

    toast

    fn toast(message~ : String, open~ : Bool, variant? :
    ToastVariant
    , on_close? :
    Cmd
    , id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    A transient notification rendered in a fixed top-center viewport. Controlled: the caller owns open; the enter/exit fade runs in the interaction sheet (mount-stable + hidden toggle). Combine with @cmd.delay to auto-dismiss.

    // show for 2.4s
    @cmd.batch([set_toast(_ => true), @cmd.delay(set_toast(_ => false), 2400)])

    tool_call_row

    fn tool_call_row(label~ : String, icon? :
    Html
    , state? :
    ToolCallState
    , expandable? : Bool, expanded? : Bool, on_toggle? :
    Cmd
    , steps? : Array[String], truncate? : Bool, aria_label? : String, id? : String, class? : String, attrs? :
    Attrs
    , style? : Array[String]) ->
    Html

    One line of agent progress: a 16px tool icon, a shimmering or settled label, and — when expandable — a chevron that flips between right (collapsed) and down (expanded). Expanding reveals steps under a thread line. The whole row is the toggle hit area when on_toggle is given; omit icon for icon-less rows like "Thinking".

    tool_call_row(icon=icon_image(), label="(0/1) Image generating…")
    tool_call_row(icon=icon_image(), state=Done, label="(1/1) Image generation completed")
    tool_call_row(
    icon=icon_adjust(), label="2 commands executed",
    expandable=true, expanded=e, on_toggle=set_e.map(v => _ => !v),
    steps=["List file directories", "Search for related content"],
    )

    toolbar

    fn[C :
    IsChildren
    ] toolbar(id? : String, class? : String, title? : String, attrs? :
    Attrs
    , style? : Array[String], children : C) ->
    Html

    A floating horizontal bar that groups controls — the design's signature pill-shaped toolbar. Compose with button(variant=Ghost), segmented, dropdown_menu and toolbar_divider.

    toolbar_divider

    fn toolbar_divider(style? : Array[String]) ->
    Html

    The thin vertical separator used between control groups inside a toolbar.

    tooltip

    A hover tooltip. The bubble reveals via the interaction sheet (pure CSS), so no state is involved. Wrap any trigger element:

    tooltip(content="Upscale to 4K", button(variant=Ghost, "4K"))