feat(layout): Plan 2.5 P6 — final shell parity (Fix 7, 9, 10)
Per RFC-WS-PRIMEVUE-PLAN-2-5 §5.6–§5.10. Final code phase of Plan 2.5
before closure docs (P7 tokens, P8 closure).
Changes:
- Fix 9: sidebar full-height. The desktop <aside> now carries
`h-screen sticky top-0` so it fills the viewport vertically and
pins to top on body scroll. Without this the aside sized to its
children's intrinsic heights (~250-400px) and ended mid-viewport
even though the surrounding grid row stretched to 100vh. With
h-screen, SidebarNav's `flex-1` claims the remaining column space
and WorkspaceSwitcher anchors to the true viewport bottom — its
`border-t` (existing from P5) is now the divider above the
switcher per crewli-starter. Mobile Drawer untouched (PrimeVue's
internal pt classes already give it 100% panel height).
- Fix 10: density toggle promoted to the store. New
useShellUiStore.toggleDensity() flips comfortable ⇔ compact and
calls applyDomAttributes() synchronously. AppTopbar's local
toggleDensity wrapper deleted; the button now invokes
shell.toggleDensity() directly and carries a stable
data-testid="density-toggle" plus a `title` matching its
aria-label. Density icons swapped from generic flex-alignment
glyphs (tabler-layout-distribute-{vertical,horizontal}) to the
literal density metaphor (tabler-baseline-density-{small,medium}).
Both new icons verified present in the loaded
@iconify-json/tabler set. Topbar right-side order
(search → density → dark → notifications → user) was already
correct from P5; locked with a new ordering spec.
Verified (no code change):
- Fix 6 (§5.6): dark mode `.dark` on <html> confirmed in
useShellUiStore.applyDomAttributes (AD-2.5-D1, P3 complete).
Component-level dark coverage remains a separate backlog item
(DARKMODE-V2-COVERAGE).
- Fix 8 (§5.8): the ▼ arrow is the Vue DevTools v8.0.2 dev-only
toggle button injected by the devtools vite plugin, not Crewli
code — diagnosed, no action.
- Fix 7 (§5.7): non-reproducible at code level. Topbar is
`sticky top-0` and is a SIBLING flex item of <main> inside the
shell's flex-col right column; normal flow stacks <main> below
the topbar at first paint, so the title cannot fall behind a
sticky topbar in this composition. Documented as no-op; if
Bert reproduces it after Fix 9 lands, the symptom is something
else (likely a per-page negative margin or a separate scroll-
container interaction worth its own ticket).
Density enum corrected against runtime data-density: 'comfortable'
(not 'comfy' — the earlier RFC assumption is wrong; the store has
always typed `'comfortable' | 'compact'`).
Tests:
- +2 useShellUiStore.spec.ts: toggleDensity flips comfortable ⇔
compact AND writes data-density via applyDomAttributes;
toggleDensity from compact returns to comfortable on call 2.
- +2 AppTopbar.spec.ts: density button reachable by
data-testid="density-toggle"; topbar right-side order locked
via HTML index comparison (search → density → dark → notif →
user). Existing density-flip specs adapted to spy on
toggleDensity (the new direct call site).
Suite delta: 554 → 558 (+4). vue-tsc clean. Scoped ESLint clean
(0 errors, pre-existing warnings only).
Manual smoke pending Bert:
1. Sidebar full-height, switcher pinned to viewport bottom (Fix 9)
2. Page title clears topbar (Fix 7 — expected no change needed)
3. Density toggle visible between search and dark with the
density icon (Fix 10)
4. Click density toggle → spacing visibly changes, <html
data-density> flips between comfortable and compact (Fix 10)
5. Topbar order: search → density → dark → notifications →
avatar (Fix 10)
6. Dark mode still toggles (Fix 6 regression)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,18 @@ export const useShellUiStore = defineStore('shellUi', () => {
|
||||
density.value = next
|
||||
}
|
||||
|
||||
/**
|
||||
* Plan 2.5 P6 Fix 10: binary UI toggle between the two density extremes
|
||||
* the topbar exposes. Calls applyDomAttributes() so consumers (PrimeVue
|
||||
* Aura preset + Tailwind component styles) react to the new
|
||||
* <html data-density> immediately, mirroring how AppShellV2's watcher
|
||||
* would update on a setDensity() call but synchronously.
|
||||
*/
|
||||
function toggleDensity(): void {
|
||||
density.value = density.value === 'compact' ? 'comfortable' : 'compact'
|
||||
applyDomAttributes()
|
||||
}
|
||||
|
||||
function applyDomAttributes(): void {
|
||||
const el = document.documentElement
|
||||
|
||||
@@ -79,6 +91,7 @@ export const useShellUiStore = defineStore('shellUi', () => {
|
||||
setMobileOpen,
|
||||
setTheme,
|
||||
setDensity,
|
||||
toggleDensity,
|
||||
applyDomAttributes,
|
||||
openDrawer,
|
||||
closeDrawer,
|
||||
|
||||
Reference in New Issue
Block a user