Current State
The admin-ui already has a strong foundation for a reusable UI system.
Well-built primitives already exist:
Button (variants, sizes, loading, icons)
- full form component system (
TextField, SelectField, TagInputField, etc.)
- shared form hooks/utilities
Badge and status badge wrappers
This is not a “rewrite the design system” problem.
The main issue is fragmentation and a few weak primitives.
Main Problems
1. Modal is fragile
Modal.tsx currently uses:
- custom portals
- manual animations
- incomplete accessibility
cloneElement coupling
- timeout-based transitions
Recommendation:
Replace with @headlessui/react Dialog + Transition.
High ROI:
- accessibility
- focus management
- scroll locking
- cleaner implementation
2. Table is structurally limited
Table.tsx lacks:
- proper typing
- sorting ownership
- row selection
- virtualization
- sticky headers
- responsive behavior
Recommendation:
Introduce a new:
using:
@tanstack/react-table
@tanstack/react-virtual
while keeping old Table.tsx temporarily for migration.
3. Too many duplicate components
Examples:
DeleteButton
HeaderDeleteButton
- multiple select/dropdown implementations
- repeated status hook logic
Recommendation:
Consolidate around:
- shared
Button
- single
Combobox
- unified status helpers
4. No unified UI export surface
Components are scattered across multiple folders.
There is currently no:
entrypoint for downstream consumers.
This blocks reusable custom admin development.
5. Missing semantic design tokens
Components hardcode styles like:
bg-white dark:bg-slate-800
throughout the codebase.
Recommendation:
Add semantic tokens:
--surface-bg
--surface-fg
--surface-border
--surface-muted
--surface-accent
--surface-danger
to support:
- centralized dark mode
- branding
- white-label deployments
6. No proper component preview system
A styleguide already exists.
Recommendation:
Extend it instead of introducing Storybook initially.
Recommended Plan
- Create
src/components/ui/index.ts
- Re-export stable primitives
- Remove duplicate wrappers
- Build a canonical styleguide page
- Add centralized surface tokens
- Migrate components gradually
- Replace
Modal with Headless UI Dialog
- Introduce new
DataTable<T>
- Build one shared
Combobox
Expose UI primitives via:
"./ui": {
"import": "./dist/ui/index.js",
"types": "./dist/ui/index.d.ts"
}
This enables downstream apps/plugins to consume the admin UI system directly.
Unlocks
- extensibility
- custom admin builds
- plugin ecosystems
- white-label branding
- better long-term maintainability
Current State
The admin-ui already has a strong foundation for a reusable UI system.
Well-built primitives already exist:
Button(variants, sizes, loading, icons)TextField,SelectField,TagInputField, etc.)Badgeand status badge wrappersThis is not a “rewrite the design system” problem.
The main issue is fragmentation and a few weak primitives.
Main Problems
1. Modal is fragile
Modal.tsxcurrently uses:cloneElementcouplingRecommendation:
Replace with
@headlessui/reactDialog + Transition.High ROI:
2. Table is structurally limited
Table.tsxlacks:Recommendation:
Introduce a new:
using:
@tanstack/react-table@tanstack/react-virtualwhile keeping old
Table.tsxtemporarily for migration.3. Too many duplicate components
Examples:
DeleteButtonHeaderDeleteButtonRecommendation:
Consolidate around:
ButtonCombobox4. No unified UI export surface
Components are scattered across multiple folders.
There is currently no:
entrypoint for downstream consumers.
This blocks reusable custom admin development.
5. Missing semantic design tokens
Components hardcode styles like:
throughout the codebase.
Recommendation:
Add semantic tokens:
to support:
6. No proper component preview system
A styleguide already exists.
Recommendation:
Extend it instead of introducing Storybook initially.
Recommended Plan
src/components/ui/index.tsModalwith Headless UIDialogDataTable<T>ComboboxExpose UI primitives via:
This enables downstream apps/plugins to consume the admin UI system directly.
Unlocks