Blinc Documentation

repository·main·Indexed 19 days ago

https://github.com/project-blinc/blinc

A GPU-accelerated, cross-platform UI framework written in Rust for desktop, mobile, and web. It features a declarative Builder API, a fine-grained reactivity system with Signals, and a comprehensive animation system including spring physics, keyframes, and timelines. The ecosystem includes blinc_app for windowed and headless rendering, blinc_cli for build and development tooling, and blinc_cn, a shadcn/ui-style component library.

Tokens
331.2K
Snippets
951
Records
1.3K
Agent score
66%

What's inside Blinc

  1. What is Blinc?

    main

    Blinc is a GPU-accelerated, reactive UI framework for Rust. It uses a declarative, component-based approach to build high-performance user interfaces. Key characteristics include:

    • GPU-Accelerated Rendering: Powered by wgpu for smooth 60fps animations and complex visual effects.
    • Declarative UI: A fluent, composable API inspired by SwiftUI.
    • Reactive State: Automatic UI updates with fine-grained reactivity.
    • Spring Physics: Uses spring dynamics for natural, physics-based animations instead of fixed durations.
    • Cross-Platform Support: macOS, Windows, Linux, Android, iOS, and Web (WASM + WebGPU).
  2. Overview of Blinc Web Development

    main

    Blinc compiles to wasm32-unknown-unknown and runs inside a <canvas> element using wgpu's WebGPU backend, with a WebGL2 fallback. The web target is currently Tier 2 / preview, meaning it is functional and includes runnable examples, but lacks certain platform-specific features like touch input, IME, file dialogs, and accessibility support.

    Key capabilities include:

    • GPU Rendering: Uses the same SDF, batching, and 3D pipelines as desktop.
    • Input: Supports mouse, wheel, and keyboard via EventRouter.
    • Gestures: Supports DRAG and DRAG_END events.
    • Reactive State: Uses BlincContextState, State::set, and Stateful::on_state.
    • Animations: Spring physics and keyframes driven by requestAnimationFrame.
    • Async Setup: Use WebApp::run_with_async_setup for tasks like loading fonts or CSS before the first frame.
  3. Explore Blinc Feature Examples

    main

    The Blinc Example Gallery provides a comprehensive suite of demos showcasing various subsystems. Use these as references for implementing specific features:

    Core UI & Layout

    • blinc_cn Components: A scrollable grid of all available blinc_cn components.
    • Table Builder API: Declarative table creation via the TableBuilder API.
    • Text Input Widgets: Ready-to-use text input and text area elements using the layout API.
    • Scroll Container: Scroll widget with opt-in webkit-style behavior.
    • Overlay System: Infrastructure for modals, dialogs, and popovers.
    • Notch Menu Bar: macOS-style menu bar with notched dropdowns.

    Graphics & Shaders

    • @flow Shader System: Demonstrates the DAG-based shader system, including semantic step/chain/use patterns.
    • Fluid Surface: Combines @flow GPU shaders with pointer-query CSS-driven interaction.
    • Canvas Element: Custom GPU drawing using the canvas element.
    • GPU Pass End-to-End: Demonstrates the DrawContext::run_gpu_pass pattern for custom GPU logic.
    • Layer Effects: GPU-accelerated layer effects.
    • 3D Mesh Rendering: Rendering glTF models (e.g., DamagedHelmet) using the SceneKit3D renderer.

    Animation & Interaction

    • Stateful API: Timeline-based animations and signal-bound modifiers.
    • Sortable: Drag-based interactions using FSM-driven stateful containers.
    • Keyframe Animation: Using the canvas element for keyframe-based motion.
    • Pointer Query: CSS-driven continuous pointer query system.

    Specialized Elements

    • Rich Text Editor: Full editable editor with cursor, selection, and inline formatting.
    • Markdown Editor: Split-view markdown editor.
    • Code Element: Read-only code display and editable code editors.
    • Video Player: video_player widget integrated with blinc_media::VideoPlayer.
  4. Understand the blinc_debugger interface and features

    main

    The debugger provides a multi-pane interface for analyzing UI state and event history:

    • Element Tree: A hierarchical view of the UI. You can expand/collapse nodes, filter by element type, and toggle the visibility of hidden elements.
    • UI Preview: A visual representation of the UI with debug overlays (showing bounds, padding, and margins). Supports zooming, panning, and snapshot comparisons.
    • Inspector Panel: Displays detailed properties of the selected element, including its type, ID, bounds (x, y, width, height), style properties (background, border), layout properties (flex, padding, margin), and attached event handlers.
    • Event Timeline: A playback control area to step through recorded events. You can play, pause, jump to timestamps, and filter by event type.
  5. Design Principles of the Zyntax UI Framework

    main

    The Zyntax UI Framework is a next-generation UI DSL designed with the following core goals:

    1. Embeddable in Rust: Provides native performance using zero-cost abstractions.
    2. AOT-compilable via Zyntax: Leverages compiler infrastructure to produce native binaries.
    3. Fine-grained Reactivity: Implements reactive state management without the overhead of a Virtual DOM (VDOM).
    4. State Machine Powered: Integrates Finite State Machines (FSM) to manage complex widget transient states.
    5. Animation-first: Supports keyframe and spring physics animations comparable to Framer Motion.
  6. Implement lazy loading for images

    main

    For performance-heavy apps, use .lazy() to defer image decoding until the image intersects the viewport. This prevents unnecessary GPU uploads and decoding for off-screen content.

    Loading Strategies:

    • Eager (default): Load and decode immediately.
    • Lazy: Defer load until visible.

    Placeholder Types:

    • None: Empty until bitmap arrives.
    • Color(color): Solid color background via .placeholder_color(color).
    • Brush(brush): Gradients or other brushes via .placeholder_brush(brush).
    • Image(url): A low-res thumbnail or blur-hash via .placeholder_image(url). These are eagerly preloaded.
    • Skeleton: An animated shimmer band via .skeleton().

    Fade-in Behavior: Images fade in once the texture is ready. Use .fade_in(Duration) to set the duration, or .no_fade() to make the image pop in instantly.

    use blinc_layout::prelude::*;
    use std::time::Duration;
    
    // Example: Skeleton shimmer with custom fade
    img("photo.jpg")
        .lazy()
        .skeleton()
        .fade_in(Duration::from_millis(250))
        .w(300.0)
        .h(200.0)
  7. How QML-style architecture works

    main

    QML provides a declarative approach focused on property bindings and state machines:

    • Property Bindings: Declarative reactive connections that automatically update when dependencies change.
    • Signal/Slot System: A pattern for first-class event handling.
    • Built-in State Machine: Uses Harel's Statecharts (SCXML) for managing UI states.
    • Transitions: Seamlessly integrates animations with state changes.
    • Syntax: Uses a highly readable JSON-like object literal syntax.
    Rectangle {
        id: root
        width: parent.width * 0.8  // Reactive binding
        height: calculateHeight()
        
        states: [
            State { name: "pressed"; PropertyChanges { target: root; color: "red" } },
            State { name: "released"; PropertyChanges { target: root; color: "blue" } }
        ]
        
        transitions: [
            Transition { from: "released"; to: "pressed"; NumberAnimation { property: "opacity" } }
        ]
    }
  8. Use Zyntax UI reactivity and animation primitives

    main

    Within a .zui file, you can use several specialized decorators to manage UI logic:

    • @prop: Defines a field in the widget struct (e.g., @prop name: Type = default).
    • @state: Creates a fine-grained signal (e.g., @state name: Type = expr). This compiles to a zui_signal_create_* call.
    • @derived: Creates a derived signal that recomputes when its dependencies change (e.g., @derived name: Type = expr).
    • @machine: Defines a Harel State Machine (FSM) with states, guards, and actions.
    • @spring: Defines a spring-based animation for smooth transitions (e.g., @spring name { stiffness: N, damping: N, target: expr }).
    • @animation: Defines a keyframe-based animation with a duration and easing.
    • @render: Defines the UI tree structure using widget calls.
  9. How reactive state works with use_state_keyed

    main

    To create reactive state that persists across UI rebuilds, use ctx.use_state_keyed(key, init_fn). The key is a string that identifies the state, and init_fn is a closure that returns the initial value. This returns a State<T> object which can be used to read, update, or pass as a dependency to stateful elements.

    fn build_ui(ctx: &WindowedContext) -> impl ElementBuilder {
        // Create keyed state for the count - persists across rebuilds
        let count = ctx.use_state_keyed("counter", || 0i32);
    
        // ...
    }
  10. How the Node Editor works in Blinc

    main

    The Blinc node editor is built on several core architectural principles that allow for extensible and type-safe graph editing:

    • Metadata-driven Node Rendering: Nodes are not hardcoded. Instead, they render based on declarative NodeTemplates. To add a new node type to the editor, you simply define and provide a new template.
    • Generic Port Compatibility: The editor is generic over the PortKind. Users implement the PortKind trait for their own custom port-type enums. Compatibility between ports (e.g., connecting an output to an input) is delegated to the implementation of PortKind::compatible_with.
    • Theme-aware UI: The editor's chrome (background, header, borders, badges) is driven by ThemeState. Switching theme bundles automatically updates visual tokens such as squircle profiles, shadows, typography, and spacing.
    • Canvas Interactions: The editor inherits pan, zoom, and selection capabilities from blinc_canvas_kit.
    • Grouping: Nodes can be wrapped in groups, which support status badges in the header.
  11. Use CSS-First Styling for Blinc UI

    main

    Blinc recommends a CSS-First approach for all styling and layout. This provides consistency, automatic handling of hover/focus/disabled states, and seamless theme integration via CSS variables.

    Best Practices:

    • Prefer CSS for layout, colors, and states (hover, active, etc.).
    • Use Builder Methods (e.g., .bg(), .w()) only for truly dynamic runtime values computed from signals.
    • Avoid direct builder calls when a CSS class or ID selector can achieve the same result.

    Specificity Order (Low to High):

    1. CSS stylesheets (ctx.add_css()) — Lowest priority
    2. css! / style! macros (inline styles)
    3. Builder methods (e.g., .bg()) — Highest priority, overrides CSS
    // Example of the preferred pattern
    let mut css_loaded = false;
    
    WindowedApp::run(config, move |ctx| {
        if !css_loaded {
            ctx.add_css(r"#my-card { background: #1e293b; }");
            css_loaded = true;
        }
        build_ui(ctx)
    });
  12. Understand the Zyntax UI compilation and linking flow

    main

    Zyntax UI follows a multi-stage compilation process that decouples the DSL from the UI implementation:

    1. Parsing: The .zui file is parsed using the zui.zyn grammar.
    2. TypedAST Generation: The grammar emits a standard TypedAST containing structs, functions, and call_expr nodes.
    3. Compilation: Zyntax compiles the TypedAST into High-Level Intermediate Representation (HIR) and then into native code.
    4. Extern Marking: All zui_* function calls are marked as extern symbols. Zyntax itself has no intrinsic knowledge of UI concepts.
    5. Linking: The resulting binary is linked against the zyntax_ui ZRTL plugin, which provides the actual implementations for all zui_* functions.
    6. Runtime: The plugin initializes the GPU renderer (wgpu/Metal/SDFs) and the event loop.