# `faststep`
`faststep` is a UIKit-inspired UI framework for embedded targets built on
[`embedded-graphics`](https://docs.rs/embedded-graphics).
The crate is aimed at projects where application code should describe views and
behavior, while the framework owns widget state, scrolling, modal transitions,
and the main update or present loop.
## What 0.1.x Is
The `0.1.x` line is the first public foundation release for the library.
It is intended to be:
- usable for real embedded UI work
- explicit about the preferred architecture
- broad enough to cover the main widget families already needed by `bazcon`
- conservative about compatibility by still exporting [`UiApp`]
It is not intended to be the final shape of a full retained-mode framework.
The point of `0.1.0` is to publish a coherent, documented base that can be
iterated on without hiding the architectural direction.
## Core Model
`faststep` is organized around three layers:
- [`UiView`] and [`UiSystem`] define the application-facing view tree and root
runtime state.
- [`StackView`], [`TabView`], [`SplitView`], [`AlertHost`], [`ScrollView`], and
[`ListView`] provide reusable container and interaction behavior.
- [`DisplayPort`], [`UiRuntimeDriver`], and [`UiRuntimePresenter`] adapt the
framework to concrete devices or future simulator backends.
The preferred entry point for new applications is [`run_ui_system`]. It keeps
`main` thin while letting `faststep` own the update, touch, and presentation
loop.
## Design Goals
The intended authoring model is:
- keep `main` thin
- point the system at a root view implementation
- let views configure their children and metadata
- keep button, list, and alert interaction state inside the framework
- push device-specific concerns behind runtime and display traits
- make new device targets and simulators plug into the same UI layer
## Main Entry Points
If you are new to the crate, start here:
- [`UiSystem`]: root owner for display, root view, theme, i18n, and
registration state
- [`UiView`]: trait implemented by the root or custom views in your app
- [`ViewRegistration`]: setup object used during `configure(...)`
- [`run_ui_system`]: framework-owned event loop
- [`FsTheme`]: semantic palette configured once at startup
- [`I18n`]: lightweight localization helper
## Widget and Container Surface
The first public release already includes the main widget families:
- [`Button`], [`ButtonSpec`], [`ButtonKind`]
- [`ImageView`], [`ImageViewStyle`], [`ImageAlignment`]
- [`TextView`], [`RichTextView`], [`TextSpan`], [`TextViewStyle`]
- [`ScrollView`], [`ScrollViewState`], [`ScrollBar`]
- [`ListView`], [`ListDataSource`], [`ListDelegate`], [`ListRowState`]
- [`StackView`], [`TabView`], [`SplitView`]
- [`AlertSpec`], [`AlertView`], [`AlertHost`], [`ModalHost`]
This gives the crate enough breadth for a first public cut without pretending
the framework is already feature-complete.
## Runtime and OEM Boundary
`faststep` does not hardcode one board implementation.
The adapter boundary is:
- [`DisplayPort`] for frame drawing and optional dirty-rect presentation
- [`UiCanvas`] for draw surfaces that also support dimmed overlays
- [`UiRuntimeDriver`] for timing, sleep, and touch polling
- [`UiRuntimePresenter`] for redraw batching and panel-specific present policy
That same seam is intended to support:
- ESP-IDF targets
- alternate boards and displays
- future desktop or simulator backends
## Typical Startup Shape
A minimal application looks like this conceptually:
```ignore
let display = MyDisplayPort::new();
let theme = FsTheme::default();
let i18n = I18n::new("en", "en", LOCALES);
let root = RootView::new();
let driver = MyRuntimeDriver::new();
let presenter = MyPresenter::new();
run_ui_system(display, root, theme, i18n, driver, presenter)?;
```
The important boundary is:
- the application owns the root view and behavior
- the framework owns the UI runtime loop
- the OEM adapter owns the hardware and present policy
## View Authoring Shape
Views are expected to register their own structure during `configure(...)`.
That includes:
- frame
- title
- alpha
- hidden state
- clipping
- child views and their kinds
Conceptually:
```ignore
fn configure(&mut self, registration: &mut ViewRegistration<'static, ViewId, 4>) {
registration.set_title(Localized::new("root.title", "Devices"));
registration.set_clips_to_bounds(true);
registration.add_child(
ChildView::new(ViewId::Devices, registration.frame())
.with_kind(ViewKind::List)
)?;
}
```
## Scrolling and Lists
The crate treats scrolling as a first-class behavior instead of something each
screen hand-rolls.
[`ScrollView`] owns:
- drag tracking
- inertial scrolling
- overscroll and snap-back behavior
- transient scroll indicator behavior
[`ListView`] builds on that and adds:
- datasource-driven row identity and sizing
- delegate-driven row drawing
- row highlight state
- row selection state
This is the first public step toward UIKit-like list behavior with clearer row
state and reusable interaction rules.
## Included Examples
The crate includes compile-checked examples for the major API families, and the
manifest enables docs.rs example scraping:
- `examples/buttons.rs`
- `examples/text_and_image.rs`
- `examples/scroll_and_list.rs`
- `examples/containers.rs`
- `examples/alerts.rs`
- `examples/runtime_shell.rs`
- `examples/uikit_root.rs`
- `examples/root_delegate.rs`
These examples are part of the packaged crate and are intended to be the
fastest way to see how a widget family is supposed to be wired up.
## Compatibility
[`UiApp`] is still exported because existing code depends on it, but it should
be treated as a compatibility layer.
For new work, prefer:
- [`UiSystem`]
- [`UiView`]
- [`ViewRegistration`]
- the container and datasource APIs
## no_std
The crate is `#![no_std]` and keeps its dependencies intentionally small. It is
intended for embedded usage first, with runtime and presentation traits used to
bridge into real hardware or simulator environments.