Skip to content

chore(example-deps)(deps): bump fluttersdk_wind from 1.1.2 to 1.2.1 in /example in the example-minor-and-patch group - #159

Open
dependabot[bot] wants to merge 1 commit into
masterfrom
dependabot/pub/example/example-minor-and-patch-bd39135162
Open

chore(example-deps)(deps): bump fluttersdk_wind from 1.1.2 to 1.2.1 in /example in the example-minor-and-patch group#159
dependabot[bot] wants to merge 1 commit into
masterfrom
dependabot/pub/example/example-minor-and-patch-bd39135162

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Aug 1, 2026

Copy link
Copy Markdown
Contributor

Bumps the example-minor-and-patch group in /example with 1 update: fluttersdk_wind.

Updates fluttersdk_wind from 1.1.2 to 1.2.1

Release notes

Sourced from fluttersdk_wind's releases.

1.2.1

Fixed

  • Unknown theme-spacing tokens (p-primary, m-foo, top-abc, gap-x-blue, ...) now silently drop instead of throwing ArgumentError: Invalid spacing multiplier: <token> inside build(), matching the "unknown className is dropped with a debug warning" contract other parsers already follow. Adds WindThemeData.tryGetSpacing(String); the padding, margin, position, and flex-gap parsers now use it (sizing already pre-validated with double.tryParse). getSpacing is unchanged for backward compatibility. (lib/src/theme/wind_theme_data.dart, lib/src/parser/parsers/padding_parser.dart, lib/src/parser/parsers/margin_parser.dart, lib/src/parser/parsers/position_parser.dart, lib/src/parser/parsers/flexbox_grid_parser.dart)
  • WAnchor now hit-tests its whole bounds via HitTestBehavior.translucent. The inner GestureDetector used the default HitTestBehavior.deferToChild, so it only fired when a painted child sat under the exact tap point. An anchor wrapping transparent content (a settings row, a checkbox row, a link with padding) ignored taps that landed on its empty regions, including the element centre that automated drivers and centred pointer events target. It now behaves like WInput/WPopover, which already use whole-box hit-testing, so the full anchor rectangle is tappable. (lib/src/widgets/w_anchor.dart; covered by test/widgets/w_anchor_test.dart)
  • WPopover no longer flickers open-then-closed on the first trigger tap on web, and its menu items now respond on the first open. A leftover focus-loss auto-close (_onFocusChange) dismissed the popover roughly 150ms after the opening click, when web transiently blurs the trigger, so it closed on the same gesture that opened it (and unmounted the overlay before a menu item's tap could resolve). The auto-close is removed; dismissal is now driven solely by an outside tap and programmatic close, matching the same fix already applied to WSelect. (lib/src/widgets/w_popover.dart)

1.2.0

Changed

  • Wind's internal flex layout is now fully intrinsic-safe: the column cross-axis stretch and the basis-* resolution no longer use a LayoutBuilder. Column stretch is a real render object (WindCrossStretch) and fractional basis-* resolves against the flex's own extent via WindMainExtentProvider/WindFractionBasis. A flex flex-col (with or without basis-*) now renders inside an items-stretch grid cell, under a Flutter IntrinsicHeight/IntrinsicWidth, or in a Table cell without the LayoutBuilder does not support returning intrinsic dimensions assert (the web _owner != null cascade that produced). (lib/src/widgets/w_div.dart, lib/src/widgets/wind_equal_height_row.dart) (WIND-4)
  • Interactive widgets (WSelect, WCheckbox, WRadio, WDatePicker) now route their selection, checkmark, and accent colors through the theme primary token instead of hardcoded blue-* classes and Colors.blue shades, so a consumer's brand color drives them. The shipped default look is unchanged (primary defaults to the Tailwind blue swatch). WindThemeData.toThemeData() keeps its indigo Material ColorScheme baseline unless a custom primary is registered, so the default Material appearance is unchanged too. (lib/src/widgets/w_select.dart, lib/src/widgets/w_checkbox.dart, lib/src/widgets/w_radio.dart, lib/src/widgets/w_date_picker.dart, lib/src/theme/wind_theme_data.dart) (WIND-3)
  • Documented and test-proved the WindRecipe/WindSlotRecipe caller-className merge contract: the recipe only appends the caller's className last (already the behavior since introduction); the conflict with a base token is resolved one layer down, at parse time, by WindParser's per-family last-wins. No twMerge/cn port was added or is planned. (test/recipe/wind_recipe_test.dart, test/parser/parsers/sizing_parser_test.dart, doc/styling/wind-recipe.md, skills/wind-ui/SKILL.md)
  • skills/wind-ui/references/tailwind-divergence.md, skills/wind-ui/SKILL.md, and doc/layout/display.md reconciled to reflect the flex-wrap alias (no longer a listed unsupported token) and the unknown-token debug hint (no longer purely silent). Example pages under example/lib/pages/ switched from flex-wrap to the canonical wrap token. (WIND-5)

Added

  • Min-width-stretch horizontal scroll primitive ("fill on desktop, scroll on narrow", the shadcn Table pattern), composed from existing tokens with no new className: overflow-x-auto on a wrapper with w-full (optionally min-w-[Npx]) on the inner content. w-full inside a horizontal scroll is now sized to max(viewport, min-w-*) via the threaded viewport width instead of asserting on the scroll's unbounded width, so the content fills the viewport when wide and honors its min width (scrolling) when narrow. (lib/src/widgets/wind_min_width_scroll.dart, lib/src/state/wind_min_width_scroll_scope.dart, lib/src/widgets/w_div.dart, example/lib/pages/layout/responsive_table.dart) (WIND-4)
  • Explicit flex flex-col items-stretch now equalizes child widths (every eligible child fills the column), closing the asymmetry with grid ... items-stretch. Like the smart-stretch default it is intrinsic-safe and unbounded-safe (no LayoutBuilder, no infinite-width SizedBox), so it also works in a bare Row slot or under an intrinsic-measuring ancestor. (lib/src/widgets/w_div.dart, lib/src/widgets/wind_equal_height_row.dart) (WIND-4)
  • Actionable dev-time assert for h-full inside a vertical scroll: a child that resolves h-full under an overflow-y-auto/overflow-y-scroll parent (an unbounded height) now fails fast with a message pointing at the fix (flex-1 inside a flex flex-col), instead of a cryptic Flutter unbounded-height error. The scrollable parent threads the signal down via WindMinWidthScrollScope; the assert is stripped in release. (lib/src/widgets/w_div.dart, lib/src/state/wind_min_width_scroll_scope.dart) (WIND-4)
  • Seeded default primary color token: Wind's default theme now includes a primary MaterialColor (aliased 1:1 to the Tailwind blue swatch), so bg-primary / text-primary / border-primary resolve out of the box and become brand-overridable via WindThemeData.colors: {'primary': ...}. Previously primary was consulted only by toThemeData() and was a silent no-op in className tokens. (lib/src/theme/defaults/colors.dart, lib/src/theme/wind_theme_data.dart) (WIND-3)
  • flex-wrap -> wrap alias: FlexboxGridParser now maps the Tailwind spelling flex-wrap directly to WindDisplayType.wrap (canParse already accepted flex-*; only the parse() handler was missing). wrap remains the canonical, unaliased token; flex-wrap prints a one-time kDebugMode hint suggesting it. (lib/src/parser/parsers/flexbox_grid_parser.dart) (WIND-5)
  • Unknown-className debug warning: WindParser.findAndGroupClasses now emits a one-time kDebugMode debugPrint naming any className that no parser recognizes, deduped per unique token per session (mirrors the existing _warnedAliases shadow/cycle dedup). The token is still dropped from output; release builds print nothing. Valid Wind tokens handled outside the parser map are exempt so the warning aims only at genuine typos: the widget-consumed object-* fit family (read by WImage), the inline-flex/inline-block/inline display keywords (emitted by WBadge, inert in Flutter), and deliberately inert compat tokens that Wind's own widget docstrings / the consumer contract emit (transition/transition-colors/etc., antialiased, sr-only, the *-nums font-variant family incl. tabular-nums). (lib/src/parser/wind_parser.dart) (WIND-5)
  • cursor-* utilities: a new CursorParser maps Tailwind cursor names (cursor-pointer, cursor-not-allowed, cursor-text, cursor-grab/cursor-grabbing, cursor-zoom-in/cursor-zoom-out, the full resize set, etc.) to the matching SystemMouseCursors. WDiv applies the resolved cursor through a MouseRegion, so a plain container can feel clickable on web/desktop without WAnchor or a manual MouseRegion; on a hover:/focus:/active: WDiv the cursor MouseRegion sits below the auto-wrapped WAnchor and wins. Inert on touch platforms; last token wins; unknown names no-op. (lib/src/parser/parsers/cursor_parser.dart, lib/src/parser/wind_style.dart, lib/src/widgets/w_div.dart) (#125)
  • size-* sizing utility (Tailwind v3.4+ shorthand): size-2, size-full, size-1/2, size-[20px], size-[50%], size-screen set BOTH width and height in one token. Fixes childless WDiv sizing: a WDiv(className: 'size-2 rounded-full bg-...') status dot now renders its box instead of collapsing (the previous gap was that size-* was unrecognized, not that w-*/h-* were ignored, which already worked childless). A later w-*/h-* overrides the matching axis. (lib/src/parser/parsers/sizing_parser.dart) (#123)
  • grid equal-height rows via items-stretch. By default a Wind grid renders as a Wrap and sizes each cell to its own content, leaving a row ragged when one card is taller. Adding items-stretch (CSS Grid's default align-items: stretch) now builds the grid as a column of IntrinsicHeight rows so every cell in a row matches the tallest, and cells divide the row width evenly. Cells should size from their own content; h-full on a stretched cell is unsupported (it inserts a LayoutBuilder that asserts under IntrinsicHeight, see the intrinsic-sizing limitation docs). (lib/src/widgets/w_div.dart) (#126)
  • WindRecipe and WindSlotRecipe (+ WindCompoundVariant, WindSlotCompoundVariant): a tv() (tailwind-variants) equivalent. WindRecipe resolves a single className from base + variant axes + compoundVariants + a caller className, in strict emission order (base ++ variant ++ compound ++ caller), with no dedupe/sort/twMerge. WindSlotRecipe extends the same model to multi-slot components and returns a Map<String, String> (slot -> className). (lib/src/recipe/wind_recipe.dart) (#120)
  • WBadge: inline status/label pill. Composes a rounded-full WDiv around a WText(text-xs); all visual tone is className-driven (bg-*, text-*, dark: pairs). (lib/src/widgets/w_badge.dart) (#120)
  • WCard: surface container with optional header and footer slots. Delegates to WDiv (flex-col); all styling is className-driven. (lib/src/widgets/w_card.dart) (#120)
  • WSwitch: controlled toggle switch. Pushes the checked: state prefix when value is true. The thumb is a flex child of the track, so the caller positions it with justify-start -> checked:justify-end on the track className (the track stays a flex Row; WSwitch does not inject relative, which would force a single-child Stack and defeat justify-*). thumbClassName supplies thumb shape/color only; translate-x-* is intentionally unsupported (Wind has no transform parser). Wraps WAnchor for hover/focus/disabled state propagation. (lib/src/widgets/w_switch.dart) (#120)
  • WRadio<T>: controlled radio button. Drives the selected: state prefix when value == groupValue. Group behavior (mutual exclusivity) is the caller's responsibility. (lib/src/widgets/w_radio.dart) (#120)
  • WTabs: controlled tabs widget. The selected: state prefix activates on the active tab; listClassName, tabClassName, selectedTabClassName, and panelClassName cover every structural region. panelBuilder receives the selected index each rebuild. The tab list defaults to full container width (fullWidthList: true) so a border-b underline spans the container rather than only the tabs; set fullWidthList: false for a content-width / pill tab strip. (#128) (lib/src/widgets/w_tabs.dart)

Fixed

  • WPopover overlay no longer overflows the right edge of the viewport when autoFlip is on. A wide panel next to a near-centered trigger on a narrow screen flipped to the opposite side but still spilled off-screen; a computeHorizontalClamp helper now folds a corrective dx into the follower offset so the panel is pulled fully inside the viewport (seated 8px from the edge, or flush when it is too wide to honor both margins). The clamp engages only on genuine off-screen overflow, so an edge-anchored popover already fully visible is left untouched. (lib/src/widgets/w_popover.dart)

  • grid ... items-stretch no longer emits a residual RenderFlex overflowed by ~2px on the bottom when it stretches an unequal cell (follow-up to #139). WindEqualHeightRow previously re-laid each cell to a TIGHT height equal to the loose-measured row max; a cell whose flex flex-col content needs a hair more under the tight re-lay (sub-pixel text/flex rounding on real rendering, e.g. CanvasKit) overflowed by a couple of pixels. It now stretches with a MIN height instead (never a tight squeeze), so a cell is never forced below its own content and the row takes the tallest resulting height, overflow-free by construction. (lib/src/widgets/wind_equal_height_row.dart) (#141)

  • grid ... items-stretch no longer asserts RenderBox was not laid out (rooted at RenderIntrinsicHeight / LayoutBuilder does not support returning intrinsic dimensions) when it stretches an unequal flex flex-col cell. The equal-height mechanism from #126 used IntrinsicHeight, which queries child intrinsics; a flex flex-col cell (or one using h-full / basis-*) carries a LayoutBuilder that cannot answer intrinsic queries, so stretching a shorter cell crashed the exact case the feature exists for. Replaced it with WindEqualHeightRow, a RenderObject that measures each cell with a real loose-height layout and re-lays it tight to the row max, so LayoutBuilder-bearing cells stretch correctly. As a bonus, h-full on a stretched cell now resolves too. (lib/src/widgets/wind_equal_height_row.dart, lib/src/widgets/w_div.dart) (#139)

  • Alias expansion now resolves state/breakpoint-prefixed alias tokens instead of silently dropping them. A prefixed token (hover:bg-surface-container, md:row, dark:hover:row) had its whole form rejected before the alias lookup, so prefix: + a known alias key was a silent no-op while plain bg-surface-container worked. The expander now peels the prefix chain off, matches the bare body against the (still bare-only) alias map, and re-applies the prefix to every produced token (md:row -> md:flex md:flex-row; hover:bg-surface carries hover: onto each token including the value's own dark: peer, yielding hover:dark:..., which the parser resolves regardless of prefix order). Cycle/depth/output guards are unchanged and now key on the bare body. (lib/src/parser/alias_expander.dart) (#124)

  • WPopover overlay no longer stretches unbounded. It applied only a minWidth (trigger width) with no upper bound, so a menu without an explicit width could fill the available space and overflow a narrow content column (the asymmetry with WSelect, which pins a width). New width and maxWidth props: width (or a w-* token) pins a fixed overlay width like WSelect's menuWidth; maxWidth (or a max-w-* token) bounds it, defaulting to the screen width so the overlay never overflows the viewport. (lib/src/widgets/w_popover.dart) (#127)

  • w-full on a direct child of a flex flex-row no longer aborts layout with "RenderBox was not laid out". A Row hands non-flex children an unbounded main-axis constraint, so a w-full child's SizedBox(width: infinity) could not resolve. Wind now treats a bare w-full Row child as flex-1: the Row wraps it in Expanded (and defaults to MainAxisSize.max), giving the child a bounded width share inside which its infinite-width box resolves, so it fills the row. flex-1 remains the idiomatic choice; a prefixed md:w-full is intentionally not auto-expanded (use md:flex-1). Nested (non-direct) w-full children are unaffected. (lib/src/widgets/w_div.dart) (#122)

  • WSelect: the dropdown no longer dismisses itself on the same click that opens it on web (verified with real browser mouse events via CDP). Two independent self-close paths fired on the opening click: (1) the overlay's TapRegion.onTapOutside received the opening tap's own pointer-up because OverlayPortal mounts synchronously on the frame it opens, and (2) _onFocusChange closed the menu when the trigger lost focus, which web does transiently (~150ms) right after the opening click. Fixes: the overlay mount is now deferred one frame (addPostFrameCallback -> OverlayPortal.show()) so the opening pointer-up is fully dispatched before the overlay's TapRegion exists; and the fragile focus-loss auto-close was removed (the tap-only trigger cannot be opened by keyboard, so it added no real dismissal path while firing spuriously on web). Dismissal is now driven solely by an outside tap (onTapOutside) and option selection; the trigger and open menu still share a TapRegion group id so a trigger re-tap toggles closed instead of self-closing. Custom triggerBuilder / multiTriggerBuilder triggers are wrapped in that same shared group too, so a custom trigger no longer reads as an outside tap and self-closes the menu. (lib/src/widgets/w_select.dart)

Quality

... (truncated)

Changelog

Sourced from fluttersdk_wind's changelog.

[1.2.1] - 2026-07-21

Fixed

  • Unknown theme-spacing tokens (p-primary, m-foo, top-abc, gap-x-blue, ...) now silently drop instead of throwing ArgumentError: Invalid spacing multiplier: <token> inside build(), matching the "unknown className is dropped with a debug warning" contract other parsers already follow. Adds WindThemeData.tryGetSpacing(String); the padding, margin, position, and flex-gap parsers now use it (sizing already pre-validated with double.tryParse). getSpacing is unchanged for backward compatibility. (lib/src/theme/wind_theme_data.dart, lib/src/parser/parsers/padding_parser.dart, lib/src/parser/parsers/margin_parser.dart, lib/src/parser/parsers/position_parser.dart, lib/src/parser/parsers/flexbox_grid_parser.dart)
  • WAnchor now hit-tests its whole bounds via HitTestBehavior.translucent. The inner GestureDetector used the default HitTestBehavior.deferToChild, so it only fired when a painted child sat under the exact tap point. An anchor wrapping transparent content (a settings row, a checkbox row, a link with padding) ignored taps that landed on its empty regions, including the element centre that automated drivers and centred pointer events target. It now behaves like WInput/WPopover, which already use whole-box hit-testing, so the full anchor rectangle is tappable. (lib/src/widgets/w_anchor.dart; covered by test/widgets/w_anchor_test.dart)
  • WPopover no longer flickers open-then-closed on the first trigger tap on web, and its menu items now respond on the first open. A leftover focus-loss auto-close (_onFocusChange) dismissed the popover roughly 150ms after the opening click, when web transiently blurs the trigger, so it closed on the same gesture that opened it (and unmounted the overlay before a menu item's tap could resolve). The auto-close is removed; dismissal is now driven solely by an outside tap and programmatic close, matching the same fix already applied to WSelect. (lib/src/widgets/w_popover.dart)

[1.2.0] - 2026-07-08

Changed

  • Wind's internal flex layout is now fully intrinsic-safe: the column cross-axis stretch and the basis-* resolution no longer use a LayoutBuilder. Column stretch is a real render object (WindCrossStretch) and fractional basis-* resolves against the flex's own extent via WindMainExtentProvider/WindFractionBasis. A flex flex-col (with or without basis-*) now renders inside an items-stretch grid cell, under a Flutter IntrinsicHeight/IntrinsicWidth, or in a Table cell without the LayoutBuilder does not support returning intrinsic dimensions assert (the web _owner != null cascade that produced). (lib/src/widgets/w_div.dart, lib/src/widgets/wind_equal_height_row.dart) (WIND-4)
  • Interactive widgets (WSelect, WCheckbox, WRadio, WDatePicker) now route their selection, checkmark, and accent colors through the theme primary token instead of hardcoded blue-* classes and Colors.blue shades, so a consumer's brand color drives them. The shipped default look is unchanged (primary defaults to the Tailwind blue swatch). WindThemeData.toThemeData() keeps its indigo Material ColorScheme baseline unless a custom primary is registered, so the default Material appearance is unchanged too. (lib/src/widgets/w_select.dart, lib/src/widgets/w_checkbox.dart, lib/src/widgets/w_radio.dart, lib/src/widgets/w_date_picker.dart, lib/src/theme/wind_theme_data.dart) (WIND-3)
  • Documented and test-proved the WindRecipe/WindSlotRecipe caller-className merge contract: the recipe only appends the caller's className last (already the behavior since introduction); the conflict with a base token is resolved one layer down, at parse time, by WindParser's per-family last-wins. No twMerge/cn port was added or is planned. (test/recipe/wind_recipe_test.dart, test/parser/parsers/sizing_parser_test.dart, doc/styling/wind-recipe.md, skills/wind-ui/SKILL.md)
  • skills/wind-ui/references/tailwind-divergence.md, skills/wind-ui/SKILL.md, and doc/layout/display.md reconciled to reflect the flex-wrap alias (no longer a listed unsupported token) and the unknown-token debug hint (no longer purely silent). Example pages under example/lib/pages/ switched from flex-wrap to the canonical wrap token. (WIND-5)

Added

  • Min-width-stretch horizontal scroll primitive ("fill on desktop, scroll on narrow", the shadcn Table pattern), composed from existing tokens with no new className: overflow-x-auto on a wrapper with w-full (optionally min-w-[Npx]) on the inner content. w-full inside a horizontal scroll is now sized to max(viewport, min-w-*) via the threaded viewport width instead of asserting on the scroll's unbounded width, so the content fills the viewport when wide and honors its min width (scrolling) when narrow. (lib/src/widgets/wind_min_width_scroll.dart, lib/src/state/wind_min_width_scroll_scope.dart, lib/src/widgets/w_div.dart, example/lib/pages/layout/responsive_table.dart) (WIND-4)
  • Explicit flex flex-col items-stretch now equalizes child widths (every eligible child fills the column), closing the asymmetry with grid ... items-stretch. Like the smart-stretch default it is intrinsic-safe and unbounded-safe (no LayoutBuilder, no infinite-width SizedBox), so it also works in a bare Row slot or under an intrinsic-measuring ancestor. (lib/src/widgets/w_div.dart, lib/src/widgets/wind_equal_height_row.dart) (WIND-4)
  • Actionable dev-time assert for h-full inside a vertical scroll: a child that resolves h-full under an overflow-y-auto/overflow-y-scroll parent (an unbounded height) now fails fast with a message pointing at the fix (flex-1 inside a flex flex-col), instead of a cryptic Flutter unbounded-height error. The scrollable parent threads the signal down via WindMinWidthScrollScope; the assert is stripped in release. (lib/src/widgets/w_div.dart, lib/src/state/wind_min_width_scroll_scope.dart) (WIND-4)
  • Seeded default primary color token: Wind's default theme now includes a primary MaterialColor (aliased 1:1 to the Tailwind blue swatch), so bg-primary / text-primary / border-primary resolve out of the box and become brand-overridable via WindThemeData.colors: {'primary': ...}. Previously primary was consulted only by toThemeData() and was a silent no-op in className tokens. (lib/src/theme/defaults/colors.dart, lib/src/theme/wind_theme_data.dart) (WIND-3)
  • flex-wrap -> wrap alias: FlexboxGridParser now maps the Tailwind spelling flex-wrap directly to WindDisplayType.wrap (canParse already accepted flex-*; only the parse() handler was missing). wrap remains the canonical, unaliased token; flex-wrap prints a one-time kDebugMode hint suggesting it. (lib/src/parser/parsers/flexbox_grid_parser.dart) (WIND-5)
  • Unknown-className debug warning: WindParser.findAndGroupClasses now emits a one-time kDebugMode debugPrint naming any className that no parser recognizes, deduped per unique token per session (mirrors the existing _warnedAliases shadow/cycle dedup). The token is still dropped from output; release builds print nothing. Valid Wind tokens handled outside the parser map are exempt so the warning aims only at genuine typos: the widget-consumed object-* fit family (read by WImage), the inline-flex/inline-block/inline display keywords (emitted by WBadge, inert in Flutter), and deliberately inert compat tokens that Wind's own widget docstrings / the consumer contract emit (transition/transition-colors/etc., antialiased, sr-only, the *-nums font-variant family incl. tabular-nums). (lib/src/parser/wind_parser.dart) (WIND-5)
  • cursor-* utilities: a new CursorParser maps Tailwind cursor names (cursor-pointer, cursor-not-allowed, cursor-text, cursor-grab/cursor-grabbing, cursor-zoom-in/cursor-zoom-out, the full resize set, etc.) to the matching SystemMouseCursors. WDiv applies the resolved cursor through a MouseRegion, so a plain container can feel clickable on web/desktop without WAnchor or a manual MouseRegion; on a hover:/focus:/active: WDiv the cursor MouseRegion sits below the auto-wrapped WAnchor and wins. Inert on touch platforms; last token wins; unknown names no-op. (lib/src/parser/parsers/cursor_parser.dart, lib/src/parser/wind_style.dart, lib/src/widgets/w_div.dart) (#125)
  • size-* sizing utility (Tailwind v3.4+ shorthand): size-2, size-full, size-1/2, size-[20px], size-[50%], size-screen set BOTH width and height in one token. Fixes childless WDiv sizing: a WDiv(className: 'size-2 rounded-full bg-...') status dot now renders its box instead of collapsing (the previous gap was that size-* was unrecognized, not that w-*/h-* were ignored, which already worked childless). A later w-*/h-* overrides the matching axis. (lib/src/parser/parsers/sizing_parser.dart) (#123)
  • grid equal-height rows via items-stretch. By default a Wind grid renders as a Wrap and sizes each cell to its own content, leaving a row ragged when one card is taller. Adding items-stretch (CSS Grid's default align-items: stretch) now builds the grid as a column of IntrinsicHeight rows so every cell in a row matches the tallest, and cells divide the row width evenly. Cells should size from their own content; h-full on a stretched cell is unsupported (it inserts a LayoutBuilder that asserts under IntrinsicHeight, see the intrinsic-sizing limitation docs). (lib/src/widgets/w_div.dart) (#126)
  • WindRecipe and WindSlotRecipe (+ WindCompoundVariant, WindSlotCompoundVariant): a tv() (tailwind-variants) equivalent. WindRecipe resolves a single className from base + variant axes + compoundVariants + a caller className, in strict emission order (base ++ variant ++ compound ++ caller), with no dedupe/sort/twMerge. WindSlotRecipe extends the same model to multi-slot components and returns a Map<String, String> (slot -> className). (lib/src/recipe/wind_recipe.dart) (#120)
  • WBadge: inline status/label pill. Composes a rounded-full WDiv around a WText(text-xs); all visual tone is className-driven (bg-*, text-*, dark: pairs). (lib/src/widgets/w_badge.dart) (#120)
  • WCard: surface container with optional header and footer slots. Delegates to WDiv (flex-col); all styling is className-driven. (lib/src/widgets/w_card.dart) (#120)
  • WSwitch: controlled toggle switch. Pushes the checked: state prefix when value is true. The thumb is a flex child of the track, so the caller positions it with justify-start -> checked:justify-end on the track className (the track stays a flex Row; WSwitch does not inject relative, which would force a single-child Stack and defeat justify-*). thumbClassName supplies thumb shape/color only; translate-x-* is intentionally unsupported (Wind has no transform parser). Wraps WAnchor for hover/focus/disabled state propagation. (lib/src/widgets/w_switch.dart) (#120)
  • WRadio<T>: controlled radio button. Drives the selected: state prefix when value == groupValue. Group behavior (mutual exclusivity) is the caller's responsibility. (lib/src/widgets/w_radio.dart) (#120)
  • WTabs: controlled tabs widget. The selected: state prefix activates on the active tab; listClassName, tabClassName, selectedTabClassName, and panelClassName cover every structural region. panelBuilder receives the selected index each rebuild. The tab list defaults to full container width (fullWidthList: true) so a border-b underline spans the container rather than only the tabs; set fullWidthList: false for a content-width / pill tab strip. (#128) (lib/src/widgets/w_tabs.dart)

Fixed

  • WPopover overlay no longer overflows the right edge of the viewport when autoFlip is on. A wide panel next to a near-centered trigger on a narrow screen flipped to the opposite side but still spilled off-screen; a computeHorizontalClamp helper now folds a corrective dx into the follower offset so the panel is pulled fully inside the viewport (seated 8px from the edge, or flush when it is too wide to honor both margins). The clamp engages only on genuine off-screen overflow, so an edge-anchored popover already fully visible is left untouched. (lib/src/widgets/w_popover.dart)

  • grid ... items-stretch no longer emits a residual RenderFlex overflowed by ~2px on the bottom when it stretches an unequal cell (follow-up to #139). WindEqualHeightRow previously re-laid each cell to a TIGHT height equal to the loose-measured row max; a cell whose flex flex-col content needs a hair more under the tight re-lay (sub-pixel text/flex rounding on real rendering, e.g. CanvasKit) overflowed by a couple of pixels. It now stretches with a MIN height instead (never a tight squeeze), so a cell is never forced below its own content and the row takes the tallest resulting height, overflow-free by construction. (lib/src/widgets/wind_equal_height_row.dart) (#141)

  • grid ... items-stretch no longer asserts RenderBox was not laid out (rooted at RenderIntrinsicHeight / LayoutBuilder does not support returning intrinsic dimensions) when it stretches an unequal flex flex-col cell. The equal-height mechanism from #126 used IntrinsicHeight, which queries child intrinsics; a flex flex-col cell (or one using h-full / basis-*) carries a LayoutBuilder that cannot answer intrinsic queries, so stretching a shorter cell crashed the exact case the feature exists for. Replaced it with WindEqualHeightRow, a RenderObject that measures each cell with a real loose-height layout and re-lays it tight to the row max, so LayoutBuilder-bearing cells stretch correctly. As a bonus, h-full on a stretched cell now resolves too. (lib/src/widgets/wind_equal_height_row.dart, lib/src/widgets/w_div.dart) (#139)

  • Alias expansion now resolves state/breakpoint-prefixed alias tokens instead of silently dropping them. A prefixed token (hover:bg-surface-container, md:row, dark:hover:row) had its whole form rejected before the alias lookup, so prefix: + a known alias key was a silent no-op while plain bg-surface-container worked. The expander now peels the prefix chain off, matches the bare body against the (still bare-only) alias map, and re-applies the prefix to every produced token (md:row -> md:flex md:flex-row; hover:bg-surface carries hover: onto each token including the value's own dark: peer, yielding hover:dark:..., which the parser resolves regardless of prefix order). Cycle/depth/output guards are unchanged and now key on the bare body. (lib/src/parser/alias_expander.dart) (#124)

  • WPopover overlay no longer stretches unbounded. It applied only a minWidth (trigger width) with no upper bound, so a menu without an explicit width could fill the available space and overflow a narrow content column (the asymmetry with WSelect, which pins a width). New width and maxWidth props: width (or a w-* token) pins a fixed overlay width like WSelect's menuWidth; maxWidth (or a max-w-* token) bounds it, defaulting to the screen width so the overlay never overflows the viewport. (lib/src/widgets/w_popover.dart) (#127)

  • w-full on a direct child of a flex flex-row no longer aborts layout with "RenderBox was not laid out". A Row hands non-flex children an unbounded main-axis constraint, so a w-full child's SizedBox(width: infinity) could not resolve. Wind now treats a bare w-full Row child as flex-1: the Row wraps it in Expanded (and defaults to MainAxisSize.max), giving the child a bounded width share inside which its infinite-width box resolves, so it fills the row. flex-1 remains the idiomatic choice; a prefixed md:w-full is intentionally not auto-expanded (use md:flex-1). Nested (non-direct) w-full children are unaffected. (lib/src/widgets/w_div.dart) (#122)

  • WSelect: the dropdown no longer dismisses itself on the same click that opens it on web (verified with real browser mouse events via CDP). Two independent self-close paths fired on the opening click: (1) the overlay's TapRegion.onTapOutside received the opening tap's own pointer-up because OverlayPortal mounts synchronously on the frame it opens, and (2) _onFocusChange closed the menu when the trigger lost focus, which web does transiently (~150ms) right after the opening click. Fixes: the overlay mount is now deferred one frame (addPostFrameCallback -> OverlayPortal.show()) so the opening pointer-up is fully dispatched before the overlay's TapRegion exists; and the fragile focus-loss auto-close was removed (the tap-only trigger cannot be opened by keyboard, so it added no real dismissal path while firing spuriously on web). Dismissal is now driven solely by an outside tap (onTapOutside) and option selection; the trigger and open menu still share a TapRegion group id so a trigger re-tap toggles closed instead of self-closing. Custom triggerBuilder / multiTriggerBuilder triggers are wrapped in that same shared group too, so a custom trigger no longer reads as an outside tap and self-closes the menu. (lib/src/widgets/w_select.dart)

Quality

... (truncated)

Commits
  • 2e598a0 release: 1.2.1 (#158)
  • a4e9e14 fix(theme): tolerate unknown spacing tokens instead of throwing (#156)
  • 3c64507 fix(popover): remove the focus-loss auto-close that flickered the first tap a...
  • aa07198 ci(deps): bump github/codeql-action/upload-sarif from 4.36.3 to 4.37.1 (#154)
  • 358fdcd ci(deps): bump zizmorcore/zizmor-action from 0.5.7 to 0.6.0 (#153)
  • 023ae8c fix(anchor): make the whole WAnchor bounds tappable via translucent hit-test ...
  • 4f63db6 release: 1.2.0 (#150)
  • 4311759 feat(layout): intrinsic-safe flex stretch and min-width-stretch scroll (WIND-...
  • 11db93d feat(theme): route widget selection colors through a seeded primary token (WI...
  • 092cb10 feat(parser): alias flex-wrap to wrap and warn on unknown classNames (WIND-5)...
  • Additional commits viewable in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore <dependency name> major version will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
  • @dependabot ignore <dependency name> minor version will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
  • @dependabot ignore <dependency name> will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
  • @dependabot unignore <dependency name> will remove all of the ignore conditions of the specified dependency
  • @dependabot unignore <dependency name> <ignore condition> will remove the ignore condition of the specified dependency and ignore conditions

Bumps the example-minor-and-patch group in /example with 1 update: [fluttersdk_wind](https://github.com/fluttersdk/wind).


Updates `fluttersdk_wind` from 1.1.2 to 1.2.1
- [Release notes](https://github.com/fluttersdk/wind/releases)
- [Changelog](https://github.com/fluttersdk/wind/blob/master/CHANGELOG.md)
- [Commits](1.1.2...1.2.1)

---
updated-dependencies:
- dependency-name: fluttersdk_wind
  dependency-version: 1.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: example-minor-and-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file example Touches example/ showcase app labels Aug 1, 2026
@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file example Touches example/ showcase app

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant