@fair-md/ui
v0.3.0
Published
Shared MD platform UI kit: shadcn/Radix primitives, product-level surfaces, design tokens, Tailwind preset, cn(), and an optional OIDC auth factory. Leaf package — it imports nothing from either app.
Downloads
383
Maintainers
Readme
@fair-md/ui
Shared UI kit for the MD platform: shadcn/Radix primitives, product-level layout
components, design tokens, and cn().
Per FRONTEND_SPEC.md §6 it lives here in the mdjourney repo and is published to npm as
@fair-md/ui; mdindex consumes the published package. mdjourney stays standalone-deployable
using this package. An eventual umbrella repo can relocate packages/ui as-is.
The one rule
@fair-md/ui is a leaf. It imports nothing from mdjourney-webapp or any app. Apps
import from @fair-md/ui, never the reverse — so mdindex can depend on it without dragging in
app code or app-release coupling.
What's here
src/lib/cn.ts— thecn()Tailwind class merger.src/styles/tokens.css— the shared color/radius design tokens (:root+.dark).tailwind-preset.cjs— shared Tailwind color/radius/animation mapping.src/components/*.tsx— shadcn/Radix-style primitives:alert-dialog,badge,button,card,checkbox,collapsible,command,data-table,dialog,dropdown-menu,input,label,popover,progress,radio-group,scroll-area,select,separator,sheet,skeleton,switch,table,tabs,textarea,toast,toolbar, andtooltip.src/product/index.tsx— app-agnostic product components:AppSidebar,PageHeader,MetricCard,ProgressSummary,Timeline,LifecycleStepper,FormSectionNav,FieldStatusIcon, andUploadDialog.src/index.ts— the public barrel.
Component tiers
Use three tiers so new tools feel seamless without copying app code:
- Foundation:
Button,Input,Select,Dialog,ScrollArea,Table,Badge,Tooltip,Tabs,DropdownMenu,Popover,Sheet,Checkbox,Switch,RadioGroup,Toast, andCommand. - Product surfaces:
AppShell,Header,Panel,Sidebar,EmptyState,PageHeader,Toolbar,MetricCard,DataTable, andUploadDialog. - Domain-adjacent affordances:
StatusBadge, expressiveProgressindicators,ProgressSummary,Timeline,LifecycleStepper,FormSectionNav, andFieldStatusIcon.
Keep API clients, route state, schemas, and workflow-specific logic out of this package. Those belong in each app. Visual language and reusable interaction patterns belong here.
Building
npm run build emits:
dist/cjs— CommonJS for older toolchains.dist/esm— ESM for modern bundlers.dist/types— declarations.
The package exports the root barrel, component subpaths, ./product, ./auth,
./tokens.css, and ./tailwind-preset.
Publishing (npm)
Published publicly as @fair-md/ui under the fair-md scope. Current version:
0.3.0 (see CHANGELOG.md).
- Automated (CD): bump
versioninpackages/ui/package.json→ merge tomain.ui-auto-tag.ymltagsui-vX.Y.Zand dispatchesui-release.yml, which builds +npm publishes. One-time: add theNPM_TOKENrepo secret (automation token with publish rights to@fair-md); thenpmGitHub environment gates the job. - Manual:
cd packages/ui && npm install && npm publish(prepublishOnlybuilds; access ispublic).
Consuming
npm install @fair-md/uiThen, per consumer:
- Import tokens once before Tailwind:
@import '@fair-md/ui/tokens.css'; - Use the Tailwind preset:
presets: [require('@fair-md/ui/tailwind-preset')] - Add package classes to Tailwind content:
content: [..., './node_modules/@fair-md/ui/dist/**/*.{js,mjs}']. - Import from the barrel or subpaths:
import { Button } from '@fair-md/ui'orimport { Button } from '@fair-md/ui/button'. - Product-level components are available from
@fair-md/ui/product.
mdjourney-webapp is wired for local package development: it depends on
file:../packages/ui, its Tailwind content scans ../packages/ui/src, and the package has
prepare so the built dist is refreshed when installed. For external tools, consume the
published @fair-md/ui package instead of the local file: dependency.
mdindex is the remaining consumer: install @fair-md/ui, import tokens.css, and render
the shared primitives (FAIR badges, Exports affordances) identically to mdjourney.
Tokens
@import '@fair-md/ui/tokens.css'; before the app's Tailwind layers. Apps should prefer
overriding tokens only when they need product-specific branding. Do not duplicate the full
:root / .dark block in consumers.
