From 65cdfbc00ffcfc1ee323a6ca3cd68f40fc7953ce Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Thu, 14 May 2026 23:42:53 +0200 Subject: [PATCH] =?UTF-8?q?docs(03):=20fix=20UI-SPEC=20checker=20blocks=20?= =?UTF-8?q?=E2=80=94=20copywriting=20labels=20and=20typography=20weight?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace generic "Save"/"Cancel" with specific labels: "Save changes", "Discard changes", "Keep tablo" throughout spec, component inventory, interaction contracts, and HTMX reference table - Remove 500 (medium) weight; form labels now use font-semibold (600), consistent with Button convention — 2 declared weights total Co-Authored-By: Claude Sonnet 4.6 (1M context) --- .planning/phases/03-tablos-crud/03-UI-SPEC.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.planning/phases/03-tablos-crud/03-UI-SPEC.md b/.planning/phases/03-tablos-crud/03-UI-SPEC.md index 0a0227c..e260e7c 100644 --- a/.planning/phases/03-tablos-crud/03-UI-SPEC.md +++ b/.planning/phases/03-tablos-crud/03-UI-SPEC.md @@ -74,10 +74,10 @@ All sizes sourced from existing codebase patterns in `templates/` and `ui/`. | Display | 28px | 600 (semibold) | 1.2 (tight) | `text-[28px] font-semibold leading-tight` | Dashboard page heading ("Your Tablos") | | Heading | 20px | 600 (semibold) | 1.3 (snug) | `text-xl font-semibold leading-snug` | Tablo card title, detail page section headings | | Body | 16px | 400 (regular) | 1.5 | `text-base text-slate-600` | Tablo descriptions, paragraph content | -| Label | 14px | 500 (medium) | 1.4 | `text-sm font-medium text-slate-700` | Form labels, metadata (created date, owner email) | +| Label | 14px | 600 (semibold) | 1.4 | `text-sm font-semibold text-slate-700` | Form labels, metadata (created date, owner email) | | Small/muted | 14px | 400 (regular) | 1.4 | `text-sm text-slate-500` | "Signed in as" subtext, timestamps | -Two declared weights: 400 (regular) and 600 (semibold). The 500 (medium) weight is used only for form labels — this follows the existing auth form pattern (`text-sm font-medium text-slate-700`). +2 declared weights: 400 (regular) and 600 (semibold). Form labels use font-semibold (600), consistent with the Button component convention already established in Phase 2. --- @@ -91,7 +91,7 @@ Two declared weights: 400 (regular) and 600 (semibold). The 500 (medium) weight | Destructive | #b91c1c | bg-red-700 / text-red-700 | Delete confirmation button, field error text, general error banner | Accent (#2563eb / blue-600) reserved for: -1. Primary action button — "New tablo" (create) and "Save" (edit submit) +1. Primary action button — "New tablo" (create) and "Save changes" (edit submit) 2. Focus ring on all interactive elements (`outline: 2px solid #2563eb`) 3. Nothing else — links, secondary actions, and navigation use slate tones @@ -110,7 +110,7 @@ Tablo color field rendering: render as a 10px × 10px filled dot (CSS circle usi | Component | Import | Usage in Phase 3 | |-----------|--------|-----------------| | `ui.Card` | `backend/internal/web/ui` | Tablo list card, create form container | -| `ui.Button` (solid/default/md) | `backend/internal/web/ui` | "New tablo" CTA, "Save" on edit, "Create tablo" submit | +| `ui.Button` (solid/default/md) | `backend/internal/web/ui` | "New tablo" CTA, "Save changes" on edit, "Create tablo" submit | | `ui.Badge` | `backend/internal/web/ui` | Optional: status labels if needed | | `ui.CSRFField` | `backend/internal/web/ui` | All forms (create, edit, delete) — AUTH-06 | | `templates.FieldError` | `backend/templates` | Inline field validation on create/edit forms | @@ -131,9 +131,9 @@ Tablo color field rendering: render as a 10px × 10px filled dot (CSS circle usi | `templates.TabloDescDisplay` | `backend/templates/tablos.templ` | Display fragment for description | | `templates.TabloDescEditFragment` | `backend/templates/tablos.templ` | Edit textarea fragment for description | | `templates.TabloDeleteButtonFragment` | `backend/templates/tablos.templ` | Delete button (swaps to confirmation row) | -| `templates.TabloDeleteConfirmFragment` | `backend/templates/tablos.templ` | "Delete tablo? Yes / Cancel" confirmation row | +| `templates.TabloDeleteConfirmFragment` | `backend/templates/tablos.templ` | "Delete tablo? Yes / Keep tablo" confirmation row | | `ui.ButtonDanger` (soft/danger/md CSS) | `backend/internal/web/ui/button.css` | Delete-confirm "Yes, delete" button (red variant) | -| `ui.ButtonNeutral` (soft/neutral/md CSS) | `backend/internal/web/ui/button.css` | "Cancel" button (slate/ghost variant) | +| `ui.ButtonNeutral` (soft/neutral/md CSS) | `backend/internal/web/ui/button.css` | "Discard changes" / "Keep tablo" button (slate/ghost variant) | --- @@ -172,14 +172,14 @@ Tablo color field rendering: render as a 10px × 10px filled dot (CSS circle usi - Save: `hx-post="/tablos/{id}"` (with `_method=PATCH` hidden input for semantic clarity, handled by chi) targeting the edit fragment container, `hx-swap="outerHTML"`. - On success: server returns the updated display fragment. - On validation error: server returns the edit fragment with a field error. -- Cancel: A "Cancel" button fires `hx-get="/tablos/{id}/show-title"` (or `/show-desc`) to restore the original display fragment without modifying the DB. +- Cancel: A "Discard changes" button fires `hx-get="/tablos/{id}/show-title"` (or `/show-desc`) to restore the original display fragment without modifying the DB. - Non-HTMX fallback: `POST /tablos/{id}` with `_method=PATCH` → `303 /tablos/{id}` redirect. ### 5. Delete Tablo — Inline Confirmation - Context: delete button visible on both the dashboard card and the detail page. - Trigger: Delete button fires `hx-get="/tablos/{id}/delete-confirm"` targeting the button's container (`hx-target="closest .tablo-delete-zone"`) with `hx-swap="outerHTML"`. -- Confirmation row: renders "Delete tablo? [Yes, delete] [Cancel]" inline. +- Confirmation row: renders "Delete tablo? [Yes, delete] [Keep tablo]" inline. - Confirm: `hx-delete="/tablos/{id}"` (or `hx-post` with `_method=DELETE`) with `hx-target="closest .ui-card"` and `hx-swap="outerHTML"` (removes the card from the DOM on success). - Cancel: fires `hx-get="/tablos/{id}/delete-cancel"` to restore the original delete button fragment. - On success (dashboard): card removed from `#tablos-list`. If list is now empty, server should return the empty state fragment via `HX-Retarget: #tablos-list` + `HX-Reswap: innerHTML`. @@ -197,13 +197,13 @@ Tablo color field rendering: render as a 10px × 10px filled dot (CSS circle usi | Primary CTA (create) | "New tablo" | | Create form heading | "Create a tablo" | | Create submit button | "Create tablo" | -| Edit save button | "Save" | -| Edit cancel button | "Cancel" | +| Edit save button | "Save changes" | +| Edit cancel button | "Discard changes" | | Delete button (card/detail) | "Delete" | | Delete confirm heading | "Delete tablo?" | | Delete confirm body | "This cannot be undone." | | Delete confirm action | "Yes, delete" | -| Delete cancel action | "Cancel" | +| Delete cancel action | "Keep tablo" | | Empty state heading | "No tablos yet" | | Empty state body | "Create your first tablo to get started." | | Empty state CTA | "New tablo" (same blue button) | @@ -225,7 +225,7 @@ Input: mt-1 block w-full rounded border border-slate-300 px-3 py-2 text-sm placeholder-slate-400 focus:border-slate-500 focus:outline-none Textarea: mt-1 block w-full rounded border border-slate-300 px-3 py-2 text-sm placeholder-slate-400 focus:border-slate-500 focus:outline-none resize-y -Label: block text-sm font-medium text-slate-700 +Label: block text-sm font-semibold text-slate-700 ``` Field error: `

