@financedistrict/apps-ui
v0.28.1
Published
Shared base-component library (Button, Input, Modal, DataTable, ...) — React + Tailwind v4, styled from @financedistrict/apps-tokens.
Readme
@financedistrict/apps-ui
The single shared base-component library for all FD apps (Prism, AI Assistant, Wallet
Manager, Launchpad). React 19 + Tailwind v4, styled through semantic design tokens from
@financedistrict/apps-tokens.
App-specific semantic components do not live here — they live in each app. A
Button is shared; a PaymentRow is Prism's. Compose app components from these base
components rather than forking one to restyle it.
Install
npm install @financedistrict/[email protected] @financedistrict/[email protected]Pin exact versions (no ^). Then load the tokens once from your app's CSS entry — the
components read the CSS variable contract but never import it themselves:
/* app's main CSS entry */
@import "@financedistrict/apps-ui/fonts.css";
@import "@financedistrict/apps-tokens/theme.css";No shared component uses it yet, but if your app wants the DS's hand-authored
utilities (currently just glass — a frosted surface, see
@financedistrict/apps-tokens's README), also load:
@import "@financedistrict/apps-tokens/utilities.css";Import components from their subpath, which keeps the bundle tree-shakeable:
import { Button } from "@financedistrict/apps-ui/button";
import { Label } from "@financedistrict/apps-ui/label";Theme switching is the .dark class on an ancestor (usually <html>). Because every
component is bound to the semantic token layer, tokened colors resolve per mode on their
own — app code needs no dark: variants.
AI agents / LLM consumers
Read llms.txt, which ships inside this tarball at
node_modules/@financedistrict/apps-ui/llms.txt. It carries the intended-usage rules
that types cannot express — most importantly the shape axis
(shape="default" | "branded"), which has one invariant (never mix shapes inside a
group), a set of defaults that are already correct when omitted (Buttons and Banners
default to branded; fields, dialogs and panels always stay default), and one judgment
call. It also carries the numbers-and-status canon: mono type for tabular figures,
uniform precision per column, and the rule that a negative delta gets destructive while
positive or flat gets the brand treatment — no green.
Working inside a repo with Claude Code? The fd-apps-ui skill bundles this catalog
plus a generated per-component prop reference.
Components
44 components in v0.28.1:
| component | import | what it is |
| ------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Accordion | @financedistrict/apps-ui/accordion | Compound accordion |
| Avatar | @financedistrict/apps-ui/avatar | The 32×32 user-initials badge used in every FD app header, realigned in v2 to the dark fleet badge |
| Banner | @financedistrict/apps-ui/banner | A promotional/announcement card surface |
| Button | @financedistrict/apps-ui/button | The shared action control, in five variations across three heights |
| ButtonGroup | @financedistrict/apps-ui/button-group | A row of sibling Buttons whose shape and size are uniform structurally rather than by memory, and which owns the… |
| Checkbox | @financedistrict/apps-ui/checkbox | Checkbox control |
| Chip | @financedistrict/apps-ui/chip | A small, inline, content-hugging pill used as a lightweight navigation/link affordance |
| ConfirmDialog | @financedistrict/apps-ui/confirm-dialog | The "are you sure?" preset |
| Dialog | @financedistrict/apps-ui/dialog | Compound modal dialog |
| FeatureCard | @financedistrict/apps-ui/feature-card | A single-row card linking to a feature or destination |
| FileCard | @financedistrict/apps-ui/file-card | A PRESENTATIONAL card for an attachment |
| Filter | @financedistrict/apps-ui/filter | A filter-chip dropdown |
| IdleWarningDialog | @financedistrict/apps-ui/idle-warning-dialog | The countdown popup for useIdleSession's warning phase |
| InlineSelect | @financedistrict/apps-ui/inline-select | A single-select styled as inline text |
| Input | @financedistrict/apps-ui/input | Text input |
| Label | @financedistrict/apps-ui/label | A small rounded-pill status badge |
| ListEditorRow | @financedistrict/apps-ui/list-editor-row | A presentational, fully-controlled row for editable lists |
| Menu | @financedistrict/apps-ui/menu | Compound action-dropdown menu |
| OverlayHeader | @financedistrict/apps-ui/overlay-header | The chrome band for a full-screen overlay flow |
| Pagination | @financedistrict/apps-ui/pagination | A minimal range pager |
| Panel | @financedistrict/apps-ui/panel | The card container + context provider |
| PrimaryTabs | @financedistrict/apps-ui/primary-tabs | Compound filled-chip primary tab bar |
| ProfileMenu | @financedistrict/apps-ui/profile-menu | The header account-menu preset |
| PropertyGrid | @financedistrict/apps-ui/property-grid | A property-grid row |
| Radio | @financedistrict/apps-ui/radio | Radio control |
| SearchBar | @financedistrict/apps-ui/search-bar | A search field composed from <Input> |
| Select | @financedistrict/apps-ui/select | A shared base select with a custom, portaled dropdown |
| SelectableFeatureCard | @financedistrict/apps-ui/selectable-feature-card | The Figma SelectableFeatureCard |
| SidebarItem | @financedistrict/apps-ui/sidebar-item | A single navigation row for the app sidebar |
| Skeleton | @financedistrict/apps-ui/skeleton | A bare loading-placeholder primitive |
| Spinner | @financedistrict/apps-ui/spinner | The standalone indeterminate loading ring |
| SuggestionChip | @financedistrict/apps-ui/suggestion-chip | A standalone interactive chip offering a suggested prompt or action |
| Switch | @financedistrict/apps-ui/switch | Switch control |
| SystemMessage | @financedistrict/apps-ui/system-message | An inline alert/message strip |
| TableCell | @financedistrict/apps-ui/table-cell | The atomic presentational cell for FD data tables |
| TableEmptyState | @financedistrict/apps-ui/table-empty-state | The empty state for a data table, as three stacked layers |
| TableHeader | @financedistrict/apps-ui/table-header | The column-header row for FD data tables |
| TableList | @financedistrict/apps-ui/table-list | The semantic list container for FD data/activity lists |
| TableTitle | @financedistrict/apps-ui/table-title | The per-column header band for column-major FD data tables |
| Tabs | @financedistrict/apps-ui/tabs | Compound underline-indicator Tabs |
| TextArea | @financedistrict/apps-ui/text-area | Multiline text field |
| Toast | @financedistrict/apps-ui/toast | The Figma Toast |
| TokenInput | @financedistrict/apps-ui/token-input | A domain-agnostic token / tag input |
| Tooltip | @financedistrict/apps-ui/tooltip | Compound tooltip |
Every component's props, variant axes and defaults are generated from source into
packages/components/plugin/skills/fd-apps-ui/references/<name>.md in the
design-system repo.
In an editor, the shipped .d.ts types are authoritative and carry the same JSDoc.
Shape-aware components
These take a shape prop; everything else is shape-intrinsic. The defaults are chosen to
be right, so omitting the prop is the correct call in almost every case — see llms.txt
before overriding one.
| tier | components | chamfer | default |
| ------------ | ---------------------------------------------------- | ------- | -------------------------------------------- |
| controls | Button, Input, Select, SearchBar, TokenInput, Filter | 8px | branded for Button, default for the rest |
| surfaces | Dialog, Panel, FeatureCard, SelectableFeatureCard | 16px | default |
| banner-scale | Banner | 24px | branded |
variation="ghost" has no fill, so the chamfer doesn't apply to it at all.
Fonts
This package doesn't own font loading — only the CSS variable contract that
@financedistrict/apps-tokens theme.css defines (--font-archivo,
--font-chakra-petch), which is all it actually reads (see
ADR-0008).
fonts.css is one optional way to satisfy that contract, using
@fontsource — self-hosted @font-face rules, no
compiler-specific transform, so it works identically under Vite, Next, a UMD build, or a
plain static HTML file with no build step. Importing the CSS registers the @font-face
rules and defines the two variables globally: no JS wrapper, no root-element className.
Any app is free to load these fonts a different way instead — a plain Google Fonts
<link>, next/font/google in a Next app's own root layout, whatever fits — as long as
it ends up defining the same two variable names.
Icons
Phosphor (regular + fill weights), passed in through
leftSlot / rightSlot:
import { PlusIcon } from "@phosphor-icons/react";
<Button leftSlot={<PlusIcon />}>Add beneficiary</Button>;FD-specific marks — the logo, currency symbols, chain and protocol icons — come from
@financedistrict/apps-icons and @financedistrict/apps-web3icons.
Consuming from a zero-build prototype (CDN)
The above covers the normal npm install + import path used by the four real apps.
Standalone HTML/JSX prototypes (Metacarbon's screen deliveries) consume a different build
of this same package — a UMD bundle loaded via <script src>, no bundler, global
window.FDAppsUI. See the
standalone prototype guide
for the exact index.html shape.
Contributing
Component authoring rules (the two-build constraint, why there's no CSS-in-JS, the RSC
boundary) and the implement→review workflow live in
CONTRIBUTING.md.
