Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/setup-wizard-ux/01-welcome-security.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/setup-wizard-ux/02-setup-mode-listview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/setup-wizard-ux/03-config-handling.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/setup-wizard-ux/04-provider-collapsed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/setup-wizard-ux/05-provider-expanded.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/setup-wizard-ux/06-auth-method.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/setup-wizard-ux/07-text-input.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions docs/setup-wizard-ux/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Setup wizard UX refresh — screens & accessibility proof

Screenshots captured from the live isolated dev app (`OPENCLAW_FORCE_ONBOARDING=1`,
`run-app-local.ps1 -NoBuild -Isolated`) walking the full gateway setup + onboard flow.
Accessibility was scanned per-screen with a standalone Axe.Windows (v2.4.1) scanner
against the live process — the same engine Accessibility Insights uses.

## Screens

| # | Screen | Notes |
|---|--------|-------|
| 01 | Welcome + security notice | Selectable RichTextBlock body |
| 02 | Setup mode | Single-selection `ListView` (ItemContainer), first item selected by default |
| 03 | Config handling | Single-selection list, standardized bottom bar |
| 04 | Model/auth provider (collapsed) | "Skip for now" pinned to top, subtle **More ▾** expander |
| 05 | Model/auth provider (expanded) | One-click expand keeps "Skip for now"; full provider list |
| 06 | Auth method | Single-selection list |
| 07 | Text input step | API-key entry |
| 08 | Capabilities | Radio group with accessible names (a11y fix) |

Bottom action bar across steps: standard **Back** button, `AccentButtonStyle`
primary (Continue), subtle **More options** / **Skip** / **Start over** controls.

## Accessibility results (Axe.Windows, actionable violations)

All refactored surfaces flagged `NameNotNull` (focusable element with a null
accessible Name) before the fix; every one is 0 after.

| Screen | Before | After |
|--------|:------:|:-----:|
| Capabilities radio group | 3 | 0 |
| Setup mode ListView | 2 | 0 |
| Provider list (collapsed) | 6 | 0 |
| Provider list (expanded) | 7 | 0 |
| Welcome / Confirm / Auth / Text input | 0 | 0 |

### Fixes
- `WizardPage` option lists: each `ListViewItem` (and multiselect `CheckBox`) now
gets `AutomationProperties.Name` = label + hint via a shared `CreateOptionItem`
helper.
- `CapabilitiesPage`: the three profile radio buttons (Read-only / Standard /
Full access) now set `AutomationProperties.Name`.

