fix(form,browse): drop divergent local overrides of shared chrome

Two more half-contract leaks surfaced by sweeping shared chrome class
usage across tools:

1. form/ had its own design-token namespace (--color-primary,
   --color-bg, --color-text, --color-border, --color-bg-alt,
   --color-text-muted) defined nowhere but fallback'd to hardcoded
   hex values different from shared (#1e3a5f vs shared's #2a5a8a).
   Form's buttons, inputs, fieldsets, array-row borders, and status
   colors all rendered with subtly different palette than the rest
   of the suite.

   Form also redefined .btn, .btn-primary, and a (form-local)
   .btn-small class — the redefinition shadowed shared/base.css's
   button system entirely. Form's JS used 'btn btn-small' for the
   add/remove row buttons in form-array widgets.

   Fixes:
   - form/css/form.css: rename every --color-* reference to the
     matching shared token (--primary, --bg, --bg-secondary, --text,
     --text-muted, --border, --radius, --danger, --success).
   - form/css/form.css: delete the .btn / .btn-primary / .btn-small
     blocks entirely. Shared covers .btn / .btn-primary /
     .btn-secondary / .btn-sm / .btn-lg / .btn-link.
   - form/js/array.js: switch the row add/remove buttons to
     'btn btn-sm btn-secondary' so they pick up shared's sizing
     and outline variant.
   - tests/form-safety.spec.js: update the selector
     button.btn-small → button.btn-sm.

2. browse/ had .hidden { display: none !important; } — exact
   duplicate of shared/base.css's rule. Delete the redundant copy
   (left a one-line comment pointer in case anyone wonders why
   it's missing from the local sheet).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-05-10 14:16:23 -05:00
parent b3e8c4127f
commit 33ce3886f2
4 changed files with 35 additions and 64 deletions

View file

@ -52,7 +52,7 @@ body {
margin: 0.4rem 0; margin: 0.4rem 0;
} }
.hidden { display: none !important; } /* .hidden lives in shared/base.css; no per-tool override needed. */
/* Status bar — shows transient errors/info */ /* Status bar — shows transient errors/info */
.status-bar { .status-bar {

View file

@ -1,5 +1,8 @@
/* form/ ZDDC generic form renderer. /* form/ ZDDC generic form renderer.
Pulls theme tokens from shared/base.css; only adds form-specific layout. */ Form-specific layout only; theme tokens (--primary, --bg, --text,
--border, --bg-secondary, --text-muted, --font-mono, --radius) come
from shared/base.css. Button styles (.btn, .btn-primary,
.btn-secondary, .btn-sm) likewise inherit from shared. */
.form-main { .form-main {
max-width: 800px; max-width: 800px;
@ -10,20 +13,20 @@
.form-status { .form-status {
padding: 0.75rem 1rem; padding: 0.75rem 1rem;
margin-bottom: 1rem; margin-bottom: 1rem;
border-radius: 4px; border-radius: var(--radius);
border: 1px solid var(--color-border); border: 1px solid var(--border);
} }
.form-status.is-error { .form-status.is-error {
background: var(--color-bg-alt); background: var(--bg-secondary);
border-color: #c43; border-color: var(--danger);
color: #c43; color: var(--danger);
} }
.form-status.is-success { .form-status.is-success {
background: var(--color-bg-alt); background: var(--bg-secondary);
border-color: #283; border-color: var(--success);
color: #283; color: var(--success);
} }
.form-root { .form-root {
@ -44,24 +47,24 @@
} }
.form-field__label .required-mark { .form-field__label .required-mark {
color: #c43; color: var(--danger);
margin-left: 0.15rem; margin-left: 0.15rem;
} }
.form-field__description { .form-field__description {
font-size: 0.85rem; font-size: 0.85rem;
color: var(--color-text-muted, #666); color: var(--text-muted);
} }
.form-field__error { .form-field__error {
font-size: 0.85rem; font-size: 0.85rem;
color: #c43; color: var(--danger);
margin-top: 0.15rem; margin-top: 0.15rem;
} }
.form-field__help { .form-field__help {
font-size: 0.8rem; font-size: 0.8rem;
color: var(--color-text-muted, #666); color: var(--text-muted);
font-style: italic; font-style: italic;
} }
@ -69,10 +72,10 @@
.form-field__textarea, .form-field__textarea,
.form-field__select { .form-field__select {
padding: 0.5rem 0.65rem; padding: 0.5rem 0.65rem;
border: 1px solid var(--color-border); border: 1px solid var(--border);
border-radius: 4px; border-radius: var(--radius);
background: var(--color-bg, #fff); background: var(--bg);
color: var(--color-text, #111); color: var(--text);
font: inherit; font: inherit;
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
@ -86,14 +89,14 @@
.form-field__input:focus, .form-field__input:focus,
.form-field__textarea:focus, .form-field__textarea:focus,
.form-field__select:focus { .form-field__select:focus {
outline: 2px solid var(--color-primary, #1e3a5f); outline: 2px solid var(--primary);
outline-offset: -1px; outline-offset: -1px;
} }
.form-field--invalid .form-field__input, .form-field--invalid .form-field__input,
.form-field--invalid .form-field__textarea, .form-field--invalid .form-field__textarea,
.form-field--invalid .form-field__select { .form-field--invalid .form-field__select {
border-color: #c43; border-color: var(--danger);
} }
.form-field__radio-group, .form-field__radio-group,
@ -113,8 +116,8 @@
} }
.form-fieldset { .form-fieldset {
border: 1px solid var(--color-border); border: 1px solid var(--border);
border-radius: 4px; border-radius: var(--radius);
padding: 0.75rem 1rem 1rem; padding: 0.75rem 1rem 1rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -136,10 +139,10 @@
display: flex; display: flex;
gap: 0.5rem; gap: 0.5rem;
align-items: flex-start; align-items: flex-start;
border: 1px solid var(--color-border); border: 1px solid var(--border);
border-radius: 4px; border-radius: var(--radius);
padding: 0.5rem; padding: 0.5rem;
background: var(--color-bg-alt, #f6f6f8); background: var(--bg-secondary);
} }
.form-array__row-body { .form-array__row-body {
@ -165,41 +168,8 @@
gap: 0.5rem; gap: 0.5rem;
} }
.btn { /* Standalone welcome shown when form.html is opened directly (no
padding: 0.5rem 1rem; server-injected #form-context). */
border-radius: 4px;
border: 1px solid var(--color-border);
background: var(--color-bg, #fff);
color: var(--color-text, #111);
cursor: pointer;
font: inherit;
}
.btn:hover {
background: var(--color-bg-alt, #f6f6f8);
}
.btn-primary {
background: var(--color-primary, #1e3a5f);
color: #fff;
border-color: var(--color-primary, #1e3a5f);
}
.btn-primary:hover {
filter: brightness(1.1);
}
.btn-small {
padding: 0.2rem 0.5rem;
font-size: 0.85rem;
}
.btn[disabled] {
opacity: 0.5;
cursor: not-allowed;
}
/* Standalone welcome — shown when form.html is opened directly (no server-injected #form-context). */
.form-welcome { .form-welcome {
max-width: 36rem; max-width: 36rem;
margin: 2rem auto; margin: 2rem auto;

View file

@ -54,7 +54,7 @@
const actions = u.h('div', { className: 'form-array__row-actions' }); const actions = u.h('div', { className: 'form-array__row-actions' });
const removeBtn = u.h('button', { const removeBtn = u.h('button', {
type: 'button', type: 'button',
className: 'btn btn-small', className: 'btn btn-sm btn-secondary',
title: 'Remove this row', title: 'Remove this row',
onClick: function () { removeRow(rowEl); } onClick: function () { removeRow(rowEl); }
}, '×'); }, '×');
@ -85,7 +85,7 @@
if (addable) { if (addable) {
const addBtn = u.h('button', { const addBtn = u.h('button', {
type: 'button', type: 'button',
className: 'btn btn-small form-array__add', className: 'btn btn-sm btn-secondary form-array__add',
onClick: function () { addRow(undefined); } onClick: function () { addRow(undefined); }
}, '+ Add'); }, '+ Add');
wrap.appendChild(addBtn); wrap.appendChild(addBtn);

View file

@ -108,8 +108,9 @@ test.describe('form/ — safety check-in renderer', () => {
await page.locator('.form-array__add').click(); await page.locator('.form-array__add').click();
await expect(page.locator('.form-array__row')).toHaveCount(2); await expect(page.locator('.form-array__row')).toHaveCount(2);
// Remove the first row. // Remove the first row. Button now uses shared .btn-sm
await page.locator('.form-array__row').first().locator('button.btn-small').click(); // instead of the legacy form-local .btn-small class.
await page.locator('.form-array__row').first().locator('button.btn-sm').click();
await expect(page.locator('.form-array__row')).toHaveCount(1); await expect(page.locator('.form-array__row')).toHaveCount(1);
}); });