feat(editor): reduce-motion clamp + edge gradient + breathing pulse + style sheet

Four polish features in one push.

1. Reduce-motion clamp. FaiEditorStyle.clampedForA11y(
   disableAnimations: ...) returns a style with glass, gradient,
   flow animation, and node shadows forced off when the OS
   reduce-motion preference is set. FlowCanvas + FlowEditorPage
   call it on every build with
   MediaQuery.disableAnimationsOf(context) so operators on
   accessibility settings get a flat, static editor without an
   explicit Studio setting.

2. Edge gradient source→target. EdgePainter now accepts an
   optional colorEnd per segment and paints a linear shader
   along the bezier when both ends carry distinct type accents.
   In practice this draws attention to type mismatches: a
   text→json wire reads as a colour transition; a same-type
   wire stays a solid colour. ModuleSpec lookup at both edge
   endpoints feeds the colour pair.

3. Breathing pulse on running steps. FlowNode accepts a
   Listenable pulse; when status=running AND the canvas's
   _flowAnim is ticking, the node wraps in an AnimatedBuilder
   that drives a sine-wave shadow halo (alpha + blur + spread
   oscillating). Stops when the run completes. Gated by
   _style.flowAnimation so reduce-motion / minimal-style modes
   stay still.

4. In-editor style sheet. Bottom-right canvas chrome gains a
   ⚙ Style button that opens a modal bottom sheet with four
   SwitchListTiles (glass, gradient backdrop, flow animation,
   node shadows) plus 'Reset to default'. Edits live in
   _styleOverride on the canvas state — operator can tweak the
   look for the session without restarting or editing code.
   No persistence in this version; follow-up could pipe the
   override through SharedPreferences via the host.

Bumps fai_studio_flow_editor to 0.10.0.

Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
flemming-it 2026-06-01 22:55:18 +02:00
parent b1fe765468
commit a71f654162
6 changed files with 377 additions and 73 deletions

View file

@ -454,7 +454,12 @@ outputs:
// operator's first instinct is the right action rather
// than staring at an empty grid.
final hasSteps = _controller.graph.steps.isNotEmpty;
final style = widget.style ?? FaiEditorStyle.modern;
// Honor the OS reduce-motion preference for the
// properties-panel glass effect same clamp the canvas
// applies to its own surfaces.
final style = (widget.style ?? FaiEditorStyle.modern).clampedForA11y(
disableAnimations: MediaQuery.disableAnimationsOf(context),
);
final glass = style.panelStyle == EditorPanelStyle.glass;
final hasSelection = _controller.selectedStepId != null;