Skip to content

Commit 4cd491a

Browse files
BornToBeRootclaude
andcommitted
Feature: Make links keyboard accessible (#3607)
New shared LinkHyperlink style (looks like LinkTextBlock, but focusable with Tab and opened with Enter). Used for the links in About (license, community, update), Web Console (WebView2 runtime download) and the RDAP notices, which were mouse-only TextBlocks before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent d538534 commit 4cd491a

5 files changed

Lines changed: 52 additions & 44 deletions

File tree

‎Source/NETworkManager/Resources/Styles/TextBlockStyles.xaml‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,24 @@
7777
</Style.Triggers>
7878
</Style>
7979

80+
<!--
81+
Link inside a TextBlock, looks like LinkTextBlock but is keyboard accessible (Tab + Enter).
82+
Usage: <TextBlock><Hyperlink Command="..." Style="{StaticResource LinkHyperlink}"><Run Text="..." /></Hyperlink></TextBlock>
83+
-->
84+
<Style x:Key="LinkHyperlink" TargetType="{x:Type Hyperlink}">
85+
<Setter Property="Foreground" Value="{DynamicResource MahApps.Brushes.Accent}" />
86+
<Setter Property="TextDecorations" Value="{x:Null}" />
87+
<Setter Property="Cursor" Value="Hand" />
88+
<Style.Triggers>
89+
<Trigger Property="IsMouseOver" Value="True">
90+
<Setter Property="Foreground" Value="{DynamicResource MahApps.Brushes.Accent2}" />
91+
</Trigger>
92+
<Trigger Property="IsKeyboardFocused" Value="True">
93+
<Setter Property="TextDecorations" Value="Underline" />
94+
</Trigger>
95+
</Style.Triggers>
96+
</Style>
97+
8098
<Style x:Key="DisabledTextBlock" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource DefaultTextBlock}">
8199
<Style.Triggers>
82100
<Trigger Property="IsEnabled" Value="False">

‎Source/NETworkManager/Views/AboutView.xaml‎

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,21 @@
4343
Margin="0,0,0,5" />
4444
<TextBlock Text="{Binding Version}" Style="{StaticResource DefaultTextBlock}" FontWeight="Bold"
4545
VerticalAlignment="Center" Margin="0,0,0,10" />
46-
<TextBlock Text="{x:Static resources:Resources.NETworkManager_License}"
47-
Style="{StaticResource LinkTextBlock}" HorizontalAlignment="Left" Margin="0,0,0,5">
48-
<TextBlock.InputBindings>
49-
<MouseBinding Command="{Binding OpenWebsiteCommand}"
50-
CommandParameter="{x:Static resources:Resources.NETworkManager_LicenseUrl}"
51-
MouseAction="LeftClick" />
52-
</TextBlock.InputBindings>
46+
<TextBlock Style="{StaticResource DefaultTextBlock}" HorizontalAlignment="Left" Margin="0,0,0,5">
47+
<Hyperlink Command="{Binding OpenWebsiteCommand}"
48+
CommandParameter="{x:Static resources:Resources.NETworkManager_LicenseUrl}"
49+
Style="{StaticResource LinkHyperlink}">
50+
<Run Text="{x:Static resources:Resources.NETworkManager_License}" />
51+
</Hyperlink>
5352
</TextBlock>
5453
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,0,0,10">
5554
<TextBlock Text="{Binding DevelopedByText}" Style="{StaticResource DefaultTextBlock}" />
56-
<TextBlock Text="{x:Static localization:Strings.Community}"
57-
Style="{StaticResource LinkTextBlock}">
58-
<TextBlock.InputBindings>
59-
<MouseBinding Command="{Binding OpenWebsiteCommand}"
60-
CommandParameter="{x:Static resources:Resources.NETworkManager_Contributors}"
61-
MouseAction="LeftClick" />
62-
</TextBlock.InputBindings>
55+
<TextBlock Style="{StaticResource DefaultTextBlock}">
56+
<Hyperlink Command="{Binding OpenWebsiteCommand}"
57+
CommandParameter="{x:Static resources:Resources.NETworkManager_Contributors}"
58+
Style="{StaticResource LinkHyperlink}">
59+
<Run Text="{x:Static localization:Strings.Community}" />
60+
</Hyperlink>
6361
</TextBlock>
6462
</StackPanel>
6563
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
@@ -99,19 +97,25 @@
9997
<StackPanel Grid.Column="2" Grid.Row="0"
10098
Orientation="Horizontal"
10199
Visibility="{Binding IsUpdateAvailable, Converter={StaticResource BooleanToVisibilityCollapsedConverter}}">
102-
<StackPanel.InputBindings>
103-
<MouseBinding Gesture="LeftClick" Command="{Binding OpenWebsiteCommand}"
104-
CommandParameter="{Binding UpdateReleaseUrl, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
105-
</StackPanel.InputBindings>
106-
<Rectangle Width="20" Height="20" Fill="{DynamicResource MahApps.Brushes.Accent}">
100+
<Rectangle Width="20" Height="20" Fill="{DynamicResource MahApps.Brushes.Accent}"
101+
Cursor="Hand">
102+
<Rectangle.InputBindings>
103+
<MouseBinding Gesture="LeftClick" Command="{Binding OpenWebsiteCommand}"
104+
CommandParameter="{Binding UpdateReleaseUrl, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
105+
</Rectangle.InputBindings>
107106
<Rectangle.OpacityMask>
108107
<VisualBrush Stretch="Uniform" Visual="{iconPacks:Material Kind=RocketLaunchOutline}" />
109108
</Rectangle.OpacityMask>
110109
</Rectangle>
111-
<TextBlock Text="{Binding UpdateText}"
112-
Style="{StaticResource LinkTextBlock}"
110+
<TextBlock Style="{StaticResource DefaultTextBlock}"
113111
VerticalAlignment="Center"
114-
Margin="10,0,0,0" />
112+
Margin="10,0,0,0">
113+
<Hyperlink Command="{Binding OpenWebsiteCommand}"
114+
CommandParameter="{Binding UpdateReleaseUrl, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
115+
Style="{StaticResource LinkHyperlink}">
116+
<Run Text="{Binding UpdateText, Mode=OneWay}" />
117+
</Hyperlink>
118+
</TextBlock>
115119
</StackPanel>
116120
<mahAppsControls:ProgressRing Grid.Column="2" Grid.Row="0"
117121
Visibility="{Binding IsUpdateCheckRunning, Converter={StaticResource BooleanToVisibilityCollapsedConverter}}"

