| name | ui-specialist-handoff |
|---|---|
| description | Explicit-invocation-only Flutter and Dart UI handoff workflow. Use only when the user specifically invokes `ui-specialist-handoff` or clearly asks for this contract-only handoff style. In that case, scaffold new UI elements, screens, controls, or presentation widgets as contract-only artifacts for a later UI specialist: define the widget class, explicit constructor and field contract, callbacks, state ownership, and direct descriptive comments inside build() instead of real UI code. |
Stop at the interface boundary when adding new UI.
- Apply this skill only on explicit user request.
- Do not use this skill as the default approach for ordinary UI tasks.
- Create the widget class with the narrowest correct public API.
- Declare every input explicitly and type it precisely.
- Include callbacks for user actions instead of burying behavior in UI code.
- Expose ownership of state, controllers, focus nodes, and async behavior clearly.
- Keep
build()free of layout, styling, and rendering code. - Write direct comments inside
build()that describe the intended widget behavior and appearance. - Use those comments to describe structure, hierarchy, states, interactions, accessibility, localization, and any design constraints the UI specialist should honor.
- When modifying an existing screen or widget, extract the new visual surface into a placeholder widget only if that boundary is already clean and maintainable.
- If the final clean implementation should stay inline or as a local helper for readability, do not force a separate placeholder widget solely for handoff.
- Treat placeholder extractions used for handoff as temporary when the cleaner final implementation would inline them later.
- If the surrounding task requires compilable code, end
build()withthrow UnimplementedError('UI specialist implementation pending');. - If compilation is not required for the task, leave only the descriptive comment block in
build().
- Prefer immutable fields and
constconstructors when the codebase allows them. - Use named parameters unless the surrounding code clearly prefers positional parameters.
- Make nullability meaningful; do not use nullable fields to avoid decisions.
- Include required domain inputs, optional display inputs, callbacks, and any enums or lightweight models needed to make the contract precise.
- Surface formatting, validation, parsing, units, and value-range expectations in the contract or in the
build()comments. - If the widget depends on a model that does not exist yet, define a minimal typed model instead of passing loose maps or dynamic values.
- Choose
StatefulWidgetonly when local ephemeral state is truly part of the contract; otherwise preferStatelessWidgetand push state ownership outward.
- Describe what the widget should display first.
- Describe how the user should interact with it.
- Describe loading, empty, disabled, validation, and error states when relevant.
- Describe responsive behavior, content priority, and any important overflow or truncation expectations when relevant.
- Describe accessibility semantics, focus behavior, keyboard behavior, and localization requirements when relevant.
- Describe any dependencies on theme tokens, design system primitives, or composition slots without choosing the final design.
- Do not write speculative widget trees, layout code, styling code, or animation code inside the new widget.
- Do not choose spacing, colors, typography, iconography, or motion details in code.
- Do not extract a new widget purely because this skill is active; extraction must improve structure or isolate a meaningful UI surface.
- Do not hide important requirements in prose outside the scaffold when they belong in the widget contract or
build()comments. - Do implement non-visual plumbing outside the widget when it clarifies the handoff.
- Do update calling code only as far as needed to show how the contract is consumed.
class DurationInput extends StatelessWidget {
const DurationInput({
super.key,
required this.minutes,
required this.onChanged,
this.label,
this.errorText,
this.enabled = true,
});
final int minutes;
final ValueChanged<int> onChanged;
final String? label;
final String? errorText;
final bool enabled;
@override
Widget build(BuildContext context) {
// Display a duration input control for minutes with clear current-value visibility.
// Let the user increase, decrease, or directly edit the duration in whole-minute units.
// Show the optional label above or beside the control according to available space.
// Reflect disabled and validation-error states clearly without defining the final visuals here.
// Preserve keyboard, screen-reader, and localization support for numeric editing and minute labels.
throw UnimplementedError('UI specialist implementation pending');
}
}Be explicit enough that a UI specialist can implement the widget from the contract and the build() comment block without needing guessed design decisions from Codex.