@polderlabs/bizar 7.0.2 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +8 -0
- package/bizar-dash/DESIGN.md +729 -969
- package/bizar-dash/GLYPH.md +418 -0
- package/bizar-dash/PLAN.md +1135 -0
- package/bizar-dash/dist/assets/ActivityFeed-BRBtQOHB.js +6 -0
- package/bizar-dash/dist/assets/ActivityFeed-BRBtQOHB.js.map +1 -0
- package/bizar-dash/dist/assets/ActivityView-CwqhxBfh.js +1 -0
- package/bizar-dash/dist/assets/ActivityView-CwqhxBfh.js.map +1 -0
- package/bizar-dash/dist/assets/AgentActivity-6MxU-a9F.js +1 -0
- package/bizar-dash/dist/assets/AgentActivity-6MxU-a9F.js.map +1 -0
- package/bizar-dash/dist/assets/AgentsView-BYrOFdwl.js +8 -0
- package/bizar-dash/dist/assets/AgentsView-BYrOFdwl.js.map +1 -0
- package/bizar-dash/dist/assets/Badge-Cd61wsBa.js +1 -0
- package/bizar-dash/dist/assets/Badge-Cd61wsBa.js.map +1 -0
- package/bizar-dash/dist/assets/Card-C_bvqXdQ.js +1 -0
- package/bizar-dash/dist/assets/Card-C_bvqXdQ.js.map +1 -0
- package/bizar-dash/dist/assets/EmptyState-BWQuKnk9.js +1 -0
- package/bizar-dash/dist/assets/EmptyState-BWQuKnk9.js.map +1 -0
- package/bizar-dash/dist/assets/GoalsView-Dok0yt9S.js +11 -0
- package/bizar-dash/dist/assets/GoalsView-Dok0yt9S.js.map +1 -0
- package/bizar-dash/dist/assets/Grid-C62gCPqt.js +1 -0
- package/bizar-dash/dist/assets/Grid-C62gCPqt.js.map +1 -0
- package/bizar-dash/dist/assets/KanbanCard-CtTKP6ZX.js +21 -0
- package/bizar-dash/dist/assets/KanbanCard-CtTKP6ZX.js.map +1 -0
- package/bizar-dash/dist/assets/LibrariesView-BcyBQXiY.js +67 -0
- package/bizar-dash/dist/assets/LibrariesView-BcyBQXiY.js.map +1 -0
- package/bizar-dash/dist/assets/MemoryView-49wR4u-y.js +13 -0
- package/bizar-dash/dist/assets/MemoryView-49wR4u-y.js.map +1 -0
- package/bizar-dash/dist/assets/OverviewView-BtQ_UWYj.js +1 -0
- package/bizar-dash/dist/assets/OverviewView-BtQ_UWYj.js.map +1 -0
- package/bizar-dash/dist/assets/ProgressBar-CpvDeq9F.js +1 -0
- package/bizar-dash/dist/assets/ProgressBar-CpvDeq9F.js.map +1 -0
- package/bizar-dash/dist/assets/SettingsRow-DmIe5OUu.js +30 -0
- package/bizar-dash/dist/assets/SettingsRow-DmIe5OUu.js.map +1 -0
- package/bizar-dash/dist/assets/SettingsView-D1KmGWbi.js +48 -0
- package/bizar-dash/dist/assets/SettingsView-D1KmGWbi.js.map +1 -0
- package/bizar-dash/dist/assets/StatTile-BkIP32gG.js +11 -0
- package/bizar-dash/dist/assets/StatTile-BkIP32gG.js.map +1 -0
- package/bizar-dash/dist/assets/TasksView-Cba3GJ42.js +1 -0
- package/bizar-dash/dist/assets/TasksView-Cba3GJ42.js.map +1 -0
- package/bizar-dash/dist/assets/ViewHeader-D6c2cw1b.js +6 -0
- package/bizar-dash/dist/assets/ViewHeader-D6c2cw1b.js.map +1 -0
- package/bizar-dash/dist/assets/brain-DeoXNDE2.js +6 -0
- package/bizar-dash/dist/assets/brain-DeoXNDE2.js.map +1 -0
- package/bizar-dash/dist/assets/calendar-DRlQkGJc.js +6 -0
- package/bizar-dash/dist/assets/calendar-DRlQkGJc.js.map +1 -0
- package/bizar-dash/dist/assets/circle-check-DmYQ3vGp.js +6 -0
- package/bizar-dash/dist/assets/circle-check-DmYQ3vGp.js.map +1 -0
- package/bizar-dash/dist/assets/cmdk-BwN8hcKQ.js +80 -0
- package/bizar-dash/dist/assets/cmdk-BwN8hcKQ.js.map +1 -0
- package/bizar-dash/dist/assets/dnd-kit-DR2Qzzxk.js +5 -0
- package/bizar-dash/dist/assets/dnd-kit-DR2Qzzxk.js.map +1 -0
- package/bizar-dash/dist/assets/git-merge-OoqBKQer.js +6 -0
- package/bizar-dash/dist/assets/git-merge-OoqBKQer.js.map +1 -0
- package/bizar-dash/dist/assets/git-pull-request-CXBQTR2f.js +6 -0
- package/bizar-dash/dist/assets/git-pull-request-CXBQTR2f.js.map +1 -0
- package/bizar-dash/dist/assets/main-COdgjqbZ.css +1 -0
- package/bizar-dash/dist/assets/main-Cw6gybzS.js +109 -0
- package/bizar-dash/dist/assets/main-Cw6gybzS.js.map +1 -0
- package/bizar-dash/dist/assets/message-square-DUTeIQAR.js +6 -0
- package/bizar-dash/dist/assets/message-square-DUTeIQAR.js.map +1 -0
- package/bizar-dash/dist/assets/minus-CrStJTZ7.js +6 -0
- package/bizar-dash/dist/assets/minus-CrStJTZ7.js.map +1 -0
- package/bizar-dash/dist/assets/wrench-BJ1WIC4u.js +6 -0
- package/bizar-dash/dist/assets/wrench-BJ1WIC4u.js.map +1 -0
- package/bizar-dash/dist/{mobile.html → v8.html} +6 -9
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/bizar-dash/src/server/server.mjs +1 -57
- package/bizar-dash/src/web/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/bizar-dash/src/web/v8/App.tsx +188 -0
- package/bizar-dash/src/web/v8/__tests__/App.test.tsx +102 -0
- package/bizar-dash/src/web/v8/__tests__/AppShell.test.tsx +79 -0
- package/bizar-dash/src/web/v8/__tests__/PageSkeleton.test.tsx +12 -0
- package/bizar-dash/src/web/v8/__tests__/SettingsView.test.tsx +84 -0
- package/bizar-dash/src/web/v8/__tests__/Sidebar.test.tsx +95 -0
- package/bizar-dash/src/web/v8/__tests__/activity.test.tsx +63 -0
- package/bizar-dash/src/web/v8/__tests__/agents.test.tsx +90 -0
- package/bizar-dash/src/web/v8/__tests__/controls.test.tsx +135 -0
- package/bizar-dash/src/web/v8/__tests__/cx.test.ts +25 -0
- package/bizar-dash/src/web/v8/__tests__/data.test.tsx +293 -0
- package/bizar-dash/src/web/v8/__tests__/feedback.test.tsx +213 -0
- package/bizar-dash/src/web/v8/__tests__/goals.test.tsx +105 -0
- package/bizar-dash/src/web/v8/__tests__/kanban.test.tsx +176 -0
- package/bizar-dash/src/web/v8/__tests__/libraries.test.tsx +70 -0
- package/bizar-dash/src/web/v8/__tests__/memory.test.tsx +60 -0
- package/bizar-dash/src/web/v8/__tests__/navigation.test.tsx +137 -0
- package/bizar-dash/src/web/v8/__tests__/settings.test.tsx +104 -0
- package/bizar-dash/src/web/v8/__tests__/theme.test.tsx +98 -0
- package/bizar-dash/src/web/v8/__tests__/views.test.tsx +112 -0
- package/bizar-dash/src/web/v8/main.tsx +28 -0
- package/bizar-dash/src/web/v8/shell/AppShell.tsx +90 -0
- package/bizar-dash/src/web/v8/shell/PageSkeleton.tsx +29 -0
- package/bizar-dash/src/web/v8/shell/Sidebar.tsx +361 -0
- package/bizar-dash/src/web/v8/shell/StatusBar.tsx +63 -0
- package/bizar-dash/src/web/v8/shell/Topbar.tsx +113 -0
- package/bizar-dash/src/web/v8/shell/index.ts +15 -0
- package/bizar-dash/src/web/v8/ui/activity/ActivityFeed.tsx +137 -0
- package/bizar-dash/src/web/v8/ui/agents/AgentActivity.tsx +101 -0
- package/bizar-dash/src/web/v8/ui/agents/AgentCard.tsx +158 -0
- package/bizar-dash/src/web/v8/ui/controls/Button.tsx +141 -0
- package/bizar-dash/src/web/v8/ui/controls/ButtonGroup.tsx +32 -0
- package/bizar-dash/src/web/v8/ui/controls/Checkbox.tsx +49 -0
- package/bizar-dash/src/web/v8/ui/controls/Field.tsx +78 -0
- package/bizar-dash/src/web/v8/ui/controls/Form.tsx +23 -0
- package/bizar-dash/src/web/v8/ui/controls/IconButton.tsx +112 -0
- package/bizar-dash/src/web/v8/ui/controls/Input.tsx +94 -0
- package/bizar-dash/src/web/v8/ui/controls/RadioGroup.tsx +74 -0
- package/bizar-dash/src/web/v8/ui/controls/Select.tsx +171 -0
- package/bizar-dash/src/web/v8/ui/controls/Slider.tsx +68 -0
- package/bizar-dash/src/web/v8/ui/controls/Switch.tsx +56 -0
- package/bizar-dash/src/web/v8/ui/controls/Textarea.tsx +64 -0
- package/bizar-dash/src/web/v8/ui/controls/Toggle.tsx +36 -0
- package/bizar-dash/src/web/v8/ui/controls/ToggleGroup.tsx +85 -0
- package/bizar-dash/src/web/v8/ui/data/Accordion.tsx +134 -0
- package/bizar-dash/src/web/v8/ui/data/Avatar.tsx +175 -0
- package/bizar-dash/src/web/v8/ui/data/Badge.tsx +93 -0
- package/bizar-dash/src/web/v8/ui/data/BarList.tsx +101 -0
- package/bizar-dash/src/web/v8/ui/data/Card.tsx +140 -0
- package/bizar-dash/src/web/v8/ui/data/Chip.tsx +96 -0
- package/bizar-dash/src/web/v8/ui/data/Kbd.tsx +42 -0
- package/bizar-dash/src/web/v8/ui/data/ProgressBar.tsx +93 -0
- package/bizar-dash/src/web/v8/ui/data/Sparkline.tsx +98 -0
- package/bizar-dash/src/web/v8/ui/data/StatTile.tsx +150 -0
- package/bizar-dash/src/web/v8/ui/data/Table.tsx +170 -0
- package/bizar-dash/src/web/v8/ui/data/Timeline.tsx +130 -0
- package/bizar-dash/src/web/v8/ui/data/ViewHeader.tsx +122 -0
- package/bizar-dash/src/web/v8/ui/feedback/Alert.tsx +95 -0
- package/bizar-dash/src/web/v8/ui/feedback/Banner.tsx +39 -0
- package/bizar-dash/src/web/v8/ui/feedback/ContextMenu.tsx +143 -0
- package/bizar-dash/src/web/v8/ui/feedback/Dialog.tsx +149 -0
- package/bizar-dash/src/web/v8/ui/feedback/Drawer.tsx +8 -0
- package/bizar-dash/src/web/v8/ui/feedback/DropdownMenu.tsx +231 -0
- package/bizar-dash/src/web/v8/ui/feedback/EmptyState.tsx +48 -0
- package/bizar-dash/src/web/v8/ui/feedback/Popover.tsx +56 -0
- package/bizar-dash/src/web/v8/ui/feedback/Sheet.tsx +103 -0
- package/bizar-dash/src/web/v8/ui/feedback/Skeleton.tsx +67 -0
- package/bizar-dash/src/web/v8/ui/feedback/Spinner.tsx +30 -0
- package/bizar-dash/src/web/v8/ui/feedback/Toast.tsx +66 -0
- package/bizar-dash/src/web/v8/ui/feedback/Tooltip.tsx +89 -0
- package/bizar-dash/src/web/v8/ui/goals/GoalCard.tsx +176 -0
- package/bizar-dash/src/web/v8/ui/goals/KeyResult.tsx +115 -0
- package/bizar-dash/src/web/v8/ui/index.ts +322 -0
- package/bizar-dash/src/web/v8/ui/kanban/KanbanBoard.tsx +80 -0
- package/bizar-dash/src/web/v8/ui/kanban/KanbanCard.tsx +247 -0
- package/bizar-dash/src/web/v8/ui/kanban/KanbanColumn.tsx +181 -0
- package/bizar-dash/src/web/v8/ui/kanban/KanbanContextMenu.tsx +122 -0
- package/bizar-dash/src/web/v8/ui/kanban/KanbanQuickAdd.tsx +141 -0
- package/bizar-dash/src/web/v8/ui/libraries/LibraryGrid.tsx +30 -0
- package/bizar-dash/src/web/v8/ui/libraries/LibraryItem.tsx +161 -0
- package/bizar-dash/src/web/v8/ui/memory/MemoryVault.tsx +144 -0
- package/bizar-dash/src/web/v8/ui/navigation/CommandPalette.tsx +224 -0
- package/bizar-dash/src/web/v8/ui/navigation/NavLink.tsx +81 -0
- package/bizar-dash/src/web/v8/ui/navigation/Pagination.tsx +164 -0
- package/bizar-dash/src/web/v8/ui/navigation/Tabs.tsx +128 -0
- package/bizar-dash/src/web/v8/ui/navigation/useCommandPaletteHotkey.test.ts +79 -0
- package/bizar-dash/src/web/v8/ui/primitives/Box.tsx +144 -0
- package/bizar-dash/src/web/v8/ui/primitives/Center.tsx +40 -0
- package/bizar-dash/src/web/v8/ui/primitives/Cluster.tsx +67 -0
- package/bizar-dash/src/web/v8/ui/primitives/Grid.tsx +104 -0
- package/bizar-dash/src/web/v8/ui/primitives/Inline.tsx +77 -0
- package/bizar-dash/src/web/v8/ui/primitives/Portal.tsx +33 -0
- package/bizar-dash/src/web/v8/ui/primitives/ScrollArea.tsx +62 -0
- package/bizar-dash/src/web/v8/ui/primitives/Separator.tsx +42 -0
- package/bizar-dash/src/web/v8/ui/primitives/Stack.tsx +73 -0
- package/bizar-dash/src/web/v8/ui/primitives/VisuallyHidden.tsx +49 -0
- package/bizar-dash/src/web/v8/ui/settings/SettingsNav.tsx +91 -0
- package/bizar-dash/src/web/v8/ui/settings/SettingsRow.tsx +88 -0
- package/bizar-dash/src/web/v8/ui/settings/SettingsSection.tsx +109 -0
- package/bizar-dash/src/web/v8/ui/styles/globals.css +220 -0
- package/bizar-dash/src/web/v8/ui/styles/reset.css +57 -0
- package/bizar-dash/src/web/v8/ui/styles/tokens.css +217 -0
- package/bizar-dash/src/web/v8/ui/theme/DensityProvider.test.tsx +74 -0
- package/bizar-dash/src/web/v8/ui/theme/DensityProvider.tsx +66 -0
- package/bizar-dash/src/web/v8/ui/theme/ThemeProvider.test.tsx +86 -0
- package/bizar-dash/src/web/v8/ui/theme/ThemeProvider.tsx +94 -0
- package/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +88 -0
- package/bizar-dash/src/web/v8/ui/theme/useDensity.ts +15 -0
- package/bizar-dash/src/web/v8/ui/theme/useTheme.ts +16 -0
- package/bizar-dash/src/web/v8/ui/utils/cx.ts +19 -0
- package/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +33 -0
- package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +108 -0
- package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.test.tsx +142 -0
- package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +144 -0
- package/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +84 -0
- package/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +41 -0
- package/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +61 -0
- package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +92 -0
- package/bizar-dash/src/web/v8/views/Router.tsx +96 -0
- package/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +305 -0
- package/bizar-dash/src/web/v8/views/Tasks/CommandPalettePlaceholder.tsx +106 -0
- package/bizar-dash/src/web/v8/views/Tasks/TasksKanbanPlaceholder.tsx +62 -0
- package/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +74 -0
- package/bizar-dash/src/web/v8/vite-env.d.ts +15 -0
- package/bizar-dash/src/web/{mobile.html → v8.html} +4 -7
- package/bizar-dash/tests/settings-layout.test.tsx +2 -2
- package/bizar-dash/tests/settings-nav.test.tsx +6 -6
- package/bizar-dash/tests/setup.ts +26 -0
- package/bizar-dash/vite.config.ts +26 -2
- package/bizar-dash/vitest.config.ts +5 -3
- package/cli/provision-claude.mjs +108 -5
- package/package.json +36 -3
- package/bizar-dash/dist/assets/EnvVarsSection-BfhAz3ax.js +0 -114
- package/bizar-dash/dist/assets/EnvVarsSection-BfhAz3ax.js.map +0 -1
- package/bizar-dash/dist/assets/MobileChat-DLWdv6tQ.js +0 -1
- package/bizar-dash/dist/assets/MobileChat-DLWdv6tQ.js.map +0 -1
- package/bizar-dash/dist/assets/MobileSettings-Bxv62uPY.js +0 -1
- package/bizar-dash/dist/assets/MobileSettings-Bxv62uPY.js.map +0 -1
- package/bizar-dash/dist/assets/Toast-ATSAmbdi.js +0 -26
- package/bizar-dash/dist/assets/Toast-ATSAmbdi.js.map +0 -1
- package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js +0 -1
- package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js.map +0 -1
- package/bizar-dash/dist/assets/main-306CZfn6.js +0 -430
- package/bizar-dash/dist/assets/main-306CZfn6.js.map +0 -1
- package/bizar-dash/dist/assets/main-G3bNDpY3.css +0 -1
- package/bizar-dash/dist/assets/mobile-C_naUN91.js +0 -1
- package/bizar-dash/dist/assets/mobile-C_naUN91.js.map +0 -1
- package/bizar-dash/dist/assets/mobile-layout-BWLtwtfQ.css +0 -1
- package/bizar-dash/dist/assets/mobile-layout-GZ3bE8L6.js +0 -211
- package/bizar-dash/dist/assets/mobile-layout-GZ3bE8L6.js.map +0 -1
- package/bizar-dash/dist/assets/useSlashCommands-BOwD7lNb.js +0 -65
- package/bizar-dash/dist/assets/useSlashCommands-BOwD7lNb.js.map +0 -1
- package/bizar-dash/dist/index.html +0 -43
- package/bizar-dash/src/web/App.tsx +0 -915
- package/bizar-dash/src/web/MobileApp.tsx +0 -414
- package/bizar-dash/src/web/components/ArtifactCreateDialog.tsx +0 -95
- package/bizar-dash/src/web/components/ArtifactListDialog.tsx +0 -55
- package/bizar-dash/src/web/components/ArtifactViewer.tsx +0 -144
- package/bizar-dash/src/web/components/AuditDialog.tsx +0 -79
- package/bizar-dash/src/web/components/AutosaveField.tsx +0 -50
- package/bizar-dash/src/web/components/BackupRestore.tsx +0 -330
- package/bizar-dash/src/web/components/BgStatusBadge.tsx +0 -32
- package/bizar-dash/src/web/components/Button.tsx +0 -56
- package/bizar-dash/src/web/components/CanvasContextMenu.tsx +0 -68
- package/bizar-dash/src/web/components/Card.tsx +0 -40
- package/bizar-dash/src/web/components/CollapsibleSection.tsx +0 -72
- package/bizar-dash/src/web/components/CommandDialog.tsx +0 -66
- package/bizar-dash/src/web/components/DoctorPanel.tsx +0 -160
- package/bizar-dash/src/web/components/EmptyState.tsx +0 -30
- package/bizar-dash/src/web/components/EnvVarManager.tsx +0 -430
- package/bizar-dash/src/web/components/EvalDiff.tsx +0 -157
- package/bizar-dash/src/web/components/EvalExportButton.tsx +0 -27
- package/bizar-dash/src/web/components/EvalRunCard.tsx +0 -78
- package/bizar-dash/src/web/components/FileBrowser.tsx +0 -633
- package/bizar-dash/src/web/components/HeadroomSettings.tsx +0 -418
- package/bizar-dash/src/web/components/HeadroomStatus.tsx +0 -158
- package/bizar-dash/src/web/components/HelpDialog.tsx +0 -55
- package/bizar-dash/src/web/components/InviteDialog.tsx +0 -205
- package/bizar-dash/src/web/components/KillConfirmDialog.tsx +0 -88
- package/bizar-dash/src/web/components/MobileBottomNav.tsx +0 -38
- package/bizar-dash/src/web/components/MobileDrawer.tsx +0 -68
- package/bizar-dash/src/web/components/MobileHeader.tsx +0 -50
- package/bizar-dash/src/web/components/MobileLayout.tsx +0 -63
- package/bizar-dash/src/web/components/Modal.tsx +0 -215
- package/bizar-dash/src/web/components/Notifications.tsx +0 -242
- package/bizar-dash/src/web/components/ScheduleTemplateCard.tsx +0 -72
- package/bizar-dash/src/web/components/ScreenshotCapture.tsx +0 -138
- package/bizar-dash/src/web/components/ScreenshotOCR.tsx +0 -42
- package/bizar-dash/src/web/components/SearchModal.tsx +0 -227
- package/bizar-dash/src/web/components/SettingsNav.tsx +0 -112
- package/bizar-dash/src/web/components/SettingsSearch.tsx +0 -328
- package/bizar-dash/src/web/components/Sidebar.tsx +0 -89
- package/bizar-dash/src/web/components/Spinner.tsx +0 -19
- package/bizar-dash/src/web/components/StatusBadge.tsx +0 -56
- package/bizar-dash/src/web/components/Tag.tsx +0 -41
- package/bizar-dash/src/web/components/TailscaleSettings.tsx +0 -161
- package/bizar-dash/src/web/components/TaskCard.tsx +0 -69
- package/bizar-dash/src/web/components/TaskCreateSheet.tsx +0 -76
- package/bizar-dash/src/web/components/Toast.tsx +0 -150
- package/bizar-dash/src/web/components/Toggle.tsx +0 -31
- package/bizar-dash/src/web/components/Topbar.tsx +0 -410
- package/bizar-dash/src/web/components/UsageChart.tsx +0 -250
- package/bizar-dash/src/web/components/UsageTable.tsx +0 -90
- package/bizar-dash/src/web/components/VirtualList.tsx +0 -53
- package/bizar-dash/src/web/components/VisualPlanDialog.tsx +0 -58
- package/bizar-dash/src/web/components/VoiceNotesPanel.tsx +0 -211
- package/bizar-dash/src/web/components/VoiceRecorder.tsx +0 -105
- package/bizar-dash/src/web/components/WorkspaceSelector.tsx +0 -158
- package/bizar-dash/src/web/components/agents/CommunicationLog.tsx +0 -126
- package/bizar-dash/src/web/components/agents/DependencyGraph.tsx +0 -163
- package/bizar-dash/src/web/components/agents/QualityGates.tsx +0 -123
- package/bizar-dash/src/web/components/agents/RealTimeEventLog.tsx +0 -127
- package/bizar-dash/src/web/components/agents/RoutingDecisions.test.tsx +0 -148
- package/bizar-dash/src/web/components/agents/RoutingDecisions.tsx +0 -160
- package/bizar-dash/src/web/components/background/AttachButton.tsx +0 -96
- package/bizar-dash/src/web/components/background/TmuxAttachCard.tsx +0 -122
- package/bizar-dash/src/web/components/chat/AgentChip.tsx +0 -68
- package/bizar-dash/src/web/components/chat/AgentNode.tsx +0 -127
- package/bizar-dash/src/web/components/chat/AgentTree.tsx +0 -80
- package/bizar-dash/src/web/components/chat/ChatBubble.tsx +0 -60
- package/bizar-dash/src/web/components/chat/ChatComposer.tsx +0 -72
- package/bizar-dash/src/web/components/chat/ChatInfoPanel.tsx +0 -370
- package/bizar-dash/src/web/components/chat/ChatRail.tsx +0 -387
- package/bizar-dash/src/web/components/chat/ChatThread.tsx +0 -127
- package/bizar-dash/src/web/components/chat/ChatTopBar.tsx +0 -50
- package/bizar-dash/src/web/components/chat/Composer.tsx +0 -166
- package/bizar-dash/src/web/components/chat/ConfirmModal.tsx +0 -54
- package/bizar-dash/src/web/components/chat/EmptyState.tsx +0 -21
- package/bizar-dash/src/web/components/chat/FirstRunGreeting.tsx +0 -18
- package/bizar-dash/src/web/components/chat/FloatingComposer.tsx +0 -38
- package/bizar-dash/src/web/components/chat/InfoPanel.tsx +0 -184
- package/bizar-dash/src/web/components/chat/JumpToLatest.tsx +0 -58
- package/bizar-dash/src/web/components/chat/LoadingSkeleton.tsx +0 -19
- package/bizar-dash/src/web/components/chat/MessageBlock.tsx +0 -260
- package/bizar-dash/src/web/components/chat/MessageBubble.tsx +0 -60
- package/bizar-dash/src/web/components/chat/SessionList.tsx +0 -163
- package/bizar-dash/src/web/components/chat/SessionRowMenu.tsx +0 -206
- package/bizar-dash/src/web/components/chat/StreamingIndicator.tsx +0 -37
- package/bizar-dash/src/web/components/chat/SuggestionCards.tsx +0 -55
- package/bizar-dash/src/web/components/chat/WelcomeScreen.tsx +0 -36
- package/bizar-dash/src/web/components/chat/_legacy.ts +0 -30
- package/bizar-dash/src/web/components/chat/index.ts +0 -31
- package/bizar-dash/src/web/components/chat/useAutoGrowTextarea.ts +0 -18
- package/bizar-dash/src/web/components/chat/useChat.ts +0 -1190
- package/bizar-dash/src/web/components/chat/useSlashCommands.ts +0 -47
- package/bizar-dash/src/web/components/goals/GoalInput.tsx +0 -86
- package/bizar-dash/src/web/components/goals/PlanVisualization.tsx +0 -111
- package/bizar-dash/src/web/components/tasks/BacklogPanel.css +0 -109
- package/bizar-dash/src/web/components/tasks/BacklogPanel.tsx +0 -209
- package/bizar-dash/src/web/hooks/useAutosave.ts +0 -107
- package/bizar-dash/src/web/hooks/useI18n.ts +0 -13
- package/bizar-dash/src/web/index.html +0 -37
- package/bizar-dash/src/web/lib/api.ts +0 -237
- package/bizar-dash/src/web/lib/goapPlanner.ts +0 -614
- package/bizar-dash/src/web/lib/i18n.ts +0 -25
- package/bizar-dash/src/web/lib/logger.ts +0 -30
- package/bizar-dash/src/web/lib/markdown.tsx +0 -59
- package/bizar-dash/src/web/lib/search.ts +0 -115
- package/bizar-dash/src/web/lib/types.ts +0 -894
- package/bizar-dash/src/web/lib/utils.ts +0 -114
- package/bizar-dash/src/web/lib/ws.ts +0 -177
- package/bizar-dash/src/web/locales/en.json +0 -52
- package/bizar-dash/src/web/main.tsx +0 -43
- package/bizar-dash/src/web/mobile/MobileApp.tsx +0 -309
- package/bizar-dash/src/web/mobile/MobileBottomNav.tsx +0 -38
- package/bizar-dash/src/web/mobile/MobileChat.tsx +0 -138
- package/bizar-dash/src/web/mobile/MobileDoctor.tsx +0 -80
- package/bizar-dash/src/web/mobile/MobileEval.tsx +0 -167
- package/bizar-dash/src/web/mobile/MobileMemory.tsx +0 -108
- package/bizar-dash/src/web/mobile/MobileOverview.tsx +0 -213
- package/bizar-dash/src/web/mobile/MobileSettings.tsx +0 -251
- package/bizar-dash/src/web/mobile/MobileTasks.tsx +0 -94
- package/bizar-dash/src/web/mobile/MobileTopbar.tsx +0 -115
- package/bizar-dash/src/web/mobile/components/MobileBottomSheet.tsx +0 -182
- package/bizar-dash/src/web/mobile/components/MobileListItem.tsx +0 -64
- package/bizar-dash/src/web/mobile/components/MobileModal.tsx +0 -123
- package/bizar-dash/src/web/mobile/views/MobileActivity.tsx +0 -273
- package/bizar-dash/src/web/mobile/views/MobileAgents.tsx +0 -374
- package/bizar-dash/src/web/mobile/views/MobileArtifactCanvas.tsx +0 -439
- package/bizar-dash/src/web/mobile/views/MobileArtifacts.tsx +0 -143
- package/bizar-dash/src/web/mobile/views/MobileChat.tsx +0 -257
- package/bizar-dash/src/web/mobile/views/MobileConfig.tsx +0 -175
- package/bizar-dash/src/web/mobile/views/MobileHistory.tsx +0 -191
- package/bizar-dash/src/web/mobile/views/MobileMods.tsx +0 -149
- package/bizar-dash/src/web/mobile/views/MobileMore.tsx +0 -121
- package/bizar-dash/src/web/mobile/views/MobileNotifications.tsx +0 -137
- package/bizar-dash/src/web/mobile/views/MobilePlans.tsx +0 -26
- package/bizar-dash/src/web/mobile/views/MobileSchedules.tsx +0 -685
- package/bizar-dash/src/web/mobile/views/MobileSearchModal.tsx +0 -172
- package/bizar-dash/src/web/mobile/views/MobileSettings.tsx +0 -363
- package/bizar-dash/src/web/mobile/views/MobileSkills.tsx +0 -153
- package/bizar-dash/src/web/mobile/views/MobileTasks.tsx +0 -564
- package/bizar-dash/src/web/mobile/views/QrCodePanel.tsx +0 -69
- package/bizar-dash/src/web/mobile.tsx +0 -14
- package/bizar-dash/src/web/styles/agents-redesign.css +0 -311
- package/bizar-dash/src/web/styles/chat.css +0 -1740
- package/bizar-dash/src/web/styles/glyphs.css +0 -960
- package/bizar-dash/src/web/styles/main.css +0 -10391
- package/bizar-dash/src/web/styles/memory.css +0 -1182
- package/bizar-dash/src/web/styles/minimax-usage.css +0 -842
- package/bizar-dash/src/web/styles/mobile-chat.css +0 -5
- package/bizar-dash/src/web/styles/mobile-layout.css +0 -233
- package/bizar-dash/src/web/styles/mobile.css +0 -2181
- package/bizar-dash/src/web/styles/settings.css +0 -795
- package/bizar-dash/src/web/styles/skills.css +0 -302
- package/bizar-dash/src/web/styles/tasks-redesign.css +0 -253
- package/bizar-dash/src/web/styles/tasks.css +0 -605
- package/bizar-dash/src/web/ui/controls/Button.tsx +0 -77
- package/bizar-dash/src/web/ui/controls/Checkbox.tsx +0 -95
- package/bizar-dash/src/web/ui/controls/IconButton.tsx +0 -66
- package/bizar-dash/src/web/ui/controls/Kbd.tsx +0 -24
- package/bizar-dash/src/web/ui/controls/NumberInput.tsx +0 -77
- package/bizar-dash/src/web/ui/controls/RadioGroup.tsx +0 -109
- package/bizar-dash/src/web/ui/controls/SearchInput.tsx +0 -91
- package/bizar-dash/src/web/ui/controls/Select.tsx +0 -92
- package/bizar-dash/src/web/ui/controls/Slider.tsx +0 -70
- package/bizar-dash/src/web/ui/controls/TextInput.tsx +0 -67
- package/bizar-dash/src/web/ui/controls/Textarea.tsx +0 -56
- package/bizar-dash/src/web/ui/controls/Toggle.tsx +0 -79
- package/bizar-dash/src/web/ui/controls/controls.css +0 -476
- package/bizar-dash/src/web/ui/controls/index.ts +0 -35
- package/bizar-dash/src/web/ui/data/BarChart.tsx +0 -60
- package/bizar-dash/src/web/ui/data/DataTable.tsx +0 -216
- package/bizar-dash/src/web/ui/data/EmptyState.tsx +0 -60
- package/bizar-dash/src/web/ui/data/ErrorState.tsx +0 -56
- package/bizar-dash/src/web/ui/data/KeyValueList.tsx +0 -106
- package/bizar-dash/src/web/ui/data/LoadingState.tsx +0 -65
- package/bizar-dash/src/web/ui/data/Sparkline.tsx +0 -87
- package/bizar-dash/src/web/ui/data/StatTile.tsx +0 -87
- package/bizar-dash/src/web/ui/data/data.css +0 -535
- package/bizar-dash/src/web/ui/data/index.ts +0 -31
- package/bizar-dash/src/web/ui/feedback/Badge.tsx +0 -49
- package/bizar-dash/src/web/ui/feedback/Dialog.tsx +0 -209
- package/bizar-dash/src/web/ui/feedback/ProgressBar.tsx +0 -69
- package/bizar-dash/src/web/ui/feedback/StatusDot.tsx +0 -50
- package/bizar-dash/src/web/ui/feedback/Toast.tsx +0 -200
- package/bizar-dash/src/web/ui/feedback/Tooltip.tsx +0 -126
- package/bizar-dash/src/web/ui/feedback/feedback.css +0 -314
- package/bizar-dash/src/web/ui/feedback/index.ts +0 -43
- package/bizar-dash/src/web/ui/index.ts +0 -56
- package/bizar-dash/src/web/ui/layout/AppShell.tsx +0 -51
- package/bizar-dash/src/web/ui/layout/Breadcrumbs.tsx +0 -97
- package/bizar-dash/src/web/ui/layout/Panel.tsx +0 -73
- package/bizar-dash/src/web/ui/layout/PanelHeader.tsx +0 -39
- package/bizar-dash/src/web/ui/layout/Sidebar.tsx +0 -131
- package/bizar-dash/src/web/ui/layout/Tabs.tsx +0 -133
- package/bizar-dash/src/web/ui/layout/Topbar.tsx +0 -42
- package/bizar-dash/src/web/ui/layout/ViewHeader.tsx +0 -48
- package/bizar-dash/src/web/ui/layout/index.ts +0 -34
- package/bizar-dash/src/web/ui/layout/layout.css +0 -464
- package/bizar-dash/src/web/ui/navigation/CommandPalette.tsx +0 -199
- package/bizar-dash/src/web/ui/navigation/NavGroup.tsx +0 -95
- package/bizar-dash/src/web/ui/navigation/NavLink.tsx +0 -93
- package/bizar-dash/src/web/ui/navigation/index.ts +0 -17
- package/bizar-dash/src/web/ui/navigation/navigation.css +0 -343
- package/bizar-dash/src/web/ui/primitives/Box.tsx +0 -91
- package/bizar-dash/src/web/ui/primitives/Grid.tsx +0 -49
- package/bizar-dash/src/web/ui/primitives/Inline.tsx +0 -55
- package/bizar-dash/src/web/ui/primitives/Separator.tsx +0 -46
- package/bizar-dash/src/web/ui/primitives/Stack.tsx +0 -54
- package/bizar-dash/src/web/ui/primitives/VisuallyHidden.tsx +0 -26
- package/bizar-dash/src/web/ui/primitives/index.ts +0 -23
- package/bizar-dash/src/web/ui/primitives/primitives.css +0 -183
- package/bizar-dash/src/web/ui/styles/globals.css +0 -86
- package/bizar-dash/src/web/ui/styles/reset.css +0 -125
- package/bizar-dash/src/web/ui/styles/tokens.css +0 -208
- package/bizar-dash/src/web/ui/theme/ThemeProvider.tsx +0 -142
- package/bizar-dash/src/web/ui/theme/tokens.ts +0 -131
- package/bizar-dash/src/web/ui/theme/useTheme.ts +0 -22
- package/bizar-dash/src/web/ui/utils/cx.ts +0 -42
- package/bizar-dash/src/web/views/Activity.tsx +0 -1221
- package/bizar-dash/src/web/views/Agents.tsx +0 -964
- package/bizar-dash/src/web/views/Artifacts.tsx +0 -1494
- package/bizar-dash/src/web/views/BackgroundAgents.tsx +0 -822
- package/bizar-dash/src/web/views/Chat.tsx +0 -532
- package/bizar-dash/src/web/views/Config.tsx +0 -3
- package/bizar-dash/src/web/views/Doctor.tsx +0 -317
- package/bizar-dash/src/web/views/Eval.tsx +0 -372
- package/bizar-dash/src/web/views/EvalReport.tsx +0 -353
- package/bizar-dash/src/web/views/GoalPlanner.tsx +0 -158
- package/bizar-dash/src/web/views/Harness.tsx +0 -306
- package/bizar-dash/src/web/views/History.tsx +0 -353
- package/bizar-dash/src/web/views/Memory.tsx +0 -161
- package/bizar-dash/src/web/views/MiniMaxUsage.tsx +0 -942
- package/bizar-dash/src/web/views/ModView.tsx +0 -207
- package/bizar-dash/src/web/views/Mods.tsx +0 -706
- package/bizar-dash/src/web/views/Overview.tsx +0 -1364
- package/bizar-dash/src/web/views/Providers.tsx +0 -302
- package/bizar-dash/src/web/views/Schedules.tsx +0 -902
- package/bizar-dash/src/web/views/Settings.tsx +0 -308
- package/bizar-dash/src/web/views/Skills.tsx +0 -383
- package/bizar-dash/src/web/views/SpawnAgentModal.tsx +0 -221
- package/bizar-dash/src/web/views/Tasks.tsx +0 -789
- package/bizar-dash/src/web/views/Workspace.tsx +0 -294
- package/bizar-dash/src/web/views/glyphs/GlyphRenderer.tsx +0 -844
- package/bizar-dash/src/web/views/glyphs/components.tsx +0 -1098
- package/bizar-dash/src/web/views/memory/ConfigPanel.tsx +0 -426
- package/bizar-dash/src/web/views/memory/FromScreenshotPanel.tsx +0 -23
- package/bizar-dash/src/web/views/memory/GitSyncPanel.tsx +0 -220
- package/bizar-dash/src/web/views/memory/LightragPanel.tsx +0 -310
- package/bizar-dash/src/web/views/memory/MemoryGraphLegend.tsx +0 -29
- package/bizar-dash/src/web/views/memory/MemoryGraphPanel.tsx +0 -192
- package/bizar-dash/src/web/views/memory/MemoryGraphView.tsx +0 -336
- package/bizar-dash/src/web/views/memory/MemoryOverview.tsx +0 -367
- package/bizar-dash/src/web/views/memory/MemoryStatusCard.tsx +0 -160
- package/bizar-dash/src/web/views/memory/ObsidianPanel.tsx +0 -650
- package/bizar-dash/src/web/views/memory/SemanticSearchPanel.tsx +0 -197
- package/bizar-dash/src/web/views/memory/VaultFromClipboardPanel.tsx +0 -101
- package/bizar-dash/src/web/views/settings/ActivitySection.tsx +0 -205
- package/bizar-dash/src/web/views/settings/AgentSection.tsx +0 -305
- package/bizar-dash/src/web/views/settings/AuthSection.tsx +0 -159
- package/bizar-dash/src/web/views/settings/EnvVarsSection.tsx +0 -15
- package/bizar-dash/src/web/views/settings/GeneralSection.tsx +0 -128
- package/bizar-dash/src/web/views/settings/HeadroomSection.tsx +0 -39
- package/bizar-dash/src/web/views/settings/MemorySection.tsx +0 -154
- package/bizar-dash/src/web/views/settings/NetworkSection.tsx +0 -87
- package/bizar-dash/src/web/views/settings/NotificationsSection.tsx +0 -34
- package/bizar-dash/src/web/views/settings/SystemLlmSection.tsx +0 -81
- package/bizar-dash/src/web/views/settings/ThemeSection.tsx +0 -168
- package/bizar-dash/src/web/views/settings/UpdatesSection.tsx +0 -256
- package/bizar-dash/src/web/views/settings/WorkspacesSection.tsx +0 -189
package/bizar-dash/DESIGN.md
CHANGED
|
@@ -1,62 +1,56 @@
|
|
|
1
|
-
# DESIGN.md — Bizar Dashboard
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
>
|
|
7
|
-
>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
3. Document its data shape in §15.
|
|
33
|
-
4. Have a P0 entry in the checklist (§14) and pass it.
|
|
1
|
+
# DESIGN.md — Bizar Dashboard v8 (Dashboard Rewrite)
|
|
2
|
+
|
|
3
|
+
> **Scope.** This document replaces the v7.0.0 design system (F-040)
|
|
4
|
+
> and the in-progress mobile pass (F-041) in their entirety. The old
|
|
5
|
+
> dashboard, its `src/web/ui/` primitives, its Norse-pantheon dark
|
|
6
|
+
> aesthetic, its views, and its previous `DESIGN.md` are all **deleted**
|
|
7
|
+
> under the rewrite. v8 ships a new file tree, a new component
|
|
8
|
+
> library, a new theme, a new layout, and a new feature scope.
|
|
9
|
+
>
|
|
10
|
+
> **Read order.** If you only read three sections, read
|
|
11
|
+
> [§1 Principles](#1--principles), [§3 Tokens](#3--design-tokens), and
|
|
12
|
+
> [§7 Layout](#7--layout). Everything else is the supporting cast.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Table of contents
|
|
17
|
+
|
|
18
|
+
1. [Principles](#1--principles)
|
|
19
|
+
2. [Brand & voice](#2--brand--voice)
|
|
20
|
+
3. [Design tokens](#3--design-tokens)
|
|
21
|
+
4. [Typography](#4--typography)
|
|
22
|
+
5. [Spacing & layout](#5--spacing--layout)
|
|
23
|
+
6. [Motion & elevation](#6--motion--elevation)
|
|
24
|
+
7. [Layout](#7--layout)
|
|
25
|
+
8. [Component library](#8--component-library)
|
|
26
|
+
9. [Interaction patterns](#9--interaction-patterns)
|
|
27
|
+
10. [Settings model](#10--settings-model)
|
|
28
|
+
11. [Accessibility](#11--accessibility)
|
|
29
|
+
12. [Banned tropes](#12--banned-tropes)
|
|
30
|
+
13. [Visual contract for new screens](#13--visual-contract-for-new-screens)
|
|
31
|
+
14. [Pre-merge checklist](#14--pre-merge-checklist)
|
|
34
32
|
|
|
35
33
|
---
|
|
36
34
|
|
|
37
35
|
## 1 · Principles
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
1. **
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
2. **One accent, used with intent.** The accent
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
37
|
+
Five rules govern every visual decision. When in doubt, follow them
|
|
38
|
+
in order; if two conflict, the higher rule wins.
|
|
39
|
+
|
|
40
|
+
1. **Data first, chrome last.** Every pixel earns its place by
|
|
41
|
+
carrying information. Whitespace is spent on legibility, not
|
|
42
|
+
decoration. Density targets a desktop operator running two
|
|
43
|
+
external monitors — never a marketing screenshot.
|
|
44
|
+
2. **One accent, used with intent.** The accent is the green primary
|
|
45
|
+
token (`--accent`). It signals primary action, active state,
|
|
46
|
+
live data, and selection — nothing else. There is exactly one
|
|
47
|
+
accent across the entire product.
|
|
50
48
|
3. **State is signal, not decoration.** Active, streaming, awaiting,
|
|
51
|
-
error, success — every state must be distinguishable at a glance
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
sizes scale with container, not viewport. Long copy wraps pretty.
|
|
57
|
-
5. **Layout over chrome.** The sidebar is rail-thin. The topbar is one
|
|
58
|
-
row. The chat thread is the product. Chrome that doesn't pay rent
|
|
59
|
-
gets removed.
|
|
49
|
+
error, success, offline — every state must be distinguishable at a glance without reading copy. Weight, fill, motion, and shape are the four channels. **Never gradients.** Never `border-left` accent stripes on containers.
|
|
50
|
+
4. **Type does hierarchy.** A single sans family for UI, a single mono family for data. Size and weight carry the hierarchy; color is secondary. Tabular figures on every number.
|
|
51
|
+
5. **Native over invented.** The browser already has menus, focus rings, scrollbars, and shortcuts. We add right-click context menus, command palettes, and keyboard shortcuts that wrap the platform — we never replace it.
|
|
52
|
+
|
|
53
|
+
**Anti-target.** v7's Norse-pantheon, dark-by-default, accent-stripe look is rejected. v8 is light-by-default, dark-mode peer, single accent (green), gradient-free, dense by intent.
|
|
60
54
|
|
|
61
55
|
---
|
|
62
56
|
|
|
@@ -64,1089 +58,855 @@ them in order; if two conflict, the higher rule wins.
|
|
|
64
58
|
|
|
65
59
|
| | |
|
|
66
60
|
|--|--|
|
|
67
|
-
| **Wordmark** | Bizar
|
|
68
|
-
| **
|
|
69
|
-
| **Voice** | Direct, technical, never marketing.
|
|
70
|
-
| **Tab labels** | Single noun (`
|
|
71
|
-
| **Status copy** | "Streaming" not "Loading…". "
|
|
72
|
-
|
|
73
|
-
**Banned tropes** (audited before each PR):
|
|
74
|
-
|
|
75
|
-
- Aggressive purple gradient backgrounds behind text or as page chrome.
|
|
76
|
-
- Vertical accent stripes on containers (`box-shadow: inset 2px 0 0 …`,
|
|
77
|
-
`border-left: 3px solid …`). State-encoded or not. Active state uses
|
|
78
|
-
background, weight, glow, or motion — **never a left-edge bar**.
|
|
79
|
-
- Generic emoji icons in feature lists (✨ 🚀 🎯 ❓). Use Lucide.
|
|
80
|
-
- Inter as a display face for hero/section titles (Inter is body;
|
|
81
|
-
display uses larger sizes of the same family but tighter tracking).
|
|
82
|
-
- Filler copy: "Feature One", "Lorem ipsum", invented metrics.
|
|
61
|
+
| **Wordmark** | `Bizar` set in `Inter` SemiBold, 16px, `var(--fg)` |
|
|
62
|
+
| **Product glyph** | A minimal `ᛒ` (runic Berkanan) in `var(--accent)` for logo and favicon |
|
|
63
|
+
| **Voice** | Direct, technical, never marketing. Numbers with units. Inline code for IDs. |
|
|
64
|
+
| **Tab labels** | Single noun (`Tasks`, `Goals`, `Agents`). No emoji decorations. |
|
|
65
|
+
| **Status copy** | "Streaming" not "Loading…". "13 of 47" not "Lots". "Awaiting reply" not "Ready". |
|
|
66
|
+
| **Errors** | One sentence: what happened + one action the user can take. No "Oops!". |
|
|
83
67
|
|
|
84
68
|
---
|
|
85
69
|
|
|
86
|
-
## 3 ·
|
|
70
|
+
## 3 · Design tokens
|
|
87
71
|
|
|
88
|
-
All values
|
|
89
|
-
or external-tool interop.
|
|
72
|
+
All values live in `:root` (light) and `.dark` (dark) in `bizar-dash/src/web/ui/styles/tokens.css`. Components consume the CSS custom properties only — never raw color values. New tokens get added to this section **before** any component uses them.
|
|
90
73
|
|
|
91
|
-
|
|
74
|
+
The user-supplied shadcn preset theme is the source of truth for color tokens. Every other token (spacing, radius, motion, typography) is layered on top.
|
|
92
75
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
`--bg-1` and `--bg-2` from v6.x are deprecated; use `--bg-elev` and
|
|
103
|
-
`--bg-elev-2` instead. (The chat composer backdrop uses
|
|
104
|
-
`color-mix(in oklch, var(--bg-elev), black 12%)` for that nested feel.)
|
|
76
|
+
### 3.1 Surface scale
|
|
77
|
+
|
|
78
|
+
| Token | Light (oklch) | Dark (oklch) | Use |
|
|
79
|
+
|--|--|--|--|
|
|
80
|
+
| `--bg` | `oklch(1 0 0)` | `oklch(0.141 0.005 285.823)` | Page canvas |
|
|
81
|
+
| `--surface-1` | `oklch(1 0 0)` | `oklch(0.21 0.006 285.885)` | Cards, topbar, sidebar, dialogs |
|
|
82
|
+
| `--surface-2` | `oklch(0.967 0.001 286.375)` | `oklch(0.274 0.006 286.033)` | Nested surfaces, table rows, hover bg |
|
|
83
|
+
| `--surface-3` | `oklch(0.92 0.004 286.32)` | `oklch(0.37 0.013 285.805)` | Pressed, selected, drag-over |
|
|
84
|
+
| `--surface-popover` | `oklch(1 0 0)` | `oklch(0.21 0.006 285.885)` | Popovers, context menus, command palette |
|
|
105
85
|
|
|
106
|
-
### 3.2 Surface scale (light)
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
--bg oklch(98% 0.004 240) #f7f8fa
|
|
110
|
-
--bg-elev oklch(100% 0 0) #ffffff
|
|
111
|
-
--bg-elev-2 oklch(96% 0.006 240) #f0f3f8
|
|
112
|
-
--bg-elev-3 oklch(92% 0.008 240) #e6ebf2
|
|
113
|
-
--border oklch(90% 0.008 240) #e2e8f0
|
|
114
|
-
--border-strong oklch(82% 0.012 240) #cbd5e1
|
|
115
|
-
```
|
|
116
86
|
|
|
117
|
-
### 3.
|
|
118
|
-
|
|
119
|
-
| Token | Dark (OKLch) | Light (hex) | Use |
|
|
120
|
-
|---|---|---|---|
|
|
121
|
-
| `--text-strong` | `oklch(96% 0.005 240)` | `#0f172a` | Headings, primary content |
|
|
122
|
-
| `--text` | `oklch(82% 0.010 245)` | `#1f2937` | Body |
|
|
123
|
-
| `--text-dim` | `oklch(72% 0.012 245)` | `#475569` | Captions, metadata |
|
|
124
|
-
| `--text-on-accent` | `oklch(100% 0 0)` | `#ffffff` | Text over accent fills |
|
|
125
|
-
|
|
126
|
-
### 3.4 Brand accent
|
|
127
|
-
|
|
128
|
-
| Token | Dark | Light | Use |
|
|
129
|
-
|---|---|---|---|
|
|
130
|
-
| `--accent` | `oklch(0.62 0.18 273)` | `oklch(0.55 0.20 273)` | Primary action, active state, focus |
|
|
131
|
-
| `--accent-2` | `oklch(0.72 0.16 273)` | `oklch(0.48 0.20 273)` | Hover state on accent |
|
|
132
|
-
| `--accent-3` | `oklch(0.82 0.10 273)` | `oklch(0.40 0.18 273)` | Subdued accent text |
|
|
133
|
-
| `--accent-bg` | `color-mix(in oklch, var(--accent) 12%, transparent)` | same, 8% | Tinted panel backgrounds |
|
|
134
|
-
| `--accent-border` | `color-mix(in oklch, var(--accent) 40%, transparent)` | same, 30% | Tinted borders |
|
|
135
|
-
| `--accent-glow` | `color-mix(in oklch, var(--accent) 18%, transparent)` | same | Focus glow shadow |
|
|
136
|
-
| `--accent-soft` | `color-mix(in oklch, var(--accent) 8%, transparent)` | same, 6% | Hover wash on neutral surface |
|
|
137
|
-
|
|
138
|
-
**Accent budget.** Two uses per region, max. Default allocation:
|
|
139
|
-
1. Active nav item background OR primary CTA fill.
|
|
140
|
-
2. Active state badge OR streaming pill.
|
|
141
|
-
|
|
142
|
-
### 3.5 Status colors (OKLch in both themes)
|
|
143
|
-
|
|
144
|
-
| Token | Dark | Light | Use |
|
|
145
|
-
|---|---|---|---|
|
|
146
|
-
| `--success` | `oklch(0.72 0.16 145)` | `oklch(0.50 0.15 145)` | Streaming OK, task done, connected |
|
|
147
|
-
| `--warning` | `oklch(0.78 0.14 70)` | `oklch(0.55 0.15 70)` | Stuck agent, retry, cost spike |
|
|
148
|
-
| `--error` | `oklch(0.66 0.20 25)` | `oklch(0.52 0.20 25)` | Failed, deleted, auth error |
|
|
149
|
-
| `--info` | `oklch(0.72 0.13 235)` | `oklch(0.50 0.15 235)` | Neutral informational |
|
|
150
|
-
| `--success-soft` | `color-mix(in oklch, var(--success) 15%, transparent)` | same, 12% | Status pill bg |
|
|
151
|
-
| `--error-soft` | `color-mix(in oklch, var(--error) 12%, transparent)` | same, 10% | Error region bg |
|
|
152
|
-
| `--warning-soft` | `color-mix(in oklch, var(--warning) 15%, transparent)` | same, 10% | Warning region bg |
|
|
153
|
-
|
|
154
|
-
### 3.6 Derived tokens (chat overhaul, v3.21 — preserved)
|
|
87
|
+
### 3.2 Foreground scale
|
|
155
88
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
89
|
+
| Token | Light | Dark | Use |
|
|
90
|
+
|--|--|--|--|
|
|
91
|
+
| `--fg` | `oklch(0.141 0.005 285.823)` | `oklch(0.985 0 0)` | Primary text |
|
|
92
|
+
| `--fg-muted` | `oklch(0.552 0.016 285.938)` | `oklch(0.705 0.015 286.067)` | Secondary text, captions, helper |
|
|
93
|
+
| `--fg-subtle` | `oklch(0.705 0.015 286.067)` | `oklch(0.552 0.016 285.938)` | Tertiary, placeholder, disabled |
|
|
94
|
+
| `--fg-on-accent` | `oklch(0.982 0.018 155.826)` | `oklch(0.982 0.018 155.826)` | Text on `--accent` backgrounds |
|
|
95
|
+
| `--fg-link` | `var(--accent)` | `var(--accent)` | Inline links, breadcrumbs |
|
|
160
96
|
|
|
161
|
-
|
|
162
|
-
and **brand mark** (`ᛒ Bizar`) — never used elsewhere.
|
|
97
|
+
### 3.3 Accent (the only color that gets to be loud)
|
|
163
98
|
|
|
164
|
-
|
|
99
|
+
| Token | Light | Dark | Use |
|
|
100
|
+
|--|--|--|--|
|
|
101
|
+
| `--accent` | `oklch(0.527 0.154 150.069)` | `oklch(0.448 0.119 151.328)` | Primary buttons, active state, focus ring tint, live indicator |
|
|
102
|
+
| `--accent-hover` | `oklch(0.477 0.154 150.069)` | `oklch(0.398 0.119 151.328)` | Hover on `--accent` |
|
|
103
|
+
| `--accent-soft` | `color-mix(in oklch, var(--accent) 12%, transparent)` | same | Selected row tint, badge bg |
|
|
104
|
+
| `--accent-ring` | `color-mix(in oklch, var(--accent) 35%, transparent)` | same | Focus ring |
|
|
165
105
|
|
|
166
|
-
|
|
167
|
-
--syntax-key oklch(0.78 0.13 235)
|
|
168
|
-
--syntax-string oklch(0.84 0.10 235)
|
|
169
|
-
--syntax-number oklch(0.78 0.16 60)
|
|
170
|
-
--syntax-boolean oklch(0.68 0.20 25)
|
|
171
|
-
--syntax-null oklch(0.68 0.20 25)
|
|
172
|
-
```
|
|
106
|
+
### 3.4 Semantic colors
|
|
173
107
|
|
|
174
|
-
|
|
108
|
+
| Token | Light | Dark | Use |
|
|
109
|
+
|--|--|--|--|
|
|
110
|
+
| `--success` | `oklch(0.527 0.154 150.069)` | `oklch(0.723 0.219 149.579)` | Passed, succeeded, completed |
|
|
111
|
+
| `--warning` | `oklch(0.7 0.15 75)` | `oklch(0.75 0.15 75)` | Awaiting, paused, queued |
|
|
112
|
+
| `--danger` | `oklch(0.577 0.245 27.325)` | `oklch(0.704 0.191 22.216)` | Failed, error, destructive |
|
|
113
|
+
| `--info` | `oklch(0.6 0.13 240)` | `oklch(0.7 0.13 240)` | Informational, neutral highlight |
|
|
175
114
|
|
|
176
|
-
|
|
177
|
-
|---|---|---|
|
|
178
|
-
| ~~`--left-stripe`~~ | *banned* | Never. See §1.3. |
|
|
179
|
-
| ~~purple page wash~~ | *banned* | Body backgrounds must be `--bg` or `--bg-elev`. |
|
|
180
|
-
| ~~`#fff` raw~~ | `--text-strong` | Pure white is jarring on dark; use `--text-strong`. |
|
|
115
|
+
### 3.5 Borders & inputs
|
|
181
116
|
|
|
182
|
-
|
|
117
|
+
| Token | Light | Dark | Use |
|
|
118
|
+
|--|--|--|--|
|
|
119
|
+
| `--border` | `oklch(0.92 0.004 286.32)` | `oklch(1 0 0 / 10%)` | Default 1px border |
|
|
120
|
+
| `--border-strong` | `oklch(0.85 0.005 286)` | `oklch(1 0 0 / 18%)` | Hover, dividers |
|
|
121
|
+
| `--input-bg` | `oklch(0.967 0.001 286.375)` | `oklch(0.274 0.006 286.033)` | Form control fill |
|
|
122
|
+
| `--focus-ring` | `oklch(0.705 0.015 286.067)` | `oklch(0.552 0.016 285.938)` | Outer focus ring |
|
|
183
123
|
|
|
184
|
-
|
|
124
|
+
### 3.6 Charts (categorical, sequential, status)
|
|
185
125
|
|
|
186
|
-
|
|
126
|
+
| Token | Value | Use |
|
|
127
|
+
|--|--|--|
|
|
128
|
+
| `--chart-1` | `oklch(0.871 0.006 286.286)` | First series, neutral |
|
|
129
|
+
| `--chart-2` | `oklch(0.552 0.016 285.938)` | Second series |
|
|
130
|
+
| `--chart-3` | `oklch(0.442 0.017 285.786)` | Third series |
|
|
131
|
+
| `--chart-4` | `oklch(0.37 0.013 285.805)` | Fourth series |
|
|
132
|
+
| `--chart-5` | `oklch(0.274 0.006 286.033)` | Fifth series |
|
|
133
|
+
| `--chart-accent` | `var(--accent)` | Highlighted series |
|
|
187
134
|
|
|
188
|
-
|
|
189
|
-
--font-sans:
|
|
190
|
-
'Inter var', 'Inter', system-ui, -apple-system, 'Segoe UI',
|
|
191
|
-
Roboto, 'Helvetica Neue', sans-serif
|
|
135
|
+
Chart colors intentionally **do not match `--accent`** — they form a neutral grayscale ramp so that the green primary is reserved for interactive state. When a chart needs to highlight a single series (e.g. "errors over time"), it switches to `--danger` or `--success`, not `--accent`.
|
|
192
136
|
|
|
193
|
-
|
|
194
|
-
'JetBrains Mono', 'Fira Code', 'SF Mono', 'Cascadia Code',
|
|
195
|
-
Consolas, monospace
|
|
196
|
-
```
|
|
137
|
+
### 3.7 Sidebar
|
|
197
138
|
|
|
198
|
-
|
|
199
|
-
|
|
139
|
+
| Token | Light | Dark | Use |
|
|
140
|
+
|--|--|--|--|
|
|
141
|
+
| `--sidebar-bg` | `oklch(0.985 0 0)` | `oklch(0.21 0.006 285.885)` | Sidebar canvas |
|
|
142
|
+
| `--sidebar-fg` | `oklch(0.141 0.005 285.823)` | `oklch(0.985 0 0)` | Sidebar text |
|
|
143
|
+
| `--sidebar-accent` | `oklch(0.627 0.194 149.214)` | `oklch(0.723 0.219 149.579)` | Active nav item, primary sidebar button |
|
|
144
|
+
| `--sidebar-accent-fg` | `oklch(0.982 0.018 155.826)` | `oklch(0.982 0.018 155.826)` | Text on sidebar accent |
|
|
145
|
+
| `--sidebar-hover` | `oklch(0.967 0.001 286.375)` | `oklch(0.274 0.006 286.033)` | Nav hover bg |
|
|
146
|
+
| `--sidebar-border` | `oklch(0.92 0.004 286.32)` | `oklch(1 0 0 / 10%)` | Sidebar right border |
|
|
200
147
|
|
|
201
|
-
###
|
|
148
|
+
### 3.8 Geometry
|
|
202
149
|
|
|
203
|
-
| Token |
|
|
204
|
-
|
|
205
|
-
| `--
|
|
206
|
-
| `--
|
|
207
|
-
| `--
|
|
208
|
-
| `--
|
|
209
|
-
| `--fs-micro` | 11 | Numeric eyebrows, badges |
|
|
150
|
+
| Token | Value | Use |
|
|
151
|
+
|--|--|--|
|
|
152
|
+
| `--radius` | `0.625rem` (10px) | Buttons, inputs, cards, popovers |
|
|
153
|
+
| `--radius-sm` | `0.375rem` (6px) | Chips, badges, small buttons |
|
|
154
|
+
| `--radius-lg` | `0.875rem` (14px) | Dialogs, sheets, large cards |
|
|
155
|
+
| `--radius-pill` | `9999px` | Avatars, pills, toggle switches |
|
|
210
156
|
|
|
211
|
-
|
|
212
|
-
that contains numbers: token counters, costs, latencies, timestamps,
|
|
213
|
-
session ids.
|
|
157
|
+
### 3.9 Elevation
|
|
214
158
|
|
|
215
|
-
|
|
159
|
+
| Token | Value | Use |
|
|
160
|
+
|--|--|--|
|
|
161
|
+
| `--shadow-1` | `0 1px 2px oklch(0 0 0 / 0.04)` | Resting cards |
|
|
162
|
+
| `--shadow-2` | `0 4px 12px oklch(0 0 0 / 0.08)` | Hover cards, popovers |
|
|
163
|
+
| `--shadow-3` | `0 12px 32px oklch(0 0 0 / 0.12)` | Drag overlay, dialogs |
|
|
164
|
+
| `--shadow-4` | `0 24px 64px oklch(0 0 0 / 0.16)` | Sheets, command palette |
|
|
216
165
|
|
|
217
|
-
|
|
218
|
-
|---|---|
|
|
219
|
-
| 400 | Body, captions |
|
|
220
|
-
| 500 | Tab labels, button text |
|
|
221
|
-
| 600 | Card titles, section heads, active nav |
|
|
222
|
-
| 700 | Reserved for hero metrics only |
|
|
166
|
+
Dark mode multiplies each shadow by `1.25` because shadows are weaker on dark surfaces.
|
|
223
167
|
|
|
224
|
-
###
|
|
168
|
+
### 3.10 Motion
|
|
225
169
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
-
|
|
229
|
-
-
|
|
170
|
+
| Token | Value | Use |
|
|
171
|
+
|--|--|--|
|
|
172
|
+
| `--motion-instant` | `50ms` | Hover color shift, focus ring |
|
|
173
|
+
| `--motion-fast` | `120ms` | Small UI: button press, chip toggle |
|
|
174
|
+
| `--motion-base` | `200ms` | Default: popovers, menus, sidebar collapse |
|
|
175
|
+
| `--motion-slow` | `320ms` | Page transitions, drag overlays |
|
|
176
|
+
| `--ease-out` | `cubic-bezier(0.16, 1, 0.3, 1)` | 90% of motion — feels like Linear |
|
|
177
|
+
| `--ease-in-out` | `cubic-bezier(0.65, 0, 0.35, 1)` | Sidebar collapse, sheet slide |
|
|
178
|
+
| `--ease-spring` | `cubic-bezier(0.34, 1.56, 0.64, 1)` | Success micro-bounces |
|
|
179
|
+
|
|
180
|
+
`prefers-reduced-motion: reduce` zeroes every `--motion-*` token.
|
|
230
181
|
|
|
231
182
|
---
|
|
232
183
|
|
|
233
|
-
##
|
|
184
|
+
## 4 · Typography
|
|
234
185
|
|
|
235
|
-
|
|
186
|
+
Two families, six sizes, five weights. That is the whole type system.
|
|
236
187
|
|
|
237
|
-
|
|
238
|
-
--space-1 4px --spacing-xs icon-to-text, micro gap
|
|
239
|
-
--space-2 8px --spacing-sm between rows in a stack
|
|
240
|
-
--space-3 12px --spacing-md default card padding
|
|
241
|
-
--space-4 16px --spacing-lg section padding
|
|
242
|
-
--space-6 24px --spacing-xl page-level padding
|
|
243
|
-
--space-8 32px topbar vertical padding
|
|
244
|
-
--space-10 40px
|
|
245
|
-
--space-12 48px panel header padding
|
|
246
|
-
--space-16 64px rare, full-page sections
|
|
247
|
-
--space-20 80px
|
|
248
|
-
--space-24 96px hero only
|
|
249
|
-
```
|
|
188
|
+
### 4.1 Families
|
|
250
189
|
|
|
251
|
-
|
|
252
|
-
|
|
190
|
+
| Token | Family | Use |
|
|
191
|
+
|--|--|--|
|
|
192
|
+
| `--font-sans` | `Inter Variable`, system-ui fallback | UI, body, headings |
|
|
193
|
+
| `--font-mono` | `JetBrains Mono Variable`, `ui-monospace` fallback | IDs, paths, code, numerics |
|
|
194
|
+
| `--font-display` | `Inter Variable` (tight tracking) | Hero text, empty states |
|
|
253
195
|
|
|
254
|
-
|
|
196
|
+
### 4.2 Sizes (modular scale 1.125)
|
|
255
197
|
|
|
256
|
-
|
|
198
|
+
| Token | Size / line-height | Use |
|
|
199
|
+
|--|--|--|
|
|
200
|
+
| `--text-xs` | `0.75rem / 1rem` (12/16) | Captions, helper, table footnotes |
|
|
201
|
+
| `--text-sm` | `0.8125rem / 1.125rem` (13/18) | Default body, table cells |
|
|
202
|
+
| `--text-base` | `0.875rem / 1.25rem` (14/20) | Default body on wide screens |
|
|
203
|
+
| `--text-md` | `1rem / 1.5rem` (16/24) | Card titles, section headers |
|
|
204
|
+
| `--text-lg` | `1.125rem / 1.625rem` (18/26) | Page titles |
|
|
205
|
+
| `--text-xl` | `1.375rem / 1.75rem` (22/28) | Hero, empty-state title |
|
|
257
206
|
|
|
258
|
-
|
|
259
|
-
--radius-sm 6px inputs, small buttons, badges
|
|
260
|
-
--radius 8px buttons, tabs, default cards
|
|
261
|
-
--radius-md 10px chat message bubbles
|
|
262
|
-
--radius-lg 14px modals, kanban cards, topbar dropdowns
|
|
263
|
-
--radius-xl 16px dialog, command palette
|
|
264
|
-
--radius-pill 999px status pills, tag chips
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
---
|
|
207
|
+
### 4.3 Weights
|
|
268
208
|
|
|
269
|
-
|
|
209
|
+
| Token | Value | Use |
|
|
210
|
+
|--|--|--|
|
|
211
|
+
| `--weight-regular` | `400` | Body |
|
|
212
|
+
| `--weight-medium` | `500` | Nav labels, button text |
|
|
213
|
+
| `--weight-semibold` | `600` | Card titles, table headers |
|
|
214
|
+
| `--weight-bold` | `700` | Page titles only |
|
|
270
215
|
|
|
271
|
-
|
|
272
|
-
--shadow-1 0 1px 2px rgba(0,0,0,0.45) hairlines on cards
|
|
273
|
-
--shadow-2 0 4px 12px rgba(0,0,0,0.45) dropdowns, popovers
|
|
274
|
-
--shadow-3 0 12px 32px rgba(0,0,0,0.45) modals
|
|
275
|
-
--shadow-glow 0 0 0 1px accent-border + glow focused/active surfaces
|
|
276
|
-
```
|
|
216
|
+
### 4.4 Numerics
|
|
277
217
|
|
|
278
|
-
|
|
279
|
-
Avoid shadows on hairline borders; the border already separates.
|
|
218
|
+
All numeric cells use `font-variant-numeric: tabular-nums` so columns of figures align. The `mono` family is reserved for IDs, paths, and raw code; numerics stay in `sans` unless they are an ID.
|
|
280
219
|
|
|
281
|
-
|
|
220
|
+
### 4.5 Long content
|
|
282
221
|
|
|
283
|
-
|
|
222
|
+
Body copy uses `text-wrap: pretty`; headings use `text-wrap: balance`. Code blocks, table cells, and IDs use `text-wrap: nowrap` with `overflow: hidden; text-overflow: ellipsis` and a tooltip on hover.
|
|
284
223
|
|
|
285
|
-
|
|
286
|
-
--motion-fast 120ms
|
|
287
|
-
--motion-base 200ms
|
|
288
|
-
--motion-slow 320ms
|
|
289
|
-
--ease cubic-bezier(0.4, 0, 0.2, 1)
|
|
290
|
-
--motion-ease cubic-bezier(0.2, 0, 0, 1) sharp, intentional
|
|
291
|
-
```
|
|
224
|
+
---
|
|
292
225
|
|
|
293
|
-
|
|
294
|
-
animation, `--motion-slow` per dot. Never use a spinner on a streaming
|
|
295
|
-
chat — the user knows it's typing.
|
|
226
|
+
## 5 · Spacing & layout
|
|
296
227
|
|
|
297
|
-
|
|
298
|
-
`--motion-slow`, infinite, alternate. Never use on content inside the
|
|
299
|
-
chat thread; only on system-state chrome.
|
|
228
|
+
### 5.1 Spacing scale (4px base)
|
|
300
229
|
|
|
301
|
-
|
|
302
|
-
|
|
230
|
+
| Token | px | Use |
|
|
231
|
+
|--|--|--|
|
|
232
|
+
| `--space-0` | `0` | Reset |
|
|
233
|
+
| `--space-1` | `4px` | Tight stack, chip padding-y |
|
|
234
|
+
| `--space-2` | `8px` | Inline gap, button padding-y |
|
|
235
|
+
| `--space-3` | `12px` | Default inline gap, control padding |
|
|
236
|
+
| `--space-4` | `16px` | Card padding, stack gap, control padding-x |
|
|
237
|
+
| `--space-5` | `20px` | Section padding |
|
|
238
|
+
| `--space-6` | `24px` | Page section gap |
|
|
239
|
+
| `--space-8` | `32px` | Page padding |
|
|
240
|
+
| `--space-10` | `40px` | Hero vertical rhythm |
|
|
241
|
+
| `--space-12` | `48px` | Page-level separators |
|
|
242
|
+
| `--space-16` | `64px` | Empty-state padding |
|
|
243
|
+
|
|
244
|
+
### 5.2 Layout grid
|
|
245
|
+
|
|
246
|
+
- Desktop default: **12-column, 16px gutter, max 1440px content.**
|
|
247
|
+
- Sidebar: **260px expanded, 60px collapsed**, `--motion-base` ease.
|
|
248
|
+
- Topbar: **56px tall**, single row.
|
|
249
|
+
- Right detail drawer: **360px** when open, slides over content on <1280px, pushes content on ≥1280px.
|
|
250
|
+
|
|
251
|
+
### 5.3 Density
|
|
252
|
+
|
|
253
|
+
Two density modes, user-toggleable per workspace:
|
|
254
|
+
|
|
255
|
+
| Mode | Row height | Padding-y | Use |
|
|
256
|
+
|--|--|--|--|
|
|
257
|
+
| **Compact** (default) | `32px` | `4px` | Power-user, screen-fillers |
|
|
258
|
+
| **Comfortable** | `40px` | `8px` | Touch, lower-resolution |
|
|
259
|
+
|
|
260
|
+
Density is a single CSS class on `<html>`: `data-density="compact"` or `"comfortable"`. Every list, table, and tree honors it. Card padding does not change with density.
|
|
261
|
+
|
|
262
|
+
### 5.4 Z-index scale
|
|
263
|
+
|
|
264
|
+
| Layer | Value | Use |
|
|
265
|
+
|--|--|--|
|
|
266
|
+
| `--z-base` | `0` | Content |
|
|
267
|
+
| `--z-sticky` | `10` | Table headers, sticky filters |
|
|
268
|
+
| `--z-dropdown` | `1000` | Dropdowns, autocomplete |
|
|
269
|
+
| `--z-sticky-nav` | `1100` | Topbar, sidebar |
|
|
270
|
+
| `--z-overlay` | `1300` | Modal backdrop |
|
|
271
|
+
| `--z-modal` | `1400` | Dialogs, sheets |
|
|
272
|
+
| `--z-popover` | `1500` | Context menus, command palette |
|
|
273
|
+
| `--z-toast` | `1600` | Toasts, notifications |
|
|
274
|
+
| `--z-tooltip` | `1700` | Tooltips |
|
|
275
|
+
|
|
276
|
+
No z-index above `1700`. If you need it, you have mis-designed.
|
|
303
277
|
|
|
304
278
|
---
|
|
305
279
|
|
|
306
|
-
##
|
|
280
|
+
## 6 · Motion & elevation
|
|
307
281
|
|
|
308
|
-
|
|
309
|
-
one of these categories.
|
|
282
|
+
### 6.1 Default transitions
|
|
310
283
|
|
|
311
|
-
|
|
284
|
+
| Element | Property | Duration | Easing |
|
|
285
|
+
|--|--|--|--|
|
|
286
|
+
| Button bg | `background-color` | `--motion-instant` | `--ease-out` |
|
|
287
|
+
| Button press | `transform` | `--motion-fast` | `--ease-out` |
|
|
288
|
+
| Card hover | `box-shadow, transform` | `--motion-base` | `--ease-out` |
|
|
289
|
+
| Popover open | `opacity, transform` | `--motion-base` | `--ease-out` |
|
|
290
|
+
| Sidebar collapse | `width` | `--motion-base` | `--ease-in-out` |
|
|
291
|
+
| Page transition | `opacity` | `--motion-slow` | `--ease-out` |
|
|
292
|
+
| Drag overlay enter | `opacity, transform` | `--motion-fast` | `--ease-spring` |
|
|
293
|
+
| Toast | `transform` | `--motion-base` | `--ease-spring` |
|
|
312
294
|
|
|
313
|
-
|
|
314
|
-
```
|
|
315
|
-
┌─────────────────────────────────────────────────────────────────────────┐
|
|
316
|
-
│ ᛒ Bizar v6.0.0 │ project ▾ │ ⌘K Search... │ • Cline·active • ws·live │ ← 1 row, ~52px tall
|
|
317
|
-
│ [Overview][Chat][Agents][Glyphs][Tasks][Activity][Active][Skills]... ← 2nd row, tabs (topbar layout only)
|
|
318
|
-
└─────────────────────────────────────────────────────────────────────────┘
|
|
319
|
-
```
|
|
295
|
+
### 6.2 Micro-interactions
|
|
320
296
|
|
|
321
|
-
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
-
|
|
325
|
-
|
|
326
|
-
- Search trigger: pill button with kbd hint `⌘K`, `--border` outline.
|
|
327
|
-
- WebSocket status: dot (8px) + label. Dot color encodes state:
|
|
328
|
-
green=live, yellow=connecting, red=closed, gray=disabled.
|
|
297
|
+
- **Live indicator:** green dot, 1.6s pulse animation (`opacity` 1→0.4→1, `--motion-slow`). Respects `prefers-reduced-motion`.
|
|
298
|
+
- **Streaming text:** no special animation. Cursor blinks at end of last token, 1s cadence.
|
|
299
|
+
- **Drag:** cursor changes to `grabbing` on `mousedown`. Drag overlay uses `--shadow-3` and `transform: rotate(1.5deg) scale(1.02)` for a "lifted" feel.
|
|
300
|
+
- **Save:** inline checkmark flash, `--motion-fast`, `--ease-spring`. No modal.
|
|
301
|
+
- **Error:** subtle 2px left border inside the input + focus ring tint `--danger`. No shake animation.
|
|
329
302
|
|
|
330
|
-
|
|
331
|
-
```
|
|
332
|
-
┌──────┐
|
|
333
|
-
│ ⌂ │ ← icon-only buttons, 56px wide × 44px tall
|
|
334
|
-
│ 💬 │
|
|
335
|
-
│ 🤖 │
|
|
336
|
-
│ ✦ │ ← ~17 tabs in scrollable column
|
|
337
|
-
│ ... │
|
|
338
|
-
│ ⚙ │ ← Settings pinned to bottom
|
|
339
|
-
└──────┘
|
|
340
|
-
```
|
|
303
|
+
### 6.3 Reduced motion
|
|
341
304
|
|
|
342
|
-
-
|
|
343
|
-
-
|
|
344
|
-
|
|
345
|
-
-
|
|
346
|
-
-
|
|
305
|
+
When `prefers-reduced-motion: reduce`:
|
|
306
|
+
- All `--motion-*` tokens set to `0ms`.
|
|
307
|
+
- Drag overlay: no rotation/scale, only opacity.
|
|
308
|
+
- Page transitions: instant.
|
|
309
|
+
- Live indicator: static dot, no pulse.
|
|
347
310
|
|
|
348
|
-
|
|
311
|
+
---
|
|
349
312
|
|
|
350
|
-
|
|
351
|
-
.btn-sm 24px tall, 8px 12px padding, 12px text
|
|
352
|
-
.btn 32px tall, default, 13px text
|
|
353
|
-
.btn-lg 40px tall, primary CTAs only
|
|
354
|
-
|
|
355
|
-
Variants
|
|
356
|
-
.btn-primary accent fill, white text, accent border
|
|
357
|
-
.btn-secondary transparent, --border, --text
|
|
358
|
-
.btn-ghost transparent, no border, hover → --fg
|
|
359
|
-
.btn-danger transparent, --error text on hover
|
|
360
|
-
.btn-icon square, icon-only, 32×32
|
|
361
|
-
```
|
|
313
|
+
## 7 · Layout
|
|
362
314
|
|
|
363
|
-
|
|
364
|
-
a disabled button with a spinner inside it — show the spinner *instead*
|
|
365
|
-
of the button or use a loading state on the button itself.
|
|
315
|
+
### 7.1 App shell
|
|
366
316
|
|
|
367
|
-
|
|
317
|
+
The app shell is a fixed two-column layout: a sticky topbar on top, a sidebar on the left, and the main content area (SidebarInset) on the right. An optional status bar lives at the bottom on desktop and is hidden by default; it surfaces when there is an active alert.
|
|
368
318
|
|
|
369
319
|
```
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
320
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
321
|
+
│ TOPBAR 56px workspace · breadcrumb · status · search · user │
|
|
322
|
+
├──────────┬──────────────────────────────────────────────────────────┤
|
|
323
|
+
│ │ │
|
|
324
|
+
│ SIDEBAR │ SIDEBAR INSET │
|
|
325
|
+
│ 260px │ max 1440px, centered │
|
|
326
|
+
│ │ │
|
|
327
|
+
│ nav │ page content │
|
|
328
|
+
│ groups │ │
|
|
329
|
+
│ │ │
|
|
330
|
+
├──────────┴──────────────────────────────────────────────────────────┤
|
|
331
|
+
│ STATUS BAR 28px (optional) online · tokens · latency · build │
|
|
332
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
373
333
|
```
|
|
374
334
|
|
|
375
|
-
|
|
376
|
-
hint inside it on the right.
|
|
335
|
+
### 7.2 Topbar
|
|
377
336
|
|
|
378
|
-
|
|
337
|
+
| Slot | Width | Contents |
|
|
338
|
+
|--|--|--|
|
|
339
|
+
| Left | 320px | Bizar logo · workspace switcher · project picker |
|
|
340
|
+
| Center | flex | breadcrumb (route) + inline search (Cmd+K opens palette; inline search is for quick find) |
|
|
341
|
+
| Right | auto | Status pills (agents online · tokens · queue) · notifications bell · theme toggle · user menu |
|
|
379
342
|
|
|
380
|
-
|
|
381
|
-
.pill 999px radius, --accent-bg bg, --accent text, 11px mono uppercase
|
|
382
|
-
.pill-success --success-soft bg, --success text
|
|
383
|
-
.pill-warning --warning-soft bg, --warning text
|
|
384
|
-
.pill-error --error-soft bg, --error text
|
|
385
|
-
.pill-info --info bg (muted), --info text
|
|
386
|
-
|
|
387
|
-
.badge square corner, --bg-elev-2 bg, --text text, 11px mono, 14px square
|
|
388
|
-
.dot 8px circle, color encodes state
|
|
389
|
-
```
|
|
343
|
+
The topbar is sticky (`--z-sticky-nav`). It is **not** a tab bar — tabs live inside views when needed.
|
|
390
344
|
|
|
391
|
-
|
|
392
|
-
Badges = numeric counts (unread messages, queued tasks).
|
|
345
|
+
### 7.3 Sidebar
|
|
393
346
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
347
|
+
| Slot | Contents |
|
|
348
|
+
|--|--|
|
|
349
|
+
| Header | Workspace switcher (240px), collapse toggle (right edge) |
|
|
350
|
+
| Section: **Workspace** | Overview, Tasks, Goals |
|
|
351
|
+
| Section: **Operations** | Agents, Activity, Memory |
|
|
352
|
+
| Section: **Libraries** | Skills, MCP servers, Hooks |
|
|
353
|
+
| Section: **System** | Settings |
|
|
354
|
+
| Footer | Status indicator (online/offline), build SHA, version |
|
|
402
355
|
|
|
403
|
-
|
|
404
|
-
on drag.
|
|
405
|
-
|
|
406
|
-
### 9.6 Modal & dialog
|
|
407
|
-
|
|
408
|
-
- Backdrop: `--overlay-bg` (60% black).
|
|
409
|
-
- Surface: `--bg-elev-2`, `--radius-xl`, `--shadow-3`.
|
|
410
|
-
- Title: `--fs-h3` weight 600, `--space-3` from top.
|
|
411
|
-
- Footer: `--border` top hairline, right-aligned actions.
|
|
412
|
-
|
|
413
|
-
Command palette (v3.1.0+): 520px wide, centered, 16px padding, kbd row
|
|
414
|
-
in footer showing shortcuts.
|
|
415
|
-
|
|
416
|
-
### 9.7 Toast
|
|
417
|
-
|
|
418
|
-
- Bottom-right, stacks upward, 4 visible max.
|
|
419
|
-
- Width 360px, `--bg-elev-2`, `--radius-md`, `--shadow-2`.
|
|
420
|
-
- Color-coded left edge of *icon*, not the toast background.
|
|
421
|
-
- Lifetimes: `info` 2.5s, `success` 3s, `warning` 5s, `error` 8s.
|
|
422
|
-
|
|
423
|
-
### 9.8 Tabs (topbar variant)
|
|
356
|
+
Each section has an 11px uppercase label in `--fg-subtle` with `letter-spacing: 0.04em`. Items are 32px tall, single line, with a 16x16 Lucide icon, label, and an optional count badge (right-aligned, `--fg-muted`). The active item uses `--sidebar-accent` background with `--sidebar-accent-fg` text and a 2px left-edge bar in `--sidebar-accent` (a single permitted use of an edge bar — it is the *only* navigation primitive allowed to use one).
|
|
424
357
|
|
|
425
|
-
|
|
426
|
-
- Active: `--text-strong` + 2px `--accent` underline (positioned at
|
|
427
|
-
bottom of the tab, full-width).
|
|
428
|
-
- Hover: `--text-strong` (no underline).
|
|
429
|
-
- Settings tab: shows a small `Settings2` icon next to its label when
|
|
430
|
-
settings mode is active.
|
|
358
|
+
### 7.4 Content area
|
|
431
359
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
- 56px wide column, 44px tall.
|
|
435
|
-
- Icon 18px, label hidden (tooltip via `title`).
|
|
436
|
-
- Active: `--accent-bg` background, `--accent` icon, 600 weight label.
|
|
437
|
-
- Inactive: `--text-dim` icon.
|
|
360
|
+
The `SidebarInset` is a 1440px-max container with `--space-8` horizontal padding and `--space-6` top padding (topbar adds the rest). Pages render their own header (ViewHeader primitive — see §8.4) and then their content.
|
|
438
361
|
|
|
439
|
-
###
|
|
362
|
+
### 7.5 Optional right detail drawer
|
|
440
363
|
|
|
441
|
-
|
|
442
|
-
-
|
|
443
|
-
|
|
444
|
-
- Each row: state indicator (8px dot, color per state) + title + time
|
|
445
|
-
+ unread badge + 3-dot menu.
|
|
446
|
-
- Active session background: `--accent-bg` with no left stripe.
|
|
447
|
-
- Sub-agent tree: collapsible, indented 12px, smaller text, hairline
|
|
448
|
-
connector.
|
|
449
|
-
|
|
450
|
-
#### Thread (`<section class="chat-thread-section">`)
|
|
451
|
-
- Center column, fills remaining width.
|
|
452
|
-
- Thread head: title + source badge (`cline` / `bizar chat`) + subtitle
|
|
453
|
-
with state (idle / Replying / Your turn).
|
|
454
|
-
- Messages: alternating bubbles. User right-aligned, `--bg-elev-2`
|
|
455
|
-
bubble. Assistant left-aligned, no bubble (transparent).
|
|
456
|
-
- Streaming indicator: three pulsing dots in `--accent`, animated.
|
|
457
|
-
- Jump-to-latest pill (when scrolled up): floating, bottom-right of
|
|
458
|
-
thread, `--bg-elev-2` + `--shadow-2`.
|
|
364
|
+
The kanban and agents views can open a right-side **DetailDrawer** (360px). It slides in from the right with `--motion-base` and pushes content (≥1280px) or overlays it (<1280px). It contains:
|
|
365
|
+
- Read view: title, metadata, body, activity, comments
|
|
366
|
+
- Edit view: same + editable fields inline
|
|
459
367
|
|
|
460
|
-
|
|
461
|
-
- Pill-shaped input, `--bg-elev` outer, `--bg-elev-2` inner field.
|
|
462
|
-
- Attachments: chip row above input.
|
|
463
|
-
- Slash command suggestions: popover above, mono, `--font-mono`.
|
|
464
|
-
- Agent + model selectors: pill chips on left, opens dropdown on
|
|
465
|
-
click.
|
|
368
|
+
### 7.6 Routes
|
|
466
369
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
370
|
+
| Path | Page | Default view |
|
|
371
|
+
|--|--|--|
|
|
372
|
+
| `/` | Overview | Dashboard summary |
|
|
373
|
+
| `/tasks` | Tasks | Kanban (the main focus) |
|
|
374
|
+
| `/tasks/list` | Tasks | List view |
|
|
375
|
+
| `/tasks/calendar` | Tasks | Calendar view |
|
|
376
|
+
| `/goals` | Goals | Active goals |
|
|
377
|
+
| `/goals/:id` | Goal detail | Single goal |
|
|
378
|
+
| `/agents` | Agents | Roster |
|
|
379
|
+
| `/agents/:id` | Agent detail | Single agent |
|
|
380
|
+
| `/activity` | Activity | Event log |
|
|
381
|
+
| `/memory` | Memory | Vault browser |
|
|
382
|
+
| `/libraries/skills` | Skills | Library |
|
|
383
|
+
| `/libraries/mcps` | MCP servers | Library |
|
|
384
|
+
| `/libraries/hooks` | Hooks | Library |
|
|
385
|
+
| `/settings/*` | Settings | Hierarchical |
|
|
474
386
|
|
|
475
|
-
|
|
387
|
+
The nav stays at **6 top-level items** (Workspace, Operations, Libraries, System — the rest are sub-routes of the existing items). The user explicitly said "I do not want too many tabs", so we surface items as nav groups with secondary tabs inside the page.
|
|
476
388
|
|
|
477
|
-
|
|
478
|
-
- Header row: `--text-dim`, `--font-mono`, 12px, uppercase, 0.04em
|
|
479
|
-
letter-spacing.
|
|
480
|
-
- Body row: 14px, `--text`, 12px 14px padding.
|
|
481
|
-
- Numerics: `--font-mono`, `tabular-nums`, right-aligned.
|
|
482
|
-
- Hover: `--bg-elev-2` wash — not a colored row.
|
|
389
|
+
### 7.7 Empty states
|
|
483
390
|
|
|
484
|
-
|
|
391
|
+
Every collection view has an `EmptyState` (see §8.5) with:
|
|
392
|
+
- A 24px Lucide icon in `--fg-subtle`
|
|
393
|
+
- A one-line title in `--text-md` `--weight-medium`
|
|
394
|
+
- A one-sentence body in `--fg-muted`
|
|
395
|
+
- One primary CTA button (`--accent`)
|
|
396
|
+
- Optional secondary text link
|
|
485
397
|
|
|
486
|
-
|
|
398
|
+
No illustrations, no emoji, no "celebrate your first task" copy.
|
|
487
399
|
|
|
488
|
-
|
|
489
|
-
body.
|
|
490
|
-
- Card: 14px radius, 16px padding, kanban-card-shadow only on drag.
|
|
491
|
-
- Team badge (v6.0.0): pill with sparkle icon, attached to cards
|
|
492
|
-
tagged `team:*`.
|
|
493
|
-
- Drag: 1px `--accent-border` outline, `--shadow-3`.
|
|
400
|
+
---
|
|
494
401
|
|
|
495
|
-
|
|
402
|
+
## 8 · Component library
|
|
403
|
+
|
|
404
|
+
The library lives at `bizar-dash/src/web/ui/`. Every component is named with PascalCase, lives in its own file, exports a named function, and has a colocated `.test.tsx` file. No default exports.
|
|
405
|
+
|
|
406
|
+
### 8.1 `ui/primitives/` — no business logic
|
|
407
|
+
|
|
408
|
+
- **Box** — `div` with tokens (bg, fg, padding, radius)
|
|
409
|
+
- **Stack** — vertical flex with `--space-N` gap
|
|
410
|
+
- **Inline** — horizontal flex with `--space-N` gap
|
|
411
|
+
- **Cluster** — wraps inline elements that pack
|
|
412
|
+
- **Grid** — CSS grid wrapper with col/row gap
|
|
413
|
+
- **Center** — centers content (empty states)
|
|
414
|
+
- **Separator** — 1px horizontal/vertical rule
|
|
415
|
+
- **ScrollArea** — themed scroll wrapper, hides scrollbars unless scrolling
|
|
416
|
+
- **Resizable** — wraps `react-resizable-panels`
|
|
417
|
+
- **VisuallyHidden** — `sr-only` helper
|
|
418
|
+
- **Portal** — Radix Portal wrapper
|
|
419
|
+
|
|
420
|
+
### 8.2 `ui/controls/` — form & input
|
|
421
|
+
|
|
422
|
+
- **Button** (variants: `primary | secondary | ghost | outline | danger | link`, sizes: `xs | sm | md | lg | icon`)
|
|
423
|
+
- **ButtonGroup** — stacked buttons with shared borders
|
|
424
|
+
- **IconButton** — square, icon-only, requires `aria-label`
|
|
425
|
+
- **Input** — single-line text, optional left/right slots
|
|
426
|
+
- **Textarea** — multi-line, autoresize
|
|
427
|
+
- **InputOTP** — segmented code input
|
|
428
|
+
- **Select** — Radix Select wrapper (single)
|
|
429
|
+
- **MultiSelect** — Radix Popover + command list (multi)
|
|
430
|
+
- **Combobox** — Radix Popover + list + input (async-capable)
|
|
431
|
+
- **Checkbox** — Radix Checkbox
|
|
432
|
+
- **RadioGroup** — Radix RadioGroup
|
|
433
|
+
- **Switch** — Radix Switch
|
|
434
|
+
- **Toggle** — single toggle button
|
|
435
|
+
- **ToggleGroup** — Radix ToggleGroup
|
|
436
|
+
- **Slider** — Radix Slider
|
|
437
|
+
- **DatePicker** — single date
|
|
438
|
+
- **DateRangePicker** — two dates
|
|
439
|
+
- **TimePicker** — single time
|
|
440
|
+
- **ColorPicker** — popover with swatches + input
|
|
441
|
+
- **Field** — label + control + error + helper wrapper
|
|
442
|
+
- **Form** — React Hook Form + Zod integration
|
|
443
|
+
|
|
444
|
+
### 8.3 `ui/feedback/` — feedback & status
|
|
445
|
+
|
|
446
|
+
- **Alert** — inline banner, variants `info | success | warning | danger`
|
|
447
|
+
- **Toast** — Sonner wrapper, top-right, auto-dismiss 5s
|
|
448
|
+
- **Dialog** — Radix Dialog (modal)
|
|
449
|
+
- **AlertDialog** — destructive confirm
|
|
450
|
+
- **Sheet** — Radix Dialog with side prop (right/left/top/bottom)
|
|
451
|
+
- **Drawer** — bottom-sheet variant for mobile
|
|
452
|
+
- **Popover** — Radix Popover
|
|
453
|
+
- **HoverCard** — Radix HoverCard (preview on hover)
|
|
454
|
+
- **Tooltip** — Radix Tooltip, 4-side aware
|
|
455
|
+
- **Progress** — linear bar
|
|
456
|
+
- **ProgressCircle** — circular determinate/indeterminate
|
|
457
|
+
- **Spinner** — single-element rotating arc
|
|
458
|
+
- **Skeleton** — shimmering placeholder
|
|
459
|
+
- **EmptyState** — see §7.7
|
|
460
|
+
- **ErrorBoundary** — React error boundary
|
|
461
|
+
- **Banner** — full-width inline banner
|
|
462
|
+
|
|
463
|
+
### 8.4 `ui/data/` — data display
|
|
464
|
+
|
|
465
|
+
- **Card** — generic container with optional header/footer slots
|
|
466
|
+
- **StatTile** — single metric, optional delta indicator
|
|
467
|
+
- **StatGrid** — N-up grid of StatTiles
|
|
468
|
+
- **Table** — semantic `<table>` (low-level)
|
|
469
|
+
- **DataTable** — TanStack Table wrapper (sort, filter, paginate, select, resize, virtualize)
|
|
470
|
+
- **Badge** — small label, variants `default | accent | success | warning | danger | neutral`
|
|
471
|
+
- **Chip** — removable tag with avatar/icon
|
|
472
|
+
- **Avatar** — image or initials, with optional status dot
|
|
473
|
+
- **AvatarStack** — overlapping avatars
|
|
474
|
+
- **Timeline** — vertical event list with timestamps
|
|
475
|
+
- **Accordion** — Radix Accordion
|
|
476
|
+
- **Collapsible** — single show/hide
|
|
477
|
+
- **Chart** — Recharts wrapper (LineChart, BarChart, AreaChart, PieChart) bound to chart tokens
|
|
478
|
+
- **Sparkline** — inline mini-chart
|
|
479
|
+
- **MetricRing** — circular progress with label
|
|
480
|
+
- **BarList** — horizontal ranked list (used in activity feeds)
|
|
481
|
+
- **TreeView** — Radix Accordion-based tree
|
|
482
|
+
- **VirtualList** — TanStack Virtual wrapper
|
|
483
|
+
- **Kbd** — keyboard key cap
|
|
484
|
+
- **CountBadge** — numeric pill, optional max cap (e.g. "99+")
|
|
485
|
+
- **ViewHeader** — page title + description + actions slot (used at top of every page)
|
|
486
|
+
|
|
487
|
+
### 8.5 `ui/navigation/` — navigation
|
|
488
|
+
|
|
489
|
+
- **Sidebar** (root + provider) — wraps `nav`, handles collapse
|
|
490
|
+
- **SidebarProvider** — context, persisted collapsed state
|
|
491
|
+
- **SidebarInset** — content slot inside SidebarProvider
|
|
492
|
+
- **SidebarSection** — labeled section
|
|
493
|
+
- **SidebarItem** — single nav row
|
|
494
|
+
- **SidebarGroup** — collapsible group
|
|
495
|
+
- **Topbar** — top bar slot composition
|
|
496
|
+
- **Breadcrumb** — list of links
|
|
497
|
+
- **NavLink** — Radix-styled anchor with active state
|
|
498
|
+
- **Tabs** — Radix Tabs wrapper
|
|
499
|
+
- **TabBar** — styled tab strip
|
|
500
|
+
- **TabPanel** — content slot
|
|
501
|
+
- **Menu** — Radix DropdownMenu with shortcut display
|
|
502
|
+
- **ContextMenu** — Radix ContextMenu (right-click trigger)
|
|
503
|
+
- **DropdownMenu** — Radix DropdownMenu
|
|
504
|
+
- **Menubar** — Radix Menubar
|
|
505
|
+
- **Pagination** — page + per-page controls
|
|
506
|
+
- **Stepper** — multi-step progress
|
|
507
|
+
- **CommandPalette** — Cmd+K overlay (see §9.4)
|
|
508
|
+
- **CommandBar** — inline command (Ctrl+K for filter focus)
|
|
509
|
+
- **NavSection** — labeled section for sidebar
|
|
510
|
+
- **NavItem** — sidebar row primitive
|
|
511
|
+
- **NavGroup** — collapsible section in sidebar
|
|
512
|
+
- **ViewTabs** — tab strip below ViewHeader
|
|
513
|
+
|
|
514
|
+
### 8.6 `ui/kanban/` — the main feature
|
|
515
|
+
|
|
516
|
+
This directory is the largest and most important. The kanban is the centerpiece of the dashboard.
|
|
517
|
+
|
|
518
|
+
- **KanbanBoard** — root container, owns DnD context
|
|
519
|
+
- **KanbanColumn** — column with header (title, count, actions), droppable body, add-task footer
|
|
520
|
+
- **KanbanCard** — task card, draggable, with all metadata visible
|
|
521
|
+
- **KanbanCardCompact** — minimal card for high-density mode
|
|
522
|
+
- **KanbanCardExpanded** — preview-on-hover or detail-drawer card
|
|
523
|
+
- **KanbanDetail** — right-side drawer content
|
|
524
|
+
- **KanbanFilters** — filter bar (assignee, label, priority, due, search)
|
|
525
|
+
- **KanbanGroupBy** — group-by selector (status / assignee / label / priority / due / project)
|
|
526
|
+
- **KanbanSort** — sort selector
|
|
527
|
+
- **KanbanDensity** — compact/comfortable toggle
|
|
528
|
+
- **KanbanEmptyState** — column empty state
|
|
529
|
+
- **KanbanKeyboardShortcuts** — helper component showing available shortcuts
|
|
530
|
+
- **KanbanQuickAdd** — inline add input at top of each column
|
|
531
|
+
- **KanbanContextMenu** — right-click menu (see §9.2)
|
|
532
|
+
- **KanbanDragOverlay** — drag preview
|
|
533
|
+
|
|
534
|
+
### 8.7 `ui/popups/` — right-click & custom popups
|
|
535
|
+
|
|
536
|
+
All popups are Radix-based or custom portals. **Browser default context menus are suppressed on all interactive surfaces** (`oncontextmenu` returns `false`); right-click opens our `ContextMenu`.
|
|
537
|
+
|
|
538
|
+
- **ContextMenu** — Radix ContextMenu (right-click + Shift+F10)
|
|
539
|
+
- **ActionMenu** — vertical list of actions with icons + shortcuts
|
|
540
|
+
- **SubActionMenu** — nested action menu (Radix Sub)
|
|
541
|
+
- **QuickAction** — single-action right-click shortcut
|
|
542
|
+
- **CommandBar** — Cmd+K overlay
|
|
543
|
+
- **DetailDrawer** — right-side drawer with read/edit toggle
|
|
544
|
+
- **ConfirmDialog** — destructive confirmation
|
|
545
|
+
- **InfoPopover** — hover/click popover with rich content
|
|
546
|
+
|
|
547
|
+
### 8.8 `ui/theme/` — theming
|
|
548
|
+
|
|
549
|
+
- **ThemeProvider** — light/dark/system, persists to `localStorage`
|
|
550
|
+
- **useTheme** — hook returning `{ theme, setTheme, resolvedTheme }`
|
|
551
|
+
- **ThemeToggle** — dropdown trigger
|
|
552
|
+
- **DensityProvider** — compact/comfortable
|
|
553
|
+
- **useDensity** — hook
|
|
554
|
+
|
|
555
|
+
### 8.9 `ui/utils/`
|
|
556
|
+
|
|
557
|
+
- **cx** — `clsx` + `tailwind-merge` wrapper
|
|
558
|
+
- **formatNumber**, **formatPercent**, **formatBytes**, **formatDuration**, **formatRelativeTime** — display formatters
|
|
559
|
+
- **useHotkeys** — global hotkey registry (see §9.3)
|
|
560
|
+
- **useFocusTrap** — focus trap for popovers
|
|
561
|
+
- **useMediaQuery** — responsive hook
|
|
562
|
+
- **useReducedMotion** — accessibility hook
|
|
563
|
+
- **useDebouncedValue** — search input debounce
|
|
564
|
+
- **useLocalStorage** — typed localStorage hook
|
|
565
|
+
|
|
566
|
+
### 8.10 `ui/hooks/` — cross-cutting hooks
|
|
567
|
+
|
|
568
|
+
- **useWebSocket** — typed WS subscriber
|
|
569
|
+
- **useAgents** — agent roster query
|
|
570
|
+
- **useTasks** — task query/mutation
|
|
571
|
+
- **useGoals** — goal query/mutation
|
|
572
|
+
- **useShortcuts** — keyboard shortcut dispatcher
|
|
573
|
+
- **useContextMenu** — opens Radix ContextMenu at cursor
|
|
574
|
+
- **useDragAndDrop** — dnd-kit wrapper
|
|
496
575
|
|
|
497
|
-
|
|
498
|
-
|---|---|---|---|
|
|
499
|
-
| idle | `--text-dim` | none | none |
|
|
500
|
-
| streaming | `--success` | `--success-soft` 4px wash on icon | pulsing glow |
|
|
501
|
-
| awaiting | `--warning` | none | none |
|
|
502
|
-
| error | `--error` | `--error-soft` ring | shake once on entry |
|
|
503
|
-
| connecting | `--text-dim` | none | opacity 0.4↔1, slow |
|
|
576
|
+
---
|
|
504
577
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
- Square 1:1, `--bg-elev`, 1px `--accent-border` on hover.
|
|
508
|
-
- Title in `--fs-h3`, 11px mono caption.
|
|
509
|
-
- Send / Copy / Edit icon row in footer.
|
|
510
|
-
|
|
511
|
-
### 9.15 Notifications bell
|
|
578
|
+
## 9 · Interaction patterns
|
|
512
579
|
|
|
513
|
-
|
|
514
|
-
- Panel: 360px wide, scrolls, items 64px tall, hairline separators.
|
|
580
|
+
### 9.1 The five inviolable rules
|
|
515
581
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
-
|
|
521
|
-
- Arrow keys to navigate, Enter to open.
|
|
522
|
-
|
|
523
|
-
### 9.17 Sparkline & metric charts
|
|
524
|
-
|
|
525
|
-
- Inline SVG, 32px tall, `--accent` stroke 1.5px, gradient fill (8% → 0%).
|
|
526
|
-
- Right-aligned delta: `--success` for "up is good", `--error` for "up is bad".
|
|
527
|
-
- Numeric body always tabular-nums.
|
|
528
|
-
|
|
529
|
-
### 9.18 Workflow DAG visualizer (v6.0.0)
|
|
530
|
-
|
|
531
|
-
Used in Tasks card detail and Eval reports.
|
|
532
|
-
- Nodes: rounded rectangles (8px radius), `--bg-elev-2` background, hairline border.
|
|
533
|
-
- Node states: idle / running / done / failed / skipped — colored border + center dot.
|
|
534
|
-
- Edges: 1.5px lines in `--text-dim`, animated dashed line on the "currently running" edge.
|
|
535
|
-
- Vertical timeline: time on the left axis in mono.
|
|
536
|
-
|
|
537
|
-
### 9.19 Approval queue (v6.0.0)
|
|
538
|
-
|
|
539
|
-
Used in Plans & Memory tabs.
|
|
540
|
-
- Each row: 56px tall, agent avatar + plan title + target file (mono) + Approve / Steer / Reject buttons.
|
|
541
|
-
- Hairline separators; rejected plans get a thin `--error-soft` wash on hover-to-undo.
|
|
542
|
-
- Bulk action toolbar floats above the queue when ≥1 selected.
|
|
543
|
-
|
|
544
|
-
### 9.20 Cost / token chart card (v6.0.0)
|
|
545
|
-
|
|
546
|
-
Used in Usage (MiniMax) and Overview.
|
|
547
|
-
- Card: title + period selector (24h / 7d / 30d) + big numeric + sparkline + breakdown bars.
|
|
548
|
-
- Breakdown bars: horizontal stacked bar by model, `--accent` for primary, `--text-dim` for others.
|
|
549
|
-
- Always tabular-nums. Always right-aligned.
|
|
550
|
-
|
|
551
|
-
### 9.21 BG agent live panel (v6.0.0)
|
|
582
|
+
1. **Right-click is sacred.** Every interactive surface has a `ContextMenu`. No element falls back to the browser default.
|
|
583
|
+
2. **Keyboard parity.** Every action has a shortcut. Every menu item shows the shortcut right-aligned in `Kbd` style.
|
|
584
|
+
3. **Cmd+K is everything.** Cmd+K opens the command palette, which contains every page, every action, every setting, every shortcut reference.
|
|
585
|
+
4. **Optimistic by default.** Mutations apply instantly; rollback on error with a toast. No spinners on the user's own actions.
|
|
586
|
+
5. **Real-time by default.** Live data refreshes via WS without user action; the green pulse indicator shows the connection is live.
|
|
552
587
|
|
|
553
|
-
|
|
554
|
-
- Row: 56px tall, agent avatar + name + status pill + elapsed (mono, 1s tick) + action buttons (pause / steer / stop).
|
|
555
|
-
- Status pill variants: `running` (success pulse) / `paused` (warning) / `stuck` (warning static + Retry) / `done` (text-dim).
|
|
556
|
-
- Collapsed by default, expands to show streaming output and tool calls.
|
|
588
|
+
### 9.2 Right-click context menus
|
|
557
589
|
|
|
558
|
-
|
|
590
|
+
Right-click menus replace browser defaults everywhere except in `<input>`, `<textarea>`, and `[contenteditable]`. The trigger is `onContextMenu` on the element, opening a Radix `ContextMenu`.
|
|
559
591
|
|
|
560
|
-
|
|
592
|
+
```tsx
|
|
593
|
+
<KanbanCard onContextMenu={(e) => {
|
|
594
|
+
e.preventDefault();
|
|
595
|
+
openContextMenu(task.id, e);
|
|
596
|
+
}}>
|
|
597
|
+
...
|
|
598
|
+
</KanbanCard>
|
|
599
|
+
```
|
|
561
600
|
|
|
562
|
-
|
|
601
|
+
Every context menu follows this structure:
|
|
563
602
|
|
|
564
|
-
|
|
603
|
+
```
|
|
604
|
+
┌─────────────────────────────────────┐
|
|
605
|
+
│ Open in drawer ⌘↵ │
|
|
606
|
+
│ Edit E │
|
|
607
|
+
│ Duplicate ⇧D │
|
|
608
|
+
│ Copy link ⌥L │
|
|
609
|
+
│ ──────────────────────────────── │
|
|
610
|
+
│ Assign to agent ▸ │
|
|
611
|
+
│ Move to column ▸ │
|
|
612
|
+
│ Set priority ▸ │
|
|
613
|
+
│ ──────────────────────────────── │
|
|
614
|
+
│ Archive ⌘⇧A │
|
|
615
|
+
│ Delete (danger) ⌫ │
|
|
616
|
+
└─────────────────────────────────────┘
|
|
617
|
+
```
|
|
565
618
|
|
|
566
|
-
|
|
567
|
-
|---|---|---|---|
|
|
568
|
-
| `topbar` | visible | hidden | topbar + view |
|
|
569
|
-
| `sidebar` | collapsed (no tabs row) | visible | sidebar + view |
|
|
570
|
-
| `both` | collapsed | visible | sidebar + view + small topbar |
|
|
619
|
+
The keyboard equivalent is **Shift+F10** when the element has focus. We render the same menu for both triggers.
|
|
571
620
|
|
|
572
|
-
|
|
573
|
-
tab.
|
|
621
|
+
### 9.3 Keyboard shortcuts
|
|
574
622
|
|
|
575
|
-
|
|
623
|
+
Every shortcut is registered in `ui/utils/shortcuts.ts` and bound through `useHotkeys`. Shortcuts are scoped:
|
|
576
624
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
│ │ [composer always at bottom] │ │
|
|
583
|
-
└────────┴──────────────────────────────┴─────────┘
|
|
584
|
-
```
|
|
625
|
+
| Scope | Modifiers | Examples |
|
|
626
|
+
|--|--|--|
|
|
627
|
+
| **Global** | `Cmd`/`Ctrl` | `Cmd+K` palette, `Cmd+B` sidebar, `Cmd+/` shortcuts |
|
|
628
|
+
| **Tasks view** | none (when focused) | `C` new, `E` edit, `/` search, `1-9` jump column |
|
|
629
|
+
| **Anywhere** | `Cmd` | `Cmd+S` save (if open editor), `Cmd+,` settings |
|
|
585
630
|
|
|
586
|
-
|
|
587
|
-
- Composer sticks to bottom of thread column (`position: sticky`,
|
|
588
|
-
`bottom: 0`, `--bg-elev` backdrop).
|
|
589
|
-
- Info panel collapses below 1100px (becomes a sheet above 768px).
|
|
631
|
+
Shortcuts ignore typing when an `<input>` or `<textarea>` has focus unless the modifier is `Cmd`/`Ctrl`. The Command Palette shows all available shortcuts and is searchable.
|
|
590
632
|
|
|
591
|
-
###
|
|
633
|
+
### 9.4 Command Palette (Cmd+K)
|
|
592
634
|
|
|
593
|
-
|
|
635
|
+
Built on `cmdk` (the same library Linear uses). Triggers:
|
|
594
636
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
637
|
+
| Command | Description |
|
|
638
|
+
|--|--|
|
|
639
|
+
| `Cmd+K` (Mac) / `Ctrl+K` (Win/Linux) | Open |
|
|
640
|
+
| `Esc` | Close |
|
|
641
|
+
| `↑↓` | Navigate |
|
|
642
|
+
| `↵` | Execute |
|
|
643
|
+
| `Tab` | Switch scope (Actions / Pages / Settings) |
|
|
600
644
|
|
|
601
|
-
|
|
645
|
+
Three scopes (tabs):
|
|
646
|
+
1. **Actions** — quick mutations on the current selection. If nothing is selected, falls back to general actions.
|
|
647
|
+
2. **Navigate** — every page, with breadcrumbs.
|
|
648
|
+
3. **Settings** — every settings key, jump to its setting page.
|
|
602
649
|
|
|
603
|
-
-
|
|
604
|
-
(sidebar).
|
|
605
|
-
- Keyboard: `1`–`9` for first 9 tabs, `0` for Overview (v3.2.0).
|
|
606
|
-
- Browser back/forward navigates tab history.
|
|
650
|
+
The palette has a fuzzy-search input at the top, a list of matches, and a footer showing the current scope + scope-switch hint.
|
|
607
651
|
|
|
608
|
-
###
|
|
652
|
+
### 9.5 Optimistic mutations
|
|
609
653
|
|
|
610
|
-
|
|
654
|
+
Every mutation goes through `useMutation` from TanStack Query:
|
|
611
655
|
|
|
612
|
-
```
|
|
613
|
-
|
|
656
|
+
```ts
|
|
657
|
+
const updateTask = useMutation({
|
|
658
|
+
mutationFn: api.tasks.update,
|
|
659
|
+
onMutate: (newTask) => {
|
|
660
|
+
queryClient.setQueryData(['tasks'], applyUpdate(old, newTask));
|
|
661
|
+
return { previous: old };
|
|
662
|
+
},
|
|
663
|
+
onError: (_err, _vars, ctx) => {
|
|
664
|
+
queryClient.setQueryData(['tasks'], ctx?.previous);
|
|
665
|
+
toast.error('Could not save — reverted');
|
|
666
|
+
},
|
|
667
|
+
onSettled: () => queryClient.invalidateQueries(['tasks']),
|
|
668
|
+
});
|
|
614
669
|
```
|
|
615
670
|
|
|
616
|
-
|
|
617
|
-
- Time elapsed updates every second (`--motion-fast`).
|
|
618
|
-
- Action buttons are `.btn-sm .btn-ghost`.
|
|
619
|
-
- Stuck agents (>5 min no progress) get a yellow dot + a `Retry`
|
|
620
|
-
button.
|
|
671
|
+
The UI updates instantly; the toast confirms or reverts. No spinners on user-initiated mutations.
|
|
621
672
|
|
|
622
|
-
###
|
|
673
|
+
### 9.6 Real-time updates
|
|
623
674
|
|
|
624
|
-
|
|
675
|
+
The dashboard maintains a single WebSocket connection (`/ws/dashboard`) that streams:
|
|
625
676
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
677
|
+
- `tasks:change` — task created/updated/deleted
|
|
678
|
+
- `agents:change` — agent registered/deregistered
|
|
679
|
+
- `goals:change` — goal progress tick
|
|
680
|
+
- `activity:event` — new event in activity log
|
|
681
|
+
- `routing:decision` — new routing decision
|
|
682
|
+
- `cost:tick` — cost reservation update
|
|
683
|
+
- `system:status` — health, version, build
|
|
632
684
|
|
|
633
|
-
|
|
634
|
-
source with the matching glyph on the left of each row.
|
|
685
|
+
All hooks consume these via `useWebSocket` + React Query cache invalidation. The connection state shows in the topbar's status pill (green pulse = connected, amber = reconnecting, red = offline).
|
|
635
686
|
|
|
636
|
-
###
|
|
687
|
+
### 9.7 Hover & focus
|
|
637
688
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
└──────────────────────────┘
|
|
642
|
-
```
|
|
689
|
+
- Hover previews use `HoverCard` with a 400ms delay, 200ms close.
|
|
690
|
+
- Focus rings: `--focus-ring` 2px outline + 2px offset, always visible on keyboard focus, never on mouse click.
|
|
691
|
+
- Tooltip: 4-side aware, 200ms delay, `--motion-base` ease.
|
|
643
692
|
|
|
644
|
-
|
|
645
|
-
green. `idle` = static dim. `unavailable` = static red. `unknown` =
|
|
646
|
-
static gray.
|
|
693
|
+
### 9.8 Empty states
|
|
647
694
|
|
|
648
|
-
|
|
695
|
+
(See §7.7.) Every collection has a deliberate empty state with one CTA. We never say "Nothing to see here." We always say what to do next.
|
|
649
696
|
|
|
650
|
-
|
|
697
|
+
---
|
|
651
698
|
|
|
652
|
-
|
|
653
|
-
[●] Cline runtime active ▰▰▰▰▰▱▱▱▱ 5/8
|
|
654
|
-
[●] Task scheduler active ▰▰▰▰▰▰▱▱▱ 6/8
|
|
655
|
-
[●] Memory store degraded ▰▰▰▱▱▱▱▱▱ 3/8
|
|
656
|
-
[●] WebSocket active ▰▰▰▰▰▰▰▰▱ 7/8
|
|
657
|
-
```
|
|
699
|
+
## 10 · Settings model
|
|
658
700
|
|
|
659
|
-
|
|
660
|
-
Progress bars: `--bg-elev-2` track, `--accent` fill. **No colored
|
|
661
|
-
track backgrounds** — color stays on the fill, not on the rail.
|
|
701
|
+
Settings is hierarchical, scoped, and always findable. The full settings surface lives at `/settings/*` with a sidebar in the page itself (not the global sidebar).
|
|
662
702
|
|
|
663
|
-
### 10.
|
|
703
|
+
### 10.1 Section structure
|
|
664
704
|
|
|
665
705
|
```
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
│ └──────────────────────┘ └──────────────────────────────┘ │
|
|
684
|
-
├────────────────────────────────────────────────────────────────┤
|
|
685
|
-
│ GRAPH ROW: │
|
|
686
|
-
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
687
|
-
│ │ Token spend · last 24h (large sparkline + breakdown) │ │
|
|
688
|
-
│ └──────────────────────────────────────────────────────────┘ │
|
|
689
|
-
└────────────────────────────────────────────────────────────────┘
|
|
706
|
+
/settings
|
|
707
|
+
├── /general Workspace name, logo, default project
|
|
708
|
+
├── /appearance Theme, density, accent color (future)
|
|
709
|
+
├── /agents Default agent roster, max concurrency
|
|
710
|
+
├── /goals Goal cadence, review interval
|
|
711
|
+
├── /tasks Default workflow, custom statuses, kanban config
|
|
712
|
+
├── /skills Skill library, default skill, auto-suggest
|
|
713
|
+
├── /mcps MCP servers, auth, per-tool permissions
|
|
714
|
+
├── /hooks Hook config (Pre/Post/UserPrompt)
|
|
715
|
+
├── /routing Model tiers, cost ceiling, fallback
|
|
716
|
+
├── /memory Vault location, retention, distillation
|
|
717
|
+
├── /notifications Per-event toggles, channels
|
|
718
|
+
├── /security Webhook secrets, HMAC keys, PII mode
|
|
719
|
+
├── /integrations GitHub, Slack, webhooks
|
|
720
|
+
├── /billing Cost gate, room budget, alerts
|
|
721
|
+
├── /team Members, roles (future)
|
|
722
|
+
└── /advanced Debug, traces, export/import, reset
|
|
690
723
|
```
|
|
691
724
|
|
|
692
|
-
### 10.
|
|
693
|
-
|
|
694
|
-
```
|
|
695
|
-
┌────────────────────────────────────────────────────────────────┐
|
|
696
|
-
│ HEADER Usage · 24h ▾ $1.84/hr −8% ▲ │
|
|
697
|
-
├────────────────────────────────────────────────────────────────┤
|
|
698
|
-
│ STAT CARDS (4): │
|
|
699
|
-
│ [spent 24h] [cost/hr] [tokens/hr] [alerts] │
|
|
700
|
-
├──────────────────────────────┬─────────────────────────────────┤
|
|
701
|
-
│ TOKEN SPEND CHART │ MODEL BREAKDOWN │
|
|
702
|
-
│ (stacked area, last 24h) │ (horizontal bars per model) │
|
|
703
|
-
│ │ │
|
|
704
|
-
├──────────────────────────────┼─────────────────────────────────┤
|
|
705
|
-
│ RECENT ALARMS │ BUDGET STATUS │
|
|
706
|
-
│ (timeline of cost spikes) │ (4 budgets, percent gauges) │
|
|
707
|
-
└──────────────────────────────┴─────────────────────────────────┘
|
|
708
|
-
```
|
|
725
|
+
### 10.2 Settings page pattern
|
|
709
726
|
|
|
710
|
-
|
|
727
|
+
Every settings page follows the same skeleton:
|
|
711
728
|
|
|
712
729
|
```
|
|
713
|
-
|
|
714
|
-
│
|
|
730
|
+
┌─ ViewHeader ────────────────────────────────────────────────────┐
|
|
731
|
+
│ Settings · Agents [ Save changes ] │
|
|
732
|
+
│ Default roster and concurrency for new sessions. │
|
|
715
733
|
├────────────────────────────────────────────────────────────────┤
|
|
716
|
-
│
|
|
717
|
-
│
|
|
718
|
-
│
|
|
719
|
-
│
|
|
720
|
-
│
|
|
721
|
-
│
|
|
722
|
-
│
|
|
734
|
+
│ ┌─ FieldGroup ──────────────────────────────────────────────┐ │
|
|
735
|
+
│ │ Default roster size [ 8 ] — help text │ │
|
|
736
|
+
│ │ Max concurrent agents [ 16 ] — help text │ │
|
|
737
|
+
│ │ Agent types [ multi-select ] — help text │ │
|
|
738
|
+
│ │ Auto-spawn on session [ toggle ON ] — help text │ │
|
|
739
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
740
|
+
│ ┌─ FieldGroup ──────────────────────────────────────────────┐ │
|
|
741
|
+
│ │ Restart agents on config change [ toggle OFF ] │ │
|
|
742
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
723
743
|
└────────────────────────────────────────────────────────────────┘
|
|
724
744
|
```
|
|
725
745
|
|
|
726
|
-
|
|
746
|
+
A field group is a `Card` containing one or more `Field` rows. Each field has a label, control, and helper text (one short sentence). Fields auto-save on blur with an inline checkmark; an explicit "Save changes" button is reserved for grouped forms.
|
|
727
747
|
|
|
728
|
-
|
|
729
|
-
tab list with the full SettingsNav (16 sections). The active section
|
|
730
|
-
lights up in the sidebar and the main panel scrolls to it.
|
|
748
|
+
### 10.3 Settings discovery
|
|
731
749
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
│ 💬 │ ────── │
|
|
736
|
-
│ 🤖 │ Accent color [color picker] │
|
|
737
|
-
│ ... │ Font family [Inter ▾] │
|
|
738
|
-
│ ⚙ → │ Compact mode [▢] │
|
|
739
|
-
│ │ │
|
|
740
|
-
│ ▼ │ Layout │
|
|
741
|
-
│ Theme│ ────── │
|
|
742
|
-
│ Layo │ UI layout (•) sidebar ( ) topnav ( ) both│
|
|
743
|
-
│ Net │ Show header [✓] │
|
|
744
|
-
│ Auth │ │
|
|
745
|
-
│ ... │ │
|
|
746
|
-
└──────┴───────────────────────────────────────────────┘
|
|
747
|
-
```
|
|
750
|
+
- Every setting is reachable via Cmd+K (palette).
|
|
751
|
+
- Every setting is reachable via `/settings` breadcrumb.
|
|
752
|
+
- The settings sidebar is **the only** place that lives in the page (not the global sidebar) so it has room to breathe.
|
|
748
753
|
|
|
749
754
|
---
|
|
750
755
|
|
|
751
|
-
## 11 ·
|
|
756
|
+
## 11 · Accessibility
|
|
752
757
|
|
|
753
|
-
|
|
758
|
+
WCAG 2.2 AA is the floor. We aim higher where it does not cost.
|
|
754
759
|
|
|
755
|
-
|
|
756
|
-
|---|---|
|
|
757
|
-
| 11px | Inline-with-text icons (chat thread head, info panel headers) |
|
|
758
|
-
| 12px | Button icons, badge icons |
|
|
759
|
-
| 14px | Topbar & sidebar nav icons |
|
|
760
|
-
| 16px | Card-level icons |
|
|
761
|
-
| 18px | Sidebar collapsed icons (intentional bump for visibility) |
|
|
762
|
-
| 20px | Hero / empty-state |
|
|
760
|
+
### 11.1 Color & contrast
|
|
763
761
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
762
|
+
- All text/background pairs meet **AA 4.5:1** (body) and **AA 3:1** (large text, icons).
|
|
763
|
+
- Charts use shape + color (never color alone).
|
|
764
|
+
- Status indicators always have a shape or label in addition to color (green dot + "live"; red dot + "errored").
|
|
767
765
|
|
|
768
|
-
|
|
766
|
+
### 11.2 Keyboard
|
|
769
767
|
|
|
770
|
-
|
|
768
|
+
- Every interactive element is reachable via Tab.
|
|
769
|
+
- Focus order is visual order.
|
|
770
|
+
- Focus ring is always visible on keyboard focus.
|
|
771
|
+
- Modals trap focus; popovers return focus on close.
|
|
772
|
+
- Drag-and-drop has a keyboard alternative (`Space` to pick up, arrows to move, `Enter` to drop, `Esc` to cancel).
|
|
771
773
|
|
|
772
|
-
|
|
773
|
-
- `:focus-visible` ring: 2px `--accent` outline, 2px offset, 4px
|
|
774
|
-
radius.
|
|
775
|
-
- Keyboard navigation: tab order follows visual order. Modals trap
|
|
776
|
-
focus. Esc closes. `Cmd/Ctrl+K` opens search.
|
|
777
|
-
- Skip-to-main link (v4.8.0): visually hidden until focused, then pops
|
|
778
|
-
in at top-left.
|
|
779
|
-
- `aria-current="true"` on active nav, active session.
|
|
780
|
-
- `aria-live="polite"` on the chat log region.
|
|
781
|
-
- `aria-selected` on tabs.
|
|
782
|
-
- Color is never the sole signal — always pair with text or icon.
|
|
774
|
+
### 11.3 Screen readers
|
|
783
775
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
776
|
+
- Every icon-only button has `aria-label`.
|
|
777
|
+
- Every form control has a `<label>` (visible or sr-only).
|
|
778
|
+
- Live regions (`aria-live="polite"`) for activity updates and toasts.
|
|
779
|
+
- Tables use `<th scope="col">`; data tables announce sort state.
|
|
787
780
|
|
|
788
|
-
|
|
789
|
-
`MobileApp.tsx`):
|
|
781
|
+
### 11.4 Motion
|
|
790
782
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
| 1100–1439 | 3-column chat, sidebar collapses to icons, info panel optional |
|
|
795
|
-
| 768–1099 | Topbar-only layout, info panel becomes sheet |
|
|
796
|
-
| < 768 | Mobile shell takes over (separate code path) |
|
|
783
|
+
- `prefers-reduced-motion` zeroes motion tokens (§6.3).
|
|
784
|
+
- Auto-playing animations have a pause control.
|
|
785
|
+
- Drag/drop has a non-motion alternative.
|
|
797
786
|
|
|
798
|
-
|
|
799
|
-
is its own tree with its own components.
|
|
800
|
-
|
|
801
|
-
---
|
|
787
|
+
### 11.5 Touch & pointer
|
|
802
788
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
blocker.
|
|
807
|
-
|
|
808
|
-
- ❌ **Left color stripes on containers.** `box-shadow: inset 2px 0 0`,
|
|
809
|
-
`border-left: 3px solid`, or any vertical accent edge. Use background,
|
|
810
|
-
weight, glow, or motion instead.
|
|
811
|
-
- ❌ **Purple gradient backgrounds behind text or as page chrome.**
|
|
812
|
-
Gradients are reserved for the greeting/brand mark only.
|
|
813
|
-
- ❌ **Generic emoji as feature icons** in cards, lists, or empty
|
|
814
|
-
states. Use Lucide or `ᛒ`.
|
|
815
|
-
- ❌ **Spinners on disabled buttons.** Use a button-loading state or
|
|
816
|
-
replace the button with the spinner.
|
|
817
|
-
- ❌ **Inter as display face at >32px.** Inter is body. If you need a
|
|
818
|
-
display face, propose it in a PR and add the stack to `--font-display`.
|
|
819
|
-
- ❌ **Filler copy**: "Feature One", "Lorem ipsum", invented metrics.
|
|
820
|
-
- ❌ **Raw hex outside `:root`.** All colors must reference a token.
|
|
821
|
-
- ❌ **Row striping in tables.** Use hover wash only.
|
|
822
|
-
- ❌ **Shadowed hairlines.** Borders OR shadows, not both.
|
|
823
|
-
- ❌ **Status conveyed by color alone.** Always pair with text/icon.
|
|
824
|
-
- ❌ **Decimal alignment broken.** Numerics in tables must use
|
|
825
|
-
`tabular-nums` or be right-aligned.
|
|
826
|
-
- ❌ **Horizontal scroll on viewport ≥ 1100px.** If your component
|
|
827
|
-
breaks the layout, fix the component.
|
|
789
|
+
- Minimum target size: **44x44px** for touch (mobile/tablet), **24x24px** for desktop.
|
|
790
|
+
- Right-click has a long-press alternative on touch (650ms hold).
|
|
791
|
+
- Hover-only patterns have a focus equivalent.
|
|
828
792
|
|
|
829
793
|
---
|
|
830
794
|
|
|
831
|
-
##
|
|
832
|
-
|
|
833
|
-
Every view declares the data it consumes. Mock data lives in
|
|
834
|
-
`canvas.html` for visual development; the live API endpoint that
|
|
835
|
-
backs each view is documented in `docs/api.md`.
|
|
836
|
-
|
|
837
|
-
### 15.1 Overview
|
|
838
|
-
|
|
839
|
-
**Layout:** §10.9. **Endpoint:** `GET /snapshot.overview`.
|
|
840
|
-
|
|
841
|
-
```ts
|
|
842
|
-
interface OverviewData {
|
|
843
|
-
// Live activity (last 50 items, newest first)
|
|
844
|
-
recentActivity: ActivityItem[];
|
|
845
|
-
|
|
846
|
-
// Hero metrics
|
|
847
|
-
metrics: {
|
|
848
|
-
tokensPerHour: number;
|
|
849
|
-
avgLatencyMs: number;
|
|
850
|
-
errorRate: number; // 0..1
|
|
851
|
-
costPerHour: number; // USD
|
|
852
|
-
activeBgAgents: number;
|
|
853
|
-
activeSessions: number;
|
|
854
|
-
};
|
|
855
|
-
|
|
856
|
-
// Active agents (subset of BackgroundAgents)
|
|
857
|
-
activeAgents: BgInstance[];
|
|
858
|
-
|
|
859
|
-
// Memory health (4 sources)
|
|
860
|
-
memoryHealth: {
|
|
861
|
-
source: 'lightrag' | 'obsidian' | 'gitsync' | 'semantic';
|
|
862
|
-
state: 'ok' | 'degraded' | 'down';
|
|
863
|
-
lastSync: string;
|
|
864
|
-
}[];
|
|
865
|
-
|
|
866
|
-
// Token spend chart (last 24h, hourly buckets)
|
|
867
|
-
tokenSpend: { hour: string; tokens: number; cost: number }[];
|
|
868
|
-
}
|
|
869
|
-
```
|
|
870
|
-
|
|
871
|
-
### 15.2 Chat
|
|
872
|
-
|
|
873
|
-
**Layout:** §10.2. **Endpoints:** `GET /snapshot.sessions` (list),
|
|
874
|
-
`GET /api/cline-sessions` (cline), `POST /api/chat` (send),
|
|
875
|
-
`WS /ws` (stream).
|
|
876
|
-
|
|
877
|
-
```ts
|
|
878
|
-
interface ChatSession {
|
|
879
|
-
id: string;
|
|
880
|
-
title: string;
|
|
881
|
-
mtime: number;
|
|
882
|
-
state: 'idle' | 'streaming' | 'awaiting';
|
|
883
|
-
source: 'bizar' | 'cline';
|
|
884
|
-
agent: string;
|
|
885
|
-
unread?: number;
|
|
886
|
-
pinned?: boolean;
|
|
887
|
-
tree?: { root: AgentTreeNode }; // orchestrator sub-agents
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
interface ChatMessage {
|
|
891
|
-
id: number;
|
|
892
|
-
role: 'user' | 'assistant' | 'tool';
|
|
893
|
-
author: string;
|
|
894
|
-
ts: string; // HH:MM
|
|
895
|
-
text: ReactNode;
|
|
896
|
-
toolCalls?: ToolCall[];
|
|
897
|
-
pinned?: boolean;
|
|
898
|
-
}
|
|
899
|
-
```
|
|
900
|
-
|
|
901
|
-
### 15.3 Agents
|
|
902
|
-
|
|
903
|
-
**Layout:** Roster grid (3-col on ≥1440px, 2-col on ≥1024px, 1-col
|
|
904
|
-
below). **Endpoint:** `GET /snapshot.agents`.
|
|
905
|
-
|
|
906
|
-
```ts
|
|
907
|
-
interface Agent {
|
|
908
|
-
name: string; // 'odin', 'thor', 'mimir', ...
|
|
909
|
-
model: string; // 'anthropic/claude-sonnet-4-6'
|
|
910
|
-
mode: string; // 'plan-then-forseti'
|
|
911
|
-
status: 'idle' | 'busy' | 'stuck' | 'down';
|
|
912
|
-
lastSeen: number;
|
|
913
|
-
tasksCompleted: number;
|
|
914
|
-
avgLatencyMs: number;
|
|
915
|
-
}
|
|
916
|
-
```
|
|
917
|
-
|
|
918
|
-
Each card: avatar (first 2 letters), name (mono), model (dim mono),
|
|
919
|
-
status pill, last seen time, 3 mini stats.
|
|
920
|
-
|
|
921
|
-
### 15.4 Glyphs (Artifacts)
|
|
922
|
-
|
|
923
|
-
**Layout:** Masonry grid of square cards. **Endpoint:**
|
|
924
|
-
`GET /snapshot.artifacts`.
|
|
925
|
-
|
|
926
|
-
```ts
|
|
927
|
-
interface Artifact {
|
|
928
|
-
id: string;
|
|
929
|
-
title: string;
|
|
930
|
-
kind: 'glyph' | 'note' | 'doc';
|
|
931
|
-
createdAt: number;
|
|
932
|
-
thumbnail?: string; // data URL or absent
|
|
933
|
-
size: number; // bytes
|
|
934
|
-
}
|
|
935
|
-
```
|
|
936
|
-
|
|
937
|
-
### 15.5 Tasks
|
|
938
|
-
|
|
939
|
-
**Layout:** 5-column kanban (§9.12). **Endpoint:** `GET /snapshot.tasks`.
|
|
940
|
-
|
|
941
|
-
```ts
|
|
942
|
-
interface Task {
|
|
943
|
-
id: string; // 'T-120'
|
|
944
|
-
title: string;
|
|
945
|
-
col: 'backlog' | 'todo' | 'in_progress' | 'review' | 'done';
|
|
946
|
-
priority: 'high' | 'mid' | 'low';
|
|
947
|
-
tags: string[];
|
|
948
|
-
team?: boolean; // v6 team badge
|
|
949
|
-
by: string; // agent name
|
|
950
|
-
when: string; // 'now', '3h', '1d'
|
|
951
|
-
}
|
|
952
|
-
```
|
|
795
|
+
## 12 · Banned tropes
|
|
953
796
|
|
|
954
|
-
|
|
797
|
+
Audited before every PR via `scripts/check-design-tropes.sh`.
|
|
955
798
|
|
|
956
|
-
**
|
|
799
|
+
- **No gradients.** Anywhere. As backgrounds, as fills, as borders, as button hovers. The accent color is solid. Charts use solid fills. Period.
|
|
800
|
+
- **No vertical accent stripes on containers.** Active state uses background tint + weight + motion. The single permitted edge bar is the 2px active-item bar inside `SidebarItem` (§7.3).
|
|
801
|
+
- **No purple, blue, or rainbow washes.** The accent is green. Charts are grayscale. Status colors are semantic.
|
|
802
|
+
- **No emoji in UI copy.** Use Lucide icons.
|
|
803
|
+
- **No "Lorem ipsum".** Every placeholder is realistic.
|
|
804
|
+
- **No "Feature One / Feature Two".** Labels are real.
|
|
805
|
+
- **No "Loading…" spinners as primary state.** Use skeleton or streaming copy ("Fetching agents…").
|
|
806
|
+
- **No default browser context menus** on any interactive surface.
|
|
807
|
+
- **No modal-on-modal stacking.** A modal cannot open another modal without an explicit close.
|
|
808
|
+
- **No tooltips on disabled buttons.** Tooltip on hover only when the action is enabled; if disabled, helper text appears inline.
|
|
809
|
+
- **No invented metrics.** Real numbers or "—" placeholder.
|
|
810
|
+
- **No glass / blur / noise effects.** Surfaces are solid fills.
|
|
811
|
+
- **No animated icons** except the live indicator pulse.
|
|
957
812
|
|
|
958
|
-
|
|
959
|
-
interface ActivityItem {
|
|
960
|
-
kind: 'agent' | 'task' | 'error' | 'info';
|
|
961
|
-
ts: string; // HH:MM
|
|
962
|
-
text: ReactNode; // allows inline mono spans
|
|
963
|
-
target?: string; // optional file/task id
|
|
964
|
-
}
|
|
965
|
-
```
|
|
966
|
-
|
|
967
|
-
### 15.7 Active (Background agents)
|
|
968
|
-
|
|
969
|
-
**Layout:** §10.11. **Endpoints:** `GET /background`, `WS bg:*`.
|
|
970
|
-
|
|
971
|
-
```ts
|
|
972
|
-
interface BgInstance {
|
|
973
|
-
instanceId: string;
|
|
974
|
-
agent: string;
|
|
975
|
-
prompt: string;
|
|
976
|
-
status: 'pending' | 'running' | 'paused' | 'done' | 'failed';
|
|
977
|
-
startedAt: number;
|
|
978
|
-
elapsedMs: number;
|
|
979
|
-
toolCalls: BgToolCall[];
|
|
980
|
-
output: string; // last 32k chars
|
|
981
|
-
stuck?: boolean; // server-flagged
|
|
982
|
-
}
|
|
983
|
-
```
|
|
984
|
-
|
|
985
|
-
### 15.8 Skills
|
|
986
|
-
|
|
987
|
-
**Layout:** Card grid (3-col), each card collapsible. **Endpoint:**
|
|
988
|
-
`GET /skills` (planned).
|
|
989
|
-
|
|
990
|
-
```ts
|
|
991
|
-
interface Skill {
|
|
992
|
-
id: string; // 'design-taste-frontend'
|
|
993
|
-
name: string;
|
|
994
|
-
description: string;
|
|
995
|
-
enabled: boolean;
|
|
996
|
-
triggers: string[];
|
|
997
|
-
updatedAt: number;
|
|
998
|
-
}
|
|
999
|
-
```
|
|
1000
|
-
|
|
1001
|
-
### 15.9 Memory
|
|
1002
|
-
|
|
1003
|
-
**Layout:** 3-column (source rail · main panel · detail). **Endpoint:**
|
|
1004
|
-
`GET /memory/overview`, `GET /memory/{source}`, `POST /memory/search`.
|
|
1005
|
-
|
|
1006
|
-
```ts
|
|
1007
|
-
interface MemoryOverview {
|
|
1008
|
-
sources: {
|
|
1009
|
-
id: 'lightrag' | 'obsidian' | 'gitsync' | 'semantic';
|
|
1010
|
-
state: 'ok' | 'degraded' | 'down';
|
|
1011
|
-
noteCount: number;
|
|
1012
|
-
lastSync: number;
|
|
1013
|
-
}[];
|
|
1014
|
-
recent: MemoryNote[];
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
interface MemoryNote {
|
|
1018
|
-
id: string;
|
|
1019
|
-
source: MemoryOverview['sources'][number]['id'];
|
|
1020
|
-
title: string;
|
|
1021
|
-
preview: string;
|
|
1022
|
-
tags: string[];
|
|
1023
|
-
updatedAt: number;
|
|
1024
|
-
}
|
|
1025
|
-
```
|
|
1026
|
-
|
|
1027
|
-
### 15.10 Mods
|
|
813
|
+
---
|
|
1028
814
|
|
|
1029
|
-
|
|
1030
|
-
|
|
815
|
+
## 13 · Visual contract for new screens
|
|
816
|
+
|
|
817
|
+
A new screen must:
|
|
818
|
+
|
|
819
|
+
1. Pick one of the seven layouts from §7 (default: topbar + sidebar).
|
|
820
|
+
2. Use tokens from §3 only — never raw colors.
|
|
821
|
+
3. Use type from §4 only — never custom families.
|
|
822
|
+
4. Use motion from §6 only — never bespoke easings.
|
|
823
|
+
5. Use icons from `lucide-react` — never emoji or custom SVGs (unless domain-specific, in which case it goes in `ui/icons/`).
|
|
824
|
+
6. Use components from `ui/` only — never rebuild primitives.
|
|
825
|
+
7. Honor density mode (§5.3).
|
|
826
|
+
8. Honor `prefers-reduced-motion`.
|
|
827
|
+
9. Honor `prefers-color-scheme` via the theme system.
|
|
828
|
+
10. Have right-click context menus on every interactive element.
|
|
829
|
+
11. Have keyboard shortcuts for every action.
|
|
830
|
+
12. Have an empty state, a loading state, and an error state.
|
|
831
|
+
13. Have at least one place where the green accent earns its keep.
|
|
832
|
+
14. Document its data shape in `bizar-dash/src/web/views/<name>/README.md`.
|
|
833
|
+
15. Have a colocated `.test.tsx` file with the AAA pattern.
|
|
1031
834
|
|
|
1032
|
-
|
|
1033
|
-
interface Mod {
|
|
1034
|
-
id: string;
|
|
1035
|
-
name: string;
|
|
1036
|
-
version: string;
|
|
1037
|
-
enabled: boolean;
|
|
1038
|
-
hasViews: boolean;
|
|
1039
|
-
installPath: string;
|
|
1040
|
-
updatedAt: number;
|
|
1041
|
-
}
|
|
1042
|
-
```
|
|
835
|
+
---
|
|
1043
836
|
|
|
1044
|
-
|
|
837
|
+
## 14 · Pre-merge checklist
|
|
1045
838
|
|
|
1046
|
-
|
|
1047
|
-
toggle. **Endpoint:** `GET /schedules`.
|
|
839
|
+
Run before opening a PR that touches UI:
|
|
1048
840
|
|
|
1049
|
-
```
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
enabled: boolean;
|
|
1057
|
-
lastRun: number | null;
|
|
1058
|
-
lastResult: 'ok' | 'fail' | null;
|
|
1059
|
-
nextRun: number;
|
|
1060
|
-
}
|
|
841
|
+
```sh
|
|
842
|
+
pnpm check:design-tropes # grep for banned patterns (§12)
|
|
843
|
+
pnpm check:a11y # axe-core on every new page
|
|
844
|
+
pnpm check:visual # screenshot diff at 1440/1100/768/390
|
|
845
|
+
pnpm test -- ui # component tests
|
|
846
|
+
pnpm e2e # full app boots, no console errors
|
|
847
|
+
pnpm check:keyboard # manual keyboard-only walkthrough (CI recorded)
|
|
1061
848
|
```
|
|
1062
849
|
|
|
1063
|
-
|
|
850
|
+
All five must pass. The visual diff must not regress at any of the four widths. The keyboard walkthrough must reach every interactive element via Tab only.
|
|
1064
851
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
```ts
|
|
1068
|
-
interface UsageData {
|
|
1069
|
-
range: '24h' | '7d' | '30d';
|
|
1070
|
-
totalCost: number;
|
|
1071
|
-
totalTokens: number;
|
|
1072
|
-
costPerHour: number;
|
|
1073
|
-
byModel: { model: string; tokens: number; cost: number }[];
|
|
1074
|
-
byHour: { hour: string; tokens: number; cost: number }[];
|
|
1075
|
-
alerts: { ts: number; severity: 'warn' | 'error'; text: string }[];
|
|
1076
|
-
budgets: { id: string; label: string; cap: number; spent: number }[];
|
|
1077
|
-
}
|
|
1078
|
-
```
|
|
852
|
+
---
|
|
1079
853
|
|
|
1080
|
-
|
|
854
|
+
## Appendix A · shadcn preset `b7kBsBkh7b`
|
|
1081
855
|
|
|
1082
|
-
|
|
1083
|
-
`GET /eval/runs`, `GET /eval/runs/:id`.
|
|
856
|
+
The dashboard is initialized with:
|
|
1084
857
|
|
|
1085
|
-
```
|
|
1086
|
-
|
|
1087
|
-
id: string;
|
|
1088
|
-
startedAt: number;
|
|
1089
|
-
finishedAt: number | null;
|
|
1090
|
-
passed: number;
|
|
1091
|
-
total: number;
|
|
1092
|
-
cases: { name: string; pass: boolean; latencyMs: number }[];
|
|
1093
|
-
}
|
|
858
|
+
```sh
|
|
859
|
+
pnpm dlx shadcn@latest init --preset b7kBsBkh7b
|
|
1094
860
|
```
|
|
1095
861
|
|
|
1096
|
-
|
|
862
|
+
Per the [shadcn CLI v4 changelog](https://ui.shadcn.com/docs/changelog/2026-03-cli-v4), presets are opaque codes resolved by the CLI. The `b7kBsBkh7b` preset ships:
|
|
1097
863
|
|
|
1098
|
-
|
|
1099
|
-
`
|
|
864
|
+
- Pre-configured `components.json` (style: `new-york`, base color: `neutral`, CSS variables: `yes`, icon library: `lucide`).
|
|
865
|
+
- Pre-tuned `tailwind.config.ts` with the OKLch color ramp.
|
|
866
|
+
- Pre-installed primitives matching the foundation in §3.
|
|
1100
867
|
|
|
1101
|
-
|
|
1102
|
-
interface DoctorData {
|
|
1103
|
-
checkedAt: number;
|
|
1104
|
-
overall: number; // 0..8
|
|
1105
|
-
subsystems: {
|
|
1106
|
-
name: string;
|
|
1107
|
-
state: 'ok' | 'degraded' | 'warning' | 'error';
|
|
1108
|
-
score: number;
|
|
1109
|
-
total: number;
|
|
1110
|
-
note: string;
|
|
1111
|
-
}[];
|
|
1112
|
-
}
|
|
1113
|
-
```
|
|
868
|
+
If the preset resolves to a different package set than expected, the plan still holds: §3 is the contract, the preset is the bootstrap. Any preset mismatch is resolved by overriding `components.json` and running `pnpm dlx shadcn@latest add <component>` for each missing primitive in §8.
|
|
1114
869
|
|
|
1115
|
-
|
|
870
|
+
The provided OKLch theme in the user's brief maps directly to §3 — every token in `:root` (light) and `.dark` is taken verbatim from the brief, then extended with the geometry, motion, and z-index tokens that the preset does not cover.
|
|
1116
871
|
|
|
1117
|
-
|
|
1118
|
-
`GET /harness/audit`.
|
|
872
|
+
---
|
|
1119
873
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
874
|
+
## Appendix B · File map
|
|
875
|
+
|
|
876
|
+
```
|
|
877
|
+
bizar-dash/src/web/
|
|
878
|
+
├── App.tsx
|
|
879
|
+
├── main.tsx
|
|
880
|
+
├── ui/
|
|
881
|
+
│ ├── index.ts # barrel export
|
|
882
|
+
│ ├── primitives/
|
|
883
|
+
│ ├── controls/
|
|
884
|
+
│ ├── feedback/
|
|
885
|
+
│ ├── data/
|
|
886
|
+
│ ├── navigation/
|
|
887
|
+
│ ├── kanban/
|
|
888
|
+
│ ├── popups/
|
|
889
|
+
│ ├── theme/
|
|
890
|
+
│ ├── hooks/
|
|
891
|
+
│ ├── utils/
|
|
892
|
+
│ └── styles/
|
|
893
|
+
│ ├── reset.css
|
|
894
|
+
│ ├── tokens.css # the entire §3, generated from JSON
|
|
895
|
+
│ └── globals.css
|
|
896
|
+
├── views/
|
|
897
|
+
│ ├── Overview/
|
|
898
|
+
│ ├── Tasks/
|
|
899
|
+
│ ├── Goals/
|
|
900
|
+
│ ├── Agents/
|
|
901
|
+
│ ├── Activity/
|
|
902
|
+
│ ├── Memory/
|
|
903
|
+
│ ├── Libraries/
|
|
904
|
+
│ └── Settings/
|
|
905
|
+
├── icons/ # domain-specific Lucide extensions
|
|
906
|
+
├── routes.tsx # TanStack Router route tree
|
|
907
|
+
└── server/ # existing REST API (unchanged)
|
|
1125
908
|
```
|
|
1126
909
|
|
|
1127
|
-
### 15.16 Settings
|
|
1128
|
-
|
|
1129
|
-
**Layout:** §10.12. **Endpoint:** `GET /settings`, `POST /settings`.
|
|
1130
|
-
|
|
1131
|
-
16 sections: theme, updates, layout, general, env-vars, network,
|
|
1132
|
-
notifications, auth, agents, dashboard, background, system-llm,
|
|
1133
|
-
headroom, activity-log, workspaces, about. Each section is its own
|
|
1134
|
-
component in `src/web/views/settings/`.
|
|
1135
|
-
|
|
1136
910
|
---
|
|
1137
911
|
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
- v7.0 — this document. Adds view index, data shapes, 5 new component
|
|
1141
|
-
patterns (DAG, approvals, cost chart, BG panel, workflow). Token
|
|
1142
|
-
system migrated to OKLch + color-mix.
|
|
1143
|
-
- v6.0.0 — Cline runtime badge, Harness tab, Tasks kanban team badge,
|
|
1144
|
-
brand version pill, Mods-only navigation.
|
|
1145
|
-
- v5.x — Eval framework, Doctor page.
|
|
1146
|
-
- v4.x — Settings mode, char-counter, semi-collapsed topbar, slash
|
|
1147
|
-
commands.
|
|
1148
|
-
- v3.x — Mods system, chat overhaul (3-column, rail, info panel),
|
|
1149
|
-
semantic spacing aliases, command palette.
|
|
1150
|
-
- v2.x — Light theme, kanban board, hooks refactor.
|
|
1151
|
-
|
|
1152
|
-
Future changes update this file first, then ship.
|
|
912
|
+
**End of DESIGN.md — v8.0.0**
|