‎Source/NETworkManager/Views/RDAPView.xaml‎

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,6 @@
4343
<Setter Property="CanUserAddRows" Value="False" />
4444
<Setter Property="SelectionMode" Value="Extended" />
4545
</Style>
46-
<!-- Keyboard accessible link (Tab + Enter), styled like LinkTextBlock -->
47-
<Style x:Key="RDAPHyperlink" TargetType="{x:Type Hyperlink}">
48-
<Setter Property="Foreground" Value="{DynamicResource MahApps.Brushes.Accent}" />
49-
<Setter Property="TextDecorations" Value="{x:Null}" />
50-
<Setter Property="Cursor" Value="Hand" />
51-
<Style.Triggers>
52-
<Trigger Property="IsMouseOver" Value="True">
53-
<Setter Property="Foreground" Value="{DynamicResource MahApps.Brushes.Accent2}" />
54-
</Trigger>
55-
<Trigger Property="IsKeyboardFocused" Value="True">
56-
<Setter Property="TextDecorations" Value="Underline" />
57-
</Trigger>
58-
</Style.Triggers>
59-
</Style>
6046
<Style x:Key="RDAPWrapColumnStyle" TargetType="{x:Type TextBlock}">
6147
<Setter Property="TextWrapping" Value="Wrap" />
6248
</Style>
@@ -178,7 +164,7 @@
178164
Command="{Binding Data.OpenUrlCommand, Source={StaticResource BindingProxy}}"
179165
CommandParameter="{Binding Url}"
180166
ToolTip="{Binding Url}"
181-
Style="{StaticResource RDAPHyperlink}">
167+
Style="{StaticResource LinkHyperlink}">
182168
<Run Text="{Binding Text, Mode=OneWay}" />
183169
</Hyperlink>
184170
</TextBlock>

‎Source/NETworkManager/Views/WebConsoleHostView.xaml‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,12 @@
280280
</StackPanel.Style>
281281
<TextBlock Text="{x:Static localization:Strings.MicrosoftEdgeWebView2RuntimeIsNotAvailable}"
282282
Style="{StaticResource MessageTextBlock}" Margin="0,0,0,10" />
283-
<TextBlock Text="{x:Static localization:Strings.DownloadMicrosoftEdgeWebView2Runtime}"
284-
Style="{StaticResource LinkTextBlock}" Margin="0,0,0,5" HorizontalAlignment="Center">
285-
<TextBlock.InputBindings>
286-
<MouseBinding Command="{Binding OpenWebsiteCommand}"
287-
CommandParameter="{x:Static resources:Resources.MicrosoftEdgeWebView2Runtime_DownloadUrl}"
288-
MouseAction="LeftClick" />
289-
</TextBlock.InputBindings>
283+
<TextBlock Style="{StaticResource DefaultTextBlock}" Margin="0,0,0,5" HorizontalAlignment="Center">
284+
<Hyperlink Command="{Binding OpenWebsiteCommand}"
285+
CommandParameter="{x:Static resources:Resources.MicrosoftEdgeWebView2Runtime_DownloadUrl}"
286+
Style="{StaticResource LinkHyperlink}">
287+
<Run Text="{x:Static localization:Strings.DownloadMicrosoftEdgeWebView2Runtime}" />
288+
</Hyperlink>
290289
</TextBlock>
291290
</StackPanel>
292291
</Grid>

‎Website/docs/changelog/next-release.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Release date: **xx.xx.2026**
4040

4141
## Improvements
4242

43+
- Links (e.g. in **About**, **Web Console** and the notices in **RDAP**) are now keyboard accessible: they can be reached with `Tab` and opened with `Enter`. [#3607](https://github.com/BornToBeRoot/NETworkManager/pull/3607)
4344
- The collapsed/expanded state of profile groups (e.g. **linux-server**) is now remembered per profile file and shared across all tools, instead of resetting every time you switch tools or restart the application. [#3539](https://github.com/BornToBeRoot/NETworkManager/pull/3539)
4445

4546
**Whois**

0 commit comments

Comments
 (0)