Settings Patterns
Convenção mestre de tela Settings em apps Koder: hierarquia canônica de grupos, ordem fixa, registro de cross-cutting settings (qual grupo, qual posição, qual controle, default state, persistence key), estrutura do tile (label/control/helper/icon) e widget SDK obrigatório (`KoderSettingsTile` em Flutter, `<koder-settings-tile>` em Web). Toda spec de feature cross-cutting que precisa de toggle em Settings registra-se aqui em vez de inventar tile próprio.
Spec — Settings Patterns
Convenção mestre da tela Settings em todo app Koder. Resolve a proliferação de tiles ad
hoc (cada feature crosscutting inventando seu próprio tile com labelposiçãodefault state diferentes).
Goals
- *onsistência visual*entre apps Koder e entre features dentro do
mesmo app — todo tile parece tile.
- *iscoverability*— usuário sabe onde encontrar cada setting porque
o grupo é canônico (Privacy sempre tem a mesma posição em qualquer app).
- *euso de SDK*—
KoderSettingsTile/<koder-settings-tile>encapsulam controlepersistencei18n sem boilerplate por app.
- *uditabilidade*—
koder.toml [settings]declara featuresesperadas; audit script verifica que app cumpre.
Hierarquia canônica de grupos
A tela Settings tem grupos *ixos em ordem* *stáveis nomenclatura* Apps com features que não se encaixam usam *Advanced`*ou criam sub-grupos dentro de grupo existente.
| # | Grupo (en-US) | Grupo (pt-BR) | Conteúdo típico |
|---|---|---|---|
| 1 | *eneral* | Geral | Idioma, fuso, locale, perfil ativo |
| 2 | *ccount* | Conta | Sign |
| 3 | *ppearance* | Aparência | Tema (light/dark), estilo de UI, cor accent, densidade |
| 4 | *otifications* | Notificações | Push, badge, som, "do not disturb" |
| 5 | *rivacy* | Privacidade | Telemetria, tracking, dados compartilhados |
| 6 | *pdates* | Atualizações | Auto-update toggle, canal (stable/beta), botão check now |
| 7 | *oice* | Voz | Wake word, talk mode, mic permissions |
| 8 | *torage* | Armazenamento | Cache, downloads, dados offline, limite de uso |
| 9 | *eporting* | Relatórios | Auto |
| 10 | *etwork* | Rede | Proxy, VPN, sync settings |
| 11 | *dvanced* | Avançado | Dev options, experimental flags, debug |
| 12 | *bout* | Sobre | Version, license, credits, links |
*egras de ordem:*
- Apps *mitem*grupos que não aplicam (ex.: app sem mic não tem Voice)
- Apps *ão reordenam*os grupos restantes
- Apps *ão criam grupos novos*sem extender esta spec primeiro
Estrutura do tile
Todo tile em Settings tem * campos*definidos:
| Campo | Required | Tipo | Exemplo | |||||
|---|---|---|---|---|---|---|---|---|
key |
sim | string snake_case | theme_mode |
|||||
label |
sim | i18n string | "Theme" / "Tema" | |||||
control |
sim | enum | `toggle | dropdown | slider | button | text | radio_group` |
default_state |
sim | depende | false / "system" / 0.5 |
|||||
persistence_key |
sim | string | koder.theme |
|||||
helper_text |
não | i18n string | "Choose how the app looks" | |||||
leading_icon |
não | icon ref | Icons.palette |
Widget de SDK obrigatório
*lutter (engines/sdk/koder_kit v0.6.0+):*
KoderSettingsPage(
groups: [
KoderSettingsGroup(
id: 'appearance',
tiles: [
KoderSettingsTile(
key: 'theme_mode',
label: l10n.settings.theme,
control: KoderSettingsControl.toggle(...),
defaultState: false,
persistenceKey: 'koder.theme',
),
// ...
],
),
],
)*eb (engines/sdk/koder_web_kit v0.3.0+):*
<koder-settings-page>
<koder-settings-group id="appearance">
<koder-settings-tile
key="theme_mode"
label="..."
control="toggle"
default-state="false"
persistence-key="koder.theme">
</koder-settings-tile>
</koder-settings-group>
</koder-settings-page>*pp proibido de:*
- Implementar tile via
ListTilepuro (Flutter) ou<div>ad-hoc (Web)quando o conteúdo é setting cross-cutting
- Salvar preferência fora do
persistence_keydeclarado pela spec dafeature (rompe sync cross-device futuro)
- Esconder toggle de feature obrigatória (ex.: omitir auto-update toggle)
Manifesto opcional em koder.toml
App pode declarar settings esperados em koder.toml:
[settings]
groups = ["general", "appearance", "privacy", "updates", "about"]
[[settings.tiles]]
group = "appearance"
key = "theme_mode"
spec = "themes/light-dark" # cross-ref pra spec que define o tile
[[settings.tiles]]
group = "appearance"
key = "ui_style"
spec = "themes/ui-style"
[[settings.tiles]]
group = "updates"
key = "auto_update"
spec = "koder-app/behaviors#4"/k-test-gen-ui consome esse manifesto pra gerar UI tests automáticos que verificam (1) cada tile renderizou, (2) controle interage, (3) estado persiste.
Cross-cutting features registradas (atual)
Specs de feature que *andam um tile em Settings* Cada uma é responsável por declarar group, key, default_state próprios:
| Spec | Group | Key | Control | Default | Required |
|---|---|---|---|---|---|
themes/light-dark.kmd |
Appearance | theme_mode |
toggle (sun/moon) | follow OS | sim |
themes/ui-style.kmd |
Appearance | ui_style |
dropdown (19 opções) | material3 |
sim |
koder-app/behaviors.kmd §1 |
Account | sign_in |
KoderSignInButton | — | sim (apps com auth) |
koder-app/behaviors.kmd §4 |
Updates | auto_update |
toggle | true (ON) |
sim (apps com release) |
errors/reporting.kmd |
Reporting | auto_report |
toggle | false (OFF) |
sim |
errors/reporting.kmd |
Reporting | report_problem |
button | — | sim |
voice/wake-word.kmd |
Voice | voice.enabled |
toggle | false |
sim (apps com mic) |
voice/wake-word.kmd |
Voice | voice.talkMode |
toggle | false |
sim (apps com mic) |
voice/wake-word.kmd |
Voice | voice.hotWord |
text | "kode" | sim (apps com mic) |
voice/wake-word.kmd |
Voice | voice.backend |
dropdown | "openWakeWord" | sim (apps com mic) |
voice/wake-word.kmd |
Voice | voice.bargeIn |
toggle | true |
sim (apps com mic) |
voice/wake-word.kmd |
Voice | voice.debugRecord |
toggle | false |
dev builds only |
Cada spec referenciada *eve*atualizar esta tabela ao introduzir novo tile (auditado pelo audit script).
Audit
/k-audit settings <module> (via koderspecaudit) verifica:
- *ettings page existe*se app tem capability humana (mobiledesktopweb/tv)
- *idget canônico em uso*— grep por
KoderSettingsPage/<koder-settings-page> - *rupos na ordem canônica*— extrair ordem de declaração e comparar
- *iles obrigatórios presentes*— pra cada spec aplicável da tabela
acima, verificar que o tile existe no grupo correto
- *ersistence keys padronizadas*—
prefs.getBool('koder.<feature>')ou equivalente
Falhas geram drift entries no JSON envelope do audit script.
Anti-patterns
*on't:*
- *nventar nome de grupo novo*sem estender esta spec
- *eordenar grupos canônicos*
- *mplementar tile com ListTile/div ad-hoc*quando feature é
cross-cutting
- *isturar settings de feature local com cross-cutting*sem grupo
"Advanced" ou sub-grupo claro
- *ardcodar default state em código*— sempre vem do spec da feature
*o:*
- *eclarar settings em
koder.toml [settings]*se app tem ≥3 tiles - *eutilizar persistence keys canônicas*— sync cross-device futuro
depende disso
- *stender esta spec*quando aparece pattern novo (PR + audit)
- *est UI gerados via
/k-test-gen-ui*lendo o manifesto
Origem
Spec criada durante o ticket KSTACK-101 ETAPA 2.1. Resolve a lacuna identificada na conversa de 20260501: cada crosscutting reinventava seu tile (KSTACK89 voice, errorsreporting, themeslightdark, koderapp/behaviors §4). Aplica princípios Meta First (#1) e SDK-first (#6) de policies/stack-principles.kmd.