Settings Patterns
settings specs/settings/patterns.kmd
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.
When this spec applies
Primary triggers
- Implementar Settings em app Koder
All triggers
- Criar tela Settings em app Koder novo
- Adicionar toggle/dropdown novo a Settings de qualquer app
- Cross-cutting feature precisa de UI de configuração
- Auditar conformidade de Settings em app existente
Specification body
Spec — Settings Patterns
Convenção mestre da tela Settings em todo app Koder. Resolve a proliferação de tiles ad-hoc (cada feature cross-cutting inventando seu próprio tile com label/posição/default state diferentes).
Goals
- Consistência visual entre apps Koder e entre features dentro do mesmo app — todo tile parece tile.
- Discoverability — usuário sabe onde encontrar cada setting porque o grupo é canônico (Privacy sempre tem a mesma posição em qualquer app).
- Reuso de SDK —
KoderSettingsTile/<koder-settings-tile>encapsulam controle/persistence/i18n sem boilerplate por app. - Auditabilidade —
koder.toml [settings]declara features esperadas; audit script verifica que app cumpre.
Hierarquia canônica de grupos
A tela Settings tem grupos fixos em ordem, está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 | General | Geral | Idioma, fuso, locale, perfil ativo |
| 2 | Account | Conta | Sign-in, badge, signout, multi-account switch |
| 3 | Appearance | Aparência | Tema (light/dark), estilo de UI, cor accent, densidade |
| 4 | Notifications | Notificações | Push, badge, som, "do not disturb" |
| 5 | Privacy | Privacidade | Telemetria, tracking, dados compartilhados |
| 6 | Updates | Atualizações | Auto-update toggle, canal (stable/beta), botão check now |
| 7 | Voice | Voz | Wake word, talk mode, mic permissions |
| 8 | Storage | Armazenamento | Cache, downloads, dados offline, limite de uso |
| 9 | Reporting | Relatórios | Auto-report toggle, "Reportar problema" button, opt-in dados |
| 10 | Network | Rede | Proxy, VPN, sync settings |
| 11 | Advanced | Avançado | Dev options, experimental flags, debug |
| 12 | About | Sobre | Version, license, credits, links |
Regras de ordem:
- Apps omitem grupos que não aplicam (ex.: app sem mic não tem Voice)
- Apps não reordenam os grupos restantes
- Apps não criam grupos novos sem extender esta spec primeiro
Estrutura do tile
Todo tile em Settings tem 6 campos definidos:
| Campo | Required | Tipo | Exemplo |
|---|---|---|---|
key |
sim | string snake_case | theme_mode |
label |
sim | i18n string | "Theme" / "Tema" |
control |
sim | enum | `toggle |
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
Flutter (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',
),
// ...
],
),
],
)
Web (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>
App 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 da feature (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 mandam 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 deve atualizar esta tabela ao introduzir novo tile (auditado pelo audit script).
Audit
/k-audit settings <module> (via koder-spec-audit) verifica:
- Settings page existe se app tem capability humana (mobile/desktop/web/tv)
- Widget canônico em uso — grep por
KoderSettingsPage/<koder-settings-page> - Grupos na ordem canônica — extrair ordem de declaração e comparar
- Tiles obrigatórios presentes — pra cada spec aplicável da tabela acima, verificar que o tile existe no grupo correto
- Persistence keys padronizadas —
prefs.getBool('koder.<feature>')ou equivalente
Falhas geram drift entries no JSON envelope do audit script.
Anti-patterns
Don't:
- Inventar nome de grupo novo sem estender esta spec
- Reordenar grupos canônicos
- Implementar tile com ListTile/div ad-hoc quando feature é cross-cutting
- Misturar settings de feature local com cross-cutting sem grupo "Advanced" ou sub-grupo claro
- Hardcodar default state em código — sempre vem do spec da feature
Do:
- Declarar settings em
koder.toml [settings]se app tem ≥3 tiles - Reutilizar persistence keys canônicas — sync cross-device futuro depende disso
- Estender esta spec quando aparece pattern novo (PR + audit)
- Test UI gerados via
/k-test-gen-uilendo o manifesto
Origem
Spec criada durante o ticket KSTACK-101 ETAPA 2.1. Resolve a lacuna identificada
na conversa de 2026-05-01: cada cross-cutting reinventava seu tile (KSTACK-89
voice, errors/reporting, themes/light-dark, koder-app/behaviors §4).
Aplica princípios Meta First (#1) e SDK-first (#6) de
policies/stack-principles.kmd.
References
policies/sdk-first.kmdpolicies/stack-principles.kmdspecs/audit/frontmatter.kmdspecs/themes/light-dark.kmdspecs/themes/ui-style.kmdspecs/koder-app/behaviors.kmdspecs/errors/reporting.kmdspecs/voice/wake-word.kmd