Files
TimeTracker/docs/UI_GUIDELINES.md
T
Dries Peeters ac74218fc9 refactor(ui): unify bottom-right FAB dock and refresh docs
Replace the separate plus and bolt floating controls with a single Actions menu inside #fabDock, driven by app/static/floating-actions.js. The dock stacks Actions, optional team chat, and AI Helper using shared CSS variables for spacing; the AI control is a circular FAB matching the other buttons.

Move the chat widget panel to a fixed viewport overlay so dock z-index no longer paints controls over the open panel, and lift the panel bottom when the admin version banner or mobile bottom nav applies. Fade non-actions dock children while the actions menu is open (fab-dock--menu-open).

Update README.md, docs/UI_GUIDELINES.md, and the advanced-features implementation summaries so contributors describe the floating hub instead of global-fab.js. Keep app/static/quick-actions.js aligned with the retired mount pattern for any remaining references.
2026-04-27 22:22:00 +02:00

107 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TimeTracker UI Guidelines
This document describes design principles, component usage, layout structure, and styling conventions for the TimeTracker web UI. Use it when adding or changing templates and static assets.
## Design principles
- **Clarity** — One primary action per block; labels and hierarchy make the next step obvious.
- **Consistency** — Use the same components and patterns across pages (page header, cards, empty states, buttons).
- **Minimal friction** — Reduce steps for the core flow: start timer → monitor → stop → review. First-class navigation for Timer and Time entries.
- **Professional appearance** — Clean spacing, readable typography, semantic color use, and accessible contrast.
- **Accessibility** — Keyboard navigation, focus visibility, ARIA where needed, and semantic HTML. See [Frontend Quality Gates](development/FRONTEND_QUALITY_GATES.md) for a11y checks.
## Component usage
### Page header
Use the `page_header` macro from `app/templates/components/ui.html` on every main page:
- **Parameters:** `icon_class`, `title_text`, `subtitle_text` (optional), `actions_html` (optional), `breadcrumbs` (optional).
- **Usage:** One h1-level title per page; put primary actions in `actions_html`; use `breadcrumbs` for deep pages (e.g. list → detail → edit).
### Stat cards and info cards
- **Stat cards:** Use `stat_card` from `components/ui.html` or `components/cards.html` for numeric summaries (e.g. total hours, entry count). Prefer a single row of compact stat cards on dashboards.
- **Info cards:** Use `info_card` for short text summaries when needed.
### Empty states
- **Full empty state:** Use `empty_state` or `empty_state_with_features` from `components/ui.html` for list or section-level “no data” (icon, title, message, primary action).
- **Compact empty state:** Use `empty_state_compact` for table body or inline “no results” (smaller icon and text, same structure).
- Always provide a clear primary action (e.g. “Start timer”, “Create project”, “View all”).
### Buttons
- **Primary:** One main action per block (`btn btn-primary`) — e.g. “Start Timer”, “Save”, “Log Time”.
- **Secondary:** Alternative or cancel (`btn btn-secondary`).
- **Danger:** Destructive actions (`btn btn-danger`).
- **Ghost:** Low emphasis (`btn btn-ghost`). Use for tertiary actions.
- **Sizes:** `btn-sm`, `btn-lg` when needed. Use consistent padding and touch targets (e.g. ≥ 44px for mobile).
### Forms
- **Labels:** Use `form-label`; mark required fields with `*` and optional with “(optional)” in helper text.
- **Inputs:** Use `form-input` from `app/static/src/input.css`. Add `form-input-error` for validation error state.
- **Validation:** Show inline errors below fields; use the existing toast system for submit/API errors.
### Modals and dialogs
- **Pattern:** Overlay + content panel; close on overlay click and Escape. Primary button submits; secondary/cancel closes.
- **Components:** Use `modal` and `confirm_dialog` from `components/ui.html`. Ensure focus is trapped inside when open and restored on close.
- **Start Timer modal:** Same pattern; single primary “Start” action; progressive disclosure (project/client → task → notes/tags) where possible.
### Floating hub (authenticated layout)
- **Where:** Authenticated layout in `app/templates/base.html`: `#fabDock` is a single `position: fixed` column (`flex-direction: column-reverse`) at the bottom-right, with shared CSS variables (`--fab-size`, `--fab-gap`, `--fab-edge`, `--fab-menu-gap`) for spacing. RTL mirrors to the bottom-left.
- **Controls:** (1) **Actions**`#unifiedActionsRoot` / `#unifiedActionsFab` opens `#unifiedActionsMenu` above the button; URLs come from `data-*` attributes on `#fabDock`. (2) **Team chat** (when `team_chat` is enabled) — `#persistentChatWidget` / `#chatWidgetToggle`; `#chatWidgetPanel` is a **fixed** overlay (`z-index: 85`) aligned to the viewport edge so dock items cannot stack on top of it. (3) **AI Helper**`#aiHelperRoot` / `#aiHelperFab` (circular FAB, same footprint as chat/actions) opens the existing drawer/backdrop (`ai-helper.js`).
- **Behavior:** `app/static/floating-actions.js` toggles the actions menu, handles outside click and Escape, and runs Start Timer (same `#openStartTimer` / dashboard `#start-timer` fallback as before), Log Time, New Task, New Project, New Client, and Reports. While the menu is open, `#fabDock` gets `fab-dock--menu-open` so other dock children fade and ignore pointer events.
- **Admin:** `#fabDock` can use `fab-dock--admin` to lift above the admin version banner; `body.fab-dock-admin` adjusts the chat panel bottom offset the same way.
- **Legacy scripts:** `app/static/global-fab.js` and `app/static/quick-actions.js` are no longer included from `base.html`; the web hub is implemented in markup plus `floating-actions.js`.
### Time entries table (inline edit)
- **Where:** `app/templates/timer/_time_entries_list.html` (included from the time entries overview). Editable **Notes** and **Duration** for rows the user may change (permissions match server rules: own entry or admin; duration also requires schedule edit permission and a completed entry with `end_time`).
- **Script:** `app/static/time-entries-inline-edit.js` (loaded from `time_entries_overview.html`). Saves with **`PUT` or `PATCH`** to **`/api/entry/<id>`** (session JSON, same-origin `fetch`). Success shows a short green check; errors use the toast manager and revert the cell.
### Notifications
- Use the existing **toast** system for success, error, warning, and info. Support optional `actionLink` and `actionLabel` for follow-up (e.g. “View time entries” after stopping the timer).
- Document types and behavior in this file; avoid ad-hoc `alert()` for user feedback.
## Layout structure
- **Content width:** Main content is wrapped in a max-width container (`max-w-7xl`, 1280px) and centered (`mx-auto`) so lines dont stretch on large screens. Applied in `base.html` to the main content area.
- **Grid:** Use Tailwind grid for dashboards and two-column layouts: e.g. `grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3`; main content often `lg:col-span-2`, sidebar `lg:col-span-1`.
- **Spacing:** Use the design tokens in `app/static/src/input.css` (`--spacing-xs` through `--spacing-3xl`). Prefer `gap-4` for card groups, `gap-6` for sections, `p-6` for card padding.
- **Mobile navigation:** From the `md` breakpoint up, the primary nav is the **sidebar** (`hidden md:flex` on the sidebar aside). Below `md`, the sidebar is off-canvas (hamburger opens it with a backdrop). The **primary** small-screen shortcuts are the **bottom bar** in `partials/_bottom_nav.html` (`md:hidden`, `z-50`, top border, `pb-safe` for the iOS home indicator). Main shell `#mainContent` uses `pb-16 md:pb-0` so scrollable content clears the bar. The **More** tab opens a bottom sheet (backdrop + panel, `z-[55]` / `z-[60]`); open/close lives in `app/static/mobile.js` (`BottomNavMoreDrawer`). Active tab styling uses `text-primary` and `bg-primary/10` (and dark variants). Prefer **inline SVG** (Heroicons-style stroke paths) in that partial for bar icons to avoid an extra icon font dependency on the bar.
## Styling conventions
- **Tailwind:** Prefer Tailwind utility classes. Design tokens and component classes live in `app/static/src/input.css` (e.g. `form-input`, `btn`, `text-h1``text-caption`, status and action classes).
- **Colors:** Use semantic tokens and classes: `primary`, `text-text-light` / `text-text-dark`, `text-text-muted-light` / `text-text-muted-dark`, `bg-card-light` / `bg-card-dark`, `border-border-light` / `border-border-dark`. Use status/action classes (`status-active`, `action-success`, etc.) for badges and feedback.
- **Typography:** Use `.text-h1``.text-h6` for headings, `.text-body` / `.text-body-sm` for body text, `.text-label` / `.text-caption` for labels and captions. Page title = h1; section = h2; card title = h3.
- **Dark mode:** Supported via `dark:` variants and `darkMode: 'class'` in Tailwind config. Test both themes when changing UI.
## Keyboard and focus
- **Escape:** Closes modals and dropdowns. Implement in `base-init.js` and feature scripts.
- **Enter:** Submits the primary form in modals and dialogs.
- **Tab order:** Logical and visible; ensure focus ring is visible (e.g. `focus:ring-2 focus:ring-primary`).
- **Skip link:** “Skip to content” is present in `base.html`; keep it and ensure the target is the main content anchor.
## File reference
| Area | Files |
|------|--------|
| Base layout | `app/templates/base.html` |
| Mobile bottom nav (partial) | `app/templates/partials/_bottom_nav.html` |
| Mobile shell behavior | `app/static/mobile.js` |
| Design tokens / Tailwind | `app/static/src/input.css`, `tailwind.config.js` |
| Components | `app/templates/components/ui.html`, `app/templates/components/cards.html` |
| Dashboard | `app/templates/main/dashboard.html`, `app/static/dashboard-enhancements.js` (value dashboard, week comparison chart, …) |
| Timer flow | `app/templates/timer/timer_page.html`, Start Timer modal (dashboard), `app/static/floating-timer-bar.js` |
| Floating hub (actions, chat, AI) | `app/templates/base.html`, `app/templates/components/persistent_chat_widget.html`, `app/static/floating-actions.js`, `app/static/ai-helper.js` |
| Time entries | `app/templates/timer/time_entries_overview.html`, `app/templates/timer/_time_entries_list.html`, `app/static/time-entries-inline-edit.js` |
For accessibility and quality checks, see [FRONTEND_QUALITY_GATES.md](development/FRONTEND_QUALITY_GATES.md).