@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.
Files changed (262) hide show
  1. package/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js → ActivityFeed-RQeyFifx.js} +1 -1
  2. package/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js.map → ActivityFeed-RQeyFifx.js.map} +1 -1
  3. package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js → ActivityView-CibyssPM.js} +1 -1
  4. package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js.map → ActivityView-CibyssPM.js.map} +1 -1
  5. package/bizar-dash/dist/assets/AdminView-BjczABeB.js +11 -0
  6. package/bizar-dash/dist/assets/AdminView-BjczABeB.js.map +1 -0
  7. package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js → AgentActivity-Bywt1twv.js} +1 -1
  8. package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js.map → AgentActivity-Bywt1twv.js.map} +1 -1
  9. package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js +15 -0
  10. package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js.map +1 -0
  11. package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js → Alert-BZGk39mB.js} +1 -1
  12. package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js.map → Alert-BZGk39mB.js.map} +1 -1
  13. package/bizar-dash/dist/assets/{ArtifactsView-znhN8GTR.js → ArtifactsView-CfYB1le1.js} +3 -3
  14. package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js.map +1 -0
  15. package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js → AuthView-D4frSShw.js} +1 -1
  16. package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js.map → AuthView-D4frSShw.js.map} +1 -1
  17. package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js +6 -0
  18. package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js.map +1 -0
  19. package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js → BackgroundJobsView-DEStvILz.js} +1 -1
  20. package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js.map → BackgroundJobsView-DEStvILz.js.map} +1 -1
  21. package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js → BackupView-B875KQa4.js} +1 -1
  22. package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js.map → BackupView-B875KQa4.js.map} +1 -1
  23. package/bizar-dash/dist/assets/Banner-C8HEcT5l.js +1 -0
  24. package/bizar-dash/dist/assets/Banner-C8HEcT5l.js.map +1 -0
  25. package/bizar-dash/dist/assets/{Card-rF59wHiO.js → Card-BtsmkhJa.js} +1 -1
  26. package/bizar-dash/dist/assets/{Card-rF59wHiO.js.map → Card-BtsmkhJa.js.map} +1 -1
  27. package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js +9 -0
  28. package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js.map +1 -0
  29. package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js → Chip-XPOk0d_E.js} +1 -1
  30. package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js.map → Chip-XPOk0d_E.js.map} +1 -1
  31. package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js → ClaudeSessionsView-BprGo67K.js} +1 -1
  32. package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js.map → ClaudeSessionsView-BprGo67K.js.map} +1 -1
  33. package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js +1 -0
  34. package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js.map +1 -0
  35. package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js → ConfigView-BntUrW7s.js} +1 -1
  36. package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js.map → ConfigView-BntUrW7s.js.map} +1 -1
  37. package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js +2 -0
  38. package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js.map +1 -0
  39. package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js +6 -0
  40. package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js.map +1 -0
  41. package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js → DoctorView-DepBdQGR.js} +2 -2
  42. package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js.map → DoctorView-DepBdQGR.js.map} +1 -1
  43. package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js → EmptyState-DjKtY1Qi.js} +1 -1
  44. package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js.map → EmptyState-DjKtY1Qi.js.map} +1 -1
  45. package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js → EnvVarsView-S4Pbm128.js} +3 -3
  46. package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js.map → EnvVarsView-S4Pbm128.js.map} +1 -1
  47. package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js → ErrorState-CBJbEQ8B.js} +1 -1
  48. package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js.map → ErrorState-CBJbEQ8B.js.map} +1 -1
  49. package/bizar-dash/dist/assets/EvalView-BeAyMCD1.js +1 -0
  50. package/bizar-dash/dist/assets/{EvalView-CpdFu_ID.js.map → EvalView-BeAyMCD1.js.map} +1 -1
  51. package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js → GoalsView-BZr8In4c.js} +1 -1
  52. package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js.map → GoalsView-BZr8In4c.js.map} +1 -1
  53. package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js → Grid--WKvqu5h.js} +1 -1
  54. package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js.map → Grid--WKvqu5h.js.map} +1 -1
  55. package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js → HistoryView-djEbzqtk.js} +1 -1
  56. package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js.map → HistoryView-djEbzqtk.js.map} +1 -1
  57. package/bizar-dash/dist/assets/{Input-CZmRw5QX.js → Input-h_nSOtwm.js} +1 -1
  58. package/bizar-dash/dist/assets/{Input-CZmRw5QX.js.map → Input-h_nSOtwm.js.map} +1 -1
  59. package/bizar-dash/dist/assets/LibrariesView-Vez8CvNq.js +6 -0
  60. package/bizar-dash/dist/assets/{LibrariesView-B1YX9wzp.js.map → LibrariesView-Vez8CvNq.js.map} +1 -1
  61. package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js → LightRAGView-DvqzQoBp.js} +1 -1
  62. package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js.map → LightRAGView-DvqzQoBp.js.map} +1 -1
  63. package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js → ListHeader-CM8QoIWG.js} +1 -1
  64. package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js.map → ListHeader-CM8QoIWG.js.map} +1 -1
  65. package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js → MemoryView-DnL8E2vI.js} +1 -1
  66. package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js.map → MemoryView-DnL8E2vI.js.map} +1 -1
  67. package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js → MessageBubble-CrCJ0SYG.js} +1 -1
  68. package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js.map → MessageBubble-CrCJ0SYG.js.map} +1 -1
  69. package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js +1 -0
  70. package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js.map +1 -0
  71. package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js → ModsView-BVM3X5xc.js} +1 -1
  72. package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js.map → ModsView-BVM3X5xc.js.map} +1 -1
  73. package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js +6 -0
  74. package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js.map +1 -0
  75. package/bizar-dash/dist/assets/ObsidianView-mI3qW9OP.js +1 -0
  76. package/bizar-dash/dist/assets/{ObsidianView-Ci80gnwS.js.map → ObsidianView-mI3qW9OP.js.map} +1 -1
  77. package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js +1 -0
  78. package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js.map +1 -0
  79. package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js → ProgressBar-BnaBqv-W.js} +1 -1
  80. package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js.map → ProgressBar-BnaBqv-W.js.map} +1 -1
  81. package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js +11 -0
  82. package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js.map +1 -0
  83. package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js → ProvidersView-2cn-TALE.js} +2 -2
  84. package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js.map → ProvidersView-2cn-TALE.js.map} +1 -1
  85. package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js → SchedulesView-o9AtIsH9.js} +1 -1
  86. package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js.map → SchedulesView-o9AtIsH9.js.map} +1 -1
  87. package/bizar-dash/dist/assets/{Select-0VcfTDeL.js → Select-CiGWEN8I.js} +1 -1
  88. package/bizar-dash/dist/assets/{Select-0VcfTDeL.js.map → Select-CiGWEN8I.js.map} +1 -1
  89. package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js → SettingsRow-CflGJymA.js} +1 -1
  90. package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js.map → SettingsRow-CflGJymA.js.map} +1 -1
  91. package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js → SettingsView-2HSFJPPK.js} +1 -1
  92. package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js.map → SettingsView-2HSFJPPK.js.map} +1 -1
  93. package/bizar-dash/dist/assets/{Sheet-BOProMs2.js → Sheet-B-CMP9-_.js} +1 -1
  94. package/bizar-dash/dist/assets/{Sheet-BOProMs2.js.map → Sheet-B-CMP9-_.js.map} +1 -1
  95. package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js → Slider-Z4TP_CXY.js} +1 -1
  96. package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js.map → Slider-Z4TP_CXY.js.map} +1 -1
  97. package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js → Sparkline-cvkv2HbU.js} +1 -1
  98. package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js.map → Sparkline-cvkv2HbU.js.map} +1 -1
  99. package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js → Switch-jcYo4lmp.js} +1 -1
  100. package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js.map → Switch-jcYo4lmp.js.map} +1 -1
  101. package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js → TasksView-CQaSFzWY.js} +2 -2
  102. package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js.map → TasksView-CQaSFzWY.js.map} +1 -1
  103. package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js → Textarea-xnAybFGd.js} +1 -1
  104. package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js.map → Textarea-xnAybFGd.js.map} +1 -1
  105. package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js +1 -0
  106. package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js.map +1 -0
  107. package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js → UsageView-DMFbBOfH.js} +1 -1
  108. package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js.map → UsageView-DMFbBOfH.js.map} +1 -1
  109. package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js → ViewHeader-C-t1U2cQ.js} +1 -1
  110. package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js.map → ViewHeader-C-t1U2cQ.js.map} +1 -1
  111. package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js +1 -0
  112. package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js.map +1 -0
  113. package/bizar-dash/dist/assets/{brain-CwZt9Kta.js → brain-DhAzcHUk.js} +1 -1
  114. package/bizar-dash/dist/assets/{brain-CwZt9Kta.js.map → brain-DhAzcHUk.js.map} +1 -1
  115. package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js → calendar-B9Wbemh7.js} +1 -1
  116. package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js.map → calendar-B9Wbemh7.js.map} +1 -1
  117. package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js → circle-6NJF_Xl6.js} +1 -1
  118. package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js.map → circle-6NJF_Xl6.js.map} +1 -1
  119. package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js → circle-alert-Dz8lGfCZ.js} +1 -1
  120. package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js.map → circle-alert-Dz8lGfCZ.js.map} +1 -1
  121. package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js → circle-check-DFB50ojt.js} +1 -1
  122. package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js.map → circle-check-DFB50ojt.js.map} +1 -1
  123. package/bizar-dash/dist/assets/{clock-DEIuPV60.js → clock-ClVA6-hQ.js} +1 -1
  124. package/bizar-dash/dist/assets/{clock-DEIuPV60.js.map → clock-ClVA6-hQ.js.map} +1 -1
  125. package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js → cmdk-C3F6LD6N.js} +5 -5
  126. package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js.map → cmdk-C3F6LD6N.js.map} +1 -1
  127. package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js → dnd-kit-BAOLODOI.js} +1 -1
  128. package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js.map → dnd-kit-BAOLODOI.js.map} +1 -1
  129. package/bizar-dash/dist/assets/{download-Clkq90Ct.js → download-BvJddD8D.js} +1 -1
  130. package/bizar-dash/dist/assets/{download-Clkq90Ct.js.map → download-BvJddD8D.js.map} +1 -1
  131. package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js → external-link-DvL89gaZ.js} +1 -1
  132. package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js.map → external-link-DvL89gaZ.js.map} +1 -1
  133. package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js → file-text-BOroDtZE.js} +1 -1
  134. package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js.map → file-text-BOroDtZE.js.map} +1 -1
  135. package/bizar-dash/dist/assets/{filter-BcbE37wP.js → filter-DwPjMRQt.js} +1 -1
  136. package/bizar-dash/dist/assets/{filter-BcbE37wP.js.map → filter-DwPjMRQt.js.map} +1 -1
  137. package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js → git-pull-request-TDb1inux.js} +1 -1
  138. package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js.map → git-pull-request-TDb1inux.js.map} +1 -1
  139. package/bizar-dash/dist/assets/{index-CASP1n-5.js → index-B1OIS316.js} +1 -1
  140. package/bizar-dash/dist/assets/{index-CASP1n-5.js.map → index-B1OIS316.js.map} +1 -1
  141. package/bizar-dash/dist/assets/{index-C4Vq_2LM.js → index-CR0TeJmc.js} +1 -1
  142. package/bizar-dash/dist/assets/{index-C4Vq_2LM.js.map → index-CR0TeJmc.js.map} +1 -1
  143. package/bizar-dash/dist/assets/{main-CcQfRfIJ.css → main-B7D_IMTh.css} +1 -1
  144. package/bizar-dash/dist/assets/main-BURAlktW.js +277 -0
  145. package/bizar-dash/dist/assets/main-BURAlktW.js.map +1 -0
  146. package/bizar-dash/dist/assets/{network-DJdvVaHx.js → network-BcCoCzIY.js} +1 -1
  147. package/bizar-dash/dist/assets/{network-DJdvVaHx.js.map → network-BcCoCzIY.js.map} +1 -1
  148. package/bizar-dash/dist/assets/{pause-DUn9L5PB.js → pause-BllItT2_.js} +1 -1
  149. package/bizar-dash/dist/assets/{pause-DUn9L5PB.js.map → pause-BllItT2_.js.map} +1 -1
  150. package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js → pencil-DAwM-CC3.js} +1 -1
  151. package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js.map → pencil-DAwM-CC3.js.map} +1 -1
  152. package/bizar-dash/dist/assets/{play-CZjsr3XM.js → play-mJh67AXo.js} +2 -2
  153. package/bizar-dash/dist/assets/{play-CZjsr3XM.js.map → play-mJh67AXo.js.map} +1 -1
  154. package/bizar-dash/dist/assets/{plug-BKuyIe5W.js → plug-BjfntCMC.js} +1 -1
  155. package/bizar-dash/dist/assets/{plug-BKuyIe5W.js.map → plug-BjfntCMC.js.map} +1 -1
  156. package/bizar-dash/dist/assets/{plus-77h62zZm.js → plus-Cm6-fo14.js} +1 -1
  157. package/bizar-dash/dist/assets/{plus-77h62zZm.js.map → plus-Cm6-fo14.js.map} +1 -1
  158. package/bizar-dash/dist/assets/{power-DLmx-gCP.js → power-CXN9y2KV.js} +1 -1
  159. package/bizar-dash/dist/assets/{power-DLmx-gCP.js.map → power-CXN9y2KV.js.map} +1 -1
  160. package/bizar-dash/dist/assets/{power-off-BFKzHXic.js → power-off-DUZqwMf9.js} +1 -1
  161. package/bizar-dash/dist/assets/{power-off-BFKzHXic.js.map → power-off-DUZqwMf9.js.map} +1 -1
  162. package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js → refresh-ccw-DA8_IB9l.js} +1 -1
  163. package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js.map → refresh-ccw-DA8_IB9l.js.map} +1 -1
  164. package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js → refresh-cw-DwlP59en.js} +1 -1
  165. package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js.map → refresh-cw-DwlP59en.js.map} +1 -1
  166. package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js → rotate-ccw-DMTASfAn.js} +1 -1
  167. package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js.map → rotate-ccw-DMTASfAn.js.map} +1 -1
  168. package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js → rotate-cw-BDX5SE2s.js} +1 -1
  169. package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js.map → rotate-cw-BDX5SE2s.js.map} +1 -1
  170. package/bizar-dash/dist/assets/{save-Db1b-1Uq.js → save-Y0jPK5D6.js} +1 -1
  171. package/bizar-dash/dist/assets/{save-Db1b-1Uq.js.map → save-Y0jPK5D6.js.map} +1 -1
  172. package/bizar-dash/dist/assets/{send-yz6HFZM5.js → send-C8wwPHhR.js} +2 -2
  173. package/bizar-dash/dist/assets/{send-yz6HFZM5.js.map → send-C8wwPHhR.js.map} +1 -1
  174. package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js → shield-alert-DEvq9UG0.js} +1 -1
  175. package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js.map → shield-alert-DEvq9UG0.js.map} +1 -1
  176. package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js → trash-2-D6qePV_q.js} +2 -2
  177. package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js.map → trash-2-D6qePV_q.js.map} +1 -1
  178. package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js → trending-up-BZzo_1ic.js} +1 -1
  179. package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js.map → trending-up-BZzo_1ic.js.map} +1 -1
  180. package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js → triangle-alert-B2oHbmoh.js} +1 -1
  181. package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js.map → triangle-alert-B2oHbmoh.js.map} +1 -1
  182. package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js → upload-Dy59aZn6.js} +1 -1
  183. package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js.map → upload-Dy59aZn6.js.map} +1 -1
  184. package/bizar-dash/dist/assets/{zap-5lAQBAPX.js → zap-DENVhJnO.js} +2 -2
  185. package/bizar-dash/dist/assets/{zap-5lAQBAPX.js.map → zap-DENVhJnO.js.map} +1 -1
  186. package/bizar-dash/dist/index.html +3 -3
  187. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  188. package/bizar-dash/src/web/v8/App.tsx +87 -6
  189. package/bizar-dash/src/web/v8/__tests__/chat-view.test.tsx +4 -4
  190. package/bizar-dash/src/web/v8/shell/AppShell.tsx +38 -2
  191. package/bizar-dash/src/web/v8/shell/Sidebar.tsx +52 -38
  192. package/bizar-dash/src/web/v8/shell/Topbar.tsx +62 -3
  193. package/bizar-dash/src/web/v8/ui/styles/globals.css +40 -0
  194. package/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +11 -6
  195. package/bizar-dash/src/web/v8/views/Admin/AdminView.tsx +32 -5
  196. package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +36 -4
  197. package/bizar-dash/src/web/v8/views/Artifacts/ArtifactsView.tsx +1 -1
  198. package/bizar-dash/src/web/v8/views/Chat/ChatView.tsx +13 -1
  199. package/bizar-dash/src/web/v8/views/ClaudeSessions/NewSessionModal.tsx +136 -0
  200. package/bizar-dash/src/web/v8/views/Clipboard/ClipboardView.tsx +1 -1
  201. package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +14 -4
  202. package/bizar-dash/src/web/v8/views/Diagnostics/DiagnosticsView.tsx +50 -7
  203. package/bizar-dash/src/web/v8/views/Dialogs/DialogsView.tsx +1 -1
  204. package/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +6 -1
  205. package/bizar-dash/src/web/v8/views/Misc/MiscView.tsx +1 -1
  206. package/bizar-dash/src/web/v8/views/Notifications/NotificationsView.tsx +82 -13
  207. package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +19 -0
  208. package/bizar-dash/src/web/v8/views/Projects/ProjectsView.tsx +21 -1
  209. package/bizar-dash/src/web/v8/views/Voice/VoiceView.tsx +1 -1
  210. package/bizar-dash/tests/admin-labels.test.mjs +42 -0
  211. package/bizar-dash/tests/admin-run-grouping.test.mjs +42 -0
  212. package/bizar-dash/tests/agents-preview-truncate.test.mjs +35 -0
  213. package/bizar-dash/tests/agents-summary-sanitize.test.ts +51 -0
  214. package/bizar-dash/tests/chat-new-session.test.mjs +63 -0
  215. package/bizar-dash/tests/empty-state-docs.test.mjs +55 -0
  216. package/bizar-dash/tests/focus-visible.test.mjs +30 -0
  217. package/bizar-dash/tests/kanban-empty-column.test.mjs +56 -0
  218. package/bizar-dash/tests/library-dedupe.test.mjs +62 -0
  219. package/bizar-dash/tests/notifications-dismiss-restore.test.mjs +85 -0
  220. package/bizar-dash/tests/palette-shortcut-hint.test.mjs +58 -0
  221. package/bizar-dash/tests/projects-filter.test.mjs +48 -0
  222. package/bizar-dash/tests/settings-labels.test.mjs +80 -0
  223. package/bizar-dash/tests/sidebar-distinct-icons.test.mjs +28 -0
  224. package/bizar-dash/tests/sidebar-responsive.test.tsx +48 -0
  225. package/bizar-dash/tests/sidebar-section-toggle.test.tsx +63 -0
  226. package/bizar-dash/tests/theme-toggle-icon.test.mjs +28 -0
  227. package/bizar-dash/tests/topbar-design-system.test.mjs +56 -0
  228. package/bizar-dash/vite.config.ts +8 -0
  229. package/package.json +1 -1
  230. package/packages/sdk/package.json +1 -1
  231. package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js +0 -11
  232. package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js.map +0 -1
  233. package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js +0 -13
  234. package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js.map +0 -1
  235. package/bizar-dash/dist/assets/ArtifactsView-znhN8GTR.js.map +0 -1
  236. package/bizar-dash/dist/assets/Avatar-B41upSD1.js +0 -6
  237. package/bizar-dash/dist/assets/Avatar-B41upSD1.js.map +0 -1
  238. package/bizar-dash/dist/assets/ChatView-CUriVEgU.js +0 -9
  239. package/bizar-dash/dist/assets/ChatView-CUriVEgU.js.map +0 -1
  240. package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js +0 -1
  241. package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js.map +0 -1
  242. package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js +0 -2
  243. package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js.map +0 -1
  244. package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js +0 -6
  245. package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js.map +0 -1
  246. package/bizar-dash/dist/assets/EvalView-CpdFu_ID.js +0 -1
  247. package/bizar-dash/dist/assets/LibrariesView-B1YX9wzp.js +0 -6
  248. package/bizar-dash/dist/assets/MiscView-DLNEGdML.js +0 -1
  249. package/bizar-dash/dist/assets/MiscView-DLNEGdML.js.map +0 -1
  250. package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js +0 -6
  251. package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js.map +0 -1
  252. package/bizar-dash/dist/assets/ObsidianView-Ci80gnwS.js +0 -1
  253. package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js +0 -1
  254. package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js.map +0 -1
  255. package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js +0 -11
  256. package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js.map +0 -1
  257. package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js +0 -6
  258. package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js.map +0 -1
  259. package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js +0 -1
  260. package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js.map +0 -1
  261. package/bizar-dash/dist/assets/main-Cxeu4LhG.js +0 -244
  262. 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
- <button
294
- type="button"
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
- </button>
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={handleNavigate}
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('POSTs to /api/chat/sessions on `+ New session`', async () => {
96
- const state = installFetchMock([
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
- const hit = state.posts.find((p) => p.url.endsWith('/api/chat/sessions') && p.method === 'POST');
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 ?? <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
- Layers,
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: Layers },
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: Layers, count: 5 },
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: Layers },
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 · v8.0.0</div>
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
- <button
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
- display: 'inline-block',
392
- transition: 'transform var(--motion-fast) var(--ease-out)',
393
- transform: sectionOpen ? 'rotate(90deg)' : 'rotate(0deg)',
394
- fontSize: 10,
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
- </button>
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
- const Icon = RESOLVED_ICON[mode];
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 ${density === 'comfortable' ? 'compact' : 'comfortable'} density`}
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 px-2 items-center justify-center',
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
- {density === 'comfortable' ? 'Cozy' : 'Compact'}
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
- <Grid cols={{ base: 1, md: 2, lg: 3 }} gap={3}>
116
- {ACTIONS.map((a) => (
117
- <AdminTile key={a.id} action={a} />
118
- ))}
119
- </Grid>
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
  }