# 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.