Skip to content

Commit

Permalink
fix: hover / focus states on radio
Browse files Browse the repository at this point in the history
  • Loading branch information
thelukewalton committed May 16, 2024
1 parent 81f122a commit 6d29ba3
Showing 1 changed file with 79 additions and 49 deletions.
128 changes: 79 additions & 49 deletions lib/src/components/radio/radio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import '../../../zeta_flutter.dart';

/// Zeta Radio Button
///
/// Radio Button can select one single option from a goup of different options.
/// Radio Button can select one single option from a group of different options.
class ZetaRadio<T> extends StatefulWidget {
/// Constructor for [ZetaRadio].
const ZetaRadio({
Expand Down Expand Up @@ -44,55 +44,71 @@ class ZetaRadio<T> extends StatefulWidget {
}

class _ZetaRadioState<T> extends State<ZetaRadio<T>> with TickerProviderStateMixin, ToggleableStateMixin {
final ToggleablePainter _painter = _RadioPainter();
ToggleablePainter? _painter;
bool _isHovered = false;
@override
Widget build(BuildContext context) {
final zetaColors = Zeta.of(context).colors;
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Semantics(
inMutuallyExclusiveGroup: true,
checked: widget._selected,
selected: value,
child: buildToggleable(
size: const Size(36, 36),
painter: _painter
..position = position
..reaction = reaction
..reactionFocusFade = reactionFocusFade
..reactionHoverFade = reactionHoverFade
..inactiveReactionColor = Colors.transparent
..reactionColor = Colors.transparent
..hoverColor = Colors.transparent
..focusColor = zetaColors.blue.shade50
..splashRadius = 12
..downPosition = downPosition
..isFocused = states.contains(WidgetState.focused)
..isHovered = states.contains(WidgetState.hovered)
..activeColor = states.contains(WidgetState.disabled) ? zetaColors.cool.shade30 : zetaColors.blue.shade60
..inactiveColor =
states.contains(WidgetState.disabled) ? zetaColors.cool.shade30 : zetaColors.cool.shade70,
mouseCursor: WidgetStateProperty.all(
WidgetStateProperty.resolveAs<MouseCursor>(
WidgetStateMouseCursor.clickable,
states,
_painter ??= _RadioPainter(colors: zetaColors);
return Semantics(
inMutuallyExclusiveGroup: true,
checked: widget._selected,
selected: value,
excludeSemantics: true,
child: MouseRegion(
onEnter: (_) => setState(() => _isHovered = true),
onExit: (_) => setState(() => _isHovered = false),
cursor: states.contains(WidgetState.disabled) ? SystemMouseCursors.forbidden : SystemMouseCursors.click,
child: SelectionContainer.disabled(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
buildToggleable(
size: const Size(ZetaSpacing.x9, ZetaSpacing.x9),
painter: _painter!
..position = position
..reaction = reaction
..reactionFocusFade = reactionFocusFade
..reactionHoverFade = reactionHoverFade
..inactiveReactionColor = Colors.transparent
..reactionColor = Colors.transparent
..hoverColor = Colors.transparent
..focusColor = zetaColors.blue.shade50
..splashRadius = ZetaSpacing.x3
..downPosition = downPosition
..isFocused = states.contains(WidgetState.focused)
..isHovered = states.contains(WidgetState.hovered)
..activeColor = _isHovered
? zetaColors.cool.shade90
: states.contains(WidgetState.disabled)
? zetaColors.cool.shade30
: zetaColors.blue.shade60
..inactiveColor = _isHovered
? zetaColors.cool.shade90
: states.contains(WidgetState.disabled)
? zetaColors.cool.shade30
: states.contains(WidgetState.focused)
? zetaColors.blue.shade50
: zetaColors.cool.shade70,
mouseCursor: WidgetStateProperty.all(
states.contains(WidgetState.disabled) ? SystemMouseCursors.forbidden : SystemMouseCursors.click,
),
),
),
if (widget.label != null)
GestureDetector(
onTap: () => onChanged?.call(true),
child: DefaultTextStyle(
style: ZetaTextStyles.bodyMedium.copyWith(
color: states.contains(WidgetState.disabled) ? zetaColors.textDisabled : zetaColors.textDefault,
height: 1.33,
),
child: widget.label!,
),
),
],
),
),
if (widget.label != null)
GestureDetector(
onTap: () => onChanged?.call(true),
child: DefaultTextStyle(
style: ZetaTextStyles.bodyMedium.copyWith(
color: states.contains(WidgetState.disabled) ? zetaColors.textDisabled : zetaColors.textDefault,
height: 1.33,
),
child: widget.label!,
),
),
],
),
);
}

Expand Down Expand Up @@ -125,7 +141,7 @@ class _ZetaRadioState<T> extends State<ZetaRadio<T>> with TickerProviderStateMix

@override
void dispose() {
_painter.dispose();
_painter?.dispose();
super.dispose();
}
}
Expand All @@ -134,17 +150,31 @@ const double _kOuterRadius = 10;
const double _kInnerRadius = 5;

class _RadioPainter extends ToggleablePainter {
_RadioPainter({required this.colors});

final ZetaColors colors;

@override
void paint(Canvas canvas, Size size) {
paintRadialReaction(canvas: canvas, origin: size.center(Offset.zero));

final Offset center = (Offset.zero & size).center;

// Outer circle
// Background mask for focus
final Paint paint = Paint()
..color = Color.lerp(inactiveColor, activeColor, position.value)!
..color = colors.surfacePrimary
..style = PaintingStyle.stroke
..strokeWidth = ZetaSpacing.x2_5;
if (isFocused) canvas.drawCircle(center, _kInnerRadius, paint);

// Outer circle
paint
..color = isHovered
? colors.black
: position.isDismissed
? inactiveColor
: activeColor
..style = PaintingStyle.stroke
..strokeWidth = 2;
..strokeWidth = ZetaSpacing.x0_5;
canvas.drawCircle(center, _kOuterRadius, paint);

// Inner circle
Expand Down

0 comments on commit 6d29ba3

Please sign in to comment.