From 29ae0aefe57b0d8fee993483d9f54bae758e1c08 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Sat, 16 May 2026 00:12:17 +0200 Subject: [PATCH] docs(10): UI design contract --- .planning/phases/10-events/10-UI-SPEC.md | 203 +++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 .planning/phases/10-events/10-UI-SPEC.md diff --git a/.planning/phases/10-events/10-UI-SPEC.md b/.planning/phases/10-events/10-UI-SPEC.md new file mode 100644 index 0000000..5800e76 --- /dev/null +++ b/.planning/phases/10-events/10-UI-SPEC.md @@ -0,0 +1,203 @@ +--- +phase: 10 +slug: events +status: approved +shadcn_initialized: false +preset: none +created: 2026-05-16 +reviewed_at: 2026-05-16 +--- + +# Phase 10 - UI Design Contract + +> Visual and interaction contract for the first functional tablo Events tab. + +## Design System + +| Property | Value | +|----------|-------| +| Tool | none | +| Preset | not applicable | +| Component library | local templ components in `backend/internal/web/ui` | +| Icon library | none for Phase 10; use text labels for clarity | +| Font | existing system sans stack from the browser/Tailwind reset | + +Phase 10 must stay inside the current Go + HTMX + templ surface. Do not introduce shadcn, React calendar widgets, third-party date pickers, or a new CSS framework. + +## Screen Contract + +The Events tab is a compact work surface inside `TabloDetailPage`, not a marketing page or decorative calendar. + +Primary screen: + +- Add an `Events` tab to the existing Overview / Tasks / Files tab row. +- Render `EventsTabFragment` inside `#tab-content`. +- Use `#events-tab` as the outer refresh target for create, update, and delete mutations. +- Use `#event-form-slot` above the calendar grid for inline create, edit, validation, and delete-confirm fragments. + +Visual focal point: + +- The month header and calendar grid are the primary anchor. +- The `New event` button is the primary action, placed in the same row as the month title/navigation. +- Day cells are secondary scan targets. Event title pills should be visually quiet and should not compete with the primary action. + +## Spacing Scale + +Declared values must be multiples of 4: + +| Token | Value | Usage | +|-------|-------|-------| +| xs | 4px | Weekday labels, event title gaps, compact metadata | +| sm | 8px | Day-cell internal gaps, form field gaps, inline button gaps | +| md | 16px | Form padding, calendar row gaps, toolbar gaps | +| lg | 24px | Tab section separation, form-to-calendar separation | +| xl | 32px | Major tab content separation if needed | +| 2xl | 48px | Not expected in this phase | +| 3xl | 64px | Not expected in this phase | + +Exceptions: + +- Interactive controls must keep the existing minimum 44px touch target when using `ui.Button` variants. +- Calendar day cells may use CSS grid sizing rather than fixed pixel heights, but each cell must have a stable minimum height of at least 96px on desktop and at least 80px on narrow screens. + +## Typography + +Use exactly these font roles for new Events UI: + +| Role | Size | Weight | Line Height | +|------|------|--------|-------------| +| Body | 16px | 400 | 1.5 | +| Label | 14px | 600 | 1.4 | +| Heading | 20px | 600 | 1.3 | +| Display | 28px | 600 | 1.2 | + +Rules: + +- Do not add new font sizes for event cells. Use 14px labels/body-small treatment for weekday labels, dates, and event titles. +- Do not add a third font weight. Existing regular and semibold are enough. +- Letter spacing stays at 0. + +## Color + +| Role | Value | Usage | +|------|-------|-------| +| Dominant (60%) | `#ffffff` | Page background, calendar cells, forms | +| Secondary (30%) | `#f8fafc`, `#f1f5f9`, `#e2e8f0` | Header strip, muted surfaces, borders, inactive day cells | +| Accent (10%) | `#2563eb` | `New event` primary CTA, focus rings, active month navigation when needed | +| Destructive | `#b91c1c` | Delete event action and confirmation only | + +Accent reserved for: + +- `New event` primary CTA. +- Focus-visible outlines through existing button/input behavior. +- Text links where the app already uses `text-blue-600`, such as event deep links if needed. + +Do not use blue for every clickable title in the calendar. Event titles should use slate text on white or slate-50 surfaces so the calendar remains scannable. + +## Calendar Layout Contract + +Calendar toolbar: + +- Left: current month label, formatted like `May 2026`. +- Right: `Previous month`, `Next month`, and `New event` controls. +- On mobile, toolbar may wrap to two rows, but controls must not overlap the month label. + +Calendar grid: + +- Seven columns on desktop and tablet. +- On narrow screens, keep seven columns if text still fits; otherwise day cells may reduce vertical detail but must preserve the month grid. +- Weekday row uses short labels: `Mon`, `Tue`, `Wed`, `Thu`, `Fri`, `Sat`, `Sun`. +- Out-of-month cells use muted slate text/background and should not contain create affordances unless the implementation chooses to show adjacent-month dates. + +Day cell contract: + +- Top-left date number, 14px semibold. +- Clicking an empty area of an in-month day cell may open the create form with `date=YYYY-MM-DD` prefilled. +- Existing event titles render as small rows/pills under the date. +- Show at most three event titles per cell, followed by `+N more` when needed. +- Event titles must truncate or wrap safely without expanding adjacent columns. + +## Form Contract + +Create form: + +- Opened by `New event` or day-cell create action. +- Rendered in `#event-form-slot`. +- Fields: `Title`, `Date`, `Start time`, `End time (optional)`, `Location (optional)`, `Description (optional)`. +- Submit CTA: `Create event`. +- Secondary action: `Close form`. + +Edit form: + +- Opened by clicking an event title. +- Rendered in `#event-form-slot`. +- Same fields as create. +- Submit CTA: `Save event changes`. +- Secondary action: `Close form`. +- Destructive entry point: `Delete event`. + +Delete confirmation: + +- Inline confirmation in `#event-form-slot`. +- Heading: `Delete event?` +- Body: `This removes the event from this tablo. This cannot be undone.` +- Confirm CTA: `Delete event`. +- Secondary action: `Keep event`. + +Validation: + +- Field errors appear below their fields using the existing `FieldError` pattern. +- General errors appear above the form using the existing `GeneralError` pattern. +- End-time validation copy: `End time must be after the start time.` +- Validation responses keep submitted values visible. + +## Copywriting Contract + +| Element | Copy | +|---------|------| +| Tab label | `Events` | +| Primary CTA | `New event` | +| Create submit | `Create event` | +| Edit submit | `Save event changes` | +| Form dismiss | `Close form` | +| Empty day | no copy | +| Empty month body | no special empty state; the visible calendar and `New event` action are the empty state | +| Error state | `End time must be after the start time.` | +| Destructive confirmation | `Delete event?` / `This removes the event from this tablo. This cannot be undone.` | + +Do not introduce instructional copy explaining how calendars work. The UI should expose the action directly. + +## Interaction Contract + +- Switching to the Events tab uses the same HTMX tab pattern as Tasks and Files. +- Previous/next month links must update `#tab-content` and push `/tablos/{id}/events?month=YYYY-MM`. +- Create, update, and delete responses refresh `#events-tab` or `#tab-content` consistently so the calendar never shows stale event titles. +- Day-cell prefill comes from query params only when rendering a new form. Submitted form values always win over query defaults. +- Non-HTMX requests must still return a full page with the Events tab active. + +## Accessibility Contract + +- The calendar must use semantic labels that make the month and day context clear. +- Event title controls must expose `aria-label="Edit event: {title}"`. +- Day create controls must expose `aria-label="Create event on YYYY-MM-DD"`. +- Month navigation controls must include the target month in their accessible label. +- Focus-visible states must remain visible on buttons, links, and form inputs. + +## Registry Safety + +| Registry | Blocks Used | Safety Gate | +|----------|-------------|-------------| +| none | none | not applicable | + +No third-party UI registry, calendar component, or date picker is approved for Phase 10. + +## Checker Sign-Off + +- [x] Dimension 1 Copywriting: PASS +- [x] Dimension 2 Visuals: PASS +- [x] Dimension 3 Color: PASS +- [x] Dimension 4 Typography: PASS +- [x] Dimension 5 Spacing: PASS +- [x] Dimension 6 Registry Safety: PASS + +**Approval:** approved 2026-05-16