@@ -35,7 +35,7 @@ class LoadSwitch extends StatefulWidget {
3535 assert (width >= height, "Width can't be less than the height." ),
3636 assert (
3737 thumbSizeRatio > 0 && thumbSizeRatio <= 1 ,
38- 'Thumb size ratio must be between 0 and 1.' ,
38+ 'Thumb size ratio must be greater than 0 and at most 1.' ,
3939 );
4040
4141 const LoadSwitch .controlled ({
@@ -64,7 +64,7 @@ class LoadSwitch extends StatefulWidget {
6464 assert (width >= height, "Width can't be less than the height." ),
6565 assert (
6666 thumbSizeRatio > 0 && thumbSizeRatio <= 1 ,
67- 'Thumb size ratio must be between 0 and 1.' ,
67+ 'Thumb size ratio must be greater than 0 and at most 1.' ,
6868 );
6969
7070 final _LoadSwitchMode _mode;
@@ -211,7 +211,17 @@ class _LoadSwitchState extends State<LoadSwitch> {
211211
212212 Future <void > _handleToggle () async {
213213 final controller = _controller;
214- if (_isLoading (controller) || ! controller.isActive) {
214+
215+ // Fire onTap whenever the user physically taps the switch, even if it is
216+ // inactive. This allows callers to show feedback (e.g. a tooltip or snackbar)
217+ // explaining why the switch is disabled. Loading is a transient lock — the
218+ // spinner makes it visually obvious, so onTap is suppressed there.
219+ if (! controller.isActive) {
220+ widget.onTap? .call (controller.value);
221+ return ;
222+ }
223+
224+ if (_isLoading (controller)) {
215225 return ;
216226 }
217227
@@ -241,8 +251,11 @@ class _LoadSwitchState extends State<LoadSwitch> {
241251 if (! _isCurrentOperation (controller, operationId)) {
242252 return ;
243253 }
254+ final previousValue = controller.value;
244255 controller.value = nextValue;
245- widget.onChanged? .call (nextValue);
256+ if (controller.value != previousValue) {
257+ widget.onChanged? .call (nextValue);
258+ }
246259 } catch (error, stackTrace) {
247260 if (_isCurrentOperation (controller, operationId)) {
248261 widget.onError? .call (error, stackTrace);
@@ -317,7 +330,10 @@ class _LoadSwitchState extends State<LoadSwitch> {
317330 child: GestureDetector (
318331 excludeFromSemantics: true ,
319332 behavior: HitTestBehavior .opaque,
320- onTap: isEnabled ? _handleToggle : null ,
333+ // Always route taps to _handleToggle so onTap can fire for
334+ // inactive switches (e.g. to show a tooltip). Loading taps are
335+ // still suppressed inside _handleToggle.
336+ onTap: _isLoading (_controller) ? null : _handleToggle,
321337 child: AnimatedContainer (
322338 width: loading ? collapsedWidth : expandedWidth,
323339 height: switchSize,
0 commit comments