GitHub - project-blinc/Blinc: A declarative, reactive UI system with first-class state machines, spring physics animations, and GPU-accelerated rendering

6 min read Original article ↗

Blinc

Build Status Tests Rust Version License

Blinc UI

A GPU-accelerated, cross-platform UI framework with a GPUI-inspired builder API, glassmorphism effects, spring physics animations, and native rendering on Desktop, Android, and iOS.

Features

  • GPU-Accelerated Rendering - SDF-based primitives via wgpu with automatic batching
  • Glassmorphism Effects - Apple-style vibrancy with backdrop blur and frosted glass
  • GPUI-Style Builder API - Declarative, chainable element builders (div(), text(), svg(), image())
  • Flexbox Layout - Powered by Taffy with 100+ Tailwind-style builder methods
  • Spring Physics - Interruptible animations with RK4 integration (Framer Motion quality)
  • Cross-Platform - Desktop (macOS, Windows, Linux), Android, iOS
  • Fine-Grained Reactivity - Signal-based state without VDOM overhead
  • State Machines - Harel statecharts for complex widget interactions
  • Image Support - PNG, JPEG, GIF, WebP, BMP with cross-platform asset loading
  • SVG Rendering - Vector graphics with fill/stroke support
  • Text Rendering - HarfBuzz shaping, glyph atlas, proper anchoring

Quick Start

Installation

# Build from source
git clone https://github.com/project-blinc/Blinc
cd Blinc
cargo build --release

Hello World

use blinc_app::prelude::*;
use blinc_app::windowed::WindowedApp;

fn main() -> Result<()> {
    WindowedApp::run(WindowConfig::default(), |ctx| {
        div()
            .w(ctx.width).h(ctx.height)
            .bg([0.1, 0.1, 0.15, 1.0])
            .flex_center()
            .child(
                text("Hello Blinc!")
                    .size(48.0)
                    .color([1.0, 1.0, 1.0, 1.0])
            )
    })
}

Glassmorphism Example

div()
    .w(ctx.width).h(ctx.height)
    .bg([0.2, 0.3, 0.5, 1.0])
    .flex_center()
    .child(
        // Glass card with backdrop blur
        div()
            .glass()
            .rounded(16.0)
            .p(24.0)
            .child(text("Frosted Glass").size(24.0))
            .child(text("With backdrop blur").size(14.0).color([0.8, 0.8, 0.8, 1.0]))
    )

Image Support

div()
    .w(400.0).h(300.0)
    .flex_center()
    .child(
        image("assets/photo.png")
            .w(200.0)
            .h(150.0)
            .rounded(8.0)
    )

Layout with Flexbox

div()
    .w_full().h_full()
    .flex_col()
    .gap(16.0)
    .p(24.0)
    .children([
        // Header
        div().h(60.0).bg([0.2, 0.2, 0.25, 1.0]).rounded(8.0),
        // Content area
        div()
            .flex_1()
            .flex_row()
            .gap(16.0)
            .children([
                div().w(200.0).bg([0.15, 0.15, 0.2, 1.0]).rounded(8.0), // Sidebar
                div().flex_1().bg([0.18, 0.18, 0.22, 1.0]).rounded(8.0), // Main
            ]),
        // Footer
        div().h(40.0).bg([0.2, 0.2, 0.25, 1.0]).rounded(8.0),
    ])

Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                           blinc_app                                  │
│          High-level API: BlincApp, WindowedApp, RenderContext        │
├─────────────────────────────────────────────────────────────────────┤
│  blinc_layout         │  blinc_gpu           │  blinc_paint          │
│  Flexbox (Taffy)      │  SDF Rendering       │  Canvas API           │
│  Element Builders     │  Glass/Blur          │  Paths/Shapes         │
│  RenderTree           │  MSAA                │  Transforms           │
├─────────────────────────────────────────────────────────────────────┤
│  blinc_text           │  blinc_svg           │  blinc_image          │
│  Font Loading         │  SVG Parsing         │  Image Decoding       │
│  Text Shaping         │  Vector Rendering    │  Texture Management   │
│  Glyph Atlas          │  Fill/Stroke         │  Cross-platform Load  │
├─────────────────────────────────────────────────────────────────────┤
│  blinc_core           │  blinc_animation     │  blinc_platform       │
│  Signals/Reactivity   │  Springs (RK4)       │  Window/Event Traits  │
│  State Machines       │  Keyframes           │  Input Events         │
│  Brush/Color Types    │  Timelines           │  Asset Loading        │
├─────────────────────────────────────────────────────────────────────┤
│     blinc_platform_desktop    │  blinc_platform_android  │   _ios   │
│     winit + wgpu              │  NDK + Vulkan            │  UIKit   │
└─────────────────────────────────────────────────────────────────────┘

