Skip to content

Adopt Input and Select everywhere and refresh the docs screenshots - #79

Merged
vincentmakes merged 4 commits into
mainfrom
fix/ui-guidelines-debt-3
Oct 17, 2026
Merged

vincentmakes merged 4 commits into
mainfrom
fix/ui-guidelines-debt-3

Conversation

@vincentmakes

Copy link
Copy Markdown
Owner

Why

The last item of the UI_GUIDELINES debt plan: dialogs, Settings panels, the admin-portal modals and both login screens still styled their own <input> / <select> with local .input classes (85 text-like inputs and 28 selects across 30 files), so field height, focus ring, label wiring and error announcement differed from form to form. The docs screenshots also predated #76–#78 and the new demo seed.

Release 1.9.0.

What changed

  • Every text-like field and dropdown is the shared Input / Select (components/common). Visible labels are passed as label (same text, including *), so fields that had an unlinked <label> are now reachable by label for the first time; add-row inputs carry an aria-label. Every value, handler, disabled, required, min, placeholder, id and name is unchanged. Empty "Select …" entries that could be picked back stay normal, selectable options (placeholder renders a disabled option and is used only where that is the intent).
  • Select gains groups (labelled <optgroup>s after the flat options) so the site form keeps its country regions.
  • Stable ids: Input / Select generate theirs with useId() instead of a per-render random id.
  • Native date pickers follow the theme: color-scheme is set per theme block in variables.css / themes.css; the per-dialog color-scheme: dark and inverted calendar-icon hacks are gone (a light-theme user used to get a dark calendar popup in two dialogs).
  • Documented exceptions stay raw (UI_GUIDELINES §3.4): the inline row-rename editors (Tags ×2, Absence types, Predefined phases), the two ARIA comboboxes (Users job-title autocomplete, TagPicker search), the Gantt CustomColumnCell editor, the header SiteSelector, the phone-only SettingsHub section picker and the read-only copy fields of CredentialsModal.
  • A second ratchet: src/components/__tests__/rawFormControls.test.ts counts raw text-like inputs and selects per component (comments ignored) against rawFormControlsAllowlist.json, which holds exactly those exceptions. A count may only fall, and the allowlist must not name a file that no longer needs it. The colour ratchet was lowered for the 13 stylesheets whose removed rules held literals.
  • Docs screenshots refreshed: all 49 PNGs retaken with the canonical pipeline against the new seed and the 1.7–1.9 UI (captured from the backend running on uvicorn with Postgres in Docker, since this environment cannot build the image through its proxy; the capture scripts are unchanged apart from the fix below).
  • Seed fix found on the way: seed_demo stopped on a real PostgreSQL right before the notifications and staff notes — the notifications insert reused $1/$2/$7 both in the SELECT list and in the WHERE NOT EXISTS comparison, which Postgres deduces as text vs character varying. The key is now passed as its own placeholders; test_no_statement_uses_a_placeholder_twice pins the shape. The collab capture read GET /api/projects as a bare list; it answers {"items": [...]}, so the helper accepts both.

Visible changes to check

  • Dialog fields are now 36 px with the shared background, radius and focus ring (they were 8 px padding, bg-primary, small radius).
  • The Settings add rows, filters and the Equipment/Users panels lose their uppercase muted filter labels and blue-bordered inline inputs for the shared look.
  • The Users panel's "Admin" role option no longer carries a trailing space; the "can't change role" text is the field's hint.
  • The admin portal's "add tenant" picker shows "Select a tenant to add..." as a disabled prompt.
  • The country dropdown keeps its four region groups (Select groups).

Tests

  • Per converted file, at least one field is reached through getByLabelText in its existing test (new assertions in the Equipment, Predefined phases, Sites, Phase, Subphase, Project, Vacation, Calendar/EquipmentBlock, admin create and organization-details tests); a new AbsenceTypeSelect.test.tsx covers the colour dot in the icon slot, the aria-label, the "No type" choice and the number/null mapping.
  • FormControls.test.tsx: option groups render as labelled optgroups; the ratchet test checks its own counter (typed, untyped and multi-line tags, native-only inputs, comments).
  • Frontend: 196 files / 2082 tests pass; tsc, eslint on the 42 changed files and npm run build are clean. Backend: ruff, the seed tests (11) and mkdocs build --strict pass.
  • trail check reports 18 "conflicts"; all are keyword matches ("Start Date"/"End Date" fields against a learning about clearing state at start, "shared picker", the removed SQL screenshot file, allowlist numbers) — nothing a learning ruled out is reintroduced.

https://claude.ai/code/session_01FPFQEucReHG1Wo9R6PpEpj


Generated by Claude Code

Every text-like field and every dropdown in the dialogs, the Settings
panels, the admin-portal modals and both login screens is the shared Input
or Select: one height, focus ring, label wiring and error announcement.
Labels are passed as `label` (fields that had an unlinked <label> are now
reachable by label), add rows carry an aria-label, and every value,
handler, disabled, required, min, placeholder, id and name is unchanged.
Empty "Select …" entries the user can pick back stay selectable options.

Select gains `groups` (labelled optgroups) so the site form keeps its
country regions. Input and Select generate stable ids with useId.
color-scheme is set per theme block, so native date pickers follow the
theme; the per-dialog dark-only hacks are gone.

The documented exceptions stay raw (inline row-rename editors, the two
ARIA comboboxes, the Gantt cell editor, the header SiteSelector, the
phone-only Settings section picker, the credentials copy fields) and
rawFormControls.test.ts pins them: raw controls are counted per component
against an allowlist that may only shrink. The colour allowlist is lowered
for the stylesheets whose removed rules held literals.

Also fixes the demo seed on a real PostgreSQL: the notifications insert
reused placeholders in the SELECT list and the duplicate check, which is
deduced as text vs character varying and refused; the key is passed
separately now and a test pins the statement shape.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPFQEucReHG1Wo9R6PpEpj
All 49 screenshots retaken with the canonical pipeline (capture.py,
capture_collab.py, capture_admin.py) against the one demo seed and the
1.7–1.9 UI. The collab capture read GET /api/projects as a bare list; the
endpoint answers {"items": [...]}, so the helper accepts both.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPFQEucReHG1Wo9R6PpEpj
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Deploying milestone-planner with  Cloudflare Pages  Cloudflare Pages

Latest commit: 089a049
Status: ✅  Deploy successful!
Preview URL: https://2b1474e3.milestone-planner.pages.dev
Branch Preview URL: https://fix-ui-guidelines-debt-3.milestone-planner.pages.dev

View logs

CI's diff-coverage gate counted the one-line onChange handlers of the
converted fields as uncovered: the tests rendered them but never changed
them. Each dialog and panel test now fires a change on every converted
field and asserts the value or the payload it ends up in (diff coverage
77 % -> 99 %). The self-only staff field in AssignmentModal gets a constant
label: that branch is always a staff assignment, so the equipment
alternative was dead.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPFQEucReHG1Wo9R6PpEpj
@vincentmakes
vincentmakes merged commit 2c0d7ce into main Oct 17, 2026
21 checks passed
@vincentmakes
vincentmakes deleted the fix/ui-guidelines-debt-3 branch October 17, 2026 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants