diff --git a/frontend/src/v2/__tests__/v2-phone-shell.test.ts b/frontend/src/v2/__tests__/v2-phone-shell.test.ts new file mode 100644 index 000000000..3d75a0287 --- /dev/null +++ b/frontend/src/v2/__tests__/v2-phone-shell.test.ts @@ -0,0 +1,40 @@ +import fs from 'fs'; +import path from 'path'; + +// TASK-730 (D223): the artboard's 390 frame is a 52px top bar over a single +// column. jsdom has no layout engine, so this pins the presence of the rules +// that carry it, the same way v2-layout-invariants.test.ts does. + +const css = fs.readFileSync(path.join(__dirname, '../v2.css'), 'utf8'); +// The block is the tail of the sheet, from its marker comment to the end. +const phone = css.slice(css.indexOf('D223 (TASK-730 shell)')); + +describe('D223 phone shell', () => { + test('feature pages get a 52px top bar with the display title', () => { + expect(phone).toMatch(/\.v2-feature__header\s*\{[^}]*min-height:\s*52px/); + expect(phone).toMatch(/\.v2-feature__header\s+\.v2-feature__title\s*\{[^}]*font:\s*800 21px\/1 var\(--v2-font-display\)/); + }); + + test('the title clips to one line, and the whole block stays inside the 760px query', () => { + const title = phone.match(/\.v2-feature__header\s+\.v2-feature__title\s*\{([^}]*)\}/); + expect(title).not.toBeNull(); + expect(title![1]).toContain('white-space: nowrap'); + expect(title![1]).toContain('overflow: hidden'); + expect(title![1]).toContain('text-overflow: ellipsis'); + const mediaAt = phone.indexOf('@media (max-width: 760px)'); + expect(mediaAt).toBeGreaterThan(-1); + expect(phone.indexOf('.v2-feature__header {')).toBeGreaterThan(mediaAt); + expect(phone.indexOf('.v2-feature__header .v2-feature__title')).toBeGreaterThan(mediaAt); + }); + + test('the page body is one tight column and settings leads with the same bar', () => { + expect(phone).toMatch(/\.v2-feature__body\s*\{[^}]*padding:\s*12px 12px 16px/); + expect(phone).toMatch(/\.v2-settings__title\s*\{[^}]*min-height:\s*52px/); + }); + + test('the block comes last in the sheet, so it outranks the earlier phone rules', () => { + const at = css.indexOf('D223 (TASK-730 shell)'); + expect(at).toBeGreaterThan(css.indexOf('.v2-settings__title {')); + expect(css.indexOf('.v2-feature__body {')).toBeLessThan(at); + }); +}); diff --git a/frontend/src/v2/v2.css b/frontend/src/v2/v2.css index 0cb32c445..0e0c63db6 100644 --- a/frontend/src/v2/v2.css +++ b/frontend/src/v2/v2.css @@ -10891,6 +10891,7 @@ details[open] > .v2-settings__summary > .v2-settings__icon:last-child { transfor .v2-root:lang(zh) .v2-inspector__detail-name, .v2-root:lang(zh) .v2-login__title, .v2-root:lang(zh) .v2-feature__title, +.v2-root:lang(zh) .v2-feature__header .v2-feature__title, .v2-root:lang(zh) .v2-settings__title, .v2-root:lang(zh) .v2-settings__label, .v2-root:lang(zh) .v2-settings__account-name, @@ -14060,3 +14061,38 @@ details[open] > .v2-settings__summary > .v2-settings__icon:last-child { transfor .v2-root button.v2-board__card-main:focus-visible, .v2-root button.v2-board__card-move:focus-visible { outline: 2px solid var(--v2-accent); outline-offset: 2px; box-shadow: none; } + +/* D223 (TASK-730 shell): the artboard's 390 frame is a 52px top bar over one + column. Feature pages (connectors, team, settings) share V2PageHead and the + V2FeaturePage body, so the bar and the tighter body live here once instead + of in each page. The tab bar's height is already reserved on .v2-feature. */ +@media (max-width: 760px) { + .v2-feature__header { + display: flex; + align-items: center; + min-height: 52px; + padding: 0 10px 0 12px; + gap: 8px; + } + .v2-feature__header .v2-page-head__identity { align-items: center; gap: 8px; } + .v2-feature__header .v2-feature__title { + font: 800 21px/1 var(--v2-font-display); + letter-spacing: -0.03em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + .v2-feature__header .v2-page-head__meta { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .v2-feature__body { padding: 12px 12px 16px; } + .v2-settings__layout { padding-top: 0; } + .v2-settings__title { + display: flex; + align-items: center; + min-height: 52px; + margin: -12px -12px 12px; + padding: 0 12px; + border-bottom: 1px solid var(--v2-border-soft); + font: 800 21px/1 var(--v2-font-display); + letter-spacing: -0.03em; + } +}