Crates

Crate Description
blinc_app High-level app framework with windowed runner
blinc_core Reactive signals, state machines, brush types
blinc_layout Flexbox layout engine with GPUI-style builders
blinc_gpu GPU rendering: SDF shapes, glass effects, MSAA
blinc_paint Canvas/paint API for custom drawing
blinc_text Text shaping, font loading, glyph atlas
blinc_image Image loading and cross-platform assets
blinc_svg SVG parsing and rendering
blinc_animation Spring physics and keyframe animations
blinc_platform Cross-platform traits and asset loading
blinc_platform_desktop Desktop backend (winit)
blinc_platform_android Android backend (NDK)
blinc_platform_ios iOS backend (UIKit/Metal)
blinc_cli Command-line tooling

Builder API Reference

Layout Methods

// Size
.w(100.0)  .h(100.0)  .size(100.0, 100.0)
.w_full()  .h_full()  .w_auto()  .h_auto()
.min_w()   .max_w()   .min_h()   .max_h()

// Flexbox
.flex_row()    .flex_col()
.flex_center() .flex_1()
.justify_start() .justify_center() .justify_end() .justify_between()
.items_start()   .items_center()   .items_end()   .items_stretch()
.gap(16.0)     .gap_x(8.0)      .gap_y(8.0)

// Spacing
.p(16.0)    .px(8.0)    .py(8.0)
.pt(4.0)    .pb(4.0)    .pl(4.0)    .pr(4.0)
.m(16.0)    .mx(8.0)    .my(8.0)

Styling Methods

// Background
.bg([r, g, b, a])
.bg_gradient(Gradient::linear(...))
.glass()  .glass_light()  .glass_dark()

// Border & Corners
.rounded(8.0)
.border(1.0, [r, g, b, a])

// Shadow
.shadow_sm()  .shadow_md()  .shadow_lg()  .shadow_xl()

// Opacity & Clipping
.opacity(0.8)
.clip()

Elements

div()                      // Container element
text("Hello")              // Text element
    .size(16.0)
    .color([1.0, 1.0, 1.0, 1.0])
    .anchor(TextAnchor::Center)

svg(svg_string)            // SVG element
    .w(24.0).h(24.0)

image("path/to/image.png") // Image element
    .w(200.0).h(150.0)
    .rounded(8.0)

Canvas API

Custom drawing with paths, shapes, and transforms:

Canvas API

use blinc_paint::prelude::*;

fn canvas_example() -> Canvas{
    canvas(move |ctx: &mut dyn DrawContext, bounds| {
        let bar_height = 20.0;
        let bar_y = (bounds.height - bar_height) / 2.0;
        let radius = CornerRadius::uniform(bar_height / 2.0);

        // Background track
        ctx.fill_rect(
            Rect::new(0.0, bar_y, bounds.width, bar_height),
            radius,
            Brush::Solid(Color::rgba(0.2, 0.2, 0.25, 1.0)),
        );

        // Progress fill with gradient
        let fill_width = bounds.width * progress.clamp(0.0, 1.0);
        if fill_width > 0.0 {
            let gradient = Brush::Gradient(Gradient::linear(
                Point::new(0.0, bar_y),
                Point::new(fill_width, bar_y),
                Color::rgba(0.4, 0.6, 1.0, 1.0),
                Color::rgba(0.6, 0.4, 1.0, 1.0),
            ));
            ctx.fill_rect(
                Rect::new(0.0, bar_y, fill_width, bar_height),
                radius,
                gradient,
            );
        }

        // Progress percentage indicator with text
        let percent = (progress * 100.0) as i32;
        let text_x = bounds.width / 2.0 - 15.0;
        let text_bg = Rect::new(text_x - 5.0, bar_y - 25.0, 50.0, 18.0);
        ctx.fill_rect(
            text_bg,
            CornerRadius::uniform(4.0),
            Brush::Solid(Color::rgba(0.1, 0.1, 0.15, 0.9)),
        );

        // Draw the percentage text
        ctx.draw_text(
            &format!("{}%", percent),
            Point::new(text_x, bar_y),
            &TextStyle::new(18.0).with_color(Color::WHITE),
        );
    })
    .w(228.0)
    .h(80.0)
}

Animation

Blinc provides a comprehensive animation system with spring physics, keyframe animations, and declarative motion containers.

keyframe animations

Spring Animations

Spring physics animations with RK4 integration for natural, interruptible motion:

use blinc_animation::{AnimatedValue, SpringConfig};

