Customization
How users + developers personalize Koder UI without leaving the design system. Material parity (`/foundations/customization`). Covers the axes available (style × scheme × density × motion × i18n × layout density × accessibility prefs), where each persists, who the audience is, and what's NOT customizable per surface.
Spec — Customization
Facet *isual*do Koder Design. Material parity: https://m3.material.io/foundations/customization.
Customization axes (canonical 8)
Every Koder app exposes the same 8 axes in Settings (where applicable), with the same default values and the same persistence pattern. Spec per axis lives in linked references; this doc catalogs them.
| Axis | Default | Spec |
|---|---|---|
| *I style*(forma/densidade) | material3 |
themes/ui-style.kmd |
| *olor scheme*(paleta) | default |
themes/color-schemes.kmd |
| *heme mode*(claro/escuro) | system |
themes/light-dark.kmd |
| *anguage*(i18n) | device locale | i18n/contract.kmd |
| *oice / wake-word* | OFF (except barge-in) | voice/wake-word.kmd |
| *rror reporting* | OFF (opt-in) | errors/reporting.kmd |
| *uto-update* | ON | koder-app/behaviors.kmd §4 |
| *ensity* | comfortable | themes/ui-style.kmd |
R1 — One Settings page, consistent shape
Every Koder app's Settings page has the SAME section order:
- *ppearance*(UI style, color scheme, theme mode, density)
- *anguage*(locale picker, ICU regional prefs)
- *otifications*(per-app)
- *oice*(wake
word, bargein, hot phrases) - *rivacy*(error reporting, telemetry opt-out, data export)
- *ccount*(sign
in, signout, tenant switch) - *bout*(version, licenses, what's new)
Order is rigid; sections can be omitted (no Voice → skip), never reordered.
R2 — Persistence
| Axis | Where it persists |
|---|---|
| Appearance + Language | Per-surface (localStorage / Flutter SharedPreferences) — sticky per device |
| Voice | Per-app (same storage) |
| Privacy | Per |
| Account | Server-side (Koder ID) |
R3 — System hints
When the user has not made a choice, surfaces follow system hints:
- Theme mode:
ThemeMode.system/prefers-color-scheme - Language:
Platform.localeName/navigator.language - High contrast / reduced motion: OS accessibility prefs (Android
View.SystemUiHints, iOSUIAccessibility, WindowsSystemSettings, GNOMEorg.gnome.desktop.a11y, etc.)
R4 — Pertenant vs peruser vs per-surface
| Scope | Examples |
|---|---|
| Per |
Custom brand color, organization name, allowed login methods |
| Per-user (synced) | Display name, notification prefs, language |
| Per |
UI style, density, theme mode, voice settings |
Pertenant customization always takes precedence over peruser; peruser always takes precedence over persurface defaults.
R5 — What's NOT customizable
The following are *eliberately fixed*to preserve product identity:
- Product logo / icon
- Element family taxonomy (
foundations/elements.kmd) - Canonical layouts (
canonical-layouts.kmd) - Error message format (
errors/user-facing-messages.kmd) - Touch target minimums (
safe-area.kmd) - Keyboard shortcuts that conflict with OS conventions
- Brand-color accent (varies by tenant, but the role "accent" stays)
User requests for these go through product feedback, not Settings.
R6 — Customization pickers in UI
Each axis has a canonical widget (in koder_kit):
| Axis | Widget | Spec ref |
|---|---|---|
| UI style | KoderUIStylePicker |
themes/ui-style.kmd |
| Color scheme | KoderColorSchemePicker (planned) |
themes/color-schemes.kmd |
| Theme mode | KoderThemeToggle |
themes/light-dark.kmd |
| Language | KoderL10nSwitcher |
i18n/contract.kmd §R3 |
| Voice | KodeVoiceSettingsTile |
voice/wake-word.kmd |
| Error reporting | KoderReportButton toggle |
errors/reporting.kmd |
R7 — Reset to defaults
Every Settings page exposes a "Reset to defaults" button in the About section. Behavior:
- Clears all per-surface preferences (returns to system hints)
- Per-user prefs preserved (the user owns those)
- Per-tenant prefs unaffected (admin owns those)
- Confirmation dialog: "Reset appearance and preferences to defaults?"
Cross-link
- All axis specs above
koder-app/behaviors.kmd— broader app behaviorspolicies/reuse-first.kmd— pickers come fromkoder_kit, not per-app