Browse Source

Merge pull request #4216 from maxkatz6/feature/focus-visible

Add :focus-visible pseudoclass support
pull/4241/head
Jumar Macato 6 years ago
committed by GitHub
parent
commit
fe7816e868
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      src/Avalonia.Input/InputElement.cs
  2. 79
      tests/Avalonia.Input.UnitTests/InputElement_Focus.cs

7
src/Avalonia.Input/InputElement.cs

@ -158,6 +158,7 @@ namespace Avalonia.Input
private bool _isEffectivelyEnabled = true; private bool _isEffectivelyEnabled = true;
private bool _isFocused; private bool _isFocused;
private bool _isFocusVisible;
private bool _isPointerOver; private bool _isPointerOver;
private GestureRecognizerCollection _gestureRecognizers; private GestureRecognizerCollection _gestureRecognizers;
@ -427,7 +428,9 @@ namespace Avalonia.Input
/// <param name="e">The event args.</param> /// <param name="e">The event args.</param>
protected virtual void OnGotFocus(GotFocusEventArgs e) protected virtual void OnGotFocus(GotFocusEventArgs e)
{ {
IsFocused = e.Source == this; var isFocused = e.Source == this;
_isFocusVisible = isFocused && (e.NavigationMethod == NavigationMethod.Directional || e.NavigationMethod == NavigationMethod.Tab);
IsFocused = isFocused;
} }
/// <summary> /// <summary>
@ -436,6 +439,7 @@ namespace Avalonia.Input
/// <param name="e">The event args.</param> /// <param name="e">The event args.</param>
protected virtual void OnLostFocus(RoutedEventArgs e) protected virtual void OnLostFocus(RoutedEventArgs e)
{ {
_isFocusVisible = false;
IsFocused = false; IsFocused = false;
} }
@ -602,6 +606,7 @@ namespace Avalonia.Input
if (isFocused.HasValue) if (isFocused.HasValue)
{ {
PseudoClasses.Set(":focus", isFocused.Value); PseudoClasses.Set(":focus", isFocused.Value);
PseudoClasses.Set(":focus-visible", _isFocusVisible);
} }
if (isPointerOver.HasValue) if (isPointerOver.HasValue)

79
tests/Avalonia.Input.UnitTests/InputElement_Focus.cs

@ -42,5 +42,84 @@ namespace Avalonia.Input.UnitTests
Assert.Null(FocusManager.Instance.Current); Assert.Null(FocusManager.Instance.Current);
} }
} }
[Fact]
public void Focus_Pseudoclass_Should_Be_Applied_On_Focus()
{
using (UnitTestApplication.Start(TestServices.RealFocus))
{
var target1 = new Decorator();
var target2 = new Decorator();
var root = new TestRoot
{
Child = new StackPanel
{
Children =
{
target1,
target2
}
}
};
target1.ApplyTemplate();
target2.ApplyTemplate();
FocusManager.Instance?.Focus(target1);
Assert.True(target1.IsFocused);
Assert.True(target1.Classes.Contains(":focus"));
Assert.False(target2.IsFocused);
Assert.False(target2.Classes.Contains(":focus"));
FocusManager.Instance?.Focus(target2, NavigationMethod.Tab);
Assert.False(target1.IsFocused);
Assert.False(target1.Classes.Contains(":focus"));
Assert.True(target2.IsFocused);
Assert.True(target2.Classes.Contains(":focus"));
}
}
[Fact]
public void Control_FocusVsisible_Pseudoclass_Should_Be_Applied_On_Tab_And_DirectionalFocus()
{
using (UnitTestApplication.Start(TestServices.RealFocus))
{
var target1 = new Decorator();
var target2 = new Decorator();
var root = new TestRoot
{
Child = new StackPanel
{
Children =
{
target1,
target2
}
}
};
target1.ApplyTemplate();
target2.ApplyTemplate();
FocusManager.Instance?.Focus(target1);
Assert.True(target1.IsFocused);
Assert.False(target1.Classes.Contains(":focus-visible"));
Assert.False(target2.IsFocused);
Assert.False(target2.Classes.Contains(":focus-visible"));
FocusManager.Instance?.Focus(target2, NavigationMethod.Tab);
Assert.False(target1.IsFocused);
Assert.False(target1.Classes.Contains(":focus-visible"));
Assert.True(target2.IsFocused);
Assert.True(target2.Classes.Contains(":focus-visible"));
FocusManager.Instance?.Focus(target1, NavigationMethod.Directional);
Assert.True(target1.IsFocused);
Assert.True(target1.Classes.Contains(":focus-visible"));
Assert.False(target2.IsFocused);
Assert.False(target2.Classes.Contains(":focus-visible"));
}
}
} }
} }

Loading…
Cancel
Save