designs / gpui
The desktop (GPUI) variant of the Fluid Attacks design system. The web variant
in designs/src is the source of truth; this workspace projects its tokens and
components onto gpui for Rust desktop apps
(common/mrq today, signals when it migrates).
Layout
Follows the federated Rust standard (common/utils/rust):
crates/domain—fluidattacks-designs-domain: the design tokens and per-component styling decisions, pure andno_std, usable from any toolkit on any platform. Grows one component at a time; the web files each module mirrors are named in its docs.crates/shell—fluidattacks-designs: the GPUI widgets over those tokens. macOS-gated with their toolkit for now, mirroring mrq (gpui's Linux build needs a native windowing stack the Linux CI runners don't carry).
Catalog
cargo run --example gallery opens the native component catalog (macOS). A
browser gallery in the spirit of gpui-component's
story-web (gpui compiled to wasm) is the intended long-term storybook
equivalent; it stays out of scope until gpui's wasm backend ships in a
crates.io release, because the federated cargo-deny policy pins all
dependencies to crates.io (allow-git = []).
Fonts
nix build .#designs-gpui-fonts materializes the design system's faces (Roboto,
Space Mono) hermetically, and the gpui dev shell exports the directory as
FLUIDATTACKS_DESIGNS_FONTS for the gallery to read.
Delivering the faces is the app's job: Theme::init(mode, cx, faces) registers
the bytes you hand it and reads no directory of its own. Bundling and signing
font files is a packaging concern, and a library that resolved them from a path
would force every consumer to reproduce this flake's environment. Pass &[] to
accept the platform fallback.
Icons and illustrations
Glyphs are FontAwesome Pro, so they live neither in git nor in the nix store
(whose cachix mirror is public) and cannot ship inside the published crate.
Illustrations carry no such licence, but they are fetched rather than versioned,
so they are absent from a checkout just the same. Assets resolves either from
FLUIDATTACKS_DESIGNS_ICONS / FLUIDATTACKS_DESIGNS_IMAGES when those
directories are present — the dev shell fetches the whole kit and the
illustration list there — and otherwise from a table the app baked in at compile
time.
To embed, a consuming app adds a build script:
emit_assets?;
which fetches nothing itself: it copies bytes out of
FLUIDATTACKS_DESIGNS_ICON_SRC and FLUIDATTACKS_DESIGNS_IMAGE_SRC, and fails
loudly if an asset is absent. It always includes icon::REQUIRED_ICONS and
empty_state::REQUIRED_IMAGES, the assets these components render themselves, so
the widgets work without the app enumerating them. The result is a binary that
needs no token, no network and no cache at runtime, which is what makes a
relocatable signed bundle possible. A miss at runtime is an Err, not a blank
square — so both kinds need embedding, not just glyphs.
Checks
Same jobs as every Rust component, from the designs flake:
nix run .#designs-gpui-lint— fmt, clippy, deny, machetenix run .#designs-gpui-conformance— federated config drift checknix run .#designs-gpui-test— nextest behind the coverage ratchetnix develop .#gpui— the Rust dev shell