embedded-gui
embedded-gui is a no_std GUI/HUD crate for embedded-graphics displays.
It is built around fixed-capacity data structures, deterministic rendering, and
embedded-friendly interaction patterns (pointer, encoder, and keyboard-style input).
Heavily inspired by the Pebble smartwatch UI framework — its animation model, interaction contracts, and cinematic motion primitives draw directly from Pebble's design language. LVGL is a secondary influence, particularly for widget composition and style-state conventions.
Current State
embedded-gui currently provides a broad baseline of widgets, interaction semantics,
fixed-capacity animation primitives, and screen transition tooling for embedded UIs.
Recent work has focused on tightening interaction fidelity, expanding state transition
coverage, and improving regression-focused examples/docs.
- Pointer release semantics now consistently target the originally pressed widget.
- Focused open dropdowns now close on
Backbefore global back handling. - State transitions now cover keyboard and pointer press feedback paths.
- Enabled/disabled flag changes now participate in state transitions with regression coverage.
- Style-class state overrides now participate correctly in transition endpoint blending.
- Select activation now supports configurable double-select recognition (
DoubleClickedevents). - Per-widget raw key input policy now supports
SelectPressed/ReleasedandBackPressed/Released. - Pointer interaction now supports configurable double-click recognition (
DoubleClickedevents). - Per-widget key bindings can override
Select/Backbehavior (Default,Ignore,Activate,Back). - Textarea no-op edits avoid emitting mutation events, with regression coverage.
- Wrapped-line selection navigation (
SelectHome/SelectEnd) now has dedicated edge-case coverage. - Cross-widget interaction matrix coverage now includes dropdown/list/tabs/roller keyboard navigation paths.
- Nested layout + clip behavior now has dedicated regression coverage for parent-relative composition.
- A dedicated interaction semantics simulator example is available in
examples/interaction_semantics_showcase.rs.
Quick Start
use *;
let mut gui = new;
gui.add_label?;
gui.add_progress_bar?;
gui.render?;
Implemented Feature Surface
Widgets and primitives
The current widget set includes:
- labels, panels, buttons, icon buttons, borders/spacers
- progress bars, sliders, toggles, checkboxes, value labels
- lists, menus, tabs, dialogs, toasts, scroll views
- dropdowns, rollers, tables
- chart (line and bars), spinner, meter/gauge/arc gauge/needle
- textareas and on-screen keyboards
- image widgets (
ImageRef,ImageFit, atlas/sprite helpers)
Input and events
InputEventsupports D-pad/encoder navigation, pointer events, and text-editing-oriented key events- UI-level events (
UiEvent) and widget-level events (WidgetEvent) are both exposed - Event flow supports capture, target, and bubble phases with filterable dispatch policy hooks
- Pointer semantics include long-press, gesture dispatch, drag scrolling, inertia, and press-repeat timing hooks
Layout, styling, and text
LinearLayoutand constraint-based item layout (Length,Min/Max,Percent,Ratio,Fill)- Style model with stateful variants (
normal,focused,pressed,disabled) - Style interpolation and transition primitives (
StyleTransition,lerp_style) - Text layout primitives (
Span,Line,Text) with alignment, wrapping, spacing, overflow controls - Text shaping interface (
TextShaper) with a basic shaping implementation for embedded-safe defaults
Animation and transitions
- Core animation manager and easing/tween/path/spring/inertia primitives
- Spatial timing (
moook_curve,TransitionPreset) — seedocs/transition-presets.md - Widget property animation (
WidgetAnimator) and preset helpers (presets) - Timeline/keyframe sequencing support (
AnimationSequence,SequencePlayer) - Screen stack + transition primitives for app-level flows (fade, slide, wipe, shutter, port-hole, round-flip, modal)
Animation Quickstart
embedded-gui includes fixed-capacity animation primitives that stay no_std friendly.
use *;
let mut animator = new;
let progress = gui.add_progress_bar?;
animator.animate_progress?;
// In your frame loop:
animator.tick?;
gui.render_dirty?;
gui.clear_dirty;
Textarea Editing Input
Textarea widgets support editor-style navigation and mutation events, including:
InputEvent::WordLeft/InputEvent::WordRightInputEvent::Home/InputEvent::EndInputEvent::Select*expansion variantsInputEvent::Undo/InputEvent::Redo- selection-replace behavior on typing/backspace/delete
See docs/textarea-input-keybindings.md for mappings and loop snippets.
Font Glyph Overrides
The build pipeline supports external glyph overrides from:
assets/fonts/ascii_3x5.txtassets/fonts/ascii_4x7.txt
Format per line:
key:row0,row1,row2,row3,row4
key: a single character orspace- each row: 3 bits using
0/1(left to right) - blank lines and
#comments are ignored
Example:
?:111,001,010,000,010
!:010,010,010,000,010
space:000,000,000,000,000
Unspecified glyphs fall back to built-in defaults in build.rs.
Preview helper:
Examples
The examples/ folder currently includes:
widgets_showcase.rsdashboard_app.rssimulator_menu.rsevent_dispatch_showcase.rsinteraction_semantics_showcase.rsraw_key_input_showcase.rsform_flow_showcase.rscomplex_layout_showcase.rsinput_gesture_drag_repeat_showcase.rslong_press_input_showcase.rstext_layout_showcase.rsfont_text_model_showcase.rsanimation_motion_showcase.rsanimation_kitchen_sink_showcase.rsanimation_dirty_showcase.rstimeline_transition_showcase.rsvisual_quality_showcase.rsembedded_3dgfx_overlay.rs
Behavior Notes
- Input and widget interaction guarantees are documented in
docs/interaction-behavior-contract.md.
Visual Showcase
Animation and transition capabilities (generated from simulator output):

Flip-card screen transition (RoundFlipLeft) — card selection between views:

Cinematic peek/glance/carddeck — launcher-style glance tiles cycling with slide-prominence animation, peek reveal, and card story transitions:

Dashboard-style UI composition:

Typography and mixed-font text model:

Static motion frame preview:
