# State Management & Interactive Styles - [Introduction](#introduction) - [How It Works](#how-it-works) - [Built-in State Prefixes](#built-in-state-prefixes) - [Quick Reference](#quick-reference) - [Interactive Widgets](#interactive-widgets) - [WAnchor: The Core Wrapper](#wanchor-the-core-wrapper) - [WButton: The High-Level Action](#wbutton-the-high-level-action) - [WInput: Focus States](#winput-focus-states) - [Custom States](#custom-states) - [State Propagation](#state-propagation) - [Related Documentation](#related-documentation) ## Introduction Interactive styles allow you to define how your UI reacts to user input without managing complex state variables. Instead of nesting multiple `MouseRegion`, `GestureDetector`, and `Focus` widgets, Wind provides a declarative way to handle states directly in your `className` string. By using prefixes like `hover:`, `focus:`, and `active:`, you can build responsive, tactile interfaces that feel native to both web and mobile platforms. ## How It Works Wind's parsing engine identifies state prefixes in your class string and stores them in a separate style map. When the widget's internal state changes (e.g., a user hovers over it), the widget rebuilds and applies the corresponding styles. Consider this basic button example: ```dart WButton( onTap: () => print('Action triggered'), className: 'bg-blue-500 hover:bg-blue-600 active:bg-blue-700 p-4 rounded-lg duration-200', child: WText('Save Changes', className: 'text-white'), ) ``` In this case, the background color transitions smoothly between shades based on the interaction state. > [!NOTE] > For state prefixes to work, the widget must be wrapped in an interactive component like `WAnchor`, `WButton`, or `WInput`. A standard `WDiv` is passive and will not trigger interaction states on its own. ## Built-in State Prefixes Wind supports several interactive states out of the box. These are automatically managed when using interactive widgets: - **hover**: Triggered when a pointer enters the widget bounds. - **focus**: Triggered when the widget receives keyboard or input focus. - **active**: Triggered while the widget is being pressed or tapped. - **disabled**: Triggered when the widget's interactivity is disabled (e.g., `onTap` is null). ## Quick Reference | Prefix | Trigger | Typical Use Case | |:-------|:--------|:-----------------| | `hover:` | Pointer entry | Changing background or elevation on desktop. | | `focus:` | Keyboard focus | Showing a ring or border on input fields. | | `active:` | Pointer press | Scaling down or darkening a button on tap. | | `disabled:` | Interactivity off | Reducing opacity or greying out actions. | ## Interactive Widgets Wind provides specific widgets designed to manage and propagate these states. ### WAnchor: The Core Wrapper `WAnchor` is the low-level engine behind Wind's interactivity. It provides no visual styling itself; its sole purpose is to detect gestures and share that state with its child tree. This is useful for making entire cards or complex layouts interactive. ```dart WAnchor( onTap: () {}, child: WDiv( className: 'bg-white hover:bg-slate-50 border p-6 rounded-xl duration-300', children: [ WText('Interactive Card', className: 'group-hover:text-blue-600'), ], ), ) ``` ### WButton: The High-Level Action While `WAnchor` is for generic wrappers, `WButton` is optimized for actions. It includes built-in support for loading states, padding defaults, and button-specific accessibility. ```dart WButton( onTap: _submit, className: 'bg-indigo-600 hover:bg-indigo-700 disabled:opacity-50 text-white px-8 py-3 rounded', child: Text('Submit'), ) ``` ### WInput: Focus States `WInput` manages its own focus state. It is common to use `focus:` prefixes here to highlight the active field or show a focus ring. ```dart WInput( placeholder: 'Search...', className: 'border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 p-3 rounded-lg', ) ``` ## Custom States Sometimes you need to style a widget based on a state that isn't built-in, such as whether an item is "selected" or "loading". You can pass custom strings to the `states` parameter. ```dart WDiv( className: 'border-2 border-gray-200 selected:border-blue-500 bg-white selected:bg-blue-50 p-4', states: isSelected ? {'selected'} : {}, child: WText('Selection Item'), ) ``` If the `states` set contains "selected", any class prefixed with `selected:` will be applied. ## State Propagation Interactivity in Wind is shared through `WindContext`. When an ancestor widget like `WAnchor` changes state, it propagates that state to all children in its subtree. Let's look at a nested example: ```dart WAnchor( onTap: () {}, child: WDiv( className: 'p-4 bg-white hover:bg-gray-50', children: [ WText('Title', className: 'font-bold hover:text-blue-600'), WText('Description', className: 'text-gray-500'), ], ), ) ``` Even if the mouse is only hovering over the padding of the `WDiv`, the `WText` widget will receive the "hover" state and update its color accordingly. ## Related Documentation - [Responsive Design](./responsive-design.md) - Combining states with breakpoints. - [Dark Mode](./dark-mode.md) - Styling for night owls. - [WAnchor Widget](../widgets/w-anchor.md) - Technical reference for the anchor engine.