Koder Style — Design Decisions
themes specs/themes/koder-style.kmd
Companion to `specs/themes/verge.kmd`. Documents every design decision made for the Koder visual identity: palette, radius, spacing, typography, and per-component decisions from form elements through surfaces. Also tracks which decisions are still deferred. This is the "rationale" document; `verge.kmd` is the normative token spec.
When this spec applies
All triggers
- Alterar aparência de um componente Koder (botão, input, card, etc.)
- Divergir do baseline Adwaita em qualquer token Verge
- Ratificar paleta, radius ou tipografia para qualquer produto Koder
Specification body
Spec — Koder Style: Design Decisions
Status: v0 — cobrindo décisions #008.1–#008.11. Atualizar a cada nova divergência editorial sobre o baseline Adwaita.
§1 — Position
Esta spec é o log editorial das decisões de design Koder.
A spec normativa de tokens é specs/themes/verge.kmd; o CSS canônico
vive em tools/design-gen/assets/css/presets.css (.preset.verge).
A relação:
KDS (Koder Design System)
└── Verge (design language — specs/themes/verge.kmd)
└── v0: Adwaita 1:1 baseline ← ponto de partida
└── v1: primeiro wave de divergência ← governado por ESTA SPEC
└── v2+: evolução subsequente
"Koder style" não é um preset separado de verge: é o caminho
de divergência que Verge percorre à medida que se afasta do baseline
Adwaita e adopta decisões específicas da identidade Koder. Quando uma
decisão está ratificada, ela entra em verge.kmd §R4.{N} como diff
de tokens + bump de versão menor.
§2 — Decisões ratificadas
D1 — Forma dos botões em formulários
Decisão (owner, 2026-05-13): Botões em formulários e ações primárias usam "formato quadrado, porém com cantos minimamente abaulados". Tradução em token:
| Token | v0 (Adwaita) | Decisão Koder |
|---|---|---|
--radius-btn | 6px | 5px |
--radius-sm (inputs) | 4px | 4px (mantido) |
--radius-md (cards) | 6px | 6px (mantido) |
--radius-lg (modals) | 8px | 8px (mantido) |
--radius-pill | — | 999px (toggles/segmented) |
Rationale: 5px cai entre "square 0" e Material's "rounded 8". Aparência profissional sem a redondeza genérica do Material 3. Pill (999px) é reservado exclusivamente para toggles e segmented controls, onde a forma circular tem significado funcional.
Implementação: tokens adicionados ao .preset.verge em
presets.css (v0 ainda usa 6px de Adwaita para --radius-btn;
flip para 5px é o primeiro commit de divergência v0→v0.1).
Pending (D1.flip): Owner precisa confirmar que o flip
--radius-btn: 5pxpode ir pro CSS. Quando confirmar, editar a linha empresets.csse bump Verge para v0.1.
D2 — Paleta de cores da identidade Koder
Decisão (2026-05-14): A paleta de identidade Koder (usada no brand mark e em hero/marketing surfaces) é índigo, derivada do gradiente visual da logomarca:
#c7d2fe (índigo 200) → #6366f1 (índigo 500) → #4338ca (índigo 700) → #1e1b4b (índigo 950) → #818cf8 (dark-mode accent)
Esta paleta NÃO é o default de Verge v0. O default de Verge v0
é Adwaita blue (#3584E4), escolhido por:
- Neutralidade cross-product (não "força" a marca Koder em apps sem relação com a brand)
- Paridade com GNOME para apps desktop nativos
- a11y:
#3584E4em--accent-strong (#1c71d8)passa AA 4.77
A paleta índigo ENTRA no preset quando um produto explicitamente se identifica como produto Koder (landing pages, produtos horizontais da Stack — Kode, Koder Hub, Koder ID, etc.). O mecanismo de aplicação é via CSS var override no nível do produto:
/* No CSS do produto, sobre .preset.verge */
:root {
--accent: #6366f1;
--accent-strong: #4338ca;
--accent-on: #ffffff;
--focus: 2px solid #818cf8;
}
Pending (D2.when): Definir quais produtos adoptam índigo vs ficam em Adwaita blue. Sugestão: produtos da Koder Stack core (Kode, Hub, ID, Pass, Drive) usam índigo; produtos sectoriais (Crescer, Vivver) usam sua própria paleta.
D3 — Tipografia
Decisão (per specs/fonts/typography.kmd, ratificada no #008):
| Role | v0 stack |
|---|---|
| Sans-serif (body + UI) | Inter, sistema fallback |
| Mono (code + terminal) | JetBrains Mono, monospace |
| Display (hero/marketing) | Koder Display custom (defer → #128) |
| Serif (longform) | Lora, Georgia, serif |
O fallback de Verge v0 ('Cabin', 'Cantarell', 'Inter', sans-serif)
mantém compatibilidade com GNOME desktop. Em web apps Koder puros,
Inter é servido como self-hosted .woff2 per specs/fonts/ typography.kmd.
Pending (D3.display): Koder Display custom (tracking em
projects/koder-stack#128). Em v0, Inter cobre display roles.
D4 — Espaçamento
Decisão (#008.1): Escala 4-base em doubling:
4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 px
Equivale ao sistema Tailwind / Material default — muscle memory preservado. Tokens CSS:
| Token | Valor |
|---|---|
--pad-y (button vertical) | 8px |
--pad-x (button horizontal) | 12px |
--gap-field (entre campos de form) | 10px |
--pad-form (padding interno do form) | 18px |
--gap-title (título → primeiro campo) | 14px |
D5 — Sombras
Decisão (#008.1): Sombras Koder são índigo-tinted (em vez de pure-black de Adwaita) para amarrar com a palette da identidade:
--shadow-form: 0 0 0 1px rgba(30,27,75,0.06);
--shadow-card: 0 1px 3px rgba(30,27,75,0.12), 0 1px 2px rgba(30,27,75,0.08);
--shadow-elevated: 0 4px 12px rgba(30,27,75,0.14), 0 2px 6px rgba(30,27,75,0.08);
Em dark mode, sombras voltam ao neutro preto (rgba(0,0,0,...))
porque o contraste índigo-on-dark é imperceptível.
Status: tokens ratificados mas não aplicados ao preset Verge v0 ainda (Adwaita usa black-channel shadows). Entram na divergência v0.1.
§3 — Component decisions (#008.2–#008.8)
§3.1 — Form elements (#008.2)
Implementados em .preset.verge (+ dark overrides):
| Elemento | Estado | Token / comportamento |
|---|---|---|
btn-primary | default/hover/focus/disabled | background: var(--accent), radius --radius-btn |
btn-secondary | default/hover/disabled | border 1px solid var(--accent), fill on hover |
btn-tertiary | text-style | cor var(--accent), underline hover |
btn-ghost | text+border | borda rgba(0,0,0,0.12), sem fill |
btn-destructive | vermelho | var(--error) |
input | default/focus/error/disabled | --input-border, focus ring 2px solid var(--accent) |
input--error | estado de erro | border-color: var(--error) |
checkbox / radio | default/checked | custom styled via CSS |
toggle/switch | on/off | --toggle-off: #c0c0c0, on = var(--accent) |
select | default | nativo com appearance: none + chevron SVG |
| Disabled treatment | global | opacity: var(--disabled-opacity, 0.42) |
Motion: todos os elementos usam transition: var(--motion, 150ms ease).
§3.2 — Containers (#008.3)
| Componente | Variante | Token chave |
|---|---|---|
| Card | outlined, elevated, interactive | --shadow-card, --card-border, border-radius: var(--radius-lg) |
| Alert/Banner | info/success/warning/error | --info-bg, --success-bg, --warning-bg, --error-bg |
| Tabs (static) | CSS-only via :checked | --tab-border, --accent active indicator |
| Accordion | <details> nativo | summary marker rotates |
| Badge/chip | primary/neutral/success/warning/error | --badge-radius: 100px (pill shape) |
§3.3 — Navegação (#008.4)
| Componente | Implementação |
|---|---|
| App bar | position: sticky; top: 0; z-index: 10 + --surface bg |
| Breadcrumb | lista <nav> com separador › |
| Pagination | botões com aria-current="page" |
| Nav rail | sidebar coluna com --rail-active-bg no item ativo |
§3.4 — Data (#008.5)
| Componente | Implementação |
|---|---|
| Table | --table-border, --table-header-bg, --table-row-hover |
| Progress bar | linear, cores primary/warning |
| Stat/KPI card | delta arrow ▲▼, --stat-label-color |
§3.5 — Feedback (#008.6)
| Componente | Implementação |
|---|---|
| Toast/Snackbar | --toast-bg: #2e3436 / dark: #424242, fixed bottom-right |
| Spinner | CSS keyframe border-radius: 50%, --spinner-track |
| Skeleton | pulsing --skeleton-bg rgba(0,0,0,0.08) |
| Empty state | ícone + heading + ação primary |
§3.6 — Tipografia aplicada (#008.7)
Escala T1–T7 alinhada com --kdr-font-size-* tokens implícitos:
| Classe | px | uso |
|---|---|---|
.t1 | 48 | Hero / display |
.t2 | 36 | H1 de página |
.t3 | 28 | H2 de seção |
.t4 | 22 | H3 / cards |
.t5 | 18 | Subtítulo |
.t6 | 14 | Body padrão |
.t7 | 12 | Caption / overline |
Tokens adicionados: --font-mono, --code-bg, --code-color.
§3.7 — Layout primitives (#008.8)
| Primitive | Classe CSS | Uso |
|---|---|---|
| Stack | .stack (flex-column) | pilha vertical de componentes |
| Row | .row (flex-row) | linha com gap |
| Divider | .divider, .divider-with-label | separador |
| Surface levels | .surface-0/1/2 | hierarquia de planos |
| Focus ring demo | .focus-demo | visualização do token |
§3.8 — Surface-specific (#008.9)
Tabs Mobile / Desktop / Web / TV na detail page de cada preset.
Density overrides por surface (via .preset.surface-<X>):
| Surface | Altura mínima btn/input | Font-size |
|---|---|---|
| Mobile | 44px | 15-16px |
| Desktop | 28px | 12px |
| Web | 36px | padrão |
| TV | 56px | 18px |
TV: focus ring explícito 4px solid var(--accent) (D-pad nav).
Web: progressive enhancement — sem hover states como requirement.
§4 — Form builder (#008.10-11)
O Preset builder em kds.koder.dev/<locale>/tools/style-builder/
implementa edição visual dos tokens Verge:
- Aba Colors: 11 tokens de cor (accent, bg, surface, on-surface, label, error, success, warning)
- Aba Shape: 4 sliders de radius (sm/md/lg/btn)
- Aba Spacing: 4 sliders (pad-y/x, gap-field, pad-form)
- Aba Type: dropdown de font-family
- Preview: form de cadastro + strip de componentes ao vivo
- Export: CSS preset block + JSON + URL compartilhável (hash base64)
- Import: JSON ou CSS vars
- Undo/Redo: stack de 50 passos (Ctrl+Z / Ctrl+Y)
- Diff: painel
<details>com alterações vs defaults Verge
§5 — Decisões pendentes
| ID | Tema | Decisão necessária |
|---|---|---|
| D1.flip | Radius btn 5px | Owner confirmar flip no CSS (atualmente 6px Adwaita) |
| D2.when | Paleta índigo | Quais produtos adoptam índigo vs Adwaita blue |
| D3.display | Koder Display | Aguardar #128 (custom font) |
| D5.shadows | Sombras índigo-tinted | Confirmar aplicação ao preset Verge v0 |
| #008.13 | Migration | Produtos Koder migrar de .preset.material3 → .preset.verge |
| #008.14 | Default preset | Confirmar .preset.verge como único default (atual: já é Default: true) |
§6 — Ferramentas e testes
| Ferramenta | Path | Propósito |
|---|---|---|
| Preset builder | kds.koder.dev/<locale>/tools/style-builder/ | Edição visual interativa |
| Contrast audit | tools/design-gen/cmd/verge-contrast-audit/ | WCAG AA check automatizado |
| Regression test | tests/regression/verge_contrast_baseline_test.go | Trava score ≥ 11 pares passing |
| Audit script | specs/themes/ui-style-audit.sh | Valida uso de preset nos apps |
§7 — Cross-links
specs/themes/verge.kmd— spec normativa de tokens + versioningspecs/themes/ui-style.kmd— registry de 43 presets + auditspecs/themes/light-dark.kmd— esquema light/dark cross-surfacespecs/fonts/typography.kmd— roles de tipografia + self-hosted.woff2specs/themes/motion/— easing + durations + transitionstools/design-gen/assets/css/presets.css— CSS canônico (.preset.verge)tools/design-gen/backlog/pending/008-koder-native-style-and-form-builder.md— épico de sub-tickets
References
specs/themes/verge.kmdspecs/themes/ui-style.kmdspecs/fonts/typography.kmdtools/design-gen/assets/css/presets.csstools/design-gen/backlog/pending/008-koder-native-style-and-form-builder.md