Skip to content

Commit c068626

Browse files
authored
Merge pull request #747 from Avid29/ColorAnalyzer/Contrast
ContrastHelper
2 parents dd483fc + 2afc220 commit c068626

11 files changed

+619
-8
lines changed

components/ColorAnalyzer/samples/AccentAnalyzer.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ icon: assets/icon.png
1717
The AccentAnalyzer provides a pure XAML way to use the colors extracted from an image as a binding source for any `Color` property.
1818

1919
> [!Sample AccentAnalyzerSample]
20+
21+
> [!Sample ContrastHelperSample]

components/ColorAnalyzer/samples/AccentAnalyzerSample.xaml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
VerticalAlignment="Center">
2626
<Image x:Name="AccentedImage"
2727
HorizontalAlignment="Center"
28-
Source="/ColorAnalyzerExperiment.Samples/Assets/StockImages/Bloom.jpg"
28+
Source="/ColorAnalyzerExperiment.Samples/Assets/StockImages/Flowers.jpg"
2929
Stretch="Uniform">
3030
<interactivity:Interaction.Behaviors>
3131
<interactivity:EventTriggerBehavior EventName="ImageOpened">
@@ -62,7 +62,7 @@
6262
<Border.Background>
6363
<SolidColorBrush Color="{x:Bind AccentAnalyzer.DominantColor, Mode=OneWay}" />
6464
</Border.Background>
65-
<TextBlock Foreground="Black"
65+
<TextBlock helpers:ContrastHelper.Opponent="{x:Bind AccentAnalyzer.DominantColor, Mode=OneWay}"
6666
Text="Dominant" />
6767
</Border>
6868

@@ -74,8 +74,14 @@
7474
<Border.Background>
7575
<SolidColorBrush Color="{x:Bind AccentAnalyzer.BaseColor, Mode=OneWay}" />
7676
</Border.Background>
77-
<TextBlock Foreground="Black"
78-
Text="Base" />
77+
<TextBlock Text="Base">
78+
<TextBlock.Foreground>
79+
<!-- ConstrastHelper used to auto-adjust text Foreground against the dynamic background per WCAG -->
80+
<SolidColorBrush helpers:ContrastHelper.MinRatio="5"
81+
helpers:ContrastHelper.Opponent="{x:Bind AccentAnalyzer.BaseColor, Mode=OneWay}"
82+
Color="{x:Bind AccentAnalyzer.PrimaryAccentColor, Mode=OneWay}" />
83+
</TextBlock.Foreground>
84+
</TextBlock>
7985
</Border>
8086

