Skip to content

Commit 562aa5f

Browse files
committed
Enhance documentation for Naked UI components: add detailed descriptions, usage examples, and references for better clarity and usability; remove unused overlay content menu.
1 parent 03d1c36 commit 562aa5f

14 files changed

Lines changed: 360 additions & 171 deletions

lib/src/naked_accordion.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import 'package:flutter/widgets.dart';
99
/// - `min` prevents closing below a floor when toggling/closing individual items.
1010
/// - `max` caps the number of expanded items; when exceeded, the *oldest* is closed.
1111
/// - All operations are idempotent (no redundant notifications).
12+
///
13+
/// See also:
14+
/// - [NakedAccordion], the headless accordion that uses this controller.
15+
/// - [NakedAccordionItem], the item widget that toggles values via this controller.
1216
class NakedAccordionController<T> with ChangeNotifier {
1317
/// Minimum number of expanded items allowed when *closing* via user actions.
1418
final int min;
@@ -145,6 +149,11 @@ class NakedAccordionScope<T> extends InheritedWidget {
145149
///
146150
/// The [children] should be [NakedAccordionItem<T>] widgets.
147151
/// State is managed by [NakedAccordionController<T>].
152+
///
153+
/// See also:
154+
/// - [NakedAccordionController], which stores expanded values and enforces
155+
/// min/max constraints.
156+
/// - [NakedAccordionItem], which renders the trigger and panel.
148157
class NakedAccordion<T> extends StatefulWidget {
149158
const NakedAccordion({
150159
super.key,
@@ -213,6 +222,10 @@ typedef NakedAccordionTriggerBuilder =
213222
/// Headless: you provide the trigger visuals and the panel content.
214223
/// Keyboard: Enter/Space toggle the header (via ActivateIntent).
215224
/// Semantics: the header is exposed as a "button" with `expanded` state.
225+
///
226+
/// See also:
227+
/// - [NakedAccordion], the container that hosts items and provides traversal.
228+
/// - [NakedAccordionController], which stores and updates expanded values.
216229
class NakedAccordionItem<T> extends StatelessWidget {
217230
const NakedAccordionItem({
218231
super.key,
@@ -245,8 +258,11 @@ class NakedAccordionItem<T> extends StatelessWidget {
245258
final T value;
246259

247260
// Interaction hooks (headless state reporting).
261+
/// Notifies when header focus changes.
248262
final ValueChanged<bool>? onFocusChange;
263+
/// Notifies when header hover changes.
249264
final ValueChanged<bool>? onHoverChange;
265+
/// Notifies when header pressed (highlight) changes.
250266
final ValueChanged<bool>? onPressChange;
251267

252268
/// Accessibility label for the header.
@@ -258,7 +274,10 @@ class NakedAccordionItem<T> extends StatelessWidget {
258274
final bool enableFeedback;
259275

260276
/// Focus configuration for the header.
277+
///
278+
/// When [autofocus] is true, the header will request focus on build.
261279
final bool autofocus;
280+
/// External [FocusNode] to control header focus.
262281
final FocusNode? focusNode;
263282

264283
void _toggle(NakedAccordionController<T> controller) =>

lib/src/naked_button.dart

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
import 'dart:async';
22

3-
import 'package:flutter/material.dart';
3+
import 'package:flutter/widgets.dart';
44
import 'package:flutter/services.dart';
55

6-
import 'mixins/naked_mixins.dart'; // your WidgetStatesMixin, etc.
6+
import 'mixins/naked_mixins.dart'; // WidgetStatesMixin, FocusableMixin
77

8-
/// Provides button interaction behavior without visual styling.
8+
/// A headless, focusable button that exposes interaction states.
99
///
10-
/// Users control presentation and semantics through the child or builder parameter.
10+
/// - No visuals are provided; pass a [child] or a [builder] to render UI.
11+
/// - Keyboard: Enter/Space activate the button. Optional [focusOnPress].
12+
/// - Semantics: exposes a "button" role and supports [tooltip]/[semanticLabel].
13+
/// - States: when using [builder], you receive a `Set<WidgetState>` that
14+
/// reflects the current hovered/pressed/focused/disabled states.
15+
///
16+
/// See also:
17+
/// - [NakedMenuItem], which composes a menu item from [NakedButton].
18+
/// - [FocusableActionDetector], the underlying keyboard/hover integration.
19+
/// - [TextButton], [ElevatedButton], and [FilledButton] for Material-styled
20+
/// buttons when you don’t need a headless control.
1121
class NakedButton extends StatefulWidget {
1222
const NakedButton({
1323
super.key,
@@ -32,28 +42,60 @@ class NakedButton extends StatefulWidget {
3242
'Either child or builder must be provided',
3343
);
3444

45+
/// Visual contents of the button when not using [builder].
3546
final Widget? child;
47+
48+
/// Called when the button is activated (tap, Enter/Space).
3649
final VoidCallback? onPressed;
50+
51+
/// Called when the button is long-pressed.
3752
final VoidCallback? onLongPress;
53+
54+
/// Called when the button is double-tapped.
3855
final VoidCallback? onDoubleTap;
3956

57+
/// Notifies when focus changes. Receives `true` when focused.
4058
final ValueChanged<bool>? onFocusChange;
59+
60+
/// Notifies when hover changes. Receives `true` when hovered.
4161
final ValueChanged<bool>? onHoverChange;
62+
63+
/// Notifies when pressed (highlight) changes. Receives `true` when down.
4264
final ValueChanged<bool>? onPressChange;
4365

66+
/// Builder that receives the current interaction [WidgetState]s.
67+
///
68+
/// The signature is `(BuildContext, Set<WidgetState>, Widget? child)`.
69+
/// Use this to render custom visuals based on button state.
4470
final ValueWidgetBuilder<Set<WidgetState>>? builder;
4571

72+
/// Whether the button is enabled.
73+
///
74+
/// The button is effectively enabled only if [enabled] is true and at least
75+
/// one handler among [onPressed], [onLongPress], or [onDoubleTap] is set.
4676
final bool enabled;
77+
78+
/// Mouse cursor when the button is enabled.
4779
final MouseCursor mouseCursor;
80+
81+
/// Whether to provide platform haptic/aural feedback on activation.
4882
final bool enableFeedback;
4983

84+
/// Optional external [FocusNode] to control focus ownership.
5085
final FocusNode? focusNode;
86+
87+
/// Whether to autofocus this button on build.
5188
final bool autofocus;
5289

53-
/// When true, pressing requests focus in addition to activating.
90+
/// Whether pressing requests focus in addition to activating.
5491
final bool focusOnPress;
5592

93+
/// Optional tooltip exposed to assistive technologies.
94+
///
95+
/// Consider providing concise text; long labels are read verbosely.
5696
final String? tooltip;
97+
98+
/// Optional semantic label announced by screen readers.
5799
final String? semanticLabel;
58100

59101
// Consider button interactive if any handler is provided.

lib/src/naked_checkbox.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import 'package:flutter/material.dart';
1+
import 'package:flutter/widgets.dart';
22
import 'package:flutter/services.dart';
33

44
import 'mixins/naked_mixins.dart';
55

6-
/// Headless checkbox built with mixins for proper semantics and callbacks.
6+
/// A headless checkbox: no visuals, exposes states and proper semantics.
7+
///
8+
/// See also:
9+
/// - [Checkbox], the Material-styled checkbox for typical apps.
710
class NakedCheckbox extends StatefulWidget {
811
const NakedCheckbox({
912
super.key,
@@ -78,7 +81,10 @@ class NakedCheckbox extends StatefulWidget {
7881
/// Whether to autofocus when created.
7982
final bool autofocus;
8083

81-
/// Optional builder that receives the current states for visuals.
84+
/// Builder that receives the current interaction [WidgetState]s.
85+
///
86+
/// States include at least: disabled, focused, hovered, pressed, selected.
87+
/// The `selected` state reflects `value == true`.
8288
final ValueWidgetBuilder<Set<WidgetState>>? builder;
8389

8490
/// Semantic label for accessibility.

lib/src/naked_dialog.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import 'package:flutter/material.dart';
1+
import 'package:flutter/widgets.dart';
22

33
/// Provides dialog functionality without default styling.
44
///

lib/src/naked_menu.dart

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import 'package:flutter/material.dart';
1+
import 'package:flutter/widgets.dart';
22
import 'package:flutter/services.dart';
33

44
import 'naked_button.dart';
55
import 'utilities/utilities.dart';
66

7-
/// Provides dropdown menu behavior without visual styling.
7+
/// A headless dropdown menu without default styling.
88
///
99
/// Uses Flutter's RawMenuAnchor to render menu content in the app overlay,
1010
/// ensuring proper z-index and context inheritance.
@@ -51,6 +51,11 @@ import 'utilities/utilities.dart';
5151
///
5252
/// Menu items use [NakedMenuItem] and automatically close the menu when selected
5353
/// unless [NakedMenuItem.closeOnSelect] is set to false.
54+
///
55+
/// See also:
56+
/// - [NakedMenuAnchor], which handles overlay placement, focus, and keyboard
57+
/// traversal for this menu.
58+
/// - [NakedButton], often used to build the trigger and items.
5459
class NakedMenu extends StatelessWidget {
5560
/// Creates a naked menu.
5661
///
@@ -119,6 +124,10 @@ class NakedMenu extends StatelessWidget {
119124
///
120125
/// Provides interaction states and accessibility features.
121126
/// Handles keyboard navigation and screen reader support.
127+
///
128+
/// See also:
129+
/// - [NakedMenu], the container that provides the overlay and positioning.
130+
/// - [NakedButton], the headless activator used to implement this item.
122131
class NakedMenuItem extends StatelessWidget {
123132
/// Creates a naked menu item.
124133
///
@@ -183,7 +192,7 @@ class NakedMenuItem extends StatelessWidget {
183192
/// Whether to automatically focus when created.
184193
final bool autofocus;
185194

186-
/// Semantic label for accessibility.
195+
/// Semantic label for accessibility (forwarded as a tooltip on the trigger).
187196
final String? semanticLabel;
188197

189198
void _handlePress(MenuController? controller) {

lib/src/naked_radio.dart

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,31 @@ import 'package:flutter/material.dart';
22

33
import 'mixins/naked_mixins.dart';
44

5-
/// Radio button built with simplified architecture.
5+
/// A headless radio that participates in a [RadioGroup] without default visuals.
66
///
7-
/// Provides radio functionality while letting users control presentation
8-
/// and semantics through the child or builder parameter.
7+
/// - Must be placed under a [RadioGroup] (or provide a custom [groupRegistry]).
8+
/// - No visuals are provided; pass a [child] or [builder] to render UI.
9+
/// - States are exposed to [builder] as a `Set<WidgetState>` including
10+
/// at least hovered/pressed/focused/selected/disabled.
11+
/// - Keyboard: focus + Enter/Space select; semantics exposed as a radio.
12+
///
13+
/// Example:
14+
/// ```dart
15+
/// RadioGroup<int>(
16+
/// value: selected,
17+
/// onChanged: (v) => setState(() => selected = v),
18+
/// child: Row(children: [
19+
/// NakedRadio<int>(value: 1, child: const Text('One')),
20+
/// NakedRadio<int>(value: 2, child: const Text('Two')),
21+
/// ]),
22+
/// )
23+
/// ```
24+
///
25+
/// See also:
26+
/// - [RawRadio], the underlying primitive widget used to implement radio
27+
/// interaction and semantics.
28+
/// - [RadioGroup], which manages the selected value and provides the grouping
29+
/// context for radios.
930
class NakedRadio<T> extends StatefulWidget {
1031
const NakedRadio({
1132
super.key,
@@ -26,24 +47,49 @@ class NakedRadio<T> extends StatefulWidget {
2647
'Either child or builder must be provided',
2748
);
2849

50+
/// Value represented by this radio.
2951
final T value;
52+
53+
/// Visual contents when not using [builder].
3054
final Widget? child;
55+
56+
/// Whether this radio is enabled.
3157
final bool enabled;
58+
59+
/// Mouse cursor when enabled.
60+
///
61+
/// Defaults to [SystemMouseCursors.click] when interactive and
62+
/// [SystemMouseCursors.basic] when disabled.
3263
final MouseCursor? mouseCursor;
64+
65+
/// External [FocusNode] to control focus ownership.
3366
final FocusNode? focusNode;
67+
68+
/// Whether to autofocus when built.
3469
final bool autofocus;
70+
71+
/// Whether tapping the selected radio clears the selection (nullable group).
3572
final bool toggleable;
3673

3774
// State change callbacks
75+
/// Notifies when focus changes.
3876
final ValueChanged<bool>? onFocusChange;
77+
78+
/// Notifies when hover changes.
3979
final ValueChanged<bool>? onHoverChange;
4080

41-
/// Called when pressed state changes.
81+
/// Notifies when pressed (highlight) changes.
4282
final ValueChanged<bool>? onPressChange;
83+
84+
/// Builder that receives the current interaction [WidgetState]s.
85+
///
86+
/// Includes the `selected` state when this radio's [value] matches the
87+
/// group's selected value.
4388
final ValueWidgetBuilder<Set<WidgetState>>? builder;
4489

45-
/// Optional registry override for advanced usage and testing.
46-
/// When null, the nearest RadioGroup<T> ancestor is used.
90+
/// Registry override for advanced usage and testing.
91+
///
92+
/// When null, the nearest [RadioGroup] ancestor is used.
4793
final RadioGroupRegistry<T>? groupRegistry;
4894

4995
@override

0 commit comments

Comments
 (0)