` (existing `templates.FieldError`). @@ -250,7 +250,7 @@ Phase 3 needs two new CSS rules in `backend/internal/web/ui/button.css`: .ui-button-solid-danger-md:hover { background-color: #991b1b; } ``` -**Neutral soft md** (cancel, secondary actions): +**Neutral soft md** (discard changes, keep tablo, secondary actions): ``` .ui-button-soft-neutral-md { background-color: #f1f5f9; /* slate-100 */ @@ -288,10 +288,10 @@ Established patterns to reuse exactly (do not invent new patterns): | Submit create (error) | hx-post="/tablos" | #create-form-slot | innerHTML | | Show edit title | hx-get="/tablos/{id}/edit-title" | `.tablo-title-zone` | outerHTML | | Save edit title | hx-post="/tablos/{id}" | `.tablo-title-zone` | outerHTML | -| Cancel edit title | hx-get="/tablos/{id}/show-title" | `.tablo-title-zone` | outerHTML | +| Discard edit title | hx-get="/tablos/{id}/show-title" | `.tablo-title-zone` | outerHTML | | Show delete confirm | hx-get="/tablos/{id}/delete-confirm" | `.tablo-delete-zone` | outerHTML | | Confirm delete | hx-post="/tablos/{id}/delete" | `.ui-card` (closest) | outerHTML | -| Cancel delete confirm | hx-get="/tablos/{id}/delete-cancel" | `.tablo-delete-zone` | outerHTML | +| Keep tablo (cancel delete) | hx-get="/tablos/{id}/delete-cancel" | `.tablo-delete-zone` | outerHTML | All state-changing requests must include the CSRF token. The `@ui.CSRFField(csrfToken)` helper must be in every `

` element. @@ -304,7 +304,7 @@ HTMX loading indicator: `class="htmx-indicator"` with `opacity-0` default, shown Inherited from `base.css` `:focus-visible` rule. Phase 3 additions: - All form `` and `