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.

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

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

  1. Consistência visual entre apps Koder e entre features dentro do mesmo app — todo tile parece tile.
  2. Discoverability — usuário sabe onde encontrar cada setting porque o grupo é canônico (Privacy sempre tem a mesma posição em qualquer app).
  3. Reuso de SDKKoderSettingsTile / <koder-settings-tile> encapsulam controle/persistence/i18n sem boilerplate por app.
  4. Auditabilidadekoder.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 ListTile puro (Flutter) ou <div> ad-hoc (Web) quando o conteúdo é setting cross-cutting
  • Salvar preferência fora do persistence_key declarado 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:

  1. Settings page existe se app tem capability humana (mobile/desktop/web/tv)
  2. Widget canônico em uso — grep por KoderSettingsPage/<koder-settings-page>
  3. Grupos na ordem canônica — extrair ordem de declaração e comparar
  4. Tiles obrigatórios presentes — pra cada spec aplicável da tabela acima, verificar que o tile existe no grupo correto
  5. Persistence keys padronizadasprefs.getBool('koder.<feature>') ou equivalente

Falhas geram drift entries no JSON envelope do audit script.

Anti-patterns

Don't:

  1. Inventar nome de grupo novo sem estender esta spec
  2. Reordenar grupos canônicos
  3. Implementar tile com ListTile/div ad-hoc quando feature é cross-cutting
  4. Misturar settings de feature local com cross-cutting sem grupo "Advanced" ou sub-grupo claro
  5. Hardcodar default state em código — sempre vem do spec da feature

Do:

  1. Declarar settings em koder.toml [settings] se app tem ≥3 tiles
  2. Reutilizar persistence keys canônicas — sync cross-device futuro depende disso
  3. Estender esta spec quando aparece pattern novo (PR + audit)
  4. Test 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 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.

Referências