Logoheadless

Guardrails for customization#

This page explains the rules that keep behavior and accessibility correct when you customize visuals.

Ownership (who is responsible for what)#

If you violate these, you can get double activation, broken keyboard support, or broken overlays.

ConcernOwnerNotes
Tap/keyboard activation Component Renderers and primitives must not create a second activation path.
Selection triggering (selectIndex) Component / safe scaffold Item widgets should not “select” manually.
Overlay close contract (completeClose) Renderer / safe scaffold If you animate exit, you must call completeClose() after the animation.
Component semantics (button/selected/enabled) Component (baseline) Renderers may add local semantics only if it cannot cause double activation.

Most customization should use slots (Decorate first) and primitives.

  • Use Decorate when you want to wrap the default UI.
  • Use Replace only if you know you can keep semantics/commands/close-contract correct.

What not to do (common footguns)#

  • Do not put onTap / onPressed on renderer roots.
  • Do not add tap handlers inside dropdown menu items (safe scaffolds own selection).
  • Do not implement your own overlay lifecycle in a primitive.
  • Do not forget completeClose() if you animate exit.

Debugging#

“Close contract timeout”#

If you see a log similar to:

[AnchoredOverlayEngine] Close contract timeout: renderer did not call completeClose().

It means:

  • the overlay entered closing,
  • but the renderer never called completeClose().

Fix:

  • call commands.completeClose() after your exit animation finishes,
  • or use a safe scaffold that manages the close contract for you.

Double activation#

Symptoms:

  • callbacks fire twice,
  • selection happens twice,
  • focus jumps unexpectedly.

Fix:

  • ensure there is exactly one activation source: the component.
  • remove tap handlers from renderer roots and primitives.

Repo hygiene (local artifacts)#

Local build/IDE artifacts may appear during development (e.g. after flutter test), but must not end up in git.

  • MUST: build/, .dart_tool/, *.iml, .idea/, .vscode/ must be listed in .gitignore.
  • MUST: before a PR/commit, verify that the diff contains no build/IDE artifacts.