@flytedan/flytebot-design-system
The flytedesk Design System's Media Planner UI kit, ported to a standalone, framework-agnostic-consumer npm package: React 18 + TypeScript components, tokens, and business-logic kits for flytedesk apps.
Install
pnpm add @flytedan/flytebot-design-system
react and react-dom (^18.3.1) are peer dependencies.
Usage
Import the vendored CSS once, near your app's entry point, then use components directly:
import "@flytedan/flytebot-design-system/styles/tokens.css";
import "@flytedan/flytebot-design-system/styles/foundations.css";
import "@flytedan/flytebot-design-system/styles/components.css";
// foundations.css also imports icons.css (the Phosphor icon font every
// component's `<i className="ph ph-*">` needs) — no separate link required.
import { Button, Card, DataTable } from "@flytedan/flytebot-design-system";
function Example() {
return (
<Card>
<Button variant="primary">Save</Button>
</Card>
);
}
Design principles
DESIGN-PRINCIPLES.md holds the UI design and interaction rules every
Flytedesk app follows. It ships in the package, so an app reads it at
node_modules/@flytedan/flytebot-design-system/DESIGN-PRINCIPLES.md, and the
docs site shows it under Guides. Read it before designing or building a screen.
What's in the package
32 core components across seven groups — actions (Button, IconButton, SegmentedControl, Popover, Menu, MenuButton), forms (Input, NumberInput, Textarea, Select, DatePicker, TimePicker, Checkbox, Radio, Switch, Slider, RangeSlider, FileGrid, Dropzone, MarkdownEditor, CodeEditor), surfaces (Card, CardRow, Collapsible, Modal, Drawer), data (DataTable, FactList, Pagination, SortMenu, StatTile, Meter, CsiBadge, CsiMeter, CsiHero, Markdown, CodeBlock, DiffBlock, StepList, SegmentedMeter, QuotaRow, Clamp, RelativeTime), feedback (Badge, Tag, Avatar, AvatarStack, Flag, Toast, Tooltip, EmptyState, KeyHint), loading (Skeleton, SkeletonText, ReservedSkeleton, LoadingRegion, Spinner, ProgressBar), and navigation (Tabs, SidebarNav, Topbar).
Platform components for identity/session UI — AccountMenu, ApiSpecBrowser, Gate/FeatureGate/PermissionDenied/PermissionHint, ProfilePage, ComingSoon, RoadmapTimeline, ModeSwitch/TestModeBar.
Planner components for media-planning UIs — SaturationDistribution, MixGap, ChannelContribution, SurroundSound, BudgetReallocator, ChannelMeta.
Chat components — AgentChatPanel, ChatComposer, ChatSessionBar, ChatTranscript, ChatTurn, chatEngine.
Business-logic kits (framework-light, no UI) — SessionKit (roles,
permissions, feature flags), QueryKit (paged/sorted/filtered list state via
useServerTable), RuntimeKit (feature-completeness/live-vs-test derivation),
FileKit, MockJobKit ({ jobId } → poll async job simulation), VersionKit
(append-only version history stores).
Every export has its own documented page — props transcribed from the real TypeScript interfaces, a live interactive example, and a usage snippet — in the docs site included in this repo (not yet published as a hosted site):
git clone [email protected]:Flytedesk/flytebot-design-system.git
cd flytebot-design-system
pnpm install
pnpm run docs
CodeEditor edits SQL by default; language="json" adds JSON highlighting, bracket
matching and indentation on Enter, shows the parser's syntax error at its line and
column, and takes validate={(text) => diagnostics} for the caller's own checks
(for example a schema path such as spec.model).
Development
pnpm run build # tsup — emits dist/{index.js,index.cjs,index.d.ts}
pnpm run typecheck # tsc --noEmit
pnpm run lint # eslint .
pnpm run test # vitest run — needs no build
pnpm run test:dist # tsup, then the checks of the built dist/ (scripts/vitest.dist.config.ts)
Releasing
There is no publish CI. Releases are manual and run only from a dedicated deploy clone — never hand-published from a working checkout, which could ship whatever a builder happens to be mid-edit on.
One-time setup, once per machine:
git clone [email protected]:Flytedesk/flytebot-design-system.git C:/Users/newms/deploy/flytebot-design-system
cd C:/Users/newms/deploy/flytebot-design-system
touch .deploy-clone-marker # git-ignored; scripts/release.sh refuses to run without it
Then, for every release:
cd C:/Users/newms/deploy/flytebot-design-system
bash scripts/release.sh <new-version> "<summary>"
scripts/release.sh:
- refuses to run anywhere except a directory carrying
.deploy-clone-marker; - refuses a dirty tree, and takes a
.release.lockso two runs can't overlap; - fetches
originand checks outorigin/main's exact tip — never unmerged work; - re-executes the
scripts/release.shit just checked out, handing over the lock, so every later step (gates, bump, publish) is the released commit's own script, never the one that was on disk before the checkout (bash reads a script from the file it opened). The second pass is marked byRELEASE_REEXEC_SHA, which carries the checked-out commit: it assertsHEADis that commit and skips the fetch and checkout; - installs with
pnpm install --frozen-lockfile; - runs the gates:
tsup, then straight away the checks of that build (vitest run --config scripts/vitest.dist.config.ts), thenvitest run,tsc --noEmit,tsc --noEmit -p tsconfig.docs.json, the docsvite build, andlintif the repo has that script; - refuses
<new-version>unless it is greater than both the working checkout'spackage.jsonversion and npm's currently publishedlatest; - bumps
package.json, commitschore(release): <new-version> — <summary>, and pushes (failing on a non-fast-forward); npm publishes (accountflytedan, via the existing~/.npmrc), then pushes tagv<new-version>;- prints
RESULT: sha=<sha> version=<new-version> status=publishedon success.
scripts/release.test.ts covers its guards (wrong directory, dirty tree,
held lock, missing/malformed version argument) and the re-execution (a fake
origin whose release.sh changed runs the new body; the second pass's HEAD
and lock checks) against throwaway git repos — no network, no real publish.
License
UNLICENSED — internal flytedesk use only.