docs(10): UI design contract
This commit is contained in:
parent
0148d71d06
commit
29ae0aefe5
1 changed files with 203 additions and 0 deletions
203
.planning/phases/10-events/10-UI-SPEC.md
Normal file
203
.planning/phases/10-events/10-UI-SPEC.md
Normal file
|
|
@ -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
|
||||
Loading…
Reference in a new issue