PROJECT / 2025
Primitive UI Library
Flutter component library built from scratch using only CustomPaint, Canvas, and custom RenderBox — no high-level widgets. Ships with a Nextra docs site featuring live embedded demos.
- stack
- Flutter · Dart · CustomPaint · Canvas API · RenderBox · AnimationController · Next.js (docs) · Nextra 4 · Tailwind v4 · Pagefind
How it works
CustomPainter
draws every pixelRenderBox
its own layoutanimation
redraws every framedocs
live demos in Nextra
01 / Overview
Nine UI and layout components (cards, toggles, sliders, progress indicators, buttons, inputs, VStack/HStack/ZStack) implemented using only CustomPaint, GestureDetector, custom RenderBox subclasses, and AnimationController. Every component draws directly to the Canvas — no Column, Row, Stack, or Card widgets anywhere. The library is paired with a Nextra 4 docs site that embeds live Flutter demos via AppEmbed iframes alongside editable DartPad snippets, plus auto-generated API tables for each component's properties.
02 / Key features
- –Six UI components (Card, ToggleSwitch, Slider, CircularProgress, Button, Input) and three layout containers (VStack, HStack, ZStack), all rendered from primitives
- –Canvas-level rendering: shadows via drawShadow, color interpolation with Color.lerp, rounded rectangles with RRect, and MaskFilter.blur for depth
- –Custom multi-child RenderBox layout that handles flex factors, intrinsic sizing, and main/cross axis alignment without Flutter's built-in flex system
- –Implicit animations using AnimationController and TweenAnimationBuilder for smooth state transitions on toggles, elevation changes, and color shifts
- –Nextra 4 docs site with 20+ live AppEmbed demos, DartPad code snippets, API parameter tables, full-text search via Pagefind, and architecture explainers
- –Widget test suite covering tap behavior, state transitions, and edge cases across all components
03 / Challenges
- –Building flex layout from scratch — VStack/HStack needed two-pass constraint propagation, flex factor division, and intrinsic size computation without any of Flutter's layout helpers
- –Getting smooth animations on components that draw directly to Canvas, where you can't lean on widget-level animation helpers
- –Embedding live Flutter demos inside a static docs site without it feeling clunky or slow to load
04 / Solution
Each component uses CustomPainter subclasses for rendering and ContainerRenderObjectMixin for multi-child layout, with AnimationController driving interpolated canvas redraws. The docs site uses Nextra 4 with AppEmbed iframes pointing at compiled Flutter web snippets, so demos load independently of the docs build.
05 / Outcome
A working Flutter component library where every pixel is owner-drawn — useful as both a course deliverable (TDDC73, grade 5) and a reference for how Flutter's rendering pipeline works under the abstraction layer. The docs site at tddc73.vercel.app serves as a living showcase with interactive examples.