@polderlabs/bizar 10.4.2 → 10.4.4
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/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js → ActivityFeed-RQeyFifx.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js.map → ActivityFeed-RQeyFifx.js.map} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js → ActivityView-CibyssPM.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js.map → ActivityView-CibyssPM.js.map} +1 -1
- package/bizar-dash/dist/assets/AdminView-BjczABeB.js +11 -0
- package/bizar-dash/dist/assets/AdminView-BjczABeB.js.map +1 -0
- package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js → AgentActivity-Bywt1twv.js} +1 -1
- package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js.map → AgentActivity-Bywt1twv.js.map} +1 -1
- package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js +15 -0
- package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js.map +1 -0
- package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js → Alert-BZGk39mB.js} +1 -1
- package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js.map → Alert-BZGk39mB.js.map} +1 -1
- package/bizar-dash/dist/assets/{ArtifactsView-znhN8GTR.js → ArtifactsView-CfYB1le1.js} +3 -3
- package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js.map +1 -0
- package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js → AuthView-D4frSShw.js} +1 -1
- package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js.map → AuthView-D4frSShw.js.map} +1 -1
- package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js +6 -0
- package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js.map +1 -0
- package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js → BackgroundJobsView-DEStvILz.js} +1 -1
- package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js.map → BackgroundJobsView-DEStvILz.js.map} +1 -1
- package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js → BackupView-B875KQa4.js} +1 -1
- package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js.map → BackupView-B875KQa4.js.map} +1 -1
- package/bizar-dash/dist/assets/Banner-C8HEcT5l.js +1 -0
- package/bizar-dash/dist/assets/Banner-C8HEcT5l.js.map +1 -0
- package/bizar-dash/dist/assets/{Card-rF59wHiO.js → Card-BtsmkhJa.js} +1 -1
- package/bizar-dash/dist/assets/{Card-rF59wHiO.js.map → Card-BtsmkhJa.js.map} +1 -1
- package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js +9 -0
- package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js.map +1 -0
- package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js → Chip-XPOk0d_E.js} +1 -1
- package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js.map → Chip-XPOk0d_E.js.map} +1 -1
- package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js → ClaudeSessionsView-BprGo67K.js} +1 -1
- package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js.map → ClaudeSessionsView-BprGo67K.js.map} +1 -1
- package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js +1 -0
- package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js.map +1 -0
- package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js → ConfigView-BntUrW7s.js} +1 -1
- package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js.map → ConfigView-BntUrW7s.js.map} +1 -1
- package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js +2 -0
- package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js.map +1 -0
- package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js +6 -0
- package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js.map +1 -0
- package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js → DoctorView-DepBdQGR.js} +2 -2
- package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js.map → DoctorView-DepBdQGR.js.map} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js → EmptyState-DjKtY1Qi.js} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js.map → EmptyState-DjKtY1Qi.js.map} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js → EnvVarsView-S4Pbm128.js} +3 -3
- package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js.map → EnvVarsView-S4Pbm128.js.map} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js → ErrorState-CBJbEQ8B.js} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js.map → ErrorState-CBJbEQ8B.js.map} +1 -1
- package/bizar-dash/dist/assets/EvalView-BeAyMCD1.js +1 -0
- package/bizar-dash/dist/assets/{EvalView-CpdFu_ID.js.map → EvalView-BeAyMCD1.js.map} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js → GoalsView-BZr8In4c.js} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js.map → GoalsView-BZr8In4c.js.map} +1 -1
- package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js → Grid--WKvqu5h.js} +1 -1
- package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js.map → Grid--WKvqu5h.js.map} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js → HistoryView-djEbzqtk.js} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js.map → HistoryView-djEbzqtk.js.map} +1 -1
- package/bizar-dash/dist/assets/{Input-CZmRw5QX.js → Input-h_nSOtwm.js} +1 -1
- package/bizar-dash/dist/assets/{Input-CZmRw5QX.js.map → Input-h_nSOtwm.js.map} +1 -1
- package/bizar-dash/dist/assets/LibrariesView-Vez8CvNq.js +6 -0
- package/bizar-dash/dist/assets/{LibrariesView-B1YX9wzp.js.map → LibrariesView-Vez8CvNq.js.map} +1 -1
- package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js → LightRAGView-DvqzQoBp.js} +1 -1
- package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js.map → LightRAGView-DvqzQoBp.js.map} +1 -1
- package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js → ListHeader-CM8QoIWG.js} +1 -1
- package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js.map → ListHeader-CM8QoIWG.js.map} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js → MemoryView-DnL8E2vI.js} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js.map → MemoryView-DnL8E2vI.js.map} +1 -1
- package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js → MessageBubble-CrCJ0SYG.js} +1 -1
- package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js.map → MessageBubble-CrCJ0SYG.js.map} +1 -1
- package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js +1 -0
- package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js.map +1 -0
- package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js → ModsView-BVM3X5xc.js} +1 -1
- package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js.map → ModsView-BVM3X5xc.js.map} +1 -1
- package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js +6 -0
- package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js.map +1 -0
- package/bizar-dash/dist/assets/ObsidianView-mI3qW9OP.js +1 -0
- package/bizar-dash/dist/assets/{ObsidianView-Ci80gnwS.js.map → ObsidianView-mI3qW9OP.js.map} +1 -1
- package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js +1 -0
- package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js.map +1 -0
- package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js → ProgressBar-BnaBqv-W.js} +1 -1
- package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js.map → ProgressBar-BnaBqv-W.js.map} +1 -1
- package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js +11 -0
- package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js.map +1 -0
- package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js → ProvidersView-2cn-TALE.js} +2 -2
- package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js.map → ProvidersView-2cn-TALE.js.map} +1 -1
- package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js → SchedulesView-o9AtIsH9.js} +1 -1
- package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js.map → SchedulesView-o9AtIsH9.js.map} +1 -1
- package/bizar-dash/dist/assets/{Select-0VcfTDeL.js → Select-CiGWEN8I.js} +1 -1
- package/bizar-dash/dist/assets/{Select-0VcfTDeL.js.map → Select-CiGWEN8I.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js → SettingsRow-CflGJymA.js} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js.map → SettingsRow-CflGJymA.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js → SettingsView-2HSFJPPK.js} +1 -1
- package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js.map → SettingsView-2HSFJPPK.js.map} +1 -1
- package/bizar-dash/dist/assets/{Sheet-BOProMs2.js → Sheet-B-CMP9-_.js} +1 -1
- package/bizar-dash/dist/assets/{Sheet-BOProMs2.js.map → Sheet-B-CMP9-_.js.map} +1 -1
- package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js → Slider-Z4TP_CXY.js} +1 -1
- package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js.map → Slider-Z4TP_CXY.js.map} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js → Sparkline-cvkv2HbU.js} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js.map → Sparkline-cvkv2HbU.js.map} +1 -1
- package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js → Switch-jcYo4lmp.js} +1 -1
- package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js.map → Switch-jcYo4lmp.js.map} +1 -1
- package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js → TasksView-CQaSFzWY.js} +2 -2
- package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js.map → TasksView-CQaSFzWY.js.map} +1 -1
- package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js → Textarea-xnAybFGd.js} +1 -1
- package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js.map → Textarea-xnAybFGd.js.map} +1 -1
- package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js +1 -0
- package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js.map +1 -0
- package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js → UsageView-DMFbBOfH.js} +1 -1
- package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js.map → UsageView-DMFbBOfH.js.map} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js → ViewHeader-C-t1U2cQ.js} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js.map → ViewHeader-C-t1U2cQ.js.map} +1 -1
- package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js +1 -0
- package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js.map +1 -0
- package/bizar-dash/dist/assets/{brain-CwZt9Kta.js → brain-DhAzcHUk.js} +1 -1
- package/bizar-dash/dist/assets/{brain-CwZt9Kta.js.map → brain-DhAzcHUk.js.map} +1 -1
- package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js → calendar-B9Wbemh7.js} +1 -1
- package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js.map → calendar-B9Wbemh7.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js → circle-6NJF_Xl6.js} +1 -1
- package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js.map → circle-6NJF_Xl6.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js → circle-alert-Dz8lGfCZ.js} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js.map → circle-alert-Dz8lGfCZ.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js → circle-check-DFB50ojt.js} +1 -1
- package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js.map → circle-check-DFB50ojt.js.map} +1 -1
- package/bizar-dash/dist/assets/{clock-DEIuPV60.js → clock-ClVA6-hQ.js} +1 -1
- package/bizar-dash/dist/assets/{clock-DEIuPV60.js.map → clock-ClVA6-hQ.js.map} +1 -1
- package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js → cmdk-C3F6LD6N.js} +5 -5
- package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js.map → cmdk-C3F6LD6N.js.map} +1 -1
- package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js → dnd-kit-BAOLODOI.js} +1 -1
- package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js.map → dnd-kit-BAOLODOI.js.map} +1 -1
- package/bizar-dash/dist/assets/{download-Clkq90Ct.js → download-BvJddD8D.js} +1 -1
- package/bizar-dash/dist/assets/{download-Clkq90Ct.js.map → download-BvJddD8D.js.map} +1 -1
- package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js → external-link-DvL89gaZ.js} +1 -1
- package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js.map → external-link-DvL89gaZ.js.map} +1 -1
- package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js → file-text-BOroDtZE.js} +1 -1
- package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js.map → file-text-BOroDtZE.js.map} +1 -1
- package/bizar-dash/dist/assets/{filter-BcbE37wP.js → filter-DwPjMRQt.js} +1 -1
- package/bizar-dash/dist/assets/{filter-BcbE37wP.js.map → filter-DwPjMRQt.js.map} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js → git-pull-request-TDb1inux.js} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js.map → git-pull-request-TDb1inux.js.map} +1 -1
- package/bizar-dash/dist/assets/{index-CASP1n-5.js → index-B1OIS316.js} +1 -1
- package/bizar-dash/dist/assets/{index-CASP1n-5.js.map → index-B1OIS316.js.map} +1 -1
- package/bizar-dash/dist/assets/{index-C4Vq_2LM.js → index-CR0TeJmc.js} +1 -1
- package/bizar-dash/dist/assets/{index-C4Vq_2LM.js.map → index-CR0TeJmc.js.map} +1 -1
- package/bizar-dash/dist/assets/{main-CcQfRfIJ.css → main-B7D_IMTh.css} +1 -1
- package/bizar-dash/dist/assets/main-BURAlktW.js +277 -0
- package/bizar-dash/dist/assets/main-BURAlktW.js.map +1 -0
- package/bizar-dash/dist/assets/{network-DJdvVaHx.js → network-BcCoCzIY.js} +1 -1
- package/bizar-dash/dist/assets/{network-DJdvVaHx.js.map → network-BcCoCzIY.js.map} +1 -1
- package/bizar-dash/dist/assets/{pause-DUn9L5PB.js → pause-BllItT2_.js} +1 -1
- package/bizar-dash/dist/assets/{pause-DUn9L5PB.js.map → pause-BllItT2_.js.map} +1 -1
- package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js → pencil-DAwM-CC3.js} +1 -1
- package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js.map → pencil-DAwM-CC3.js.map} +1 -1
- package/bizar-dash/dist/assets/{play-CZjsr3XM.js → play-mJh67AXo.js} +2 -2
- package/bizar-dash/dist/assets/{play-CZjsr3XM.js.map → play-mJh67AXo.js.map} +1 -1
- package/bizar-dash/dist/assets/{plug-BKuyIe5W.js → plug-BjfntCMC.js} +1 -1
- package/bizar-dash/dist/assets/{plug-BKuyIe5W.js.map → plug-BjfntCMC.js.map} +1 -1
- package/bizar-dash/dist/assets/{plus-77h62zZm.js → plus-Cm6-fo14.js} +1 -1
- package/bizar-dash/dist/assets/{plus-77h62zZm.js.map → plus-Cm6-fo14.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-DLmx-gCP.js → power-CXN9y2KV.js} +1 -1
- package/bizar-dash/dist/assets/{power-DLmx-gCP.js.map → power-CXN9y2KV.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-off-BFKzHXic.js → power-off-DUZqwMf9.js} +1 -1
- package/bizar-dash/dist/assets/{power-off-BFKzHXic.js.map → power-off-DUZqwMf9.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js → refresh-ccw-DA8_IB9l.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js.map → refresh-ccw-DA8_IB9l.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js → refresh-cw-DwlP59en.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js.map → refresh-cw-DwlP59en.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js → rotate-ccw-DMTASfAn.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js.map → rotate-ccw-DMTASfAn.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js → rotate-cw-BDX5SE2s.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js.map → rotate-cw-BDX5SE2s.js.map} +1 -1
- package/bizar-dash/dist/assets/{save-Db1b-1Uq.js → save-Y0jPK5D6.js} +1 -1
- package/bizar-dash/dist/assets/{save-Db1b-1Uq.js.map → save-Y0jPK5D6.js.map} +1 -1
- package/bizar-dash/dist/assets/{send-yz6HFZM5.js → send-C8wwPHhR.js} +2 -2
- package/bizar-dash/dist/assets/{send-yz6HFZM5.js.map → send-C8wwPHhR.js.map} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js → shield-alert-DEvq9UG0.js} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js.map → shield-alert-DEvq9UG0.js.map} +1 -1
- package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js → trash-2-D6qePV_q.js} +2 -2
- package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js.map → trash-2-D6qePV_q.js.map} +1 -1
- package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js → trending-up-BZzo_1ic.js} +1 -1
- package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js.map → trending-up-BZzo_1ic.js.map} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js → triangle-alert-B2oHbmoh.js} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js.map → triangle-alert-B2oHbmoh.js.map} +1 -1
- package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js → upload-Dy59aZn6.js} +1 -1
- package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js.map → upload-Dy59aZn6.js.map} +1 -1
- package/bizar-dash/dist/assets/{zap-5lAQBAPX.js → zap-DENVhJnO.js} +2 -2
- package/bizar-dash/dist/assets/{zap-5lAQBAPX.js.map → zap-DENVhJnO.js.map} +1 -1
- package/bizar-dash/dist/index.html +3 -3
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/web/v8/App.tsx +87 -6
- package/bizar-dash/src/web/v8/__tests__/chat-view.test.tsx +4 -4
- package/bizar-dash/src/web/v8/shell/AppShell.tsx +38 -2
- package/bizar-dash/src/web/v8/shell/Sidebar.tsx +52 -38
- package/bizar-dash/src/web/v8/shell/Topbar.tsx +62 -3
- package/bizar-dash/src/web/v8/ui/styles/globals.css +40 -0
- package/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +11 -6
- package/bizar-dash/src/web/v8/views/Admin/AdminView.tsx +32 -5
- package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +36 -4
- package/bizar-dash/src/web/v8/views/Artifacts/ArtifactsView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Chat/ChatView.tsx +13 -1
- package/bizar-dash/src/web/v8/views/ClaudeSessions/NewSessionModal.tsx +136 -0
- package/bizar-dash/src/web/v8/views/Clipboard/ClipboardView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +14 -4
- package/bizar-dash/src/web/v8/views/Diagnostics/DiagnosticsView.tsx +50 -7
- package/bizar-dash/src/web/v8/views/Dialogs/DialogsView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +6 -1
- package/bizar-dash/src/web/v8/views/Misc/MiscView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Notifications/NotificationsView.tsx +82 -13
- package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +19 -0
- package/bizar-dash/src/web/v8/views/Projects/ProjectsView.tsx +21 -1
- package/bizar-dash/src/web/v8/views/Voice/VoiceView.tsx +1 -1
- package/bizar-dash/tests/admin-labels.test.mjs +42 -0
- package/bizar-dash/tests/admin-run-grouping.test.mjs +42 -0
- package/bizar-dash/tests/agents-preview-truncate.test.mjs +35 -0
- package/bizar-dash/tests/agents-summary-sanitize.test.ts +51 -0
- package/bizar-dash/tests/chat-new-session.test.mjs +63 -0
- package/bizar-dash/tests/empty-state-docs.test.mjs +55 -0
- package/bizar-dash/tests/focus-visible.test.mjs +30 -0
- package/bizar-dash/tests/kanban-empty-column.test.mjs +56 -0
- package/bizar-dash/tests/library-dedupe.test.mjs +62 -0
- package/bizar-dash/tests/notifications-dismiss-restore.test.mjs +85 -0
- package/bizar-dash/tests/palette-shortcut-hint.test.mjs +58 -0
- package/bizar-dash/tests/projects-filter.test.mjs +48 -0
- package/bizar-dash/tests/settings-labels.test.mjs +80 -0
- package/bizar-dash/tests/sidebar-distinct-icons.test.mjs +28 -0
- package/bizar-dash/tests/sidebar-responsive.test.tsx +48 -0
- package/bizar-dash/tests/sidebar-section-toggle.test.tsx +63 -0
- package/bizar-dash/tests/theme-toggle-icon.test.mjs +28 -0
- package/bizar-dash/tests/topbar-design-system.test.mjs +56 -0
- package/bizar-dash/vite.config.ts +8 -0
- package/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js +0 -11
- package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js.map +0 -1
- package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js +0 -13
- package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js.map +0 -1
- package/bizar-dash/dist/assets/ArtifactsView-znhN8GTR.js.map +0 -1
- package/bizar-dash/dist/assets/Avatar-B41upSD1.js +0 -6
- package/bizar-dash/dist/assets/Avatar-B41upSD1.js.map +0 -1
- package/bizar-dash/dist/assets/ChatView-CUriVEgU.js +0 -9
- package/bizar-dash/dist/assets/ChatView-CUriVEgU.js.map +0 -1
- package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js +0 -1
- package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js.map +0 -1
- package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js +0 -2
- package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js.map +0 -1
- package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js +0 -6
- package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js.map +0 -1
- package/bizar-dash/dist/assets/EvalView-CpdFu_ID.js +0 -1
- package/bizar-dash/dist/assets/LibrariesView-B1YX9wzp.js +0 -6
- package/bizar-dash/dist/assets/MiscView-DLNEGdML.js +0 -1
- package/bizar-dash/dist/assets/MiscView-DLNEGdML.js.map +0 -1
- package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js +0 -6
- package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js.map +0 -1
- package/bizar-dash/dist/assets/ObsidianView-Ci80gnwS.js +0 -1
- package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js +0 -1
- package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js.map +0 -1
- package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js +0 -11
- package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js.map +0 -1
- package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js +0 -6
- package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js.map +0 -1
- package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js +0 -1
- package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js.map +0 -1
- package/bizar-dash/dist/assets/main-Cxeu4LhG.js +0 -244
- package/bizar-dash/dist/assets/main-Cxeu4LhG.js.map +0 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Suspense, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { Menu } from 'lucide-react';
|
|
2
3
|
import { AppShell } from './shell/AppShell.js';
|
|
3
4
|
import { Topbar } from './shell/Topbar.js';
|
|
4
5
|
import { Sidebar, type SidebarSection } from './shell/Sidebar.js';
|
|
5
6
|
import { Box } from './ui/primitives/Box.js';
|
|
6
7
|
import { Inline } from './ui/primitives/Inline.js';
|
|
8
|
+
import { Button } from './ui/controls/Button.js';
|
|
7
9
|
import { useViewForId } from './views/Router.js';
|
|
8
10
|
import { AppCommandPalette } from './views/CommandPalette/AppCommandPalette.js';
|
|
9
11
|
import { useCommandPaletteHotkey } from './ui/navigation/CommandPalette.js';
|
|
@@ -139,6 +141,7 @@ function iconFor(id: string): LucideIcon {
|
|
|
139
141
|
|
|
140
142
|
export function App(): JSX.Element {
|
|
141
143
|
const [activeId, setActiveId] = useState<string>('overview');
|
|
144
|
+
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
142
145
|
const theme = useTheme();
|
|
143
146
|
const density = useDensity();
|
|
144
147
|
|
|
@@ -154,6 +157,36 @@ export function App(): JSX.Element {
|
|
|
154
157
|
mainRef.current?.focus({ preventScroll: true });
|
|
155
158
|
}, [activeId]);
|
|
156
159
|
|
|
160
|
+
// H6 — URL routing: sync activeId to/from window.location.hash.
|
|
161
|
+
// On mount, parse the hash (e.g. "#/tasks") and set activeId.
|
|
162
|
+
// On popstate (browser back/forward), re-parse and update.
|
|
163
|
+
// On every activeId change, push the new hash so deep links work.
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
const hash = window.location.hash;
|
|
166
|
+
if (hash.startsWith('#/')) {
|
|
167
|
+
const id = hash.slice(2);
|
|
168
|
+
if (id) setActiveId(id);
|
|
169
|
+
}
|
|
170
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps -- mount-only
|
|
171
|
+
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
const onPop = (): void => {
|
|
174
|
+
const hash = window.location.hash;
|
|
175
|
+
if (hash.startsWith('#/')) {
|
|
176
|
+
const id = hash.slice(2);
|
|
177
|
+
if (id) setActiveId(id);
|
|
178
|
+
} else {
|
|
179
|
+
setActiveId('overview');
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
window.addEventListener('popstate', onPop);
|
|
183
|
+
return () => window.removeEventListener('popstate', onPop);
|
|
184
|
+
}, []);
|
|
185
|
+
|
|
186
|
+
useEffect(() => {
|
|
187
|
+
window.history.pushState(null, '', '#/' + activeId);
|
|
188
|
+
}, [activeId]);
|
|
189
|
+
|
|
157
190
|
// Live counts for the sidebar. Polled on mount + WS refresh.
|
|
158
191
|
const tasksRes = useFetch<{ tasks?: { id: string; status: string }[]; count?: number }>('/api/tasks');
|
|
159
192
|
const goalsRes = useFetch<{ goals?: { id: string }[]; count?: number }>('/api/goals');
|
|
@@ -288,11 +321,37 @@ export function App(): JSX.Element {
|
|
|
288
321
|
ref={mainRef}
|
|
289
322
|
topbar={
|
|
290
323
|
<Topbar
|
|
324
|
+
leading={
|
|
325
|
+
<button
|
|
326
|
+
type="button"
|
|
327
|
+
aria-label="Open navigation menu"
|
|
328
|
+
data-testid="mobile-menu-toggle"
|
|
329
|
+
onClick={() => setMobileMenuOpen(true)}
|
|
330
|
+
style={{
|
|
331
|
+
display: 'none',
|
|
332
|
+
alignItems: 'center',
|
|
333
|
+
justifyContent: 'center',
|
|
334
|
+
width: 32,
|
|
335
|
+
height: 32,
|
|
336
|
+
background: 'transparent',
|
|
337
|
+
border: '1px solid var(--border)',
|
|
338
|
+
borderRadius: 'var(--radius-sm)',
|
|
339
|
+
color: 'var(--fg-muted)',
|
|
340
|
+
cursor: 'pointer',
|
|
341
|
+
}}
|
|
342
|
+
className="mobile-menu-toggle"
|
|
343
|
+
>
|
|
344
|
+
<Menu size={16} aria-hidden="true" />
|
|
345
|
+
</button>
|
|
346
|
+
}
|
|
291
347
|
center={
|
|
292
348
|
<Inline align="center" gap={2}>
|
|
293
|
-
<
|
|
294
|
-
|
|
349
|
+
<Button
|
|
350
|
+
variant="ghost"
|
|
351
|
+
size="sm"
|
|
295
352
|
onClick={() => setPaletteOpen(true)}
|
|
353
|
+
aria-label="Open command palette"
|
|
354
|
+
data-testid="palette-trigger"
|
|
296
355
|
style={{
|
|
297
356
|
display: 'inline-flex',
|
|
298
357
|
alignItems: 'center',
|
|
@@ -307,7 +366,6 @@ export function App(): JSX.Element {
|
|
|
307
366
|
maxWidth: '100%',
|
|
308
367
|
justifyContent: 'space-between',
|
|
309
368
|
}}
|
|
310
|
-
aria-label="Open command palette"
|
|
311
369
|
>
|
|
312
370
|
<span>Type a command, page, or setting…</span>
|
|
313
371
|
<Box
|
|
@@ -320,7 +378,25 @@ export function App(): JSX.Element {
|
|
|
320
378
|
>
|
|
321
379
|
⌘K
|
|
322
380
|
</Box>
|
|
323
|
-
</
|
|
381
|
+
</Button>
|
|
382
|
+
<Button
|
|
383
|
+
variant="ghost"
|
|
384
|
+
size="icon"
|
|
385
|
+
aria-label="Keyboard shortcuts"
|
|
386
|
+
data-testid="shortcuts-help"
|
|
387
|
+
title="Keyboard shortcuts"
|
|
388
|
+
onClick={() => {
|
|
389
|
+
const shortcuts = [
|
|
390
|
+
'⌘K — Command palette',
|
|
391
|
+
'⌘/ — Toggle sidebar',
|
|
392
|
+
'⌘, — Settings',
|
|
393
|
+
'⌘. — Dismiss notification',
|
|
394
|
+
].join('\n');
|
|
395
|
+
window.alert('Keyboard Shortcuts\n\n' + shortcuts);
|
|
396
|
+
}}
|
|
397
|
+
>
|
|
398
|
+
?
|
|
399
|
+
</Button>
|
|
324
400
|
</Inline>
|
|
325
401
|
}
|
|
326
402
|
/>
|
|
@@ -330,9 +406,14 @@ export function App(): JSX.Element {
|
|
|
330
406
|
sections={sections}
|
|
331
407
|
defaultSections={false}
|
|
332
408
|
activeId={activeId}
|
|
333
|
-
onItemSelect={
|
|
409
|
+
onItemSelect={(id) => {
|
|
410
|
+
handleNavigate(id);
|
|
411
|
+
setMobileMenuOpen(false);
|
|
412
|
+
}}
|
|
334
413
|
/>
|
|
335
414
|
}
|
|
415
|
+
mobileMenuOpen={mobileMenuOpen}
|
|
416
|
+
onMobileMenuClose={() => setMobileMenuOpen(false)}
|
|
336
417
|
>
|
|
337
418
|
<Suspense fallback={<PageSkeleton />}>{view}</Suspense>
|
|
338
419
|
<AppCommandPalette
|
|
@@ -342,4 +423,4 @@ export function App(): JSX.Element {
|
|
|
342
423
|
/>
|
|
343
424
|
</AppShell>
|
|
344
425
|
);
|
|
345
|
-
}
|
|
426
|
+
}
|
|
@@ -92,17 +92,17 @@ describe('S38 ChatView', () => {
|
|
|
92
92
|
expect(await screen.findByTestId('chat-bubble-assistant')).toBeTruthy();
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
it('
|
|
96
|
-
|
|
95
|
+
it('opens the New session modal on `+ New session` click', async () => {
|
|
96
|
+
installFetchMock([
|
|
97
97
|
[/^\/api\/chat(\?|$)/, () => jsonResponse(200, { messages: [], sessions: [] })],
|
|
98
98
|
[/^\/api\/chat\/sessions/, () => jsonResponse(200, { sessions: [] })],
|
|
99
99
|
]);
|
|
100
100
|
render(<ChatView />);
|
|
101
101
|
const create = await screen.findByTestId('chat-create-session');
|
|
102
102
|
fireEvent.click(create);
|
|
103
|
+
// Modal should open with title "New Claude session"
|
|
103
104
|
await waitFor(() => {
|
|
104
|
-
|
|
105
|
-
expect(hit).toBeTruthy();
|
|
105
|
+
expect(screen.getByText('New Claude session')).toBeTruthy();
|
|
106
106
|
});
|
|
107
107
|
});
|
|
108
108
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { forwardRef, type ReactNode } from 'react';
|
|
2
|
+
import * as RxDialog from '@radix-ui/react-dialog';
|
|
2
3
|
import { Box } from '../ui/primitives/Box.js';
|
|
3
4
|
import { Topbar } from './Topbar.js';
|
|
4
5
|
import { Sidebar } from './Sidebar.js';
|
|
@@ -27,11 +28,14 @@ import { Sidebar } from './Sidebar.js';
|
|
|
27
28
|
export interface AppShellProps {
|
|
28
29
|
topbar?: ReactNode;
|
|
29
30
|
sidebar?: ReactNode;
|
|
31
|
+
/** Controls the mobile sidebar drawer (open/close). */
|
|
32
|
+
mobileMenuOpen?: boolean;
|
|
33
|
+
onMobileMenuClose?: () => void;
|
|
30
34
|
children?: ReactNode;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
export const AppShell = forwardRef<HTMLElement, AppShellProps>(function AppShell(
|
|
34
|
-
{ topbar, sidebar, children },
|
|
38
|
+
{ topbar, sidebar, mobileMenuOpen, onMobileMenuClose, children },
|
|
35
39
|
ref,
|
|
36
40
|
) {
|
|
37
41
|
return (
|
|
@@ -55,7 +59,39 @@ export const AppShell = forwardRef<HTMLElement, AppShellProps>(function AppShell
|
|
|
55
59
|
minHeight: 0, // critical: lets the body actually scroll instead of expanding
|
|
56
60
|
}}
|
|
57
61
|
>
|
|
58
|
-
{sidebar
|
|
62
|
+
{/* Desktop sidebar — always present at >=768px */}
|
|
63
|
+
<Box className="v8-desktop-sidebar" style={{ flexShrink: 0 }}>
|
|
64
|
+
{sidebar ?? <Sidebar />}
|
|
65
|
+
</Box>
|
|
66
|
+
|
|
67
|
+
{/* Mobile sidebar drawer — shown via Dialog overlay on <768px */}
|
|
68
|
+
<RxDialog.Root open={mobileMenuOpen} onOpenChange={(open) => { if (!open) onMobileMenuClose?.(); }}>
|
|
69
|
+
<RxDialog.Portal>
|
|
70
|
+
<RxDialog.Overlay
|
|
71
|
+
className="v8-mobile-sidebar-overlay"
|
|
72
|
+
style={{
|
|
73
|
+
position: 'fixed',
|
|
74
|
+
inset: 0,
|
|
75
|
+
background: 'oklch(0 0 0 / 0.4)',
|
|
76
|
+
zIndex: 'var(--z-modal)',
|
|
77
|
+
}}
|
|
78
|
+
/>
|
|
79
|
+
<RxDialog.Content
|
|
80
|
+
className="v8-mobile-sidebar"
|
|
81
|
+
aria-label="Navigation"
|
|
82
|
+
style={{
|
|
83
|
+
position: 'fixed',
|
|
84
|
+
top: 0,
|
|
85
|
+
left: 0,
|
|
86
|
+
bottom: 0,
|
|
87
|
+
width: 'var(--sidebar-w)',
|
|
88
|
+
zIndex: 'calc(var(--z-modal) + 1)',
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
{sidebar ?? <Sidebar />}
|
|
92
|
+
</RxDialog.Content>
|
|
93
|
+
</RxDialog.Portal>
|
|
94
|
+
</RxDialog.Root>
|
|
59
95
|
|
|
60
96
|
<Box
|
|
61
97
|
as="main"
|
|
@@ -14,9 +14,11 @@ import {
|
|
|
14
14
|
Folder,
|
|
15
15
|
Goal,
|
|
16
16
|
History,
|
|
17
|
-
|
|
17
|
+
LayoutDashboard,
|
|
18
18
|
Library,
|
|
19
19
|
Network,
|
|
20
|
+
Package,
|
|
21
|
+
Webhook,
|
|
20
22
|
ServerCog,
|
|
21
23
|
Settings as SettingsIcon,
|
|
22
24
|
Stethoscope,
|
|
@@ -117,7 +119,7 @@ const DEFAULT_SECTIONS: SidebarSection[] = [
|
|
|
117
119
|
id: 'workspace',
|
|
118
120
|
label: 'Workspace',
|
|
119
121
|
items: [
|
|
120
|
-
{ id: 'overview', label: 'Overview', icon:
|
|
122
|
+
{ id: 'overview', label: 'Overview', icon: LayoutDashboard },
|
|
121
123
|
{ id: 'tasks', label: 'Tasks', icon: CheckSquare, count: 47, active: true },
|
|
122
124
|
{ id: 'goals', label: 'Goals', icon: Target, count: 3 },
|
|
123
125
|
{ id: 'chat', label: 'Chat', icon: MessageSquareText, live: true },
|
|
@@ -140,7 +142,7 @@ const DEFAULT_SECTIONS: SidebarSection[] = [
|
|
|
140
142
|
items: [
|
|
141
143
|
{ id: 'skills', label: 'Skills', icon: Goal, count: 18 },
|
|
142
144
|
{ id: 'mcps', label: 'MCPs', icon: Library, count: 3 },
|
|
143
|
-
{ id: 'hooks', label: 'Hooks', icon:
|
|
145
|
+
{ id: 'hooks', label: 'Hooks', icon: Webhook, count: 5 },
|
|
144
146
|
],
|
|
145
147
|
},
|
|
146
148
|
{
|
|
@@ -156,7 +158,7 @@ const DEFAULT_SECTIONS: SidebarSection[] = [
|
|
|
156
158
|
{ id: 'providers', label: 'Providers', icon: Sparkles },
|
|
157
159
|
{ id: 'mods', label: 'Mods', icon: Boxes },
|
|
158
160
|
{ id: 'update', label: 'Update', icon: ArrowUpCircle },
|
|
159
|
-
{ id: 'artifacts', label: 'Artifacts', icon:
|
|
161
|
+
{ id: 'artifacts', label: 'Artifacts', icon: Package },
|
|
160
162
|
{ id: 'lightrag', label: 'LightRAG', icon: Database },
|
|
161
163
|
{ id: 'voice', label: 'Voice', icon: Mic },
|
|
162
164
|
{ id: 'clipboard', label: 'Clipboard', icon: ClipboardPaste },
|
|
@@ -283,8 +285,9 @@ export function Sidebar({
|
|
|
283
285
|
) : (
|
|
284
286
|
<>
|
|
285
287
|
<Box style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>
|
|
286
|
-
<div>◉ online ·
|
|
288
|
+
<div data-testid="sidebar-version">◉ online · v{import.meta.env.VITE_APP_VERSION}</div>
|
|
287
289
|
<div
|
|
290
|
+
data-testid="sidebar-build-sha"
|
|
288
291
|
style={{ fontFamily: 'var(--font-mono)' }}
|
|
289
292
|
title={`build ${import.meta.env.VITE_BUILD_SHA}`}
|
|
290
293
|
>
|
|
@@ -359,44 +362,54 @@ function SidebarSectionView({
|
|
|
359
362
|
return (
|
|
360
363
|
<Stack gap={1} data-sidebar-section={section.id}>
|
|
361
364
|
{!collapsed && (
|
|
362
|
-
<
|
|
363
|
-
type="button"
|
|
364
|
-
onClick={toggle}
|
|
365
|
-
aria-expanded={sectionOpen}
|
|
366
|
-
aria-controls={`sidebar-section-${section.id}`}
|
|
367
|
-
data-testid={`sidebar-section-toggle-${section.id}`}
|
|
368
|
-
style={{
|
|
369
|
-
display: 'flex',
|
|
370
|
-
alignItems: 'center',
|
|
371
|
-
justifyContent: 'space-between',
|
|
372
|
-
gap: 'var(--space-2)',
|
|
373
|
-
padding: 'var(--space-1) var(--space-3)',
|
|
374
|
-
background: 'transparent',
|
|
375
|
-
border: 0,
|
|
376
|
-
fontSize: 'var(--fs-12)',
|
|
377
|
-
fontWeight: 600,
|
|
378
|
-
color: 'var(--fg-subtle)',
|
|
379
|
-
letterSpacing: 'var(--tracking-wide)',
|
|
380
|
-
textTransform: 'uppercase',
|
|
381
|
-
cursor: 'pointer',
|
|
382
|
-
width: '100%',
|
|
383
|
-
textAlign: 'left',
|
|
384
|
-
}}
|
|
385
|
-
>
|
|
386
|
-
<span>{section.label}</span>
|
|
365
|
+
<div role="presentation" style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>
|
|
387
366
|
<span
|
|
388
|
-
aria-hidden="true"
|
|
389
|
-
data-testid={`sidebar-section-chevron-${section.id}`}
|
|
390
367
|
style={{
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
368
|
+
fontSize: 'var(--fs-12)',
|
|
369
|
+
fontWeight: 600,
|
|
370
|
+
color: 'var(--fg-subtle)',
|
|
371
|
+
letterSpacing: 'var(--tracking-wide)',
|
|
372
|
+
textTransform: 'uppercase',
|
|
373
|
+
flex: 1,
|
|
374
|
+
padding: 'var(--space-1) var(--space-3)',
|
|
395
375
|
}}
|
|
396
376
|
>
|
|
397
|
-
|
|
377
|
+
{section.label}
|
|
398
378
|
</span>
|
|
399
|
-
|
|
379
|
+
<button
|
|
380
|
+
type="button"
|
|
381
|
+
onClick={toggle}
|
|
382
|
+
aria-expanded={sectionOpen}
|
|
383
|
+
aria-controls={`sidebar-section-${section.id}`}
|
|
384
|
+
data-section-toggle={section.id}
|
|
385
|
+
data-testid={`sidebar-section-toggle-${section.id}`}
|
|
386
|
+
style={{
|
|
387
|
+
display: 'inline-flex',
|
|
388
|
+
alignItems: 'center',
|
|
389
|
+
justifyContent: 'center',
|
|
390
|
+
width: 20,
|
|
391
|
+
height: 20,
|
|
392
|
+
background: 'transparent',
|
|
393
|
+
border: 0,
|
|
394
|
+
color: 'var(--fg-subtle)',
|
|
395
|
+
cursor: 'pointer',
|
|
396
|
+
padding: 0,
|
|
397
|
+
}}
|
|
398
|
+
>
|
|
399
|
+
<span
|
|
400
|
+
aria-hidden="true"
|
|
401
|
+
data-testid={`sidebar-section-chevron-${section.id}`}
|
|
402
|
+
style={{
|
|
403
|
+
display: 'inline-block',
|
|
404
|
+
transition: 'transform var(--motion-fast) var(--ease-out)',
|
|
405
|
+
transform: sectionOpen ? 'rotate(90deg)' : 'rotate(0deg)',
|
|
406
|
+
fontSize: 10,
|
|
407
|
+
}}
|
|
408
|
+
>
|
|
409
|
+
▸
|
|
410
|
+
</span>
|
|
411
|
+
</button>
|
|
412
|
+
</div>
|
|
400
413
|
)}
|
|
401
414
|
{sectionOpen && (
|
|
402
415
|
<div id={`sidebar-section-${section.id}`} role="group" aria-label={section.label}>
|
|
@@ -435,6 +448,7 @@ function SidebarItemView({
|
|
|
435
448
|
aria-label={item.label}
|
|
436
449
|
title={collapsed ? item.label : undefined}
|
|
437
450
|
data-sidebar-item={item.id}
|
|
451
|
+
data-nav-item={item.id}
|
|
438
452
|
className={cx('v8-sidebar-item', active && 'is-active')}
|
|
439
453
|
style={{
|
|
440
454
|
display: 'flex',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, type ReactNode } from 'react';
|
|
2
|
-
import { ChevronDown } from 'lucide-react';
|
|
2
|
+
import { ChevronDown, Search } from 'lucide-react';
|
|
3
3
|
import { Box } from '../ui/primitives/Box.js';
|
|
4
4
|
import { Inline } from '../ui/primitives/Inline.js';
|
|
5
5
|
import { Cluster } from '../ui/primitives/Cluster.js';
|
|
@@ -28,6 +28,8 @@ import { fetchJson, FetchError } from '../data/fetcher.js';
|
|
|
28
28
|
|
|
29
29
|
export interface TopbarProps {
|
|
30
30
|
brand?: ReactNode;
|
|
31
|
+
/** Leading slot — renders before brand (hamburger on mobile). */
|
|
32
|
+
leading?: ReactNode;
|
|
31
33
|
center?: ReactNode;
|
|
32
34
|
/** Right-aligned action cluster. */
|
|
33
35
|
actions?: ReactNode;
|
|
@@ -35,7 +37,7 @@ export interface TopbarProps {
|
|
|
35
37
|
status?: ReactNode;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
export function Topbar({ brand, center, actions, status }: TopbarProps): JSX.Element {
|
|
40
|
+
export function Topbar({ leading, brand, center, actions, status }: TopbarProps): JSX.Element {
|
|
39
41
|
return (
|
|
40
42
|
<Box
|
|
41
43
|
as="header"
|
|
@@ -51,8 +53,9 @@ export function Topbar({ brand, center, actions, status }: TopbarProps): JSX.Ele
|
|
|
51
53
|
}}
|
|
52
54
|
>
|
|
53
55
|
<Inline align="center" justify="between" gap={4} style={{ height: '100%' }}>
|
|
54
|
-
{/* left: brand */}
|
|
56
|
+
{/* left: leading (hamburger) + brand */}
|
|
55
57
|
<Cluster align="center" gap={3}>
|
|
58
|
+
{leading}
|
|
56
59
|
{brand ?? <BrandPlaceholder />}
|
|
57
60
|
</Cluster>
|
|
58
61
|
|
|
@@ -222,10 +225,66 @@ function DefaultActions({ status }: { status?: ReactNode }): JSX.Element {
|
|
|
222
225
|
</Inline>
|
|
223
226
|
)}
|
|
224
227
|
<Separator orientation="vertical" style={{ height: 16 }} />
|
|
228
|
+
<CommandPaletteTrigger />
|
|
229
|
+
<Separator orientation="vertical" style={{ height: 16 }} />
|
|
225
230
|
<NotificationsPopover />
|
|
226
231
|
<Separator orientation="vertical" style={{ height: 16 }} />
|
|
227
232
|
<DensityToggle />
|
|
228
233
|
<ThemeToggle />
|
|
229
234
|
</>
|
|
230
235
|
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* CommandPaletteTrigger — a single inline button that opens the command
|
|
240
|
+
* palette. Renders a kbd hint next to the magnifier icon so users discover
|
|
241
|
+
* the ⌘K shortcut. The full palette is wired through `useCommandPaletteHotkey`
|
|
242
|
+
* in App.tsx; this trigger just dispatches the same shortcut keydown.
|
|
243
|
+
*/
|
|
244
|
+
function CommandPaletteTrigger(): JSX.Element {
|
|
245
|
+
const isMac = typeof navigator !== 'undefined' && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
|
246
|
+
const kbd = isMac ? '⌘K' : 'Ctrl K';
|
|
247
|
+
return (
|
|
248
|
+
<button
|
|
249
|
+
type="button"
|
|
250
|
+
onClick={() => {
|
|
251
|
+
// Dispatch the same key the global hotkey listens for so we don't
|
|
252
|
+
// duplicate the open/close logic.
|
|
253
|
+
window.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: isMac, ctrlKey: !isMac, bubbles: true }));
|
|
254
|
+
}}
|
|
255
|
+
aria-label="Open command palette"
|
|
256
|
+
title={`Open command palette (${kbd})`}
|
|
257
|
+
data-testid="topbar-palette-trigger"
|
|
258
|
+
style={{
|
|
259
|
+
display: 'inline-flex',
|
|
260
|
+
alignItems: 'center',
|
|
261
|
+
gap: 'var(--space-2)',
|
|
262
|
+
height: 28,
|
|
263
|
+
padding: '0 8px 0 6px',
|
|
264
|
+
borderRadius: 'var(--radius-sm)',
|
|
265
|
+
border: '1px solid var(--border)',
|
|
266
|
+
background: 'var(--surface-1)',
|
|
267
|
+
color: 'var(--fg-muted)',
|
|
268
|
+
fontSize: 'var(--fs-12)',
|
|
269
|
+
cursor: 'pointer',
|
|
270
|
+
}}
|
|
271
|
+
>
|
|
272
|
+
<Search size={14} aria-hidden="true" />
|
|
273
|
+
<span>Search…</span>
|
|
274
|
+
<kbd
|
|
275
|
+
aria-hidden="true"
|
|
276
|
+
style={{
|
|
277
|
+
padding: '1px 4px',
|
|
278
|
+
borderRadius: 'var(--radius-sm)',
|
|
279
|
+
border: '1px solid var(--border)',
|
|
280
|
+
background: 'var(--surface-2)',
|
|
281
|
+
fontSize: 'var(--fs-11)',
|
|
282
|
+
fontFamily: 'var(--font-mono)',
|
|
283
|
+
color: 'var(--fg)',
|
|
284
|
+
}}
|
|
285
|
+
>
|
|
286
|
+
{kbd}
|
|
287
|
+
</kbd>
|
|
288
|
+
</button>
|
|
289
|
+
);
|
|
231
290
|
}
|
|
@@ -103,6 +103,32 @@ h4 {
|
|
|
103
103
|
font-weight: var(--fw-medium);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
/* ── mobile sidebar (C2 — < 768px) ─────────────────────────────────── */
|
|
107
|
+
@media (max-width: 767px) {
|
|
108
|
+
/* Desktop sidebar hidden on mobile */
|
|
109
|
+
.v8-desktop-sidebar {
|
|
110
|
+
display: none;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Show hamburger button on mobile */
|
|
114
|
+
.mobile-menu-toggle {
|
|
115
|
+
display: inline-flex !important;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@media (min-width: 768px) {
|
|
120
|
+
/* Mobile sidebar hidden on desktop */
|
|
121
|
+
.v8-mobile-sidebar,
|
|
122
|
+
.v8-mobile-sidebar-overlay {
|
|
123
|
+
display: none !important;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Hide hamburger on desktop */
|
|
127
|
+
.mobile-menu-toggle {
|
|
128
|
+
display: none !important;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
106
132
|
/* ── a11y helpers (see VisuallyHidden primitive) ────────────────────── */
|
|
107
133
|
.sr-only {
|
|
108
134
|
position: absolute;
|
|
@@ -223,3 +249,17 @@ h4 {
|
|
|
223
249
|
.v8-dropdown-menu__radio[data-state='checked'] .v8-dropdown-menu__radio-indicator {
|
|
224
250
|
display: inline-flex;
|
|
225
251
|
}
|
|
252
|
+
|
|
253
|
+
/* Universal focus-visible ring for keyboard navigation across custom
|
|
254
|
+
buttons, sidebar items, and design-system Button variants. v10.4.3
|
|
255
|
+
L4 audit fix. */
|
|
256
|
+
.v8-btn:focus-visible,
|
|
257
|
+
.v8-button:focus-visible,
|
|
258
|
+
button[data-section-toggle]:focus-visible,
|
|
259
|
+
button[data-nav-item]:focus-visible,
|
|
260
|
+
.v8-theme-toggle:focus-visible,
|
|
261
|
+
.v8-density-toggle:focus-visible,
|
|
262
|
+
.v8-icon-button:focus-visible {
|
|
263
|
+
outline: 2px solid var(--accent);
|
|
264
|
+
outline-offset: 2px;
|
|
265
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Monitor, Moon, Sun } from 'lucide-react';
|
|
1
|
+
import { AlignJustify, Monitor, Moon, Rows3, Sun } from 'lucide-react';
|
|
2
2
|
import { useTheme } from './useTheme.js';
|
|
3
3
|
import { useDensity } from './useDensity.js';
|
|
4
4
|
import { cx } from '../utils/cx.js';
|
|
@@ -36,7 +36,10 @@ export interface ThemeToggleProps {
|
|
|
36
36
|
|
|
37
37
|
export function ThemeToggle({ className }: ThemeToggleProps): JSX.Element {
|
|
38
38
|
const { mode, resolved, cycle } = useTheme();
|
|
39
|
-
|
|
39
|
+
// Show the icon for the *resolved* (actually applied) theme so the visual
|
|
40
|
+
// matches what the user is seeing — Sun when light is active, Moon when
|
|
41
|
+
// dark is active, Monitor when system is in effect.
|
|
42
|
+
const Icon = RESOLVED_ICON[resolved];
|
|
40
43
|
return (
|
|
41
44
|
<button
|
|
42
45
|
type="button"
|
|
@@ -66,23 +69,25 @@ export interface DensityToggleProps {
|
|
|
66
69
|
}
|
|
67
70
|
export function DensityToggle({ className }: DensityToggleProps): JSX.Element {
|
|
68
71
|
const { density, toggle } = useDensity();
|
|
72
|
+
const isCozy = density === 'comfortable';
|
|
73
|
+
const Icon = isCozy ? Rows3 : AlignJustify;
|
|
69
74
|
return (
|
|
70
75
|
<button
|
|
71
76
|
type="button"
|
|
72
77
|
onClick={toggle}
|
|
73
|
-
aria-label={`Switch to ${
|
|
78
|
+
aria-label={`Switch to ${isCozy ? 'compact' : 'comfortable'} density`}
|
|
74
79
|
title={`Density: ${density}`}
|
|
80
|
+
data-density={density}
|
|
75
81
|
className={cx(
|
|
76
82
|
'v8-density-toggle',
|
|
77
|
-
'inline-flex h-8
|
|
83
|
+
'inline-flex h-8 w-8 items-center justify-center',
|
|
78
84
|
'rounded-[var(--radius-sm)]',
|
|
79
|
-
'text-[var(--fs-12)] font-medium tracking-[var(--tracking-wide)] uppercase',
|
|
80
85
|
'text-[var(--fg-muted)] hover:text-[var(--fg)] hover:bg-[var(--surface-1)]',
|
|
81
86
|
'transition-colors duration-[var(--motion-fast)]',
|
|
82
87
|
className,
|
|
83
88
|
)}
|
|
84
89
|
>
|
|
85
|
-
{
|
|
90
|
+
<Icon size={16} aria-hidden="true" />
|
|
86
91
|
</button>
|
|
87
92
|
);
|
|
88
93
|
}
|
|
@@ -37,6 +37,7 @@ interface AdminAction {
|
|
|
37
37
|
endpoint: string;
|
|
38
38
|
method: 'POST' | 'GET';
|
|
39
39
|
destructive: boolean;
|
|
40
|
+
group: 'data' | 'service' | 'logs';
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
const ACTIONS: AdminAction[] = [
|
|
@@ -48,6 +49,7 @@ const ACTIONS: AdminAction[] = [
|
|
|
48
49
|
endpoint: '/api/admin/gc',
|
|
49
50
|
method: 'POST',
|
|
50
51
|
destructive: false,
|
|
52
|
+
group: 'data',
|
|
51
53
|
},
|
|
52
54
|
{
|
|
53
55
|
id: 'cache-clear',
|
|
@@ -57,6 +59,7 @@ const ACTIONS: AdminAction[] = [
|
|
|
57
59
|
endpoint: '/api/admin/cache/clear',
|
|
58
60
|
method: 'POST',
|
|
59
61
|
destructive: true,
|
|
62
|
+
group: 'data',
|
|
60
63
|
},
|
|
61
64
|
{
|
|
62
65
|
id: 'memory-reindex',
|
|
@@ -66,6 +69,7 @@ const ACTIONS: AdminAction[] = [
|
|
|
66
69
|
endpoint: '/api/admin/memory/reindex',
|
|
67
70
|
method: 'POST',
|
|
68
71
|
destructive: false,
|
|
72
|
+
group: 'data',
|
|
69
73
|
},
|
|
70
74
|
{
|
|
71
75
|
id: 'logs-purge',
|
|
@@ -75,6 +79,7 @@ const ACTIONS: AdminAction[] = [
|
|
|
75
79
|
endpoint: '/api/admin/logs/purge',
|
|
76
80
|
method: 'POST',
|
|
77
81
|
destructive: true,
|
|
82
|
+
group: 'logs',
|
|
78
83
|
},
|
|
79
84
|
{
|
|
80
85
|
id: 'restart',
|
|
@@ -84,6 +89,7 @@ const ACTIONS: AdminAction[] = [
|
|
|
84
89
|
endpoint: '/api/admin/restart',
|
|
85
90
|
method: 'POST',
|
|
86
91
|
destructive: true,
|
|
92
|
+
group: 'service',
|
|
87
93
|
},
|
|
88
94
|
{
|
|
89
95
|
id: 'rebuild',
|
|
@@ -93,6 +99,7 @@ const ACTIONS: AdminAction[] = [
|
|
|
93
99
|
endpoint: '/api/admin/rebuild',
|
|
94
100
|
method: 'POST',
|
|
95
101
|
destructive: true,
|
|
102
|
+
group: 'service',
|
|
96
103
|
},
|
|
97
104
|
{
|
|
98
105
|
id: 'export-activity',
|
|
@@ -102,9 +109,16 @@ const ACTIONS: AdminAction[] = [
|
|
|
102
109
|
endpoint: '/api/admin/activity/export',
|
|
103
110
|
method: 'GET',
|
|
104
111
|
destructive: false,
|
|
112
|
+
group: 'logs',
|
|
105
113
|
},
|
|
106
114
|
];
|
|
107
115
|
|
|
116
|
+
const GROUPS: Array<{ id: 'data' | 'service' | 'logs'; title: string }> = [
|
|
117
|
+
{ id: 'data', title: 'Data & cache' },
|
|
118
|
+
{ id: 'service', title: 'Service' },
|
|
119
|
+
{ id: 'logs', title: 'Logs' },
|
|
120
|
+
];
|
|
121
|
+
|
|
108
122
|
export function AdminView(): JSX.Element {
|
|
109
123
|
return (
|
|
110
124
|
<Stack gap={4} data-testid="admin-view">
|
|
@@ -112,11 +126,24 @@ export function AdminView(): JSX.Element {
|
|
|
112
126
|
title="Admin"
|
|
113
127
|
description="Maintenance actions. Destructive actions require an inline confirm."
|
|
114
128
|
/>
|
|
115
|
-
<
|
|
116
|
-
{
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
<Stack gap={4} data-testid="admin-groups">
|
|
130
|
+
{GROUPS.map((group) => {
|
|
131
|
+
const items = ACTIONS.filter((a) => a.group === group.id);
|
|
132
|
+
if (items.length === 0) return null;
|
|
133
|
+
return (
|
|
134
|
+
<Stack key={group.id} gap={2} data-testid={`admin-group-${group.id}`}>
|
|
135
|
+
<h3 style={{ margin: 0, fontSize: 'var(--fs-12)', textTransform: 'uppercase', letterSpacing: 'var(--tracking-wide)', color: 'var(--fg-muted)' }}>
|
|
136
|
+
{group.title}
|
|
137
|
+
</h3>
|
|
138
|
+
<Grid cols={{ base: 1, md: 2, lg: 3 }} gap={3}>
|
|
139
|
+
{items.map((a) => (
|
|
140
|
+
<AdminTile key={a.id} action={a} />
|
|
141
|
+
))}
|
|
142
|
+
</Grid>
|
|
143
|
+
</Stack>
|
|
144
|
+
);
|
|
145
|
+
})}
|
|
146
|
+
</Stack>
|
|
120
147
|
</Stack>
|
|
121
148
|
);
|
|
122
149
|
}
|