Mobile UI pass: sheet swipe, ice-scene layering, contrast, touch targets

Phones (<=639px) only for layout/gestures; the theme-level fixes apply
everywhere, as they are token/design changes.

Settings sheet
- Swipe-to-dismiss reusing the InstallSheet gesture: the sheet follows the
  finger, closes past ~90px or on a fast flick, snaps back otherwise. Drag
  starts only from the handle/header and only while the body is scrolled to
  the top. Backdrop tap still closes.
- Fixed header + scrollable body: pb-safe + spacer, so nothing is clipped;
  a scroll cue (chevron) fades in while more content is below and out at
  the end.
- Show/Save stack under the field at 44px on phones; close, Test connection
  and Remove key are 44px too. Remove key is now a rose destructive action
  with a confirmation that the full-screen key setup comes back.
- API key note split into a short privacy line plus a collapsible
  'Using the local daemon?' tip (OLLAMA_AUTH=local / .env.local / signin).
- Fixed the missing space in the English tip ('ollama signin instead.').
- Health: kept the auto-check and banner; added a loading row and a
  'Checked just now' / 'Checked at HH:MM' freshness label (also for errors).

Ice scene / readability
- Verified the orbs were never above content (fixed z-index:-1 layer,
  pointer-events:none); they were just shining through the glass. Phones get
  lower blob/orb opacity and orbs tucked to the edges; the bottom-right orb
  is moved out from under the tab bar and the tab bar paints a more opaque
  surface so its labels hold contrast.

Contrast / themes
- Dark --text-subtle raised to #9db1d0 (8.6:1 page, 7.2:1 glass); helper
  text now uses the tokens.
- Disabled buttons are a visible muted chip (.btn-disabled) instead of a
  40%-opacity ghost.
- One ice primary gradient in both themes; danger/success now actually show
  their colour (bg-none strips the primary background-image that used to
  paint over !bg-rose-600).
- Light mode: cool card rims instead of white-on-white, stronger shadow.

Redundancy / touch
- Removed only the header gear; the hamburger drawer (folders, Settings,
  theme) and the tab-bar Settings stay.
- Theme toggle is a bordered chip with an action aria-label (drawer row too).
- Empty library hides the folder pills, demotes Import to a quiet link and
  keeps a single primary CTA. 44px targets for nav rows, segmented control
  and folder pills on phones.
- Fixed a pre-existing 16px horizontal overflow (header -mx-4 vs a
  padding-less parent) and let info values wrap instead of truncating.

Verified: mobile suite 47/47 (EN+CS, 360/390px), pixel-sampled contrast
audit 0 runs below WCAG AA (8 runs, both themes/locales; axe marks the glass
'incomplete'), i18n 27/27, desktop regression 72/72, lint + build clean.
Service worker cache bumped to freezmo-v5.
This commit is contained in:
Martin Dvořák 2026-10-08 17:37:51 +00:00
commit 9fb728d735
12 changed files with 519 additions and 235 deletions

View file

@ -119,10 +119,15 @@ const en: Record<string, string> = {
"settings.hide": "Hide",
"settings.show": "Show",
"settings.keyNote":
"Stored only in this browser's local storage and sent with each request so the server can talk to Ollama for you. It is never written to the server, never logged and never put in a cookie. Prefer the local daemon? Set",
"Stored only in this browser's local storage and sent with each request so the server can talk to Ollama for you. It is never written to the server, never logged and never put in a cookie.",
"settings.localTipTitle": "Using the local daemon?",
"settings.localTipSet": "Set",
"settings.keyNoteAfter": "in",
"settings.keyNoteEnd": "and use",
"settings.keyNoteEnd2": "instead.",
"settings.keyNoteEnd2": " instead.",
"settings.removeKeyConfirm":
"Remove the key? The full-screen key setup comes back until you add one.",
"settings.removeKeyYes": "Yes, remove it",
"settings.testConnection": "Test connection",
"settings.removeKey": "Remove key from this browser",
"settings.savedTesting": "Saved — testing…",
@ -156,6 +161,8 @@ const en: Record<string, string> = {
"health.notFound": "not found",
"health.unknown": "unknown",
"health.configuredAs": "configured as {model}",
"health.checkedNow": "Checked just now",
"health.checkedAt": "Checked at {time}",
"health.createKey.before": "Create a key at",
"health.createKey.after": "and paste it above. Tip: with the local daemon you can run",
"health.createKey.end": "instead and set",
@ -633,10 +640,15 @@ const cs: Record<string, string> = {
"settings.hide": "Skrýt",
"settings.show": "Zobrazit",
"settings.keyNote":
"Ukládá se jen do místního úložiště tohoto prohlížeče a posílá se s každým požadavkem, aby server mohl komunikovat s Ollamou. Nikdy se neukládá na server, nezapisuje do logů ani do cookies. Radši místní daemon? Nastav",
"Ukládá se jen do místního úložiště tohoto prohlížeče a posílá se s každým požadavkem, aby server mohl komunikovat s Ollamou. Nikdy se neukládá na server, nezapisuje do logů ani do cookies.",
"settings.localTipTitle": "Používáš místní daemon?",
"settings.localTipSet": "Nastav",
"settings.keyNoteAfter": "v",
"settings.keyNoteEnd": "a použij",
"settings.keyNoteEnd2": ".",
"settings.removeKeyConfirm":
"Odstranit klíč? Dokud klíč znovu nepřidáš, vrátí se celoobrazovková obrazovka pro nastavení klíče.",
"settings.removeKeyYes": "Ano, odstranit",
"settings.testConnection": "Otestovat připojení",
"settings.removeKey": "Odstranit klíč z prohlížeče",
"settings.savedTesting": "Uloženo — testuji…",
@ -670,6 +682,8 @@ const cs: Record<string, string> = {
"health.notFound": "nenalezen",
"health.unknown": "neznámý",
"health.configuredAs": "nakonfigurováno jako {model}",
"health.checkedNow": "Zkontrolováno právě teď",
"health.checkedAt": "Zkontrolováno v {time}",
"health.createKey.before": "Vytvoř klíč na",
"health.createKey.after": "a vlož ho výše. Tip: s místním daemonem můžeš spustit",
"health.createKey.end": "a nastavit",