From 1454cd816532a39c84dd67b240b66e3b555f0b74 Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Fri, 1 May 2026 14:26:16 -0400 Subject: [PATCH] refactor(ext/popup): extract renderFormHeader + .form-header CSS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code-review feedback on Task 8: the conditional empty
spacer was an inline-styled magic number and the 6-line header pattern was duplicated across all 7 typed forms. Now: - .form-header class owns the bottom margin in both stylesheets. - :has(+ .form-subtitle) selector drops the margin when a subtitle follows, so spacing tokens stay in CSS instead of inline styles. - renderFormHeader(titleText) shared helper collapses the 6-line duplication to a one-liner per form. item-form.ts (type-selection screen) is unaffected — it uses a different header structure. Co-Authored-By: Claude Opus 4.7 --- extension/src/popup/components/form-header.ts | 20 +++++++++++++++++++ extension/src/popup/components/types/card.ts | 10 +++------- .../src/popup/components/types/document.ts | 10 +++------- .../src/popup/components/types/identity.ts | 10 +++------- extension/src/popup/components/types/key.ts | 10 +++------- extension/src/popup/components/types/login.ts | 8 ++------ .../src/popup/components/types/secure-note.ts | 8 ++------ extension/src/popup/components/types/totp.ts | 10 +++------- extension/src/popup/styles.css | 12 +++++++++++ extension/src/vault/vault.css | 12 +++++++++++ 10 files changed, 63 insertions(+), 47 deletions(-) create mode 100644 extension/src/popup/components/form-header.ts diff --git a/extension/src/popup/components/form-header.ts b/extension/src/popup/components/form-header.ts new file mode 100644 index 0000000..61e6f67 --- /dev/null +++ b/extension/src/popup/components/form-header.ts @@ -0,0 +1,20 @@ +/// Shared header chrome for typed form views (login, secure-note, identity, card, +/// key, totp, document). Renders the title row plus a fullscreen-only "esc to +/// cancel" subtitle. Use the existing `${...}` template-literal interpolation +/// at call sites: `${renderFormHeader('new login')}`. +/// +/// item-form.ts (the type-selection screen) uses a different header structure +/// and does NOT consume this helper. + +import { isInTab } from '../../shared/state'; + +export function renderFormHeader(titleText: string): string { + return ` +
+
${titleText}
+ + ${isInTab() ? '' : ''} +
+ ${isInTab() ? '
esc to cancel
' : ''} + `; +} diff --git a/extension/src/popup/components/types/card.ts b/extension/src/popup/components/types/card.ts index 59c66ab..9f8d7c0 100644 --- a/extension/src/popup/components/types/card.ts +++ b/extension/src/popup/components/types/card.ts @@ -1,7 +1,8 @@ /// Card: number / holder / expiry MonthYear / cvv / pin / kind. /// Detail view has a styled card-silhouette signature block. -import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab, isInTab } from '../../../shared/state'; +import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../../shared/state'; +import { renderFormHeader } from '../form-header'; import { REQUIRED_PILL_HTML } from '../../../shared/glyphs'; import type { Item, ItemId, ManifestEntry, CardKind, Section, AttachmentRef } from '../../../shared/types'; import { @@ -174,12 +175,7 @@ export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Ite app.innerHTML = `
-
-
${mode === 'add' ? 'new card' : 'edit card'}
- - ${isInTab() ? '' : ''} -
- ${isInTab() ? '
esc to cancel
' : '
'} + ${renderFormHeader(mode === 'add' ? 'new card' : 'edit card')} ${state.error ? `
${escapeHtml(state.error)}
` : ''}
diff --git a/extension/src/popup/components/types/document.ts b/extension/src/popup/components/types/document.ts index 16531e8..3d9b850 100644 --- a/extension/src/popup/components/types/document.ts +++ b/extension/src/popup/components/types/document.ts @@ -2,7 +2,8 @@ /// notes/tags + optional supplementary attachments. /// Primary attachment is referenced by ID from the item's attachments array. -import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab, isInTab } from '../../../shared/state'; +import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../../shared/state'; +import { renderFormHeader } from '../form-header'; import { REQUIRED_PILL_HTML } from '../../../shared/glyphs'; import type { Item, ItemId, ManifestEntry, Section, AttachmentRef } from '../../../shared/types'; import { @@ -85,12 +86,7 @@ export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Ite app.innerHTML = `
-
-
${isEdit ? 'edit document' : 'new document'}
- - ${isInTab() ? '' : ''} -
- ${isInTab() ? '
esc to cancel
' : '
'} + ${renderFormHeader(isEdit ? 'edit document' : 'new document')} ${state.error ? `
${escapeHtml(state.error)}
` : ''}
diff --git a/extension/src/popup/components/types/identity.ts b/extension/src/popup/components/types/identity.ts index 858714f..76b3075 100644 --- a/extension/src/popup/components/types/identity.ts +++ b/extension/src/popup/components/types/identity.ts @@ -1,7 +1,8 @@ /// Identity: full_name, address (multiline), phone, email, date_of_birth. /// Detail view shows a "profile card" signature block + plain rows. -import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab, isInTab } from '../../../shared/state'; +import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../../shared/state'; +import { renderFormHeader } from '../form-header'; import { REQUIRED_PILL_HTML } from '../../../shared/glyphs'; import type { Item, ItemId, ManifestEntry, Section, AttachmentRef } from '../../../shared/types'; import { @@ -134,12 +135,7 @@ export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Ite app.innerHTML = `
-
-
${mode === 'add' ? 'new identity' : 'edit identity'}
- - ${isInTab() ? '' : ''} -
- ${isInTab() ? '
esc to cancel
' : '
'} + ${renderFormHeader(mode === 'add' ? 'new identity' : 'edit identity')} ${state.error ? `
${escapeHtml(state.error)}
` : ''}
diff --git a/extension/src/popup/components/types/key.ts b/extension/src/popup/components/types/key.ts index 9e73ad5..e5c3720 100644 --- a/extension/src/popup/components/types/key.ts +++ b/extension/src/popup/components/types/key.ts @@ -2,7 +2,8 @@ /// Form's key_material textarea uses CSS text-security to mask characters /// since