Skip to content

Commit 2aae927

Browse files
committed
Row/column spacing skips children hidden at runtime
CodelesslyFlex puts its spacing only between consecutive shown children, like CSS gap and Figma auto layout, so a column of state panels of which one shows has no stray gaps. A row/column wraps each child in a FlexChildVisibility (parent data) that marks it collapsed while its visibility formula is false; a zero-size child alone still gets gaps. RenderCodelesslyFlex lays out its own gaps: RenderFlex runs without spacing on a main axis shortened by the gaps between shown children, then children move along by the gaps before them in visual order and the flex grows by the gaps. Flex sharing, alignment, overflow, the squeeze pass, RTL / bottom-to-top, dry layout and intrinsic sizes all count the same gaps. A child hidden with the eye toggle keeps its space and gaps. CodelesslyFlex.squeeze (default true) lets the design canvas keep the flex for its spacing without squeezing overflowing children. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UErtKMSFkZWHUh8DrQMcZW
1 parent 6605f1b commit 2aae927

3 files changed

Lines changed: 468 additions & 31 deletions

File tree

‎lib/src/transformers/node_transformers/passive_row_column_transformer.dart‎

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -341,42 +341,50 @@ class PassiveRowColumnWidget extends StatelessWidget {
341341
final NodeTransformerManager manager;
342342
final WidgetBuildSettings settings;
343343

344-
/// A flexing child hidden at runtime gives up its share of the free space,
345-
/// so a visible sibling (an empty state next to a hidden spinner) can take
346-
/// all of it. The flex drops to zero rather than removing the [Flexible] so
347-
/// the child keeps its state when it shows again.
344+
/// A child hidden at runtime collapses: it tells the [CodelesslyFlex] so
345+
/// the row/column's spacing skips it, and a flexing one gives up its share
346+
/// of the free space, so a visible sibling (an empty state next to a
347+
/// hidden spinner) can take all of it. The flex drops to zero rather than
348+
/// removing the [Flexible] so the child keeps its state when it shows
349+
/// again.
348350
Widget _collapseWhenHidden(
349351
BuildContext context,
350352
BaseNode child,
351353
Widget sizedWidget,
352354
) {
353355
final NodeTransformerManager manager = this.manager;
354-
if (sizedWidget is! Flexible || manager is! PassiveNodeTransformerManager) {
355-
return sizedWidget;
356+
if (manager is! PassiveNodeTransformerManager) {
357+
return FlexChildVisibility(collapsed: false, child: sizedWidget);
356358
}
357359

358-
Widget buildFlexible(BuildContext context) {
360+
Widget buildChild(BuildContext context) {
359361
final bool hidden = manager.runtimeVisibility(context, child) == false;
362+
if (sizedWidget is! Flexible) {
363+
return FlexChildVisibility(collapsed: hidden, child: sizedWidget);
364+
}
360365
// Without flex the hidden child would be laid out with unbounded
361366
// main-axis constraints, which a scrollable inside it can't take
362367
// (a hidden grid computed NaN offsets), so it gets no space at all.
363-
return Flexible(
364-
flex: hidden ? 0 : sizedWidget.flex,
365-
fit: sizedWidget.fit,
366-
child: SizedBox(
367-
width: hidden ? 0 : null,
368-
height: hidden ? 0 : null,
369-
child: sizedWidget.child,
368+
return FlexChildVisibility(
369+
collapsed: hidden,
370+
child: Flexible(
371+
flex: hidden ? 0 : sizedWidget.flex,
372+
fit: sizedWidget.fit,
373+
child: SizedBox(
374+
width: hidden ? 0 : null,
375+
height: hidden ? 0 : null,
376+
child: sizedWidget.child,
377+
),
370378
),
371379
);
372380
}
373381

374382
final List<Listenable> listenables = manager.listenablesFor(context, child);
375-
if (listenables.isEmpty) return buildFlexible(context);
383+
if (listenables.isEmpty) return buildChild(context);
376384
return ManagedListenableBuilder(
377385
key: ValueKey('${child.id}-flex'),
378386
listenables: listenables,
379-
builder: buildFlexible,
387+
builder: buildChild,
380388
);
381389
}
382390

0 commit comments

Comments
 (0)