Skip to content

Commit 1a9d486

Browse files
docs(migrations): document PageHeader split + tabs spacing/alignment refactor
Adds a new migration entry above the previous chrome convergence entry covering the changes in this batch: - PageHeader is content-sized (56px enforcement removed) - #tabs slot on PageHeader dropped (dead since #4187) - mx-4 on v-tabs inside CoreSurfaceTabBar (horizontal alignment with title) - New CorePageHeaderTabs primitive that bundles PageHeader + SurfaceTabBar and re-enforces the 56px rhythm for tabbed surfaces - pb-0 on the tabbed-layout container to collapse the gap below tabs - Empty-state v-row regression pattern (guard the populated row with v-if) Downstream impact: minimal — only projects with custom tabbed layouts need to migrate to CorePageHeaderTabs; default consumers get the new convention via /update-stack automatically.
1 parent 14c02b5 commit 1a9d486

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

MIGRATIONS.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,116 @@ Breaking changes and upgrade notes for downstream projects.
44

55
---
66

7+
## PageHeader split + tabs spacing/alignment refactor (2026-05-21, v2)
8+
9+
**Non-breaking for default consumers** — affects 3 stack layouts (Account, Organization detail, Admin) which were already refactored upstream. Downstream projects only need to act if they wrote a custom layout using `PageHeader` + `CoreSurfaceTabBar` directly, or relied on the (now removed) `#tabs` slot on `PageHeader`.
10+
11+
This entry supersedes the spacing/structure parts of the previous "Account / Organization / Admin chrome convergence" entry below; the four conventions still apply for child views, dialogs, etc.
12+
13+
### What changed
14+
15+
1. **`PageHeader` is now content-sized** — the canonical `min-height: 56px / max-height: 56px` is gone from `core.pageHeader.component.vue`. Pages without tabs (list views like Tasks, Scraps) no longer pay the chrome tax.
16+
2. **`PageHeader`'s `#tabs` slot is removed** — it was dead code since #4187 (tabs are siblings of the header, not inside it).
17+
3. **`CoreSurfaceTabBar` aligns tabs horizontally with the title**`<v-tabs class="mx-4">` is now applied internally, so the tab strip sits at the same x-offset as `PageHeader`'s icon+title.
18+
4. **New primitive `CorePageHeaderTabs`** (`src/modules/core/components/core.pageHeaderTabs.component.vue`) bundles `PageHeader` + `CoreSurfaceTabBar` and enforces the 56px title↔breadcrumb rhythm via a scoped `:deep()` rule — used wherever a section needs both a header and a tab bar.
19+
5. **Tabbed layouts use `<v-container fluid class="pb-0">`** to collapse the dead gap between the tab underline and the routed child's top edge.
20+
21+
### The new convention
22+
23+
Pages **with tabs** (Account, Org detail, Admin) — single primitive:
24+
25+
```vue
26+
<template>
27+
<v-container fluid class="pb-0">
28+
<CorePageHeaderTabs
29+
icon="fa-solid fa-X"
30+
title="Section"
31+
:tabs="config.section.tabs"
32+
:can="sectionCan"
33+
:base-path="basePath"
34+
:hide-tabs="false"
35+
>
36+
<template #actions>...</template>
37+
<template #breadcrumb v-if="...">...</template>
38+
</CorePageHeaderTabs>
39+
</v-container>
40+
<router-view />
41+
</template>
42+
```
43+
44+
Pages **without tabs** (Tasks, Scraps, simple list views) — content-sized `PageHeader`, unchanged shape:
45+
46+
```vue
47+
<template>
48+
<v-container fluid>
49+
<PageHeader icon="fa-solid fa-X" title="Section">
50+
<template #actions>...</template>
51+
</PageHeader>
52+
<v-row class="pa-2 mt-0">
53+
<!-- content -->
54+
</v-row>
55+
</v-container>
56+
</template>
57+
```
58+
59+
### Breadcrumb mode
60+
61+
The pattern from the previous migration entry still holds. Now expressed via `CorePageHeaderTabs`:
62+
63+
```vue
64+
<CorePageHeaderTabs
65+
icon="fa-solid fa-user-tie"
66+
:title="currentBreadcrumb ? '' : 'Section'"
67+
:tabs="tabs"
68+
:can="can"
69+
:base-path="basePath"
70+
:hide-tabs="!!currentBreadcrumb"
71+
>
72+
<template v-if="currentBreadcrumb" #breadcrumb>
73+
<router-link to="/section">Section</router-link>
74+
<v-icon icon="fa-solid fa-chevron-right" size="x-small" class="mx-2 text-medium-emphasis" />
75+
<span>{{ currentBreadcrumb.title }}</span>
76+
</template>
77+
</CorePageHeaderTabs>
78+
```
79+
80+
Set `:hide-tabs="true"` when in breadcrumb mode (user has drilled into a sub-record) so the tab bar disappears; the 56px height stays consistent across the title↔breadcrumb route transition.
81+
82+
### Empty-state regression to watch for
83+
84+
If a list view renders both a populated row AND an empty-state row in the same template, **guard the populated row with `v-if`** so it doesn't take vertical space when the list is empty. Example fixed in this batch (`tasks.view.vue`):
85+
86+
```vue
87+
<v-row v-if="tasks && tasks.length" class="pa-2 mt-0">
88+
<taskComponent v-for="..." />
89+
</v-row>
90+
<v-row v-if="!tasks || !tasks.length" class="pa-2 mt-0">
91+
<!-- empty state -->
92+
</v-row>
93+
```
94+
95+
Without the guard, the empty populated row still consumes ~16-24px (pa-2 + default v-row margins) and pushes the empty-state card down.
96+
97+
### Migration for downstream projects
98+
99+
Most downstream projects don't write custom layouts using `PageHeader` + `CoreSurfaceTabBar` — they consume the layouts via the stack. `/update-stack` will pick up the new convention automatically.
100+
101+
**If your project has a custom tabbed layout** (rare):
102+
103+
1. Replace `<PageHeader>` + `<CoreSurfaceTabBar>` siblings with a single `<CorePageHeaderTabs>` (import from `src/modules/core/components/core.pageHeaderTabs.component.vue`).
104+
2. Add `class="pb-0"` to the wrapping `<v-container fluid>` so the gap below tabs collapses.
105+
3. Drop any local CSS that compensated for the 56px PageHeader height — the new primitive handles it.
106+
107+
**If your project uses `PageHeader` with the `#tabs` slot** (very rare):
108+
109+
- Remove the slot usage. Render tabs as a sibling of `PageHeader` (or use `CorePageHeaderTabs`).
110+
111+
### Tests touched
112+
113+
Stack tests updated to find `CorePageHeaderTabs` by name instead of looking for `PageHeader` + `CoreSurfaceTabBar` separately. Downstream test files that follow the same pattern will need the same update; if a downstream stub-tests `PageHeader` directly, no change needed.
114+
115+
---
116+
7117
## Account / Organization / Admin chrome convergence (2026-05-21)
8118

9119
**Non-breaking for default consumers.** Builds on #4183 (`corePageTabs`), #4184 (org tabs), #4185 (Account chrome), and #4187 (Admin chrome + `coreConfirmDialog` + `coreAvatarUploader`). Locks in one chrome convention across all "section + tab bar + routed children" layouts.

0 commit comments

Comments
 (0)