Swedish translation contributed by @olsson82 (PR #19), integrated with
minor corrections (dayShortSunday: Sun → Sön, amountLabel aligned with
v0.11.2, new v0.11.2 currency keys added).
Italian was already supported server-side but is now explicitly listed
in the locale picker alongside German, English, and Swedish.
Add household-wide currency preference for the budget section.
Users can select from 13 currencies (EUR, USD, GBP, SEK, NOK, DKK,
CHF, PLN, CZK, HUF, JPY, AUD, CAD) in Settings → Budget.
- preferences API (GET/PUT) now includes currency field
- budget page loads currency from preferences on render
- formatAmount() uses locale-aware Intl.NumberFormat with chosen currency
- settings page gains a Budget section with a currency select
- all three locales (de, en, it) updated with new i18n keys
min-height: 100dvh lets the shell grow unbounded, so app-content never
overflows and touch scroll has nothing to scroll. height: 100dvh constrains
the shell to exactly the viewport, making overflow-y: auto on app-content work.
- inputmode=decimal on budget amount input for correct decimal keyboard
- inputmode=numeric on rrule interval input for numeric keyboard
- autocomplete attributes on contacts form (name, tel, email, street-address)
- Replace hardcoded px values with design tokens (--space-0h, --space-px,
--space-1, --target-sm/md/lg) across layout, calendar, dashboard CSS
- Fix rgba(255,255,255,0.35) spinner border to use var(--color-glass-hover)
- Fix modal close icon from off-grid 18px to 16px
- Fix touch scrolling on mobile: add min-height: 0 and
-webkit-overflow-scrolling: touch to .app-content
- Add --color-text-on-accent token to tokens.css
- Migrate all hardcoded color:#fff/#ffffff to var(--color-text-on-accent) across all module stylesheets
- Fix toggle thumb background (#fff -> var(--color-surface)) for dark mode
- Migrate hardcoded transition durations to token vars (--transition-fast/base/slow)
- Replace off-grid spacing (3px, 5px) with space tokens (--space-0h, --space-1)
- Replace below-minimum font-size 9px with var(--text-xs) in calendar, dashboard, notes
- Replace hardcoded 2.5rem with var(--text-4xl) in weather widget
- Replace hardcoded box-shadow with var(--shadow-sm) in toggle thumb
- Replace 0.85em and #666 with type/color tokens in print styles
Users can now toggle which meal types (breakfast, lunch, dinner, snack)
are displayed in the meal planner via a new Settings section. Preference
is stored household-wide in sync_config and applied as a filter on the
meals page. Includes preferences API, i18n (DE/EN/IT), and Settings UI.
View mode (list/kanban) is now saved to localStorage and restored on
page load. URL parameter ?view=kanban takes precedence, enabling tablet
kiosk setups to default to Kanban view. Toggle buttons reflect the
active view correctly on initial render.
Closes#17
New tasks default to "none" priority instead of "medium". Tasks with no
priority hide the badge in list and dashboard views, reducing visual noise
for routine items. Includes DB migration v4 and i18n keys (de, en, it).
Closes#15
Three root causes fixed:
1. Double safe-area padding: pwa.css set padding-top/bottom on body
globally, but page containers already account for safe-area-inset
in their height calculations. Removed body vertical padding (kept
only in standalone media query for padding-top).
2. Wrong nav token: all page containers used --nav-height-mobile (56px)
instead of --nav-bottom-height (68px = 56px scroll + 12px dots),
causing 12px of content to render behind the bottom nav.
3. Scroll bleed: fixed-height page containers lacked overflow:hidden,
allowing scroll events to propagate to the body. Added
overscroll-behavior-y:contain on app-content globally.
Fixes#16
Native browser prompt() is unreliable on mobile browsers and PWAs,
often requiring multiple clicks to close. Replace all prompt() calls
with custom promptModal() and selectModal() functions that use the
existing modal system with proper focus management and animations.
Affected pages: shopping (create/rename list), tasks (add subtask),
meals (choose shopping list).
Fixes#12
Show shopping lists with open items directly on the dashboard.
Each list displays a progress bar, the first few unchecked items,
and a "+N more" overflow indicator. Widget only appears when there
are lists with open items.
Backend: new shoppingLists query in /api/v1/dashboard (up to 3 lists,
6 open items each). Frontend: renderShoppingLists() widget following
existing widget pattern. CSS: compact list/progress/item styles.
i18n: shoppingMore key added to de/en/it.
Requested in discussion #9
On mobile, closeModal() relies on the CSS animationend event to call
_doClose(). When the animation does not fire (prefers-reduced-motion,
tab switch, browser quirk), the modal stays stuck and the user cannot
dismiss it. A 300ms fallback timer now guarantees cleanup runs.
Reported in discussion #9
Category group headers in tasks and bar chart labels / transaction meta
in budget were showing raw German database keys instead of going through
CATEGORY_LABELS() i18n mapping.
Closes#11
Previous fix removed the old CSS when new CSS loaded, but that happened
BEFORE the out-animation completed - causing a flash of unstyled content.
Now the old stylesheet stays until replaceChildren removes the old DOM.
Audit found ~35 violations against the token system. Fixed:
- Hardcoded shadows in layout.css replaced with --shadow-sm/md
- 8 rgba colors extracted to new glass tokens (--color-glass-*)
- border-radius: 50% replaced with var(--radius-full)
- ~25 off-grid spacing values (5px, 6px, 7px, 14px, 15px, 22px,
26px, 34px) aligned to 4px grid using space tokens
Increase font-size to 16px on mobile for shopping quick-add inputs,
notes search, and contacts search. Desktop breakpoint restores compact
sizes. Move 9 page-specific stylesheets from index.html to on-demand
loading in router.js, reducing initial CSS payload.
- Rename #page-content to #main-content so skip-to-content link
targets the semantic <main> landmark
- Add sr-only priority labels to dashboard task items for screen
readers (WCAG 1.4.1 color-not-only)
- Replace hardcoded hex in greeting gradient with accent tokens
so dark mode themes the banner correctly
- Replace hardcoded gap: 2px with --space-0h token
- Bump version to 0.7.2
- Extract shared esc() utility (public/utils/html.js) replacing 8
duplicate escHtml() functions across all page modules
- Apply HTML escaping to all user-controlled data in innerHTML
templates: titles, names, locations, descriptions, colors, notes
content, weather data, autocomplete suggestions
- Remove user-scalable=no and maximum-scale=1 from viewport meta
tag, restoring pinch-to-zoom for WCAG 1.4.4 compliance
- Bump version to 0.7.1
Fix stored XSS in tasks (titles/subtasks) and settings (member list)
by applying escHtml(). Harden trust proxy to loopback default, add
OAuth state parameter for Google Calendar CSRF protection, sanitize
CSV export against formula injection, invalidate sessions on user
deletion, restrict usernames to alphanumeric chars, and require admin
role for calendar sync triggers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all — with - in all source files (JS, CSS, HTML, JSON,
Markdown) for consistency and readability.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add complete Italian translation (497 keys) based on PR #7 by
@albanobattistella. Fixed filename from "it. json" to "it.json" and
registered Italian in SUPPORTED_LOCALES and the locale picker component.
Co-Authored-By: albanobattistella <34811668+albanobattistella@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cleanup() set dragging = null, then onUp accessed dragging.slot,
.mealId, .sourceDate, .sourceType on the now-null reference.
Fix: destructure all needed values before calling cleanup().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
External image requests to openweathermap.org fail silently in Chrome
Android PWA standalone mode. Icons are now proxied via
GET /api/v1/weather/icon/:code, making them same-origin — cacheable by
the service worker and free of CORS/CSP issues.
Tightened CSP: removed openweathermap.org from imgSrc (no longer needed).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add id field and display_override to manifest.json for reliable
Chrome Android PWA recognition
- Serve manifest.json with application/manifest+json MIME type
- Add /i18n.js and locale files to SW app shell cache (were missing)
- Bump SW cache version to v21
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Android was showing only a blue circle because maskable icons had no
visible content after the adaptive icon mask was applied. All icons now
use the actual Oikos house logo from docs/logo.svg. Maskable variants
use full-bleed background with logo within the 80% safe zone.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The locale JSON files use nested structure (e.g. {"nav":{"tasks":"…"}}),
but t() did a flat lookup, always falling back to the raw key string.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all hardcoded German strings in router.js (navItems labels,
aria-labels, skip-link, error/toast messages) with t() calls. Add a
locale-changed event listener that re-renders sidebar and bottom-nav
items on language switch.
Replace hardcoded German strings in modal.js and oikos-install-prompt.js
with t() calls; wire locale-changed event listener for live re-render on
locale switch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracts all German UI strings from public/pages/, public/components/,
and public/router.js into 482 i18n keys organized by module prefix.
English translations added for all keys.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>