limn
    ↑↓ ChooseEnter OpenEsc Close
    GitHub

    Components/States

    ContextWindow

    What fills a model's context window: the figure in use, a field of cells shared out among the shares, one row for each share with its count, and a foot with a status line and an action.

    Native componentGuide source

    Preview

    CodeSource
    fn view(state: &State, palette: ComponentPalette, tones: ContextTones) -> Element {
        let shares = vec![
            ContextShare::new("system", "System", 4_200, palette.text),
            ContextShare::new("tools", "Tools", 12_800, palette.muted),
            ContextShare::new("chat", "Conversation", state.chat_tokens, state.accent),
        ];
        ContextWindow::new("context", "Context window", shares, 200_000, palette, tones)
            .caption("of 200K tokens")
            .status(&state.context_status)
            .render()
    }

    Examples

    Each one is the library drawing it. Press, type and hover.

    Context window
    CodeSource
    row(vec![Element::column(vec![card.render()])
        .background(palette.surface)
        .border(palette.border, 1.0)
        .radius(16.0)
        .clip_children()]),
    row(vec![
        Button::new("context-busy", if busy { "Stop compacting" } else { "Simulate compaction in progress" }, palette)
            .variant(ButtonVariant::Outline)
            .render(),
        Button::new(reset, "Reset", palette).variant(ButtonVariant::Outline).render(),
    ])

    ContextWindow

    What fills a model’s context window: the figure in use, a field of cells shared out among the shares, one row for each share with its count, and a foot with a status line and an action.

    Import

    use limn::{
        Component, ContextItem, ContextShare, ContextShareAction, ContextTones, ContextWindow,
    };

    Usage

    The host owns every figure and passes them on each rebuild. A card needs an ID, a title, its shares, the capacity of the window in tokens, the palette and the colors that carry meaning.

    fn view(state: &State, palette: ComponentPalette, tones: ContextTones) -> Element {
        let shares = vec![
            ContextShare::new("system", "System", 4_200, palette.text),
            ContextShare::new("tools", "Tools", 12_800, palette.muted),
            ContextShare::new("chat", "Conversation", state.chat_tokens, state.accent),
        ];
        ContextWindow::new("context", "Context window", shares, 200_000, palette, tones)
            .caption("of 200K tokens")
            .status(&state.context_status)
            .render()
    }

    Each ContextShare has an ID, a label, a count of tokens and a color. The card draws its own card on a frame a shade apart, with the foot on the frame, so give it a surface with rounded corners and no padding. It is 320 px wide unless width sets it, and never narrower than 200 px.

    A capacity of zero is a window of unknown size: the shares fill the cells between them and no percentage is shown.

    Tones

    let tone = |tone| AlertColors::for_tone(tone, palette).accent;
    let tones = ContextTones {
        warning: tone(AlertTone::Warning),
        danger: tone(AlertTone::Error),
        success: tone(AlertTone::Success),
    };

    The percentage is drawn in warning from 80% of the window and in danger from 95%. success colors a share’s finished action and a status set with status_done.

    Shares that open

    fn view(state: &State, palette: ComponentPalette, tones: ContextTones) -> Element {
        let files = state.files.iter().map(|file| ContextItem {
            id: file.id.clone(),
            label: file.name.clone(),
            tokens: file.tokens,
        });
        let shares = vec![
            ContextShare::new("files", "Files", state.file_tokens(), palette.muted).items(files.collect()),
        ];
        ContextWindow::new("context", "Context window", shares, 200_000, palette, tones)
            .expanded(state.files_open.then_some("files"))
            .render()
    }
    
    fn update(state: &mut State, action: &UiAction) {
        if let UiAction::Clicked { id } = action {
            if id == "context:share:files" {
                state.files_open = !state.files_open;
            } else if let Some(file) = id.strip_prefix("context:remove:files:") {
                state.remove_file(file);
            }
        }
    }

    A share with items shows a chevron and opens to list them, each with its count and a button that removes it. The host decides which shares are open: expanded takes their IDs, and a click on a share’s row reports "{id}:share:{share}" for the host to answer.

    A share’s action

    ContextShare::new("chat", "Conversation", state.chat_tokens, accent).action(match state.compaction {
        Compaction::Idle => ContextShareAction::Offer("Compact".into()),
        Compaction::Running => ContextShareAction::Busy("Compacting".into()),
        Compaction::Done => ContextShareAction::Done("Compacted".into()),
    })

    Offer is an action in the share’s row that reports "{id}:action:{share}". Busy shows its label beside a spinner while the host carries it out, and Done shows it with a check in the success color. Neither can be clicked.

    Focus

    let focused = tree
        .hovered_id()
        .and_then(|hovered| ContextWindow::share_under("context", hovered));
    
    ContextWindow::new("context", "Context window", shares, 200_000, palette, tones)
        .caption("of 200K tokens")
        .focused(focused)
        .render()

    focused makes one share stand out: the figure becomes its count, the caption its label, and the other shares recede. share_under gives the share whose row or action a control ID belongs to, so the host passes the ID under the pointer.

    Unmeasured shares

    ContextShare::new("memory", "Memory", 0, palette.muted).unmeasured()

    A share the host could not measure is listed with a dash where its count would be, also in the figure while it is in focus, and takes no cells.

    Header and foot

    ContextWindow::new("context", "Context window", shares, 200_000, palette, tones)
        .badge("model-name")
        .header_icon("context-copy", Icon::Copy, "Copy diagnostics")
        .status_lead("Files")
        .status("Files · 23% of the window")
        .footer_action("context-new", "New chat")
        .render()

    badge is a short name beside the title. header_icon adds a small action at the end of the header, with its hint; call it again for another. status is the line at the foot and status_done the same in the success color. status_lead names the words the status opens with, which read stronger. footer_action is an action opposite the status.

    Format

    format takes a fn(f32) -> String that writes a count of tokens, also while it counts. The default is ContextWindow::tokens_text: “950”, “4.2K”, “175.6K”, “1.25M”.

    Inside a popover

    flat is for a host whose surface already is the card, such as a popover: the content stands on that surface, with no frame and no card around it. parts then returns the body and the foot apart, for a host that scrolls one and pins the other under it.

    Motion

    When a figure changes, the counts roll to the new value over three times move_ms, and the cells of a share that shrinks empty from its end while the shares after it follow. The caption and the status change as a Ticker line does, over move_ms, and the percentage fades to the color of its new state. An item that is removed closes where it was, as a Collapse does. With reduced motion the new state is shown at once.

    Actions

    ActionWhen
    UiAction::Clicked { id: "{id}:share:{share}" }A share’s row is clicked. The host opens or closes it.
    UiAction::Clicked { id: "{id}:action:{share}" }A share’s Offer action is clicked.
    UiAction::Clicked { id: "{id}:remove:{share}:{item}" }An item’s remove button is clicked.
    UiAction::Clicked { id }A header_icon or the footer_action is clicked, with the ID given to it.

    API reference

    The guide covers composition, options and actions. Generate the complete Rust type and builder reference from the checkout:

    cargo doc -p limn --open

    Component API overview · State and actions

    The example is drawn by crates/limn-gallery/src/pages/context.rs.