ratkit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ratkit

ratkit

Comprehensive Rust TUI component library built on ratatui 0.29, providing 21 feature-gated modules (primitives, widgets, services) for building rich terminal applications.
This file provides a complete reference for working with the ratkit codebase. The repository is organized as a single crate at the root level with feature-based modularity. Use this guide to understand component relationships, find APIs, and follow established patterns when implementing new features.
基于 ratatui 0.29 构建的综合 Rust TUI 组件库,提供21个受功能开关管控的模块(原语、组件、服务),用于开发功能丰富的终端应用。
本文件是 ratkit 代码库的完整参考文档。仓库根目录下为单个 crate,采用基于功能的模块化设计,你可以通过本指南理解组件关联关系、查找 API,以及在实现新功能时遵循既定的开发模式。

Agent Operating Rules

操作规范

  1. Single crate at root: All code is in
    src/
    with 21 feature flags (e.g.,
    button
    ,
    pane
    ,
    markdown-preview
    )
  2. Enable features explicitly: No default features; add required features to Cargo.toml (e.g.,
    features = ["button", "dialog"]
    )
  3. Cross-feature dependencies: Some features auto-enable others (e.g.,
    tree-view
    enables
    widget-event
    ,
    repo-watcher
    enables
    file-watcher
    and
    git-watcher
    )
  4. Use
    just
    for all operations
    : Build (
    just build
    ), test (
    just test
    ), check (
    just check
    ), demos (
    just demo
    )
  5. Run examples with
    --features
    flag
    : Examples require their specific features (e.g.,
    --features markdown-preview
    )
  6. Use module-path imports first: Prefer explicit module paths (e.g.,
    use ratkit::primitives::button::Button
    ,
    use ratkit::widgets::markdown_preview::MarkdownWidget
    ) because crate-root re-exports are not guaranteed for every type
  7. StatefulWidget pattern: Complex widgets require separate state structs persisted in app state
  8. Event loop polling: Services require regular
    check_for_changes()
    calls in the event loop
  9. Mouse capture required: Enable crossterm mouse capture for interactive widgets
  10. Persist widget state: Never create widget state in render loops - store in app struct
  11. Validate before commits: Run
    just check
    (format + lint + test) before committing
  12. Verify feature flags: Compilation errors often indicate missing feature flags in Cargo.toml
  1. 根目录单个 crate:所有代码都存放在
    src/
    目录下,共21个功能开关(例如
    button
    pane
    markdown-preview
  2. 显式启用功能:无默认启用的功能,需要在 Cargo.toml 中添加所需功能(例如
    features = ["button", "dialog"]
  3. 跨功能依赖:部分功能会自动启用其他依赖功能(例如
    tree-view
    会自动启用
    widget-event
    repo-watcher
    会自动启用
    file-watcher
    git-watcher
  4. 所有操作使用
    just
    :构建(
    just build
    )、测试(
    just test
    )、检查(
    just check
    )、演示(
    just demo
  5. 运行示例需指定
    --features
    参数
    :示例需要启用对应的功能(例如
    --features markdown-preview
  6. 优先使用模块路径导入:推荐使用显式模块路径(例如
    use ratkit::primitives::button::Button
    use ratkit::widgets::markdown_preview::MarkdownWidget
    ),因为 crate 根目录的重导出不保证覆盖所有类型
  7. StatefulWidget 模式:复杂组件需要单独的状态结构体,持久化存储在应用状态中
  8. 事件循环轮询:服务需要在事件循环中定期调用
    check_for_changes()
  9. 需要启用鼠标捕获:交互式组件需要开启 crossterm 鼠标捕获功能
  10. 持久化组件状态:不要在渲染循环中创建组件状态,应存储在应用结构体中
  11. 提交前验证:提交代码前运行
    just check
    (格式化+代码检查+测试)
  12. 验证功能开关:编译报错通常是因为 Cargo.toml 中缺少对应的功能开关

Environment and Version Constraints

环境与版本约束

  • Rust 1.70+ required (workspace.rust-version in Cargo.toml)
  • ratatui 0.29 as the underlying rendering library
  • crossterm 0.28 for terminal input/events
  • tokio for async runtime
  • Single crate at root with 21 feature flags (no workspace members)
  • 23 examples in
    examples/
    (moved from
    crates/ratkit/examples/
    )
  • Optional external deps: notify (file watching), reqwest (ai-chat), pulldown-cmark/syntect (markdown), similar (code-diff)
  • 需要 Rust 1.70+(Cargo.toml 中 workspace.rust-version 指定)
  • 底层渲染库为 ratatui 0.29
  • 终端输入/事件处理使用 crossterm 0.28
  • 异步运行时使用 tokio
  • 根目录单个 crate,共21个功能开关(无 workspace 成员)
  • 23个示例存放在
    examples/
    目录下(从
    crates/ratkit/examples/
    迁移而来)
  • 可选外部依赖:notify(文件监听)、reqwest(ai-chat)、pulldown-cmark/syntect(markdown)、similar(code-diff)

Quick Task Playbooks

快速任务手册

Run an example

运行示例

  • Where to edit: N/A
  • Related files:
    examples/
  • Validation:
    cargo run --example button_button_demo --features button
  • 修改位置:无
  • 相关文件
    examples/
  • 验证命令
    cargo run --example button_button_demo --features button

Extract smooth-redraw patterns from markdown preview demo

从 markdown 预览 demo 中提取流畅重绘模式

  • Where to edit: target app event loop (
    on_event
    ) and draw path (
    on_draw
    )
  • Related files:
    examples/markdown_preview_markdown_preview_demo.rs
  • Goal: Port the demo's event-pressure controls and redraw strategy into other TUIs
  • Validation: Under rapid mouse movement and wheel input, app remains responsive without event backlog
  • 修改位置:目标应用事件循环(
    on_event
    )和渲染路径(
    on_draw
  • 相关文件
    examples/markdown_preview_markdown_preview_demo.rs
  • 目标:将 demo 的事件压力控制和重绘策略移植到其他 TUI 应用中
  • 验证效果:在快速移动鼠标和滚动滚轮的场景下,应用保持响应,无事件积压

Run with just

使用 just 运行

  • Where to edit: N/A
  • Related files:
    justfile
  • Validation:
    just demo
    (interactive picker) or
    just demo-md
    ,
    just demo-md-small
    ,
    just demo-term
    , etc.
  • 修改位置:无
  • 相关文件
    justfile
  • 验证命令
    just demo
    (交互式选择器)或
    just demo-md
    just demo-md-small
    just demo-term

Build with specific features

使用指定功能构建

  • Where to edit:
    Cargo.toml
    (root level)
  • Related files: Feature definitions
  • Validation:
    cargo build --features "button,pane,dialog"
  • 修改位置:根目录
    Cargo.toml
  • 相关文件:功能定义
  • 验证命令
    cargo build --features "button,pane,dialog"

Build all features

构建所有功能

  • Where to edit: N/A
  • Related files: All source files
  • Validation:
    cargo build --all-features
  • 修改位置:无
  • 相关文件:所有源文件
  • 验证命令
    cargo build --all-features

Run full verification

运行完整验证

  • Where to edit: N/A
  • Related files: All source files
  • Validation:
    just check
    (runs fmt-check, lint, test)
  • 修改位置:无
  • 相关文件:所有源文件
  • 验证命令
    just check
    (运行格式化检查、lint、测试)

Getting Started

快速开始

toml
undefined
toml
undefined

Cargo.toml - enable specific features

Cargo.toml - 启用指定功能

[dependencies] ratkit = { version = "0.2.12", features = ["button", "dialog", "pane"] }

```rust
use ratkit::prelude::*;
use ratatui::Frame;

struct MyApp;

impl CoordinatorApp for MyApp {
    fn on_event(&mut self, event: CoordinatorEvent) -> LayoutResult<CoordinatorAction> {
        match event {
            CoordinatorEvent::Keyboard(keyboard) => {
                if keyboard.is_escape() {
                    return Ok(CoordinatorAction::Quit);
                }
            }
            _ => {}
        }
        Ok(CoordinatorAction::Continue)
    }

    fn on_draw(&mut self, frame: &mut Frame) {
        // Render your UI here
    }
}

fn main() -> std::io::Result<()> {
    let app = MyApp;
    run(app, RunnerConfig::default())
}
[dependencies] ratkit = { version = "0.2.12", features = ["button", "dialog", "pane"] }

```rust
use ratkit::prelude::*;
use ratatui::Frame;

struct MyApp;

impl CoordinatorApp for MyApp {
    fn on_event(&mut self, event: CoordinatorEvent) -> LayoutResult<CoordinatorAction> {
        match event {
            CoordinatorEvent::Keyboard(keyboard) => {
                if keyboard.is_escape() {
                    return Ok(CoordinatorAction::Quit);
                }
            }
            _ => {}
        }
        Ok(CoordinatorAction::Continue)
    }

    fn on_draw(&mut self, frame: &mut Frame) {
        // 在此处渲染你的UI
    }
}

fn main() -> std::io::Result<()> {
    let app = MyApp;
    run(app, RunnerConfig::default())
}

Workspace Overview

工作空间概览

The ratkit workspace contains a single crate with 21 feature-gated modules organized into:
  • Primitives (11 modules): Core UI building blocks in
    src/primitives/
    • button, pane, dialog, toast, statusline, scroll, menu_bar, resizable_grid, tree_view, widget_event, termtui
  • Widgets (6 modules): Higher-level composite widgets in
    src/widgets/
    • markdown_preview, code_diff, ai_chat, hotkey_footer, file_system_tree, theme_picker
  • Services (4 modules): Background monitoring services in
    src/services/
    • file_watcher, git_watcher, repo_watcher, hotkey_service
  • Core Runtime (1 module): Application lifecycle in
    src/core/
All modules follow feature-gated compilation. Enable only what you need.
ratkit 工作空间包含单个 crate,共21个受功能开关管控的模块,分类如下:
  • 原语(11个模块):核心UI构建块,存放在
    src/primitives/
    • button、pane、dialog、toast、statusline、scroll、menu_bar、resizable_grid、tree_view、widget_event、termtui
  • 组件(6个模块):高阶复合组件,存放在
    src/widgets/
    • markdown_preview、code_diff、ai_chat、hotkey_footer、file_system_tree、theme_picker
  • 服务(4个模块):后台监控服务,存放在
    src/services/
    • file_watcher、git_watcher、repo_watcher、hotkey_service
  • 核心运行时(1个模块):应用生命周期管理,存放在
    src/core/
所有模块都采用功能开关编译,你可以仅启用所需的模块。

Core Runtime

核心运行时

The core runtime provides the application lifecycle, event routing, and element management for terminal UI applications.
核心运行时为终端UI应用提供应用生命周期、事件路由和元素管理能力。

Key Components

核心组件

  • CoordinatorApp trait: Applications implement this to receive events and render
  • run() / run_with_diagnostics(): Entry points to start the event loop
  • Element trait: Implement for custom widgets that integrate with the coordinator
  • RunnerConfig: Configuration for tick rate, layout debounce, mouse capture
  • CoordinatorApp trait:应用实现该trait来接收事件和执行渲染
  • run() / run_with_diagnostics():启动事件循环的入口函数
  • Element trait:自定义组件实现该trait即可与协调器集成
  • RunnerConfig: tick 频率、布局防抖、鼠标捕获的配置项

Architecture

架构

  • Three-region layout: Top, Center, Bottom
  • Focus management with stack and traversal
  • Mouse routing with z-order hit testing
  • Element registry with weak references
  • 三区域布局:顶部、中部、底部
  • 基于栈和遍历的焦点管理
  • 基于z-order命中测试的鼠标路由
  • 存储弱引用的元素注册表

UI Primitives

UI 原语

Core UI building blocks for TUI applications, located in
src/primitives/
.
TUI应用的核心UI构建块,存放在
src/primitives/

Feature Flags

功能开关

Each primitive has an individual feature flag:
  • button
    ,
    pane
    ,
    dialog
    ,
    toast
    ,
    statusline
    ,
    scroll
  • menu-bar
    (enables
    widget-event
    )
  • resizable-grid
  • tree-view
    (enables
    widget-event
    )
  • widget-event
  • termtui
每个原语都有独立的功能开关:
  • button
    pane
    dialog
    toast
    statusline
    scroll
  • menu-bar
    (自动启用
    widget-event
  • resizable-grid
  • tree-view
    (自动启用
    widget-event
  • widget-event
  • termtui

Common Patterns

通用模式

  • Builder pattern with
    new()
    and
    with_*
    methods
  • StatefulWidget pattern for complex state
  • Event emission via
    WidgetEvent
  • Mouse/keyboard interaction support
  • 采用
    new()
    with_*
    方法的构建者模式
  • 复杂状态采用 StatefulWidget 模式
  • 通过
    WidgetEvent
    发射事件
  • 支持鼠标/键盘交互

MenuBar Layout Contract (updated)

MenuBar 布局约定(更新版)

  • MenuBar::render_with_offset(frame, area, left_offset)
    now uses the full available container width for the border:
    area.width - left_offset
  • The menu bar border should stretch to the right edge of the provided container, while menu items remain left-aligned within the bar
  • If available width is zero after offset, rendering exits early and clears
    self.area
  • This behavior was validated with
    examples/menu-bar_menu_bar_demo.rs
    at fixed 120-column terminal width
  • MenuBar::render_with_offset(frame, area, left_offset)
    现在使用容器的全部可用宽度绘制边框:
    area.width - left_offset
  • 菜单栏边框应延伸到提供的容器右边缘,而菜单项则在栏内保持左对齐
  • 如果扣除偏移后可用宽度为0,会提前退出渲染并清空
    self.area
  • 该行为已在固定120列终端宽度下通过
    examples/menu-bar_menu_bar_demo.rs
    验证

Complex Widgets

复杂组件

Higher-level composite widgets in
src/widgets/
.
高阶复合组件,存放在
src/widgets/

Feature Flags

功能开关

  • markdown-preview
    - Most complex (syntax highlighting, TOC, themes, selection)
  • code-diff
    - VS Code-style diff viewer
  • ai-chat
    - AI chat interface (requires reqwest, serde)
  • hotkey-footer
    - Keyboard shortcut footer
  • file-system-tree
    - File browser with devicons
  • theme-picker
    - Theme selector with 25+ themes
  • markdown-preview
    - 最复杂,支持语法高亮、目录、主题、选择
  • code-diff
    - VS Code风格的差异查看器
  • ai-chat
    - AI聊天界面(需要reqwest、serde)
  • hotkey-footer
    - 快捷键页脚
  • file-system-tree
    - 带devicons的文件浏览器
  • theme-picker
    - 支持25+主题的主题选择器

External Dependencies

外部依赖

WidgetDependencies
ai-chatreqwest, serde, serde_json
markdown-previewpulldown-cmark, syntect, syntect-tui, notify, arboard, dirs
code-diffsimilar
file-system-treedevicons
组件依赖
ai-chatreqwest、serde、serde_json
markdown-previewpulldown-cmark、syntect、syntect-tui、notify、arboard、dirs
code-diffsimilar
file-system-treedevicons

FileSystemTree visual parity notes (Yazi-style)

FileSystemTree 视觉一致性说明(Yazi风格)

When adjusting
file-system-tree
visuals, keep these conventions to match Yazi-like behavior:
  • Prefer
    devicons::icon_for_file(...).color
    (hex) for file icon colors instead of hardcoded extension maps.
  • Parse devicons hex colors into
    ratatui::style::Color::Rgb
    before rendering.
  • Selected row background should use item color (directory rows use dir color; file rows use file color) with black foreground text.
  • Keep row content alignment stable between selected and non-selected states (avoid 1-column shifts when drawing decorations).
  • Directory selection should use a filled highlight; file selection may use rounded edge glyphs if desired.
调整
file-system-tree
视觉效果时,请遵循以下约定以匹配类Yazi的行为:
  • 优先使用
    devicons::icon_for_file(...).color
    (十六进制)作为文件图标颜色,而不是硬编码的扩展名映射
  • 渲染前将devicons的十六进制颜色解析为
    ratatui::style::Color::Rgb
  • 选中行背景应使用对应项的颜色(目录行使用目录颜色,文件行使用文件颜色),前景文字为黑色
  • 保持选中和未选中状态下的行内容对齐稳定(绘制装饰时避免偏移1列)
  • 目录选中应使用填充高亮;文件选中可根据需要使用圆角字形

Services

服务

Background monitoring services in
src/services/
.
后台监控服务,存放在
src/services/

Feature Flags

功能开关

  • file-watcher
    - Watch files/directories for changes
  • git-watcher
    - Monitor git repository state
  • repo-watcher
    - Combined file + git watching (enables file-watcher and git-watcher)
  • hotkey-service
    - Global hotkey registration and management
  • file-watcher
    - 监听文件/目录变更
  • git-watcher
    - 监控git仓库状态
  • repo-watcher
    - 组合文件+git监听(自动启用file-watcher和git-watcher)
  • hotkey-service
    - 全局快捷键注册与管理

Common Dependencies

通用依赖

All watcher services use the
notify
crate for filesystem events.
所有监听服务都使用
notify
crate 处理文件系统事件。

Usage Cards

使用卡片

CoordinatorApp

CoordinatorApp

  • Use when: Building any ratkit TUI application
  • Enable/Install: Core runtime, no feature flag needed
  • Import/Invoke:
    use ratkit::prelude::*;
  • Minimal flow:
    1. Define struct implementing
      CoordinatorApp
    2. Implement
      on_event()
      to handle events
    3. Implement
      on_draw()
      to render UI
    4. Call
      run(app, RunnerConfig::default())
  • Key APIs:
    on_event()
    ,
    on_draw()
    ,
    on_layout_changed()
  • Pitfalls: Runner takes ownership; wrap shared state in
    Arc<RwLock<>>
  • Source:
    src/coordinator.rs
    ,
    src/runner_helper.rs
  • 适用场景:构建任何ratkit TUI应用
  • 启用/安装:核心运行时,无需功能开关
  • 导入/调用
    use ratkit::prelude::*;
  • 最小流程
    1. 定义实现
      CoordinatorApp
      的结构体
    2. 实现
      on_event()
      处理事件
    3. 实现
      on_draw()
      渲染UI
    4. 调用
      run(app, RunnerConfig::default())
  • 核心API
    on_event()
    on_draw()
    on_layout_changed()
  • 注意事项:Runner会获取所有权,共享状态需要用
    Arc<RwLock<>>
    包裹
  • 源码
    src/coordinator.rs
    src/runner_helper.rs

run()

run()

  • Use when: Starting the main application event loop
  • Enable/Install: Core runtime, no feature flag
  • Import/Invoke:
    use ratkit::{run, run_with_diagnostics};
  • Minimal flow:
    1. Create app implementing
      CoordinatorApp
    2. Create
      RunnerConfig::default()
      or custom
    3. Call
      run(app, config)
      or
      run_with_diagnostics(app, config)
      for debug overlay
  • Key APIs:
    run()
    ,
    run_with_diagnostics()
    ,
    RunnerConfig
  • Pitfalls: Blocks until exit; handles terminal init/cleanup
  • Source:
    src/runner_helper.rs
  • 适用场景:启动主应用事件循环
  • 启用/安装:核心运行时,无需功能开关
  • 导入/调用
    use ratkit::{run, run_with_diagnostics};
  • 最小流程
    1. 创建实现
      CoordinatorApp
      的应用实例
    2. 创建
      RunnerConfig::default()
      或自定义配置
    3. 调用
      run(app, config)
      run_with_diagnostics(app, config)
      开启调试浮层
  • 核心API
    run()
    run_with_diagnostics()
    RunnerConfig
  • 注意事项:会阻塞直到退出,自动处理终端初始化/清理
  • 源码
    src/runner_helper.rs

Element

Element

  • Use when: Creating custom widgets that integrate with coordinator
  • Enable/Install: Core runtime
  • Import/Invoke:
    use ratkit::Element;
  • Minimal flow:
    1. Implement
      Element
      trait for your widget
    2. Define
      id()
      ,
      on_render()
      ,
      on_keyboard()
      ,
      on_mouse()
    3. Register with
      ElementMetadata
      and region
  • Key APIs:
    id()
    ,
    on_render()
    ,
    on_keyboard()
    ,
    on_mouse()
    ,
    on_focus_gain()
    ,
    on_focus_loss()
    ,
    on_tick()
  • Pitfalls: Registry stores weak refs - keep strong refs in app state; return
    true
    when handling events
  • Source:
    src/registry.rs
  • 适用场景:创建可与协调器集成的自定义组件
  • 启用/安装:核心运行时
  • 导入/调用
    use ratkit::Element;
  • 最小流程
    1. 为你的组件实现
      Element
      trait
    2. 定义
      id()
      on_render()
      on_keyboard()
      on_mouse()
    3. 注册到
      ElementMetadata
      和对应区域
  • 核心API
    id()
    on_render()
    on_keyboard()
    on_mouse()
    on_focus_gain()
    on_focus_loss()
    on_tick()
  • 注意事项:注册表存储弱引用,需要在应用状态中保留强引用;处理事件时返回
    true
  • 源码
    src/registry.rs

Button

Button

  • Use when: Clickable button with hover states
  • Enable/Install:
    features = ["button"]
  • Import/Invoke:
    use ratkit::Button;
  • Minimal flow:
    1. Create
      Button::new("Label")
    2. Call
      update_hover(x, y)
      on mouse move
    3. Call
      is_clicked(x, y)
      on click
    4. Render with
      render_with_title()
  • Key APIs:
    new()
    ,
    normal_style()
    ,
    hover_style()
    ,
    update_hover()
    ,
    is_clicked()
  • Pitfalls: State must persist in app struct
  • Source:
    src/primitives/button/widget.rs
  • 适用场景:带悬停状态的可点击按钮
  • 启用/安装
    features = ["button"]
  • 导入/调用
    use ratkit::Button;
  • 最小流程
    1. 创建
      Button::new("Label")
    2. 鼠标移动时调用
      update_hover(x, y)
    3. 点击时调用
      is_clicked(x, y)
    4. 使用
      render_with_title()
      渲染
  • 核心API
    new()
    normal_style()
    hover_style()
    update_hover()
    is_clicked()
  • 注意事项:状态必须持久化存储在应用结构体中
  • 源码
    src/primitives/button/widget.rs

Pane

Pane

  • Use when: Styled panel container with title/icon/padding
  • Enable/Install:
    features = ["pane"]
  • Import/Invoke:
    use ratkit::Pane;
  • Minimal flow:
    1. Create
      Pane::new("Title")
    2. Chain builder methods:
      with_icon()
      ,
      with_padding()
      ,
      border_style()
    3. Render as widget
  • Key APIs:
    new()
    ,
    with_icon()
    ,
    with_padding()
    ,
    with_uniform_padding()
    ,
    border_style()
  • Pitfalls: Padding reduces inner content area
  • Source:
    src/primitives/pane/mod.rs
  • 适用场景:带标题/图标/内边距的样式面板容器
  • 启用/安装
    features = ["pane"]
  • 导入/调用
    use ratkit::Pane;
  • 最小流程
    1. 创建
      Pane::new("Title")
    2. 链式调用构建方法:
      with_icon()
      with_padding()
      border_style()
    3. 作为组件渲染
  • 核心API
    new()
    with_icon()
    with_padding()
    with_uniform_padding()
    border_style()
  • 注意事项:内边距会缩小内部内容区域
  • 源码
    src/primitives/pane/mod.rs

Dialog

Dialog

  • Use when: Modal dialogs for confirmation/information
  • Enable/Install:
    features = ["dialog"]
  • Import/Invoke:
    use ratkit::primitives::dialog::{Dialog, DialogWidget, DialogAction, DialogActionsLayout, DialogWrap, DialogShadow, DialogModalMode};
  • Minimal flow:
    1. Create
      Dialog::new(title, message)
      or
      Dialog::confirm(...)
    2. Configure layout and visuals with
      .actions_layout(...)
      ,
      .message_alignment(...)
      ,
      .content_padding(...)
      ,
      .wrap_mode(...)
      ,
      .shadow(...)
      ,
      .overlay(...)
    3. Configure actions/keys with
      .buttons(...)
      ,
      .default_selection(...)
      ,
      .next_keys(...)
      ,
      .previous_keys(...)
      ,
      .confirm_keys(...)
      ,
      .cancel_keys(...)
    4. In event loop, route keys to
      dialog.handle_key_event(...)
      and react to
      DialogAction
    5. Render with
      DialogWidget::new(&mut dialog)
  • Key APIs:
    actions_layout()
    ,
    actions_alignment()
    ,
    message_alignment()
    ,
    content_padding()
    ,
    wrap_mode()
    ,
    hide_footer()
    ,
    footer()
    ,
    footer_style()
    ,
    shadow()
    ,
    overlay()
    ,
    modal_mode()
    ,
    body_renderer()
    ,
    handle_key_event()
    ,
    handle_mouse_confirm()
    ,
    blocks_background_events()
  • Pitfalls: If you want
    Tab
    to control inner body UI (for example a list) instead of dialog actions, remove
    Tab
    from dialog keymap and handle it in your app event loop; if you want no action row, set
    .buttons(vec![])
  • Source:
    src/primitives/dialog/
  • 适用场景:用于确认/信息提示的模态对话框
  • 启用/安装
    features = ["dialog"]
  • 导入/调用
    use ratkit::primitives::dialog::{Dialog, DialogWidget, DialogAction, DialogActionsLayout, DialogWrap, DialogShadow, DialogModalMode};
  • 最小流程
    1. 创建
      Dialog::new(title, message)
      Dialog::confirm(...)
    2. 通过
      .actions_layout(...)
      .message_alignment(...)
      .content_padding(...)
      .wrap_mode(...)
      .shadow(...)
      .overlay(...)
      配置布局和视觉效果
    3. 通过
      .buttons(...)
      .default_selection(...)
      .next_keys(...)
      .previous_keys(...)
      .confirm_keys(...)
      .cancel_keys(...)
      配置操作/按键
    4. 在事件循环中将按键路由到
      dialog.handle_key_event(...)
      ,并响应
      DialogAction
    5. 使用
      DialogWidget::new(&mut dialog)
      渲染
  • 核心API
    actions_layout()
    actions_alignment()
    message_alignment()
    content_padding()
    wrap_mode()
    hide_footer()
    footer()
    footer_style()
    shadow()
    overlay()
    modal_mode()
    body_renderer()
    handle_key_event()
    handle_mouse_confirm()
    blocks_background_events()
  • 注意事项:如果你希望
    Tab
    控制内部主体UI(例如列表)而非对话框操作,请从对话框按键映射中移除
    Tab
    ,在应用事件循环中自行处理;如果不需要操作行,设置
    .buttons(vec![])
  • 源码
    src/primitives/dialog/

Dialog interaction patterns

Dialog 交互模式

  • Vertical actions:
    .actions_layout(DialogActionsLayout::Vertical)
    for stacked action menus
  • Horizontal actions:
    .actions_layout(DialogActionsLayout::Horizontal)
    for classic Yes/No rows
  • No actions shown:
    .buttons(vec![])
    hides the actions row so dialog body content can be primary
  • Custom body widget: implement
    DialogBodyRenderer
    and pass
    .body_renderer(Box::new(...))
    to render a selectable list/menu inside dialog chrome
  • Blocking modal:
    .modal_mode(DialogModalMode::Blocking)
    plus
    blocks_background_events()
    to prevent background input handling
  • Tab delegation: use
    .next_keys(...)
    /
    .previous_keys(...)
    to exclude
    Tab
    and route
    Tab
    to body-level focus/selection logic
  • 垂直操作
    .actions_layout(DialogActionsLayout::Vertical)
    用于堆叠操作菜单
  • 水平操作
    .actions_layout(DialogActionsLayout::Horizontal)
    用于经典的是/否行
  • 不显示操作
    .buttons(vec![])
    隐藏操作行,让对话框主体内容成为核心
  • 自定义主体组件:实现
    DialogBodyRenderer
    并传入
    .body_renderer(Box::new(...))
    ,可在对话框边框内渲染可选择的列表/菜单
  • 阻塞模态
    .modal_mode(DialogModalMode::Blocking)
    搭配
    blocks_background_events()
    可阻止后台输入处理
  • Tab 委托:使用
    .next_keys(...)
    /
    .previous_keys(...)
    排除
    Tab
    ,将
    Tab
    路由到主体级别的焦点/选择逻辑

Toast

Toast

  • Use when: Auto-dismissing notifications
  • Enable/Install:
    features = ["toast"]
  • Import/Invoke:
    use ratkit::{ToastManager, ToastLevel};
  • Minimal flow:
    1. Create
      ToastManager::new()
      in app state
    2. Add toasts via
      .success()
      ,
      .error()
      ,
      .info()
      ,
      .warning()
    3. Call
      cleanup()
      before render
    4. Render with
      render_toasts()
  • Key APIs:
    ToastManager::new()
    ,
    .add()
    ,
    .success()
    ,
    .error()
    ,
    .cleanup()
  • Pitfalls: Must call
    cleanup()
    to remove expired; doesn't auto-expire
  • Source:
    src/primitives/toast/
  • 适用场景:自动消失的通知
  • 启用/安装
    features = ["toast"]
  • 导入/调用
    use ratkit::{ToastManager, ToastLevel};
  • 最小流程
    1. 在应用状态中创建
      ToastManager::new()
    2. 通过
      .success()
      .error()
      .info()
      .warning()
      添加通知
    3. 渲染前调用
      cleanup()
    4. 使用
      render_toasts()
      渲染
  • 核心API
    ToastManager::new()
    .add()
    .success()
    .error()
    .cleanup()
  • 注意事项:必须调用
    cleanup()
    移除过期通知,不会自动过期
  • 源码
    src/primitives/toast/

MenuBar

MenuBar

  • Use when: Top-level horizontal navigation with mouse and keyboard selection
  • Enable/Install:
    features = ["menu-bar"]
    (auto-enables
    widget-event
    )
  • Import/Invoke:
    use ratkit::primitives::menu_bar::{MenuBar, MenuItem};
  • Minimal flow:
    1. Create
      MenuBar::new(vec![MenuItem::new("File", 0), ...])
    2. Optionally set initial selection with
      .with_selected(index)
    3. On mouse move: call
      update_hover(x, y)
      ; on click: call
      handle_click(x, y)
      or
      handle_mouse(x, y)
    4. Render with
      render()
      or
      render_with_offset()
  • Key APIs:
    new()
    ,
    with_selected()
    ,
    update_hover()
    ,
    handle_click()
    ,
    handle_mouse()
    ,
    selected()
    ,
    render_with_offset()
  • Pitfalls: Border fills full container width; do not assume border auto-sizes to label content
  • Source:
    src/primitives/menu_bar/menu_bar.rs
    ,
    examples/menu-bar_menu_bar_demo.rs
  • 适用场景:支持鼠标和键盘选择的顶层水平导航栏
  • 启用/安装
    features = ["menu-bar"]
    (自动启用
    widget-event
  • 导入/调用
    use ratkit::primitives::menu_bar::{MenuBar, MenuItem};
  • 最小流程
    1. 创建
      MenuBar::new(vec![MenuItem::new("File", 0), ...])
    2. 可选使用
      .with_selected(index)
      设置初始选中项
    3. 鼠标移动时调用
      update_hover(x, y)
      ;点击时调用
      handle_click(x, y)
      handle_mouse(x, y)
    4. 使用
      render()
      render_with_offset()
      渲染
  • 核心API
    new()
    with_selected()
    update_hover()
    handle_click()
    handle_mouse()
    selected()
    render_with_offset()
  • 注意事项:边框会填充整个容器宽度,不要假设边框会自动适配标签内容大小
  • 源码
    src/primitives/menu_bar/menu_bar.rs
    examples/menu-bar_menu_bar_demo.rs

TreeView

TreeView

  • Use when: Hierarchical data with expand/collapse/selection
  • Enable/Install:
    features = ["tree-view"]
    (auto-enables widget-event)
  • Import/Invoke:
    use ratkit::{TreeNode, TreeView, TreeViewState, TreeNavigator};
  • Minimal flow:
    1. Build
      TreeNode
      hierarchy
    2. Create
      TreeView::new(nodes)
      with render_fn
    3. Create
      TreeViewState::new()
      for selection/expansion
    4. Use
      TreeNavigator
      for keyboard handling
  • Key APIs:
    TreeNode::new()
    ,
    TreeView::new()
    ,
    TreeViewState::new()
    ,
    TreeNavigator::new()
  • Pitfalls: TreeViewState must persist; TreeNavigator handles all keyboard nav
  • Source:
    src/primitives/tree_view/
  • 适用场景:支持展开/收起/选择的层级数据展示
  • 启用/安装
    features = ["tree-view"]
    (自动启用 widget-event)
  • 导入/调用
    use ratkit::{TreeNode, TreeView, TreeViewState, TreeNavigator};
  • 最小流程
    1. 构建
      TreeNode
      层级结构
    2. 使用渲染函数创建
      TreeView::new(nodes)
    3. 创建
      TreeViewState::new()
      存储选中/展开状态
    4. 使用
      TreeNavigator
      处理键盘操作
  • 核心API
    TreeNode::new()
    TreeView::new()
    TreeViewState::new()
    TreeNavigator::new()
  • 注意事项:TreeViewState 必须持久化存储,所有键盘导航由 TreeNavigator 处理
  • 源码
    src/primitives/tree_view/

MarkdownWidget

MarkdownWidget

  • Use when: Rendering markdown with syntax highlighting, TOC, themes
  • Enable/Install:
    features = ["markdown-preview"]
    (complex dependencies)
  • Import/Invoke:
    use ratkit::widgets::markdown_preview::{MarkdownWidget, ScrollState, SourceState, ...};
  • Minimal flow:
    1. Create state structs (ScrollState, SourceState, etc.) in app state
    2. Create
      MarkdownWidget::new(content, scroll, source, ...)
    3. Handle keyboard with
      handle_key()
    4. Render with ratatui
  • Key APIs:
    new()
    ,
    handle_key()
    ,
    handle_mouse()
    ,
    .show_toc()
    ,
    .toggle_toc()
    ,
    .with_frontmatter_collapsed()
    ,
    set_frontmatter_collapsed()
    ,
    .show_scrollbar()
  • Pitfalls: Requires mouse capture enabled; state must persist across renders; frontmatter collapse is section-based (section id
    0
    ); large markdown with many fenced code blocks can increase first-render time if syntax highlighter initialization is repeated (parser now reuses one
    SyntaxHighlighter
    per parse call)
  • Source:
    src/widgets/markdown_preview/widgets/markdown_widget/
  • 适用场景:渲染带语法高亮、目录、主题的markdown
  • 启用/安装
    features = ["markdown-preview"]
    (依赖较多)
  • 导入/调用
    use ratkit::widgets::markdown_preview::{MarkdownWidget, ScrollState, SourceState, ...};
  • 最小流程
    1. 在应用状态中创建状态结构体(ScrollState、SourceState等)
    2. 创建
      MarkdownWidget::new(content, scroll, source, ...)
    3. 使用
      handle_key()
      处理键盘事件
    4. 使用 ratatui 渲染
  • 核心API
    new()
    handle_key()
    handle_mouse()
    .show_toc()
    .toggle_toc()
    .with_frontmatter_collapsed()
    set_frontmatter_collapsed()
    .show_scrollbar()
  • 注意事项:需要启用鼠标捕获;状态必须在渲染间持久化;frontmatter 收起是基于 section 的(section id 为
    0
    );如果语法高亮器初始化重复执行,包含大量代码块的大型 markdown 会增加首次渲染时间(现在解析器每次解析调用会复用同一个
    SyntaxHighlighter
  • 源码
    src/widgets/markdown_preview/widgets/markdown_widget/

Markdown demo variants

Markdown demo 变体

  • Use when: Choosing markdown content size for preview behavior checks
  • Run:
    just demo-md
    (opencode SDK skill markdown) and
    just demo-md-small
    (ratkit skill markdown)
  • Expected behavior: Both variants render with TOC, statusline, hover interactions, and copy support
  • Startup profiling: Run
    target/debug/examples/markdown_preview_markdown_preview_demo --startup-probe
    (with
    RATKIT_MD_DEMO_FILE=...
    ) to print
    MARKDOWN_DEMO_READY_MS=<ms>
    for repeatable load-time comparisons
  • Source:
    examples/markdown_preview_markdown_preview_demo.rs
    ,
    justfiles/utilities/demo-md.just
  • 适用场景:选择markdown内容大小来验证预览行为
  • 运行命令
    just demo-md
    (opencode SDK skill markdown)和
    just demo-md-small
    (ratkit skill markdown)
  • 预期行为:两个变体都渲染目录、状态栏、悬停交互和复制支持
  • 启动性能分析:运行
    target/debug/examples/markdown_preview_markdown_preview_demo --startup-probe
    (搭配
    RATKIT_MD_DEMO_FILE=...
    )会输出
    MARKDOWN_DEMO_READY_MS=<ms>
    ,可用于可重复的加载时间对比
  • 源码
    examples/markdown_preview_markdown_preview_demo.rs
    justfiles/utilities/demo-md.just

FileSystemTree

FileSystemTree

  • Use when: Browsing local files/directories with icons and keyboard navigation
  • Enable/Install:
    features = ["file-system-tree"]
  • Import/Invoke:
    use ratkit::widgets::file_system_tree::{FileSystemTree, FileSystemTreeState, FileSystemTreeConfig};
  • Minimal flow:
    1. Create
      FileSystemTree::new(root_path)
      or
      with_config(...)
    2. Persist
      FileSystemTreeState
      in app state
    3. Route nav keys to
      handle_navigation_key(...)
    4. Route filter keys to
      handle_filter_key(...)
      when filter mode is active
  • Key APIs:
    new()
    ,
    with_config()
    ,
    handle_navigation_key()
    ,
    enter_filter_mode()
    ,
    expand_selected()
    ,
    collapse_selected()
  • Pitfalls: Keep icon colors sourced from devicons, and preserve selection-row alignment when adding rounded highlight glyphs
  • Source:
    src/widgets/file_system_tree/widget.rs
    ,
    src/widgets/file_system_tree/config.rs
    ,
    src/widgets/file_system_tree/state.rs
  • 适用场景:带图标和键盘导航的本地文件/目录浏览
  • 启用/安装
    features = ["file-system-tree"]
  • 导入/调用
    use ratkit::widgets::file_system_tree::{FileSystemTree, FileSystemTreeState, FileSystemTreeConfig};
  • 最小流程
    1. 创建
      FileSystemTree::new(root_path)
      with_config(...)
    2. 在应用状态中持久化
      FileSystemTreeState
    3. 将导航按键路由到
      handle_navigation_key(...)
    4. 过滤模式激活时将过滤按键路由到
      handle_filter_key(...)
  • 核心API
    new()
    with_config()
    handle_navigation_key()
    enter_filter_mode()
    expand_selected()
    collapse_selected()
  • 注意事项:图标颜色应来自 devicons,添加圆角高亮字形时保持选中行对齐
  • 源码
    src/widgets/file_system_tree/widget.rs
    src/widgets/file_system_tree/config.rs
    src/widgets/file_system_tree/state.rs

FileWatcher

FileWatcher

  • Use when: Detecting file/directory changes
  • Enable/Install:
    features = ["file-watcher"]
    (uses notify crate)
  • Import/Invoke:
    use ratkit::services::file_watcher::FileWatcher;
  • Minimal flow:
    1. Create
      FileWatcher::for_file()
      or
      FileWatcher::for_directory()
    2. Call
      watch(path)
    3. Poll
      check_for_changes()
      in event loop
    4. Get changes with
      get_changed_paths()
  • Key APIs:
    for_file()
    ,
    for_directory()
    ,
    watch()
    ,
    check_for_changes()
    ,
    get_changed_paths()
  • Pitfalls: Must poll regularly;
    get_changed_paths()
    clears queue; debounced (100ms/200ms)
  • Source:
    src/services/file_watcher/
  • 适用场景:检测文件/目录变更
  • 启用/安装
    features = ["file-watcher"]
    (使用 notify crate)
  • 导入/调用
    use ratkit::services::file_watcher::FileWatcher;
  • 最小流程
    1. 创建
      FileWatcher::for_file()
      FileWatcher::for_directory()
    2. 调用
      watch(path)
    3. 在事件循环中轮询
      check_for_changes()
    4. 使用
      get_changed_paths()
      获取变更路径
  • 核心API
    for_file()
    for_directory()
    watch()
    check_for_changes()
    get_changed_paths()
  • 注意事项:必须定期轮询;
    get_changed_paths()
    会清空队列;已做防抖(100ms/200ms)
  • 源码
    src/services/file_watcher/

HotkeyService

HotkeyService

  • Use when: Centralized hotkey management with scope filtering
  • Enable/Install:
    features = ["hotkey-service"]
  • Import/Invoke:
    use ratkit::services::hotkey_service::{Hotkey, HotkeyRegistry, HotkeyScope};
  • Minimal flow:
    1. Create
      HotkeyRegistry::new()
    2. Register hotkeys with
      Hotkey::new(key, description).scope(scope)
    3. Set active scope with
      set_active_scope()
    4. Query with
      lookup(key, scope)
      in event loop
  • Key APIs:
    HotkeyRegistry::new()
    ,
    register()
    ,
    lookup()
    ,
    set_active_scope()
  • Pitfalls: Uses
    &'static str
    for scopes; must handle crossterm events separately
  • Source:
    src/services/hotkey_service/
  • 适用场景:支持范围过滤的集中式快捷键管理
  • 启用/安装
    features = ["hotkey-service"]
  • 导入/调用
    use ratkit::services::hotkey_service::{Hotkey, HotkeyRegistry, HotkeyScope};
  • 最小流程
    1. 创建
      HotkeyRegistry::new()
    2. 使用
      Hotkey::new(key, description).scope(scope)
      注册快捷键
    3. 使用
      set_active_scope()
      设置激活范围
    4. 在事件循环中使用
      lookup(key, scope)
      查询
  • 核心API
    HotkeyRegistry::new()
    register()
    lookup()
    set_active_scope()
  • 注意事项:范围使用
    &'static str
    ;需要单独处理 crossterm 事件
  • 源码
    src/services/hotkey_service/

API Reference

API 参考

Core Runtime

核心运行时

ComponentKey APIs
CoordinatorApp
on_event()
,
on_draw()
,
on_layout_changed()
run
run()
,
run_with_diagnostics()
Element
id()
,
on_render()
,
on_keyboard()
,
on_mouse()
,
on_focus_gain()
,
on_focus_loss()
,
on_tick()
RunnerConfig
tick_rate
,
layout_debounce
,
mouse_router_config
组件核心API
CoordinatorApp
on_event()
,
on_draw()
,
on_layout_changed()
run
run()
,
run_with_diagnostics()
Element
id()
,
on_render()
,
on_keyboard()
,
on_mouse()
,
on_focus_gain()
,
on_focus_loss()
,
on_tick()
RunnerConfig
tick_rate
,
layout_debounce
,
mouse_router_config

Primitives

原语

PrimitiveKey APIs
Button
new()
,
normal_style()
,
hover_style()
,
update_hover()
,
is_clicked()
Pane
new()
,
with_icon()
,
with_padding()
,
with_uniform_padding()
,
border_style()
Dialog
new()
,
info()
,
warning()
,
error()
,
success()
,
confirm()
,
buttons()
Toast
ToastManager::new()
,
.add()
,
.success()
,
.error()
,
.cleanup()
TreeView
TreeNode::new()
,
TreeView::new()
,
TreeViewState::new()
,
TreeNavigator::new()
Scroll
calculate_scroll_offset()
原语核心API
Button
new()
,
normal_style()
,
hover_style()
,
update_hover()
,
is_clicked()
Pane
new()
,
with_icon()
,
with_padding()
,
with_uniform_padding()
,
border_style()
Dialog
new()
,
info()
,
warning()
,
error()
,
success()
,
confirm()
,
buttons()
Toast
ToastManager::new()
,
.add()
,
.success()
,
.error()
,
.cleanup()
TreeView
TreeNode::new()
,
TreeView::new()
,
TreeViewState::new()
,
TreeNavigator::new()
Scroll
calculate_scroll_offset()

Services

服务

ServiceKey APIs
FileWatcher
for_file()
,
for_directory()
,
watch()
,
check_for_changes()
,
get_changed_paths()
GitWatcher
new()
,
with_config()
,
watch()
,
check_for_changes()
RepoWatcher
new()
,
with_config()
,
watch()
,
check_for_changes()
,
get_change_set()
HotkeyRegistry
new()
,
register()
,
lookup()
,
set_active_scope()
服务核心API
FileWatcher
for_file()
,
for_directory()
,
watch()
,
check_for_changes()
,
get_changed_paths()
GitWatcher
new()
,
with_config()
,
watch()
,
check_for_changes()
RepoWatcher
new()
,
with_config()
,
watch()
,
check_for_changes()
,
get_change_set()
HotkeyRegistry
new()
,
register()
,
lookup()
,
set_active_scope()

Common Pitfalls

常见问题

Feature Flags

功能开关

  1. No default features: Must explicitly enable every feature you use
  2. Cross-feature deps:
    tree-view
    enables
    widget-event
    ;
    repo-watcher
    enables
    file-watcher
    and
    git-watcher
  3. Missing feature errors: "unresolved import" usually means missing feature flag
  1. 无默认功能:必须显式启用你使用的每个功能
  2. 跨功能依赖
    tree-view
    会自动启用
    widget-event
    repo-watcher
    会自动启用
    file-watcher
    git-watcher
  3. 功能缺失错误:「unresolved import」通常意味着缺少功能开关

State Management

状态管理

  1. StatefulWidget pattern: Complex widgets require persistent state in app struct
  2. Never create state in render: Always store widget state in app struct
  3. Weak references: Element registry stores weak refs - keep strong refs in app
  1. StatefulWidget 模式:复杂组件需要在应用结构体中持久化状态
  2. 不要在渲染中创建状态:始终将组件状态存储在应用结构体中
  3. 弱引用:元素注册表存储弱引用,需要在应用中保留强引用

Event Handling

事件处理

  1. Return values: Return
    true
    when consuming events,
    false
    to propagate
  2. Mouse capture: Must enable crossterm mouse capture for interactions
  3. Poll services: Must call
    check_for_changes()
    regularly on watchers
  1. 返回值:消费事件时返回
    true
    ,返回
    false
    会继续传播事件
  2. 鼠标捕获:交互功能需要启用 crossterm 鼠标捕获
  3. 轮询服务:监听器必须定期调用
    check_for_changes()

Examples

示例

  1. Feature flags required: Examples need their specific features:
    --features markdown-preview
  2. Just commands: Use
    just demo
    for interactive picker or
    just demo-*
    for specific demos
  3. Port behavior, not just API calls: Reuse input coalescing and selective redraw patterns from demos, not only widget construction code
  1. 需要指定功能开关:示例需要启用对应的功能:
    --features markdown-preview
  2. Just 命令:使用
    just demo
    打开交互式选择器,或使用
    just demo-*
    运行指定demo
  3. 移植行为,而非仅API调用:复用demo中的输入合并和选择性重绘模式,而不仅仅是组件构建代码

Smooth Redraw Patterns (Extracted from Markdown Preview Demo)

流畅重绘模式(提取自Markdown预览Demo)

Use this section to transfer the demo's responsiveness patterns into other ratkit apps.
你可以参考本节将demo的响应性模式移植到其他ratkit应用中。

Core anti-throttling techniques

核心防阻塞技术

  1. Coalesce high-rate mouse move events
    • Pattern: On
      MouseEventKind::Moved
      , skip handling if last processed move was too recent.
    • Demo value: ~24ms guard (
      last_move_processed.elapsed() < Duration::from_millis(24)
      ).
    • Effect: Prevents motion events from overwhelming the queue during fast pointer movement.
  2. Gate redraws to meaningful state changes
    • Pattern: Return
      CoordinatorAction::Continue
      by default for move events; return
      Redraw
      only when UI state actually changes.
    • Demo behavior: Move events redraw only on
      MarkdownEvent::TocHoverChanged { .. }
      .
    • Effect: Avoids redraw storms and keeps frame pacing stable.
  3. Use differential handling for move vs non-move mouse events
    • Pattern: Treat clicks/wheel/drag as higher-value events and redraw immediately; aggressively filter move-only noise.
    • Effect: Maintains interaction fidelity while reducing unnecessary render pressure.
  4. Bound periodic work with moderate tick rate
    • Pattern: Configure non-aggressive ticks and use tick handler for lightweight maintenance only.
    • Demo value:
      RunnerConfig { tick_rate: Duration::from_millis(250), .. }
      .
    • Effect: Reduces idle churn and avoids periodic tasks competing with interactive redraws.
  5. Persist heavy widget state outside draw loop
    • Pattern: Store all stateful structs in app state and mutate incrementally in event handlers.
    • Demo structures:
      ScrollState
      ,
      SourceState
      ,
      CacheState
      ,
      CollapseState
      ,
      ExpandableState
      ,
      GitStatsState
      ,
      VimState
      ,
      SelectionState
      ,
      DoubleClickState
      .
    • Effect: Prevents reallocation/reparse overhead on each frame and stabilizes render latency.
  6. Keep
    on_draw
    render-only
    • Pattern: Avoid heavy parsing, file reads, or expensive recomputation in
      on_draw
      ; do those on state transitions.
    • Effect: More predictable frame time and smoother UI under bursty input.
  1. 合并高频鼠标移动事件
    • 模式:收到
      MouseEventKind::Moved
      时,如果距离上次处理移动事件的时间过短则跳过处理
    • Demo取值:~24ms防护(
      last_move_processed.elapsed() < Duration::from_millis(24)
    • 效果:防止快速移动指针时运动事件占满队列
  2. 仅在状态发生有意义变更时才重绘
    • 模式:移动事件默认返回
      CoordinatorAction::Continue
      ;仅当UI状态实际变更时才返回
      Redraw
    • Demo行为:仅在
      MarkdownEvent::TocHoverChanged { .. }
      时移动事件才会触发重绘
    • 效果:避免重绘风暴,保持帧速率稳定
  3. 对移动和非移动鼠标事件做差异化处理
    • 模式:将点击/滚轮/拖拽视为高价值事件,立即重绘;对仅移动的噪声做严格过滤
    • 效果:保持交互保真度的同时减少不必要的渲染压力
  4. 用适中的tick频率限制周期性工作
    • 模式:配置非激进的tick频率,tick处理仅用于轻量级维护工作
    • Demo取值:
      RunnerConfig { tick_rate: Duration::from_millis(250), .. }
    • 效果:减少空闲损耗,避免周期性任务与交互式重绘竞争资源
  5. 将重的组件状态持久化在绘制循环外
    • 模式:将所有有状态的结构体存储在应用状态中,在事件处理中增量修改
    • Demo结构:
      ScrollState
      SourceState
      CacheState
      CollapseState
      ExpandableState
      GitStatsState
      VimState
      SelectionState
      DoubleClickState
    • 效果:避免每帧重新分配/解析的开销,稳定渲染延迟
  6. on_draw
    仅做渲染
    • 模式:避免在
      on_draw
      中做 heavy 解析、文件读取或昂贵的重计算;这些操作应在状态转换时执行
    • 效果:帧时间更可预测,在突发输入下UI更流畅

Event-loop blueprint to reuse in other apps

可在其他应用中复用的事件循环蓝图

  • Keyboard: early-return
    Continue
    for non-keydown; map only actionable keys to state changes, then redraw.
  • Mouse moved: coalesce by time window; update hover state; redraw only on meaningful diff.
  • Mouse non-moved: apply action (click/wheel/selection), then redraw.
  • Tick: run lightweight expirations/cleanup; redraw only when cleanup changed visible state.
  • Resize: redraw.
  • 键盘:非按键按下事件直接返回
    Continue
    ;仅将可操作的按键映射到状态变更,然后重绘
  • 鼠标移动:按时间窗口合并;更新悬停状态;仅在有意义的差异时才重绘
  • 非移动鼠标事件:执行对应操作(点击/滚轮/选择),然后重绘
  • Tick:运行轻量级过期/清理工作;仅当清理变更了可见状态时才重绘
  • 窗口大小调整:重绘

Porting checklist (copy into new feature work)

移植检查清单(可复制到新功能开发中)

  • Add
    last_move_processed: Instant
    to app state and time-gate move handling.
  • Ensure event handlers return
    Continue
    unless visible state changed.
  • Separate ephemeral notifications/cleanup into tick-driven maintenance.
  • Keep widget state persistent and mutate in place.
  • Verify smoothness under rapid mouse movement and continuous wheel scrolling.
  • 在应用状态中添加
    last_move_processed: Instant
    ,对移动处理做时间门控
  • 确保事件处理仅在可见状态变更时才不返回
    Continue
  • 将临时通知/清理工作分离到tick驱动的维护任务中
  • 保持组件状态持久化,原地修改
  • 验证在快速鼠标移动和连续滚轮滚动下的流畅度

Optional

可选内容

Additional Resources

额外资源

  • Examples: 23 examples in
    examples/
  • Just commands: Run
    just help
    for all available commands
  • Build:
    just build
    or
    cargo build -p ratkit --all-features
  • Test:
    just test
  • 示例
    examples/
    目录下有23个示例
  • Just 命令:运行
    just help
    查看所有可用命令
  • 构建
    just build
    cargo build -p ratkit --all-features
  • 测试
    just test

Version

版本

  • Current: 0.2.12
  • Rust: 1.70+
  • 当前版本:0.2.12
  • Rust版本要求:1.70+