### Known framework limitation (not fixed)
Inline `Hyperlink` elements inside a `RichTextBlock` (security disclaimer link)
report a null `BoundingRectangle` to UIA when scrolled out of view. This is a
WinUI framework behavior for inline hyperlinks, not a control we construct.
4 changes: 2 additions & 2 deletions src/OpenClaw.SetupEngine.UI/Pages/AdvancedSetupPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
</StackPanel>
<Button x:Name="BackButton" Grid.Column="0" Content="Back"
Height="44" MinWidth="96" HorizontalAlignment="Left"
MinWidth="100" HorizontalAlignment="Left"
Click="Back_Click" />
<Button x:Name="OpenConnectionButton" Grid.Column="1" Content="Open Companion Settings"
Height="44" MinWidth="200" HorizontalAlignment="Right"
MinWidth="100" HorizontalAlignment="Right"
Style="{StaticResource AccentButtonStyle}"
Click="OpenConnection_Click" />
</Grid>
Expand Down
10 changes: 5 additions & 5 deletions src/OpenClaw.SetupEngine.UI/Pages/CapabilitiesPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="OpenClaw runs your agent in a private, self-hosted gateway on this PC. Pick what it's allowed to do — you can change this later in Companion Settings." />
<RadioButtons x:Name="ProfileRadio" SelectionChanged="Profile_Changed" MaxColumns="1">
<RadioButton>
<RadioButton AutomationProperties.Name="Read-only">
<StackPanel Spacing="1">
<TextBlock Text="Read-only" Style="{StaticResource BodyStrongTextBlockStyle}" />
<TextBlock Text="See your screen, render on canvas, read device info. No commands."
Style="{StaticResource CaptionTextBlockStyle}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</StackPanel>
</RadioButton>
<RadioButton>
<RadioButton AutomationProperties.Name="Standard (Recommended)">
<StackPanel Spacing="1">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="Standard" Style="{StaticResource BodyStrongTextBlockStyle}" VerticalAlignment="Center" />
Expand All @@ -63,7 +63,7 @@
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</StackPanel>
</RadioButton>
<RadioButton>
<RadioButton AutomationProperties.Name="Full access">
<StackPanel Spacing="1">
<TextBlock Text="Full access" Style="{StaticResource BodyStrongTextBlockStyle}" />
<TextBlock Text="Everything, plus camera, location, and browser control."
Expand Down Expand Up @@ -165,10 +165,10 @@
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
</StackPanel>
<Button x:Name="BackButton" Grid.Column="0" Content="Back"
Height="44" MinWidth="96" HorizontalAlignment="Left"
MinWidth="100" HorizontalAlignment="Left"
Visibility="Collapsed" Click="Back_Click" />
<Button x:Name="PrimaryButton" Grid.Column="1" Content="Next"
Height="44" MinWidth="140" HorizontalAlignment="Right"
MinWidth="100" HorizontalAlignment="Right"
Style="{StaticResource AccentButtonStyle}" Click="Primary_Click" />
</Grid>
</Grid>
Expand Down
2 changes: 1 addition & 1 deletion src/OpenClaw.SetupEngine.UI/Pages/CompletePage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
</StackPanel>
<Button x:Name="LaunchButton" Grid.Column="1"
Content="Finish"
HorizontalAlignment="Right" MinHeight="44" MinWidth="140"
HorizontalAlignment="Right" MinWidth="100"
Style="{StaticResource AccentButtonStyle}"
Click="LaunchButton_Click" />
</Grid>
Expand Down
2 changes: 1 addition & 1 deletion src/OpenClaw.SetupEngine.UI/Pages/ProgressPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
</StackPanel>
<Button x:Name="OnboardButton" Grid.Column="1" Content="Start OpenClaw onboard"
Visibility="Collapsed" MinHeight="44" MinWidth="180" HorizontalAlignment="Right"
Visibility="Collapsed" MinWidth="100" HorizontalAlignment="Right"
Margin="48,0" Style="{StaticResource AccentButtonStyle}"
Click="Onboard_Click" />
</Grid>
Expand Down
2 changes: 1 addition & 1 deletion src/OpenClaw.SetupEngine.UI/Pages/SecurityNoticePage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
</StackPanel>
<Button Grid.Column="1" x:Name="ContinueButton" Content="Continue"
Height="44" MinWidth="140" HorizontalAlignment="Right"
MinWidth="100" HorizontalAlignment="Right"
Style="{StaticResource AccentButtonStyle}"
Click="Continue_Click" />
</Grid>
Expand Down
52 changes: 30 additions & 22 deletions src/OpenClaw.SetupEngine.UI/Pages/WelcomePage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
<StackPanel Grid.Row="1" VerticalAlignment="Top" Margin="0,24,0,0" Spacing="12"
MaxWidth="560" HorizontalAlignment="Stretch">

<Button x:Name="InstallButton" Click="StartButton_Click"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
<Border x:Name="InstallCard"
HorizontalAlignment="Stretch"
Padding="16" CornerRadius="4"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource AccentFillColorDefaultBrush}"
BorderThickness="1"
BorderThickness="2"
PointerPressed="InstallCard_Pressed"
AutomationProperties.Name="Install a local gateway (WSL), recommended">
<Grid ColumnDefinitions="Auto,*,Auto" ColumnSpacing="16">
<Grid ColumnDefinitions="Auto,*" ColumnSpacing="16">
<Border Grid.Column="0" Width="44" Height="44" CornerRadius="6"
Background="{ThemeResource AccentFillColorDefaultBrush}" VerticalAlignment="Top">
<FontIcon Glyph="&#xE756;" FontSize="20" IsTextScaleFactorEnabled="False"
Expand All @@ -56,19 +57,18 @@
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="A private, self-hosted OpenClaw gateway in an isolated Ubuntu WSL instance. We'll show exactly what gets installed before anything runs." />
</StackPanel>
<FontIcon Grid.Column="2" Glyph="&#xE76C;" FontSize="14" IsTextScaleFactorEnabled="False"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
</Grid>
</Button>
</Border>

<Button x:Name="ConnectButton" Click="AdvancedSetup_Click"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
<Border x:Name="ConnectCard"
HorizontalAlignment="Stretch"
Padding="16" CornerRadius="4"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
PointerPressed="ConnectCard_Pressed"
AutomationProperties.Name="Connect to an existing gateway">
<Grid ColumnDefinitions="Auto,*,Auto" ColumnSpacing="16">
<Grid ColumnDefinitions="Auto,*" ColumnSpacing="16">
<Border Grid.Column="0" Width="44" Height="44" CornerRadius="6"
Background="{ThemeResource SubtleFillColorSecondaryBrush}" VerticalAlignment="Top">
<FontIcon Glyph="&#xE71B;" FontSize="20" IsTextScaleFactorEnabled="False"
Expand All @@ -82,21 +82,29 @@
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Already run an OpenClaw gateway — here, on another machine, or remote? Pair without installing anything." />
</StackPanel>
<FontIcon Grid.Column="2" Glyph="&#xE76C;" FontSize="14" IsTextScaleFactorEnabled="False"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
</Grid>
</Button>
</Border>

