# State-Based Styling Apply styles that react to a widget's state, such as `hover` or `disabled`, using prefixed utility classes. Wind's `classNameParser` function resolves these prefixes against the list of currently active states you pass in, so state-aware styling stays declarative. - [Basic Usage](#basic-usage) - [How It Works](#how-it-works) - [Building a Stateful Widget](#building-a-stateful-widget) - [Best Practices](#best-practices) - [Related Documentation](#related-documentation) ```dart import 'package:flutter/material.dart'; import 'package:fluttersdk_wind/fluttersdk_wind.dart'; // Inside a widget that tracks its own active states: final List states = []; if (isHovered) states.add('hover'); if (isDisabled) states.add('disabled'); final String parsed = classNameParser( 'bg-primary-500 p-4 rounded-lg hover:bg-white disabled:bg-gray-500', states: states, ); WFlexContainer( className: parsed, children: [ WText('Submit', className: 'text-white'), ], ); ``` ## Basic Usage Prefix a utility with a state name and pass the active states to `classNameParser`. When a state is active, its prefix is stripped and the underlying utility applies; when it is not active, the prefixed token is removed: ```dart final String parsed = classNameParser( 'bg-primary-500 hover:bg-white disabled:bg-gray-500', states: ['hover'], ); // hover active -> bg-white wins; disabled token dropped. ``` State names are not a fixed set. Any token you list in `states` matches the corresponding prefix, so `hover`, `disabled`, `pressed`, `selected`, or your own custom name all work the same way. ## How It Works `classNameParser(className, {states})` walks the `className` and, for each active state, strips the matching `state:` prefix so the utility behind it is applied. Prefixed tokens whose state is not active are dropped before the parsers run. This is why state-based styling needs a stateful host widget: your widget decides which states are active (a hover from an `InkWell`, a `disabled` flag, a selection), assembles them into a list, and feeds that list to `classNameParser`. Wind does not track widget state for you; it resolves the class names against the states you report. ## Building a Stateful Widget Here is a reusable button that tracks hover and disabled states and styles itself through `classNameParser`: ```dart import 'package:flutter/material.dart'; import 'package:fluttersdk_wind/fluttersdk_wind.dart'; class AppButton extends StatefulWidget { final String? className; final String? textClassName; final String? text; final bool disabled; const AppButton({ super.key, this.className, this.textClassName, this.text, this.disabled = false, }); @override State createState() => _AppButtonState(); } class _AppButtonState extends State { bool isHovered = false; @override Widget build(BuildContext context) { final List states = []; if (widget.disabled) states.add('disabled'); if (isHovered) states.add('hover'); final String parsedClassName = classNameParser(widget.className, states: states); final String parsedTextClassName = classNameParser(widget.textClassName, states: states); return InkWell( onHover: (hovered) { if (!widget.disabled) { setState(() => isHovered = hovered); } }, onTap: widget.disabled ? null : () {}, child: WFlexContainer( className: parsedClassName, children: [ WText(widget.text ?? 'Button', className: parsedTextClassName), ], ), ); } } ``` Used like this, the prefixed utilities resolve as the button's state changes: ```dart AppButton( className: 'bg-primary-500 p-4 rounded-lg hover:bg-white', textClassName: 'text-white hover:text-primary-600', text: 'Submit', ); ``` ## Best Practices - Drive states from your widget's own logic (hover callbacks, flags) and pass them into `classNameParser`; Wind does not manage state for you. - Parse every class string that should react to state, including separate text class names, with the same `states` list. - Keep base styles unprefixed and add only the state-specific overrides behind a prefix. - Reuse one stateful wrapper (like `AppButton`) across your app instead of wiring state tracking into every call site. ## Related Documentation - [Dark Mode](dark-mode.md) — the `dark:` prefix, resolved separately from interaction states. - [Responsive Design](responsive-design.md) — breakpoint prefixes that compose with utilities. - [Background Color](../backgrounds/background-color.md) — the `bg-*` utilities commonly toggled per state. - [Text Color](../typography/text-color.md) — the `text-*` utilities for state-driven text styling.