8187
<!-- Primary -->
@@ -86,7 +92,7 @@
8692
<Border.Background>
8793
<SolidColorBrush Color="{x:Bind AccentAnalyzer.PrimaryAccentColor, Mode=OneWay}" />
8894
</Border.Background>
89-
<TextBlock Foreground="Black"
95+
<TextBlock helpers:ContrastHelper.Opponent="{x:Bind AccentAnalyzer.PrimaryAccentColor, Mode=OneWay}"
9096
Text="Primary" />
9197
</Border>
9298
<!-- Secondary -->
@@ -97,7 +103,7 @@
97103
<Border.Background>
98104
<SolidColorBrush Color="{x:Bind AccentAnalyzer.SecondaryAccentColor, Mode=OneWay}" />
99105
</Border.Background>
100-
<TextBlock Foreground="Black"
106+
<TextBlock helpers:ContrastHelper.Opponent="{x:Bind AccentAnalyzer.SecondaryAccentColor, Mode=OneWay}"
101107
Text="Secondary" />
102108
</Border>
103109
<!-- Tertiary -->
@@ -108,7 +114,7 @@
108114
<Border.Background>
109115
<SolidColorBrush Color="{x:Bind AccentAnalyzer.TertiaryAccentColor, Mode=OneWay}" />
110116
</Border.Background>
111-
<TextBlock Foreground="Black"
117+
<TextBlock helpers:ContrastHelper.Opponent="{x:Bind AccentAnalyzer.TertiaryAccentColor, Mode=OneWay}"
112118
Text="Tertiary" />
113119
</Border>
114120

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
2+
<Page x:Class="ColorAnalyzerExperiment.Samples.ContrastHelperSample"
3+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
6+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7+
xmlns:helpers="using:CommunityToolkit.WinUI.Helpers"
8+
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
9+
xmlns:local="using:ColorAnalyzerExperiment.Samples"
10+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
11+
mc:Ignorable="d">
12+
<Page.Background>
13+
<SolidColorBrush Color="{x:Bind DesiredBackground, Mode=OneWay}" />
14+
</Page.Background>
15+
16+
<StackPanel Padding="20"
17+
HorizontalAlignment="Center"
18+
VerticalAlignment="Top"
19+
Spacing="2">
20+
<TextBlock x:Name="TextSample"
21+
helpers:ContrastHelper.MinRatio="{x:Bind MinRatio, Mode=OneWay}"
22+
helpers:ContrastHelper.Opponent="{x:Bind DesiredBackground, Mode=OneWay}"
23+
FontSize="24"
24+
Text="Legible Text">
25+
<TextBlock.Foreground>
26+
<SolidColorBrush Color="{x:Bind DesiredForeground, Mode=OneWay}" />
27+
</TextBlock.Foreground>
28+
</TextBlock>
29+
<Rectangle x:Name="ShapeSample"
30+
Width="28"
31+
Height="28">
32+
<Rectangle.Stroke>
33+
<SolidColorBrush helpers:ContrastHelper.MinRatio="{x:Bind MinRatio, Mode=OneWay}"
34+
helpers:ContrastHelper.Opponent="{x:Bind DesiredBackground, Mode=OneWay}"
35+
Color="{x:Bind DesiredForeground, Mode=OneWay}" />
36+
</Rectangle.Stroke>
37+
</Rectangle>
38+
</StackPanel>
39+
</Page>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Microsoft.UI;
6+
using Windows.UI;
7+
8+
namespace ColorAnalyzerExperiment.Samples;
9+
10+
/// <summary>
11+
/// An example sample page of a custom control inheriting from Panel.
12+
/// </summary>
13+
[ToolkitSample(id: nameof(ContrastHelperSample), "ContrastAnalyzer helper", description: $"A sample for showing how the contrast analyzer can be used.")]
14+
public sealed partial class ContrastHelperSample : Page
15+
{
16+
public static readonly DependencyProperty DesiredBackgroundProperty =
17+
DependencyProperty.Register(nameof(DesiredBackground), typeof(Color), typeof(ContrastHelperSample), new PropertyMetadata(Colors.Black));
18+
19+
public static readonly DependencyProperty DesiredForegroundProperty =
20+
DependencyProperty.Register(nameof(DesiredForeground), typeof(Color), typeof(ContrastHelperSample), new PropertyMetadata(Colors.White));
21+
22+
private static readonly DependencyProperty MinRatioProperty =
23+
DependencyProperty.Register(nameof(MinRatio), typeof(double), typeof(ContrastHelperSample), new PropertyMetadata(0d));
24+
25+
public Color DesiredBackground
26+
{
27+
get => (Color)GetValue(DesiredBackgroundProperty);
28+
set => SetValue(DesiredBackgroundProperty, value);
29+
}
30+
31+
public Color DesiredForeground
32+
{
33+
get => (Color)GetValue(DesiredForegroundProperty);
34+
set => SetValue(DesiredForegroundProperty, value);
35+
}
36+
37+
public double MinRatio
38+
{
39+
get => (double)GetValue(MinRatioProperty);
40+
set => SetValue(MinRatioProperty, value);
41+
}
42+
43+
public ContrastHelperSample()
44+
{
45+
this.InitializeComponent();
46+
}
47+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<UserControl x:Class="ColorAnalyzerExperiment.Samples.ContrastOptionsPane"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:local="using:ColorAnalyzerExperiment.Samples"
7+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
8+
mc:Ignorable="d">
9+
10+
<StackPanel Spacing="2">
11+
<TextBlock Text="Desired Foreground" />
12+
<controls:ColorPicker ColorChanged="Foreground_ColorChanged"
13+
IsColorChannelTextInputVisible="True"
14+
IsColorSliderVisible="True"
15+
Color="White" />
16+
17+
<TextBlock Text="Background" />
18+
<controls:ColorPicker ColorChanged="Background_ColorChanged"
19+
IsColorChannelTextInputVisible="True"
20+
IsColorSliderVisible="True"
21+
Color="Black" />
22+
23+
<Slider Header="Minimum Ratio"
24+
Maximum="21"
25+
Minimum="1"
26+
ValueChanged="Ratio_ValueChanged"
27+
Value="3" />
28+
29+
<Slider Header="Font Size"
30+
Maximum="48"
31+
Minimum="8"
32+
ValueChanged="FontSize_ValueChanged"
33+
Value="18" />
34+
35+
<Slider Header="Stroke Thickness"
36+
Maximum="8"
37+
Minimum="0"
38+
ValueChanged="Thickness_ValueChanged"
39+
Value="4" />
40+
</StackPanel>
41+
</UserControl>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#if !WINDOWS_UWP
6+
using Microsoft.UI.Xaml.Media.Imaging;
7+
#elif WINDOWS_UWP
8+
using Windows.UI.Xaml.Media.Imaging;
9+
#endif
10+
11+
namespace ColorAnalyzerExperiment.Samples;
12+
13+
[ToolkitSampleOptionsPane(nameof(ContrastHelperSample))]
14+
public partial class ContrastOptionsPane : UserControl
15+
{
16+
private ContrastHelperSample _sample;
17+
private ContrastHelperSample.XamlNamedPropertyRelay _sampleXamlRelay;
18+
19+
public ContrastOptionsPane(ContrastHelperSample sample)
20+
{
21+
_sample = sample;
22+
_sampleXamlRelay = new ContrastHelperSample.XamlNamedPropertyRelay(sample);
23+
24+
this.InitializeComponent();
25+
}
26+
27+
private void Foreground_ColorChanged(MUXC.ColorPicker sender, MUXC.ColorChangedEventArgs args)
28+
{
29+
// TODO: Disect the colorpicker
30+
if (args.NewColor.A != 255)
31+
return;
32+
33+
_sample.DesiredForeground = args.NewColor;
34+
}
35+
36+
private void Background_ColorChanged(MUXC.ColorPicker sender, MUXC.ColorChangedEventArgs args)
37+
{
38+
// TODO: Disect the colorpicker
39+
if (args.NewColor.A != 255)
40+
return;
41+
42+
_sample.DesiredBackground = args.NewColor;
43+
}
44+
45+
private void Ratio_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
46+
{
47+
_sample.MinRatio = (double)e.NewValue;
48+
}
49+
50+
private void FontSize_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
51+
{
52+
_sampleXamlRelay.TextSample.FontSize = (double)e.NewValue;
53+
}
54+
55+
private void Thickness_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
56+
{
57+
_sampleXamlRelay.ShapeSample.StrokeThickness = (double)e.NewValue;
58+
}
59+
}

components/ColorAnalyzer/samples/Dependencies.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
<ItemGroup Condition="'$(WinUIMajorVersion)' == '2'">
1414
<!-- <PackageReference Include="Uno.Microsoft.Toolkit.Uwp.UI.Controls.Primitives" Version="7.1.11"/> -->
1515
<PackageReference Include="CommunityToolkit.Uwp.Behaviors" Version="8.2.250402"/>
16+
<PackageReference Include="CommunityToolkit.Uwp.Controls.ColorPicker" Version="8.2.250402"/>
1617
</ItemGroup>
1718

1819
<!-- WinUI 3 -->
1920
<ItemGroup Condition="'$(WinUIMajorVersion)' == '3'">
2021
<PackageReference Include="CommunityToolkit.WinUI.Behaviors" Version="8.2.250402"/>
22+
<PackageReference Include="CommunityToolkit.WinUI.Controls.ColorPicker" Version="8.2.250402"/>
2123
</ItemGroup>
2224
</Project>

components/ColorAnalyzer/src/AccentAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
namespace CommunityToolkit.WinUI.Helpers;
1818

1919
/// <summary>
20-
/// A resource that can be used to extract color palettes out of any UIElement.
20+
/// A resource that can be used to extract color palettes out of any <see cref="UIElement"/>.
2121
/// </summary>
2222
public partial class AccentAnalyzer : DependencyObject
2323
{

0 commit comments

Comments
 (0)