// Create a spring-animated value
let mut position = AnimatedValue::new(0.0);

// Animate to a target with spring physics
position.animate_to(100.0, SpringConfig::default());

// Or use presets
position.animate_to(100.0, SpringConfig::snappy());   // Quick, responsive
position.animate_to(100.0, SpringConfig::bouncy());   // Playful bounce
position.animate_to(100.0, SpringConfig::smooth());   // Gentle, smooth

Keyframe Animations

Multi-keyframe animations with custom easing:

use blinc_animation::{AnimatedTimeline, AnimatedKeyframe, Easing};

let timeline = AnimatedTimeline::new()
    .keyframe(AnimatedKeyframe::new(0.0).opacity(0.0).scale(0.8))
    .keyframe(AnimatedKeyframe::new(0.5).opacity(1.0).scale(1.1))
    .keyframe(AnimatedKeyframe::new(1.0).opacity(1.0).scale(1.0))
    .duration_ms(500)
    .easing(Easing::EaseOutCubic);

Animation Presets

Built-in presets for common animations:

use blinc_animation::AnimationPreset;

// Fade animations
AnimationPreset::fade_in(300)
AnimationPreset::fade_out(200)

// Scale animations
AnimationPreset::scale_in(300)
AnimationPreset::scale_out(200)

// Bounce animations
AnimationPreset::bounce_in(500)
AnimationPreset::bounce_out(400)

// Pop (scale with overshoot)
AnimationPreset::pop_in(400)

// Slide animations
AnimationPreset::slide_in_left(300, 50.0)
AnimationPreset::slide_in_right(300, 50.0)
AnimationPreset::slide_in_top(300, 50.0)
AnimationPreset::slide_in_bottom(300, 50.0)

Motion Container

The motion() container provides declarative enter/exit animations:

use blinc_layout::prelude::*;

// Single element with enter/exit animations
motion()
    .fade_in(300)
    .scale_in(300)
    .fade_out(200)
    .child(
        div()
            .w(100.0).h(100.0)
            .bg([0.4, 0.7, 1.0, 1.0])
            .rounded(8.0)
    )

// Slide animations
motion()
    .slide_in(SlideDirection::Left, 400)
    .slide_out(SlideDirection::Right, 300)
    .child(panel)

// Custom animation presets
motion()
    .enter_animation(AnimationPreset::bounce_in(500))
    .exit_animation(AnimationPreset::fade_out(200))
    .child(modal)

Stagger Animations

Animate lists with staggered delays:

use blinc_layout::prelude::*;

// Forward stagger (first to last)
motion()
    .gap(8.0)
    .stagger(StaggerConfig::new(50, AnimationPreset::fade_in(300)))
    .children(items.iter().map(|item| card(item)))

// Reverse stagger (last to first)
motion()
    .stagger(StaggerConfig::new(50, AnimationPreset::fade_in(300)).reverse())
    .children(items)

// From center outward
motion()
    .stagger(StaggerConfig::new(50, AnimationPreset::fade_in(300)).from_center())
    .children(items)

// Limit stagger delay (cap at N items)
motion()
    .stagger(StaggerConfig::new(50, AnimationPreset::fade_in(300)).limit(5))
    .children(items)

Easing Functions

use blinc_animation::Easing;

Easing::Linear
Easing::EaseIn
Easing::EaseOut
Easing::EaseInOut
Easing::EaseInCubic
Easing::EaseOutCubic
Easing::EaseInOutCubic
Easing::EaseOutBack      // Overshoot
Easing::EaseOutBounce    // Bounce effect

Platform Support

Platform Status Backend
macOS Stable wgpu (Metal)
Windows Stable wgpu (DX12/Vulkan)
Linux Stable wgpu (Vulkan)
Android Stable wgpu (Vulkan), ~530KB
iOS In Progress wgpu (Metal)

Roadmap

Completed

  • GPU-accelerated SDF rendering
  • Glassmorphism with backdrop blur
  • GPUI-style builder API
  • Flexbox layout (Taffy)
  • Text rendering with shaping
  • SVG rendering
  • Image support with cross-platform loading
  • Spring physics animations
  • Keyframe animations with presets
  • Motion containers (enter/exit animations)
  • Stagger animations for lists
  • Reactive signals and state machines
  • Desktop and Android platforms

In Progress

  • iOS platform completion
  • Widget library (Button, Checkbox, Toggle, etc.)
  • Theming system

Future

  • Zyntax DSL - .blinc file syntax with compile-time optimization
  • Hot reload during development
  • Developer tools (inspector, animation debugger)
  • IDE integration (VS Code extension, LSP)

License

Apache License 2.0 - see LICENSE