</StackPanel>

<StackPanel Grid.Row="2" Orientation="Horizontal" Spacing="8" HorizontalAlignment="Center" Margin="0,16,0,0"
IsTabStop="False" AutomationProperties.Name="Step 2 of 6">
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
<Border Width="20" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupIndicatorAccentBrush}" />
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
</StackPanel>
<Grid Grid.Row="2" ColumnDefinitions="*,Auto" Margin="0,16,0,0">
<StackPanel Grid.ColumnSpan="2" Orientation="Horizontal" Spacing="8"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsTabStop="False" AutomationProperties.Name="Step 2 of 6">
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
<Border Width="20" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupIndicatorAccentBrush}" />
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
<Border Width="8" Height="8" CornerRadius="4" VerticalAlignment="Center" Background="{ThemeResource SetupInactiveDotBrush}" />
</StackPanel>
<Button x:Name="BackButton" Grid.Column="0" Content="Back"
MinWidth="100" HorizontalAlignment="Left"
Click="Back_Click" />
<Button x:Name="NextButton" Grid.Column="1" Content="Next"
MinWidth="100" HorizontalAlignment="Right"
Style="{StaticResource AccentButtonStyle}"
Click="Next_Click" />
</Grid>
</Grid>
</Page>
65 changes: 51 additions & 14 deletions src/OpenClaw.SetupEngine.UI/Pages/WelcomePage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Hosting;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using OpenClaw.SetupEngine;
using OpenClaw.SetupEngine.UI;
Expand All @@ -15,11 +17,13 @@ public sealed partial class WelcomePage : Page
private const string InstallButtonText = "Install a local gateway (WSL)";
private const string CheckingButtonText = "Checking existing setup...";
private SetupConfig? _config;
private bool _installSelected = true; // default selection

public WelcomePage()
{
InitializeComponent();
Loaded += OnLoaded;
UpdateCardSelection();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
Expand Down Expand Up @@ -50,19 +54,58 @@ private void StartMascotBreatheAnimation()
visual.StartAnimation("Scale", pulse);
}

private void StartButton_Click(object sender, RoutedEventArgs e) =>
AsyncEventHandlerGuard.Run(
StartButtonClickAsync,
NullLogger.Instance,
nameof(StartButton_Click));
private void InstallCard_Pressed(object sender, PointerRoutedEventArgs e)
{
_installSelected = true;
UpdateCardSelection();
}

private void ConnectCard_Pressed(object sender, PointerRoutedEventArgs e)
{
_installSelected = false;
UpdateCardSelection();
}

private void UpdateCardSelection()
{
InstallCard.BorderBrush = _installSelected
? (Brush)Application.Current.Resources["AccentFillColorDefaultBrush"]
: (Brush)Application.Current.Resources["CardStrokeColorDefaultBrush"];
InstallCard.BorderThickness = new Thickness(_installSelected ? 2 : 1);

ConnectCard.BorderBrush = !_installSelected
? (Brush)Application.Current.Resources["AccentFillColorDefaultBrush"]
: (Brush)Application.Current.Resources["CardStrokeColorDefaultBrush"];
ConnectCard.BorderThickness = new Thickness(!_installSelected ? 2 : 1);
}

private void Back_Click(object sender, RoutedEventArgs e)
{
SetupWindow.Active?.NavigateToSecurityNotice(back: true);
}

private async Task StartButtonClickAsync()
private void Next_Click(object sender, RoutedEventArgs e)
{
if (_installSelected)
{
AsyncEventHandlerGuard.Run(
StartInstallAsync,
NullLogger.Instance,
nameof(Next_Click));
}
else
{
SetupWindow.Active?.NavigateToAdvancedSetup();
}
}

private async Task StartInstallAsync()
{
var config = _config ?? throw new InvalidOperationException("Setup configuration has not been loaded.");
var setupWindow = SetupWindow.Active;
var dataDir = setupWindow?.DataDir ?? SetupContext.ResolveDataDir();

InstallButton.IsEnabled = false;
NextButton.IsEnabled = false;
InstallTitle.Text = CheckingButtonText;
var navigating = false;
try
Expand Down Expand Up @@ -98,14 +141,8 @@ private async Task StartButtonClickAsync()
if (!navigating && setupWindow is { IsClosed: false })
{
InstallTitle.Text = InstallButtonText;
InstallButton.IsEnabled = true;
NextButton.IsEnabled = true;
}
}
}

private void AdvancedSetup_Click(object sender, RoutedEventArgs e)
{
// Show quick connect instructions before handing off to the companion app.
SetupWindow.Active?.NavigateToAdvancedSetup();
}
}
Loading