# WKeyboardActions A wrapper that renders a Done button and field-navigation toolbar above the keyboard for any group of input fields, with optional platform targeting and custom close widget. ## Table of Contents - [Basic Usage](#basic-usage) - [Constructor](#constructor) - [Props](#props) - [Platform Targeting](#platform-targeting) - [Navigation Between Fields](#navigation-between-fields) - [Toolbar Styling](#toolbar-styling) - [Custom Close Button](#custom-close-button) - [Styling Examples](#styling-examples) - [Related Documentation](#related-documentation) ```dart WKeyboardActions( focusNodes: [_nameFocus, _amountFocus], toolbarClassName: 'bg-gray-100 dark:bg-gray-800', child: Column( children: [ WInput(focusNode: _nameFocus, placeholder: 'Jane Doe'), WInput( focusNode: _amountFocus, placeholder: '0.00', type: InputType.number, ), ], ), ) ``` ## Basic Usage Create a `FocusNode` for each input field and pass them all in the `focusNodes` list. `WKeyboardActions` attaches listeners to every node and shows the toolbar as long as any one of them is focused. ```dart class _MyFormState extends State { final _nameFocus = FocusNode(); final _amountFocus = FocusNode(); @override void dispose() { _nameFocus.dispose(); _amountFocus.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return WKeyboardActions( focusNodes: [_nameFocus, _amountFocus], child: Column( children: [ WInput(focusNode: _nameFocus, placeholder: 'Full Name'), WInput( focusNode: _amountFocus, placeholder: '0.00', type: InputType.number, ), ], ), ); } } ``` ## Constructor ```dart const WKeyboardActions({ Key? key, required Widget child, required List focusNodes, String platform = 'all', bool nextFocus = true, String? toolbarClassName, Widget Function(FocusNode)? closeWidgetBuilder, }) ``` ## Props | Prop | Type | Default | Description | |:-----|:-----|:--------|:------------| | `child` | `Widget` | **Required** | The form or column of inputs the toolbar is attached to. | | `focusNodes` | `List` | **Required** | FocusNodes for the inputs that need keyboard actions. Order determines navigation order. | | `platform` | `String` | `'all'` | Platform gate: `'all'`, `'ios'`, or `'android'`. | | `nextFocus` | `bool` | `true` | When true, Previous/Next arrow buttons appear in the toolbar for field navigation. | | `toolbarClassName` | `String?` | `null` | Wind utility classes applied to the toolbar background (typically `bg-*` classes). | | `closeWidgetBuilder` | `Widget Function(FocusNode)?` | `null` | Builder that replaces the default "Done" button. Receives the currently-focused FocusNode. | ## Platform Targeting The `platform` prop gates the toolbar to a specific OS. The most common value is `'ios'`, because iOS numeric keyboards have no built-in Done button. | Value | Toolbar visible on | |:------|:-------------------| | `'all'` | iOS and Android (default) | | `'ios'` | iOS only | | `'android'` | Android only | ```dart WKeyboardActions( platform: 'ios', focusNodes: [_amountFocus], child: WInput( focusNode: _amountFocus, placeholder: '0.00', type: InputType.number, ), ) ``` ## Navigation Between Fields When `nextFocus: true` (the default), the toolbar shows Previous and Next arrow buttons. They move focus to the previous or next node in the `focusNodes` list, in the order they were provided. The Previous button is disabled at the first field; the Next button is disabled at the last. Set `nextFocus: false` to show only the Done button, which is useful for single-field forms. ```dart WKeyboardActions( focusNodes: [_nameFocus, _emailFocus, _amountFocus], nextFocus: true, child: Column( children: [ WInput(focusNode: _nameFocus, placeholder: 'Jane Doe'), WInput(focusNode: _emailFocus, placeholder: 'jane@example.com'), WInput(focusNode: _amountFocus, placeholder: '0.00'), ], ), ) ``` ## Toolbar Styling Pass Wind `bg-*` utility classes via `toolbarClassName` to set the toolbar background. The `dark:` pair is required. ```dart WKeyboardActions( toolbarClassName: 'bg-gray-100 dark:bg-gray-800', focusNodes: [_focusNode], child: myInputField, ) ``` When `toolbarClassName` is null, the toolbar uses `Theme.of(context).colorScheme.surfaceContainerHighest`. ## Custom Close Button Supply `closeWidgetBuilder` to replace the default "Done" label with any widget. The builder receives the currently-focused `FocusNode`, which you can call `unfocus()` on. ```dart WKeyboardActions( focusNodes: [_focusNode], closeWidgetBuilder: (node) => WButton( onTap: node.unfocus, className: 'bg-blue-600 text-white px-4 py-1.5 rounded-md text-sm font-medium', child: const WText('Save & Close', className: 'text-white text-sm font-medium'), ), child: myInputField, ) ``` ## Styling Examples ### Minimal (single field, iOS only) ```dart WKeyboardActions( platform: 'ios', nextFocus: false, focusNodes: [_amountFocus], toolbarClassName: 'bg-white dark:bg-gray-900', child: WInput( focusNode: _amountFocus, placeholder: '0.00', type: InputType.number, ), ) ``` ### Multi-field form with custom toolbar color ```dart WKeyboardActions( focusNodes: [_nameFocus, _emailFocus, _amountFocus], toolbarClassName: 'bg-blue-50 dark:bg-blue-950', child: Column( children: [ WInput(focusNode: _nameFocus, placeholder: 'Jane Doe'), WInput(focusNode: _emailFocus, placeholder: 'jane@example.com'), WInput(focusNode: _amountFocus, placeholder: '0.00'), ], ), ) ``` ### Custom close widget ```dart WKeyboardActions( focusNodes: [_focusNode], toolbarClassName: 'bg-emerald-50 dark:bg-emerald-900', closeWidgetBuilder: (node) => TextButton.icon( onPressed: node.unfocus, icon: const Icon(Icons.check_circle_outlined), label: const Text('Done'), ), child: myInputField, ) ``` ## Related Documentation - [WInput - The unstyled text input widget](./w-input.md) - [WFormInput - Form-bound WInput with validator](./w-form-input.md) - [WDiv - General-purpose container for laying out form fields](../widgets/w-div.md)