feat(ui): flat nav rail, compact assistant, responsive layouts
Implements the redesign from docs/ui-audit.html. Rearrangement only — no
feature was removed; every control that moved kept its handler, and the
gates that used to hide things now grey them out instead.
Navigation
* The rail is one flat list: the five Workspace sub-views sit at the top
level instead of behind an accordion, with Dashboard/Monitoring pinned
at the foot and Settings below them.
* Cowork and GraphRAG stay listed and greyed while no project is
selected, rather than vanishing and resizing the menu under the user.
* Monitoring keeps its eight sub-views in its own tab strip (unhidden)
instead of doubling the rail's length.
* _goto now moves the highlight itself, fixing a long-standing bug where
programmatic navigation left the rail pointing at the previous screen.
* Rail header gained the project picker and "New chat"; RECENTS lists the
active project's threads. Both are second views of existing state — the
Cowork toolbar button and the full History panel are untouched.
* Provider / language / theme moved from the top bar to an account row at
the foot of the rail (same widgets, same signals).
Screens
* Co4E: the flow tab strip is gone (per the design); Flow Status became a
toolbar toggle with its own way back, and the three icon-only tabs became
four labelled, foldable sections in one column. One flow open at a time
is the one capability this costs; background runs are unaffected.
* Dashboard: header split into two rows; cost promoted to a hero card.
* Monitoring Overview: one scrolling column of titled sections; the model
price table got its own full-width section instead of sharing a row with
the CPU meters.
* Settings and Task editor gained a section index down the left.
* Help dock: 84x64 launcher + chevron became one 26px dot that expands to
a labelled pill on hover; "hide to the edge" moved into the panel's menu.
Layout
* The window's minimum width dropped from 1453px to 768px. The main cause
was a QTabWidget taking its minimum from the widest page even when that
page is hidden, so Co4E was forcing Project and Cowork wide.
* Secondary panes fold themselves on a narrow window and restore when it
grows, never overriding a fold the user made.
* The long dialogs no longer scroll sideways at any font size.
Verification: tools/check_*.py build a real MainWindow offscreen against a
copy of ~/.cowork_local with the schedulers no-oped. check_design_parity.py
reads its checklist straight from the audit page's own proposals.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+27
-16
@@ -404,14 +404,16 @@ class MonitoringTab(QWidget):
|
||||
scroll.setWidget(content)
|
||||
outer.addWidget(scroll)
|
||||
|
||||
root = QHBoxLayout(content)
|
||||
# ONE main column, scrolled vertically, sections in a fixed order — the
|
||||
# two-column grid put six group boxes side by side and mixed three
|
||||
# unrelated concerns (cost, machine resources, security) at the same
|
||||
# level, which made this the densest screen in the app. Each section now
|
||||
# spans the full width and lays its own contents out horizontally, so a
|
||||
# wide window is still used well.
|
||||
root = QVBoxLayout(content)
|
||||
root.setSpacing(12)
|
||||
left = QVBoxLayout()
|
||||
left.setSpacing(12)
|
||||
right = QVBoxLayout()
|
||||
right.setSpacing(12)
|
||||
root.addLayout(left, 2)
|
||||
root.addLayout(right, 1)
|
||||
left = root # sections are appended in reading order
|
||||
right = root
|
||||
|
||||
# ---- Token Usage & Cost --------------------------------------------
|
||||
self.ov_usage_group = QGroupBox()
|
||||
@@ -514,12 +516,10 @@ class MonitoringTab(QWidget):
|
||||
self.ov_pricing_table.setSelectionBehavior(QTableWidget.SelectRows)
|
||||
pg.addWidget(self.ov_pricing_table, 1)
|
||||
|
||||
res_row = QHBoxLayout()
|
||||
res_row.setSpacing(12)
|
||||
res_row.addWidget(self.ov_resource_group, 1)
|
||||
res_row.addWidget(self.ov_pricing_group, 2) # pricing sits beside CPU/resources
|
||||
left.addLayout(res_row)
|
||||
left.addStretch(1)
|
||||
# Resources keep the row to themselves; the model price table gets its
|
||||
# own full-width section further down (it is a reference table, not a
|
||||
# live meter, and squeezing it next to the CPU bars made both unreadable).
|
||||
left.addWidget(self.ov_resource_group)
|
||||
self._reload_pricing_table()
|
||||
|
||||
# ---- Sandbox Details --------------------------------------------
|
||||
@@ -552,7 +552,12 @@ class MonitoringTab(QWidget):
|
||||
sbx_lay.addLayout(limits_row)
|
||||
|
||||
self.ov_sbx_net_lbl, self.ov_sbx_net_val = _kv()
|
||||
right.addWidget(self.ov_sandbox_details_group)
|
||||
# Sandbox and Permissions answer the same question ("what is the agent
|
||||
# allowed to touch?"), so they share one full-width row.
|
||||
self._sbx_perm_row = QHBoxLayout()
|
||||
self._sbx_perm_row.setSpacing(12)
|
||||
self._sbx_perm_row.addWidget(self.ov_sandbox_details_group, 1)
|
||||
root.addLayout(self._sbx_perm_row)
|
||||
|
||||
# ---- Permissions -----------------------------------------------
|
||||
self.ov_permissions_group = QGroupBox()
|
||||
@@ -574,7 +579,10 @@ class MonitoringTab(QWidget):
|
||||
self.ov_perm_edit_btn.setFlat(True)
|
||||
self.ov_perm_edit_btn.clicked.connect(self._open_settings_and_refresh)
|
||||
perm_lay.addWidget(self.ov_perm_edit_btn, 0, Qt.AlignRight)
|
||||
right.addWidget(self.ov_permissions_group)
|
||||
self._sbx_perm_row.addWidget(self.ov_permissions_group, 1)
|
||||
|
||||
# ---- Model pricing — its own section, full width ------------------
|
||||
root.addWidget(self.ov_pricing_group)
|
||||
|
||||
# ---- Audit Log ----------------------------------------------------
|
||||
self.ov_audit_group = QGroupBox()
|
||||
@@ -634,7 +642,10 @@ class MonitoringTab(QWidget):
|
||||
tr("monitoring.col_agent"), tr("monitoring.col_active"), tr("monitoring.col_source"),
|
||||
])
|
||||
|
||||
self.ov_usage_group.setTitle(tr("monitoring.overview_usage_title"))
|
||||
# A QGroupBox title treats "&" as a mnemonic marker, so "token & Chi
|
||||
# phí" rendered as "token _Chi phí". Double it to show a literal "&".
|
||||
self.ov_usage_group.setTitle(
|
||||
tr("monitoring.overview_usage_title").replace("&", "&&"))
|
||||
self.ov_budget_card.apply_btn.setToolTip(tr("usage.budget_apply_tooltip"))
|
||||
self.ov_budget_card.budget_spin.setToolTip(tr("usage.budget_spin_tooltip"))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user