UI Framework First
Sub-policy de `reuse-first` para padrões UI cross-cutting. Herda decision tree, protocolo pré-Write e promotion pipeline da meta; acrescenta apenas as regras categoricamente distintas de UI: theme contract, safe-area, a11y baseline, i18n, paridade entre variantes (mobile/desktop/web/TV) e disciplina de testes (golden + a11y).
Sub-policy of
reuse-first. Inherits the decision tree, the pre-Write protocol and the promotion pipeline. Do not redeclare them here — they live in the meta. This file contributes only the rules that are categorically distinct for UI framework code.
Scope
Applies to any code in:
- `enginessdkkoder_kit
app**.dart` — any Koder product with a Flutter UI.
productsapp/**/*.{js,ts,jsx,tsx}— web client UIs of Koder products.
Out of scope: server-side code, CLIs, runtime libs, build tooling, wire-format clients (each has its own sub-policy).
Categorical rules
Each rule below is normative for code in scope. The rule lives here, not in the meta, because it is meaningless or counter-productive in non-UI categories.
1. Theme contract
- Light/dark switching is mandatory. The product MUST follow the OS theme by default (
ThemeMode.systemin Flutter,prefers-color-schemeon web), and persist user override via the SDK (KoderTheme/KoderApp.theme). - Color tokens are consumed from the SDK palette; no hardcoded hex in product code outside designated brand assets (icons, splash).
- Anti-flash on theme switch is mandatory (no white-flash on dark mode reload). Reference implementation:
KoderAppinjects pre-render style. - Spec:
specs/themes/light-dark.kmd.
2. UI Style (presets) and visual identity
- The 19 canonical UI Style presets ship in
koder_kit. Products may select a default but MUST allow user override in Settings viaKoderUIStylePicker. - New presets land in the SDK with a spec-audit pass on
specs/themes/ui-style.kmd— never in a product.
3. Safe-area and window-insets
- Every screen MUST consume window insets via
KoderSafeScaffold(Flutter) orenv(safe-area-inset-*)(web). No content under status bar, nav bar or display cutout. - Apps with mic/camera capability MUST honour the privacy indicator overlay; the SDK widget already accounts for it.
- Spec:
specs/app-layout/safe-area.kmd.
4. Navigation and back behaviour
- Back gesture / ESC / browser-back MUST always pop one screen at a time on the Navigator stack; only the root screen exits/minimises the app.
- Reference implementation:
KoderBackScope(enableSystemExitAtRoot: true). - Spec:
specs/navigation/back-behavior.kmd.
5. Accessibility baseline
A new shared widget is not promotable to koder_kit until it satisfies:
- Focus order: keyboard / screen-reader traversal follows visual reading order.
- Screen-reader labels: every interactive element has a non-empty
Semantics(label:)or ARIA equivalent. - Contrast: text and interactive elements meet WCAG AA (4.5:1 normal, 3:1 large).
- Tap targets: ≥ 44 × 44 dp on touch surfaces.
- Reduced motion: animations honour
MediaQuery.disableAnimations/prefers-reduced-motion.
These requirements are stricter than the generic "≥ 3 consumers" promotion gate from the meta, because UI accessibility regressions are user-visible and class-action risk in many jurisdictions.
6. Internationalisation (i18n)
- No string literals in production code paths. All user-facing strings go through
KoderL10n(planned) — even single-language MVPs use the indirection so future translation does not require a refactor. - Spec hooks:
policies/language.kmd(pt-BR for chat, en-US for product strings) andspecs/koder-app/behaviors.kmd §9. - Exception: error IDs (
<PRODUCT>-<CAT>-<CODE>-<SEQ>) are not translatable by design.
7. Cross-variant parity
- Any new shared widget that targets
app/MUST ship with implementations for all sectors that the consuming module declares in itskoder.toml. RFC-006 sectors:mobile/,desktop/,tv/,web/, pluscli/andtui/where applicable (with the understanding that cli/tui are not "UI framework" scope and are covered elsewhere). - A widget that lands in koder_kit only on Flutter is acceptable if the module catalog declares "no web variant"; landing only on web is acceptable in the symmetric case. Mid-state (Flutter-only when web is in scope) blocks promotion.
8. Error display
- Every user-facing error MUST be rendered via
KoderErrorBanner/ equivalent SDK widget. Three pillars: (a) humanised message in pt-BR + en-US; (b) "Show details" disclosure with raw technical error; (c) unique ID<PRODUCT>-<CAT>-<CODE>-<SEQ>for log correlation. - Spec:
specs/errors/user-facing-messages.kmd.
9. Auth, update and telemetry chrome
- Auth UI: use
KoderSignInButton,KoderUserBadge,KoderAuthGatefrom koder_kit v0.5+. Never hand-roll an OAuth button. - In-app update:
KoderUpdatershows the mandatory-update gate; toggle in Settings, default ON. - Error reporting toggle:
KoderReportButton+KoderErrorReporter, default OFF. - Specs:
specs/koder-app/behaviors.kmd§1, §4, andspecs/errors/reporting.kmd.
10. Test discipline
- Golden tests required for any visual widget promoted to koder_kit (light + dark variants minimum; UI Style variants when the widget reacts to UI Style).
- A11y tests required for any widget that takes input. Use Flutter's
expectAccessibilityGuidelines(textContrastGuideline). - Coverage threshold for koder_kit lib: ≥ 80% line, ≥ 70% branch (lower than runtime libs because golden + a11y tests provide additional confidence the line-coverage number does not capture).
11. Promotion criterion (overrides the meta default)
The meta default is "≥ 3 consumers plausibly need this pattern". For UI widgets, the threshold is stricter:
- ≥ 2 confirmed consumers AND
- Spec-audit pass on the relevant
specs/file (themelayouterrorauthetc.) AND - Golden + a11y tests in the SDK PR.
The lower consumer count is intentional: UI drift is user-visible and expensive to retrofit; it is cheaper to land in the SDK earlier than to migrate three forks later.
Audit
./ui-framework-first-audit.sh (initial implementation in Phase 2; substantive checks land in Phase 4 per policies-RFC-001):
- Structural (Phase 2, this commit): validate
inherits_from: policies/reuse-first.kmdin this file's frontmatter; verify the meta still exists; verify the four canonical specs cited above resolve. - Behavioural (Phase 4, future): scan
productsapp/**/lib/main.dartforMaterialApp(not wrapped inKoderApp; scan for theme literals (Color(0xFF...)outside designated paths); scan widgets for missingSemantics(label:).
The audit is strict for structural validation (build-blocking) and advisory for behavioural findings until a major release window.
Cross-references to other policies
- Meta:
policies/reuse-first.kmd— decision tree, protocol, promotion pipeline. - Sibling:
policies/code-first.kmd— orthogonal axis (mechanical-vs-analytical). - Inverse-direction command:
commands/k-sdkify.md— sweeps existing UI drift back to the SDK. - Adjacent specs: theme, layout, navigation, errors, app behaviours, voice (mic-aware UIs).