Commit Graph
5 Commits
Author SHA1 Message Date
Marc-André Bombeck 6704579c25 fix(forms): wire the ResponsiveSheet footer slot across every page-level form mount
Until now every <ResponsiveSheet> consumer (except export-section) inlined the
form footer inside the body slot, so the primitive's sticky-pinned bottom rail
on the Sheet branch only painted empty. The Save / Cancel row therefore
scrolled with the body and slid out from under the soft keyboard on mobile.

This rewires the action-row through the footer prop on all seven page-level
mounts (dashboard quick-entry measurement + mood, /measurements, /mood,
/medications, side-effects sheet, inventory add sheet, intake-history edit +
create sheets, medication create/edit sheet). Each form receives an optional
footerSlot prop; when set, the kebab + Cancel + Save row is portalled into
the ResponsiveSheet footer slot so the bottom-sheet branch can sticky-pin it.
The Save button keeps its <form> association via the HTML form attribute so
submit-on-Enter and native validation continue to work end-to-end.
2026-05-15 21:05:50 +02:00
Marc-André Bombeck bd7cb938c9 feat(ui): lift the password toggle into a shared primitive
Move `<PasswordInput>` from `src/components/settings/password-input.tsx`
to `src/components/ui/password-input.tsx` so the auth surfaces (login
and register) and every settings card that masks a secret consume one
primitive. The two surfaces previously diverged on toggle markup and
aria-label wiring; the new home in `ui/` keeps them in lock-step.

While the primitive moves, lift the icon-only show/hide toggle to a
44 px hit area per WCAG 2.5.5 — `inline-flex h-11 w-11` wrapper with
the eye icon centred inside. The input itself gets `pr-12` so user
input never collides with the toggle glyph.

Consumer imports updated in:
- `src/components/settings/account-section.tsx`
- `src/components/settings/ai-section.tsx`
- `src/components/settings/integrations-section.tsx`
- `src/components/settings/ntfy-card.tsx`
- `src/components/settings/telegram-card.tsx`
- `src/components/admin/_shared.tsx`

The `<DialogContent>` close-X tap-target lift to `min-h-9 min-w-9`
landed in the parallel `ResponsiveSheet` commit because both buckets
share the same `dialog.tsx` file. See Decision I — 36 px is the
intentional exception for fixed icon-only close affordances.
2026-05-15 18:26:06 +02:00
Marc-André Bombeck 32a023dfff chore(ui): apply M7 + L1 + L3 + L4 polish across medication form, motion-reduce, details aria, therapy timeline
W10 design-review carry-over items. M7 lifts the medication-form
day-of-week buttons, the more-horizontal trigger, and the schedule
label-input gaps to the 44 px / space-y-2 standard used by every
other settings surface. L1 pairs every animate-spin/pulse/bounce
with motion-reduce:animate-none across the component tree so users
with prefers-reduced-motion get a still surface. L3 adds the
aria-controls + panel-id pairing to the inventory + coach-evidence
<details> blocks for parity with the Health Score provenance
accordion. L4 inserts a sr-only h4 per therapy-timeline entry so
screen-reader users can jump between medication blocks.
2026-05-15 17:13:42 +02:00
Marc-André BombeckandClaude Opus 4.7 1d65f3b925 feat(lists): empty states for measurements, mood, medications, achievements (impl)
Follow-up to 9a74f8e — that commit's pathspec didn't pick up the
implementation files, only the new test. This commit lands the actual
EmptyState wiring described in the previous message:

- src/components/measurements/measurement-list.tsx — Activity icon,
  filter-aware empty state, optional onAddFirst CTA prop.
- src/components/mood/mood-list.tsx — Smile icon, mirroring filter
  semantics + optional onAddFirst.
- src/app/measurements/page.tsx + src/app/mood/page.tsx — pass
  onAddFirst so the empty-state CTA opens the same dialog as the
  header button.
- src/app/medications/page.tsx — refactor inline icon+text+button
  block to the EmptyState primitive (Pill icon).
- src/app/achievements/page.tsx — Trophy icon for the no-achievements
  state, reusing the existing noneUnlockedYet string.

Together with 9a74f8e the four feature lists now share a consistent
empty-state surface with the rest of the app.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 21:51:48 +02:00
Marc-André Bombeck 0c0c345e82 i18n: migrate from German-first to English-first default locale
Switch defaultLocale from "de" to "en" and make English the code-level
language throughout. All ~145 hardcoded German strings translated:

- API error messages (52 routes) now return English
- Zod validation messages in English
- Classification/analytics functions return English categories
- Notification type labels in English
- Component strings use i18n t() calls (heatmap, mood chart,
  medication form, intake history, password strength, insights card)
- ~50 new i18n keys in both de.json and en.json

Route migration:
- /stimmung → /mood, /zielwerte → /targets (new pages)
- 301 redirects in proxy.ts for legacy URLs
- Sidebar + bottom nav updated

Bump version to 1.0.1.
2026-03-12 21:31:48 +01:00