# HealthLog UI Guidelines > Interaction patterns for the HealthLog web app. Card anatomy, spacing, > text colour, colour tokens, typography and the choice of primitive are > owned by [`contributing/ui-standards.md`](./contributing/ui-standards.md); > this page covers what those rules leave open. Where the two disagree, the > standards win. If a pattern below doesn't fit your case, propose an > addition in the same PR. --- ## 1. Foundations Theme, spacing, typography, radius and colour tokens are defined in the standards (§1 to §5 there). Two things to add: - Dark is the default theme, and the light theme remaps the same semantic tokens. Check every component in both before shipping it. - Elevation stays light: `shadow-xs` or `shadow-sm` in chrome, never the heavy `shadow-lg` and up. --- ## 2. Components This section is **prescriptive, not exhaustive**. Each entry names the primitive for a case and the case where another one wins. ### 2.1 Buttons Every button comes from `@/components/ui/button`. Pick by purpose: | Purpose | Variant | Size | | ----------------------------------------------------- | ------------- | ----------------- | | Primary action on a page or dialog | `default` | `default` | | Cancel, dismiss, secondary action next to primary | `outline` | `default` | | Tertiary in-row action (edit, copy, snooze) | `ghost` | `sm` | | Destructive (delete, revoke, disconnect) | `destructive` | `default` or `sm` | | Icon-only action (toolbar, chart toggles, table rows) | `ghost` | `icon-sm` | | Inline link to external help docs | `link` | `sm` | | Toolbar / table row action when space is tight | `outline` | `xs` | Where buttons sit in a card (one action row, last in the card, primary on the right) is standards §12. Two additions: - A Test button (Telegram test, AI ping and the like) sits in the same row as the Save or Apply control it belongs to. - An irreversible action (delete account, revoke an API token, wipe data) asks in its own confirm dialog, with a type-to-confirm field where the loss is large. **Disabled state.** A disabled button always comes with helper text that says why. A tooltip is not enough: it never opens on a phone. ### 2.2 Inputs and forms Forms keep a controlled draft in component state and validate it with the Zod schemas from `src/lib/validations/`; the server's schema is the authority. Every input has a visible `