Made the tool selection in the chat and the assistants more compact (#962)
Some checks are pending
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Sync Flatpak repo (push) Blocked by required conditions
Build and Release / Collect Flatpak artifacts (push) Blocked by required conditions
Build and Release / Verify (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions

This commit is contained in:
Thorsten Sommer 2026-09-13 14:59:26 +02:00 committed by GitHub
parent d85b4e71b6
commit 358c161e7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 53 deletions

View File

@ -7,7 +7,7 @@
<MudPopover Open="@this.showSelection" AnchorOrigin="Origin.TopLeft" TransformOrigin="Origin.BottomLeft" DropShadow="@true" Class="border-solid border-4 rounded-lg"> <MudPopover Open="@this.showSelection" AnchorOrigin="Origin.TopLeft" TransformOrigin="Origin.BottomLeft" DropShadow="@true" Class="border-solid border-4 rounded-lg">
<MudCard> <MudCard>
<MudCardHeader> <MudCardHeader Class="pa-2 pb-0">
<CardHeaderContent> <CardHeaderContent>
<MudStack Row="true" AlignItems="AlignItems.Center"> <MudStack Row="true" AlignItems="AlignItems.Center">
<MudText Typo="Typo.h5">@T("Tool Selection")</MudText> <MudText Typo="Typo.h5">@T("Tool Selection")</MudText>
@ -15,8 +15,8 @@
</MudStack> </MudStack>
</CardHeaderContent> </CardHeaderContent>
</MudCardHeader> </MudCardHeader>
<MudCardContent Style="min-width: 28em; max-height: 60vh; max-width: 48vw; overflow: auto;"> <MudCardContent Class="pa-2" Style="min-width: 22em; max-height: 60vh; max-width: 34vw; overflow: auto;">
<MudText Typo="Typo.body1" Class="mb-3"> <MudText Typo="Typo.body2" Class="mb-2">
@T("Tools allow the LLM to perform targeted additional actions such as web searches or reading web pages.") @T("Tools allow the LLM to perform targeted additional actions such as web searches or reading web pages.")
</MudText> </MudText>
@if (!this.SupportsTools) @if (!this.SupportsTools)
@ -25,7 +25,7 @@
} }
else if (this.Disabled) else if (this.Disabled)
{ {
<MudAlert Dense="@true" Severity="Severity.Info" Variant="Variant.Outlined" Class="mb-3"> <MudAlert Dense="@true" Severity="Severity.Info" Variant="Variant.Outlined" Class="mb-2">
@T("Tool changes are locked while a response is running. Your current selection is shown below and applies again from the next message once the run is finished.") @T("Tool changes are locked while a response is running. Your current selection is shown below and applies again from the next message once the run is finished.")
</MudAlert> </MudAlert>
} }
@ -36,56 +36,62 @@
@if (this.SupportsTools && this.catalog.Count > 0) @if (this.SupportsTools && this.catalog.Count > 0)
{ {
@foreach (var item in this.catalog) @*
{ The striping sits on this wrapper: the rows share their parent with the
var isSelected = this.SelectedToolIds.Contains(item.Definition.Id); introduction and the occasional alert, which would shift the parity.
var isConfigured = item.ConfigurationState.IsConfigured; *@
var providerConfidenceHint = this.GetProviderConfidenceHint(item); <div class="tool-selection-rows">
<MudPaper Class="pa-2 mb-2 border rounded-lg"> @foreach (var item in this.catalog)
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween"> {
@* var isSelected = this.SelectedToolIds.Contains(item.Definition.Id);
Everything but the settings button switches the tool, so aiming for the var isConfigured = item.ConfigurationState.IsConfigured;
small switch is optional. The button spans that part of the row, which var providerConfidenceHint = this.GetProviderConfidenceHint(item);
keeps the settings button outside of it without any event plumbing. <div class="tool-selection-row">
*@ <MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Spacing="1">
<MudButton Variant="Variant.Text" Color="Color.Default" Class="px-2 py-1 justify-start" @*
Style="min-width:auto; text-transform:none; flex-grow:1;" Everything but the settings button switches the tool, so aiming for the
Disabled="@this.IsRowDisabled(item)" OnClick="@(async () => await this.ToggleToolFromRow(item))"> small switch is optional. The button spans that part of the row, which
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2"> keeps the settings button outside of it without any event plumbing.
@* *@
The switch only shows the state; the surrounding button does the switching. <MudButton Variant="Variant.Text" Color="Color.Default" Class="px-1 py-0 justify-start"
It therefore takes no pointer events at all: its label reaches past the visible Style="min-width:auto; text-transform:none; flex-grow:1;"
switch and would otherwise swallow the clicks landing in that strip. Disabled="@this.IsRowDisabled(item)" OnClick="@(async () => await this.ToggleToolFromRow(item))">
*@ <MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
<MudSwitch T="bool" Color="Color.Primary" Value="@isSelected" ReadOnly="@true" Disabled="@this.IsRowDisabled(item)" Style="pointer-events: none;" /> @*
<MudIcon Icon="@item.Implementation.Icon" Color="Color.Info" /> The switch only shows the state; the surrounding button does the switching.
@if (!item.IsActive) It therefore takes no pointer events at all: its label reaches past the visible
{ switch and would otherwise swallow the clicks landing in that strip.
<MudTooltip Text="@T("This tool has been disabled by your organization.")"> *@
<MudIcon Icon="@Icons.Material.Filled.Lock" Color="Color.Error" Size="Size.Small" /> <MudSwitch T="bool" Size="Size.Small" Color="Color.Primary" Value="@isSelected" ReadOnly="@true" Disabled="@this.IsRowDisabled(item)" Style="pointer-events: none;" />
<MudIcon Icon="@item.Implementation.Icon" Color="Color.Info" />
@if (!item.IsActive)
{
<MudTooltip Text="@T("This tool has been disabled by your organization.")">
<MudIcon Icon="@Icons.Material.Filled.Lock" Color="Color.Error" Size="Size.Small" />
</MudTooltip>
}
<MudTooltip Text="@item.Implementation.GetDescription()">
<MudText Typo="Typo.body1">@item.Implementation.GetDisplayName()</MudText>
</MudTooltip> </MudTooltip>
} </MudStack>
<MudTooltip Text="@item.Implementation.GetDescription()"> </MudButton>
<MudText Typo="Typo.body1">@item.Implementation.GetDisplayName()</MudText> <MudIconButton Icon="@Icons.Material.Filled.Settings" Size="Size.Small" OnClick="@(async () => await this.OpenSettings(item.Definition.Id))" />
</MudTooltip> </MudStack>
</MudStack> @if (!isConfigured)
</MudButton> {
<MudIconButton Icon="@Icons.Material.Filled.Settings" OnClick="@(async () => await this.OpenSettings(item.Definition.Id))" /> <MudText Typo="Typo.caption" Color="Color.Warning" Class="ml-2">@(string.IsNullOrWhiteSpace(item.ConfigurationState.Message) ? T("Required settings are missing. Configure this tool before enabling it.") : item.ConfigurationState.Message)</MudText>
</MudStack> }
@if (!isConfigured) @if (!item.IsActive)
{ {
<MudText Typo="Typo.caption" Color="Color.Warning">@(string.IsNullOrWhiteSpace(item.ConfigurationState.Message) ? T("Required settings are missing. Configure this tool before enabling it.") : item.ConfigurationState.Message)</MudText> <MudText Typo="Typo.caption" Color="Color.Warning" Class="ml-2">@T("This tool has been disabled by your organization.")</MudText>
} }
@if (!item.IsActive) @if (!string.IsNullOrWhiteSpace(providerConfidenceHint))
{ {
<MudText Typo="Typo.caption" Color="Color.Warning">@T("This tool has been disabled by your organization.")</MudText> <MudText Typo="Typo.caption" Color="Color.Warning" Class="ml-2">@providerConfidenceHint</MudText>
} }
@if (!string.IsNullOrWhiteSpace(providerConfidenceHint)) </div>
{ }
<MudText Typo="Typo.caption" Color="Color.Warning">@providerConfidenceHint</MudText> </div>
}
</MudPaper>
}
} }
</MudCardContent> </MudCardContent>
<MudCardActions> <MudCardActions>

View File

@ -470,3 +470,25 @@ tr:has(> .provider-group-header) .mud-icon-button {
padding-top: 0.25rem; padding-top: 0.25rem;
padding-bottom: 0.25rem; padding-bottom: 0.25rem;
} }
/*
* Rows of the tool selection which the chat and the assistants open from their footer. There will be
* far more tools than the ones we start with, so a row must not waste height: MudBlazor's settings
* button alone puts 12px of padding around a 24px icon, which makes a row 48px tall before the
* switch and the frame are counted at all. Size.Small takes most of that away; the rule below takes
* the rest, and it has to name the MudBlazor class to outweigh its specificity. Alternating rows
* carry a grey ground, which tells a long list apart better than a separator line does and costs no
* height at all. The colors are MudBlazor palette variables, so both grounds follow the theme.
*/
.tool-selection-rows > .tool-selection-row {
padding: 0.15rem 0.25rem;
border-radius: var(--mud-default-borderradius);
}
.tool-selection-rows > .tool-selection-row:nth-child(odd) {
background-color: var(--mud-palette-background-gray);
}
.tool-selection-row .mud-icon-button {
padding: 0.2em;
}