# G01 Centered Minimum-Height Add Sheet Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:executing-plans` to implement this plan task-by-task. Subagents and worktrees are prohibited for this project. **Goal:** Make the G01 “添加家谱” sheet use a `780rpx` minimum height whose visible upper edge reaches the user-marked position, center the complete title-and-actions group, and separate adjacent buttons by `24rpx` while preserving safe growth and scrolling for longer content. **Architecture:** Keep the existing single `g01-add-sheet-background-v3.png` nine-slice sheet and existing `AppButton` assets. The `add-dialog__body` flow container uses vertical `auto` margins to remain centered as its two adjacent-button gaps increase from `6rpx` to `24rpx`; the margins collapse when content grows, while the close control follows the heading in every height state. **Tech Stack:** uni-app Vue single-file component, SCSS with `rpx`, PowerShell visual-contract tests, Chrome DevTools Protocol on the existing port-9222 project tab. ## Global Constraints - Modify only G01’s current “添加家谱” sheet; do not change other G01 states, the genealogy switcher, or other pages. - Do not use subagents, worktrees, `git add`, `git commit`, `git push`, `git reset`, or `git checkout`. - Preserve every existing modified, untracked, ignored, test, document, screenshot, master, candidate, and asset file. - Do not loosen test thresholds and do not connect APIs. - Keep the single complete background asset and existing project `AppButton` styles. - Keep `max-height: calc(100vh - 80rpx)` and content scrolling. - H5 evidence is internal only; Android/HBuilderX remains unverified. - Do not mark G01 `[x]`, frozen, or accepted without the user’s explicit “通过”. --- ### Task 1: Tighten the G01 visual contract for the centered body **Files:** - Modify: `tests/g01-visual-contract.ps1:78-135` - Test: `tests/g01-visual-contract.ps1` **Interfaces:** - Consumes: the G01 add-sheet template and SCSS as plain UTF-8 source text. - Produces: a source contract requiring `add-dialog__body`, nested close control, `780rpx` minimum height, symmetric content padding, and flow-based centering. - [ ] **Step 1: Require the new body structure and nested close control** Add `class="add-dialog__body"` to the required markup tokens and add this structural check: ```powershell if ($addMarkup -notmatch '(?s)\s*.*?class="add-dialog__close".*?\s*\s*') { throw 'G-01 add sheet must keep the close control with the centered heading and actions body.' } ``` - [ ] **Step 2: Replace the obsolete `620rpx` and fixed-close assertions** Use these exact contracts: ```powershell if ($page -notmatch '(?s)\.add-dialog\s*\{[^}]*min-height:\s*780rpx;[^}]*max-height:\s*calc\(100vh\s*-\s*80rpx\);') { throw 'G-01 add sheet does not reach the approved arrow-aligned minimum height.' } if ($page -notmatch '(?s)\.add-dialog__content\s*\{[^}]*min-height:\s*780rpx;[^}]*max-height:\s*calc\(100vh\s*-\s*80rpx\);[^}]*padding:\s*96rpx\s+52rpx\s+calc\(96rpx\s*\+\s*env\(safe-area-inset-bottom\)\);') { throw 'G-01 add sheet does not reserve the approved symmetric centering area.' } if ($page -notmatch '(?s)\.add-dialog__body\s*\{[^}]*margin:\s*auto\s+0;') { throw 'G-01 add sheet body does not center safely with collapsible auto margins.' } if ($page -notmatch '(?s)\.add-dialog__heading\s*\{[^}]*position:\s*relative;[^}]*padding-right:\s*96rpx;') { throw 'G-01 add sheet heading does not own the close-control positioning context.' } if ($page -notmatch '(?s)\.add-dialog__close\s*\{[^}]*position:\s*absolute;[^}]*top:\s*0;[^}]*right:\s*-22rpx;') { throw 'G-01 add sheet close control does not follow the centered heading.' } if ($page -notmatch '(?s)\.add-dialog__actions\s*>\s*\.app-button\s*\+\s*\.app-button\s*\{[^}]*margin-top:\s*24rpx;') { throw 'G-01 add sheet buttons do not keep the approved 24rpx spacing.' } ``` Remove the assertions requiring `620rpx`, `118rpx 52rpx calc(64rpx...)`, and `top: 116rpx`. - [ ] **Step 3: Run the contract and observe the intended failure** Run: ```powershell powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-visual-contract.ps1 ``` Expected: FAIL with `G-01 add sheet must keep the close control with the centered heading and actions body.` or the new `780rpx` minimum-height failure. A script parse error is not an acceptable red state. --- ### Task 2: Implement the centered, safely growing sheet body **Files:** - Modify: `pages/genealogy/g01-my-genealogies.vue:235-250` - Modify: `pages/genealogy/g01-my-genealogies.vue:952-961` - Test: `tests/g01-visual-contract.ps1` **Interfaces:** - Consumes: existing `addDialogVisible`, `closeAddDialog`, `applyToJoin`, `joinByInvite`, and `createGenealogy` behavior. - Produces: `add-dialog__body`, which centers at the minimum height, grows with content, and becomes top-origin scroll content at the maximum height. - [ ] **Step 1: Group the heading and actions, and nest close under the heading** Replace only the inner add-sheet markup with: ```vue 添加家谱 建议先搜索已有家谱,避免重复创建 ``` - [ ] **Step 2: Apply the minimum-height and safe-centering styles** Use these exact declarations while preserving the current border-image declarations: ```scss .add-dialog { position: relative; width: 100%; min-height: 780rpx; max-height: calc(100vh - 80rpx); box-sizing: border-box; border: 1px solid transparent; border-image-source: url("/static/assets/modules/genealogy/transparent/g01-add-sheet-background-v3.png"); border-image-slice: 220 0 1 0 fill; border-image-width: 118rpx 0 1rpx; border-image-repeat: stretch; } .add-dialog__content { position: relative; z-index: 2; display: flex; min-height: 780rpx; max-height: calc(100vh - 80rpx); flex-direction: column; align-items: stretch; box-sizing: border-box; padding: 96rpx 52rpx calc(96rpx + env(safe-area-inset-bottom)); overflow-y: auto; } .add-dialog__body { margin: auto 0; } .add-dialog__heading { position: relative; padding-right: 96rpx; } .add-dialog__close { position: absolute; z-index: 3; top: 0; right: -22rpx; display: flex; width: 80rpx; height: 80rpx; align-items: center; justify-content: center; } .add-dialog__actions { display: flex; flex-direction: column; margin: 62rpx -32rpx 0; } .add-dialog__actions > .app-button + .app-button { margin-top: 24rpx; } ``` - [ ] **Step 3: Run the focused contract** Run: ```powershell powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-visual-contract.ps1 ``` Expected: `PASS G-01 visual contract`. - [ ] **Step 4: Run the adjacent G01 state contracts** Run: ```powershell powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-empty-state-contract.ps1 powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-loading-state-contract.ps1 powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-error-state-contract.ps1 git diff --check ``` Expected: all four G01 contracts pass; `git diff --check` exits 0. Existing line-ending warnings may remain, but no whitespace error may be introduced. --- ### Task 3: Verify minimum, growth, overflow, and interactions in the existing Chrome tab **Files:** - Create evidence only: `docs/design/screens/runtime/2026-07-19/g01-approval/05-add-dialog-centered-min-412x915.png` - Create evidence only: `docs/design/screens/runtime/2026-07-19/g01-approval/05-add-dialog-centered-six-buttons-412x915.png` - No production or test file changes. **Interfaces:** - Consumes: the unique existing `http://localhost:5173` page exposed by Chrome debugging port 9222. - Produces: measured H5 evidence without opening another browser or project tab. - [ ] **Step 1: Assert the unique project tab and restore 412×915** Connect through CDP, filter pages with: ```js const projectPages = pages.filter(page => page.type === 'page' && page.url.startsWith('http://localhost:5173')) if (projectPages.length !== 1) throw new Error(`Expected one existing project tab, found ${projectPages.length}`) ``` Set device metrics to `412×915`, navigate that same page to G01, and open `.create-action`. - [ ] **Step 2: Measure the three-button minimum and centering** Capture the dialog and body rectangles: ```js const dialog = document.querySelector('.add-dialog').getBoundingClientRect() const body = document.querySelector('.add-dialog__body').getBoundingClientRect() const topSpace = body.top - dialog.top const bottomSpace = dialog.bottom - body.bottom ``` Expected at 412×915: - `dialog.height` is approximately `429px` (`780rpx`, tolerance ±3px). - `Math.abs(topSpace - bottomSpace) <= 3` in H5 where the safe-area inset is zero. - Each adjacent-button visual gap is approximately `13.2px` (`24rpx`, tolerance ±2px). - Three `.app-button` elements are visible and horizontal overflow is `0`. - Save `05-add-dialog-centered-min-412x915.png`. - [ ] **Step 3: Verify 320×568** Set `320×568`, reopen the same state, and measure again. Expected: - Dialog minimum is approximately `333px` (tolerance ±3px). - Each adjacent-button visual gap is approximately `10.2px` (`24rpx`, tolerance ±2px). - The last button bottom is not below the viewport. - No horizontal overflow or heading/close overlap. - [ ] **Step 4: Verify natural six-button growth** At 412×915, clone the three existing button nodes once inside `.add-dialog__actions` for pressure evidence only. Expected: - Button count is 6. - Dialog height is greater than the three-button minimum and less than its maximum. - `content.scrollHeight === content.clientHeight` for this medium pressure state. - Save `05-add-dialog-centered-six-buttons-412x915.png`. - [ ] **Step 5: Verify safe maximum-height scrolling** Continue cloning button nodes until content exceeds the maximum height. Expected: - Dialog height does not exceed `calc(100vh - 80rpx)` by more than 2px. - `content.scrollHeight > content.clientHeight`. - Initial `content.scrollTop === 0` and the title is reachable at the top. - Setting `content.scrollTop = content.scrollHeight` produces a positive scroll position and reaches the final button. - [ ] **Step 6: Verify close behavior and restore approval state** Verify in order: - Clicking `.add-dialog__content` keeps the layer open. - Clicking `.add-dialog__close` closes it. - Reopening and clicking `.add-dialog-layer` closes it. - No runtime exceptions or failed 4xx/5xx asset responses occur on a fresh navigation. Finally restore the same tab to 412×915, three buttons, no injected clones, and keep the add sheet open. --- ### Task 4: Record internal design QA without claiming user or Android acceptance **Files:** - Modify: `design-qa.md` - Test: `tests/g01-visual-contract.ps1` **Interfaces:** - Consumes: the user-marked screenshot, three-button capture, six-button capture, measured centering, responsive check, interaction results, and console/network results. - Produces: an internal H5 QA entry whose final result describes only the candidate evidence. - [ ] **Step 1: Create a same-viewport comparison image** Place the previous 412×915 state and `05-add-dialog-centered-min-412x915.png` side by side without rescaling either app viewport. Save it under the existing G01 approval evidence folder. - [ ] **Step 2: Inspect the combined comparison and both pressure captures** Check the five required surfaces explicitly: typography, spacing/layout, color/tokens, image quality/assets, and copy. Record any P0/P1/P2 finding before claiming an internal pass. - [ ] **Step 3: Update `design-qa.md`** Record: - Source screenshot and approved arrow target. - Implementation and comparison paths. - 412×915 and 320×568 metrics. - Three-button centering, six-button growth, and maximum-height scrolling. - Interaction and console/network evidence. - `final result: passed` only if no actionable H5 P0/P1/P2 issue remains. - Explicit limits: user acceptance pending; Android/HBuilderX unverified; G01 not frozen. - [ ] **Step 4: Run the final verification gate** Run: ```powershell powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-visual-contract.ps1 powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-empty-state-contract.ps1 powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-loading-state-contract.ps1 powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-error-state-contract.ps1 git diff --check ``` Expected: all contracts pass and `git diff --check` exits 0. Report line-ending warnings separately from failures. Do not run any Git write command. Leave the existing 412×915 Chrome tab showing only the three-button add sheet and wait for explicit user approval.