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">
<MudCard>
<MudCardHeader>
<MudCardHeader Class="pa-2 pb-0">
<CardHeaderContent>
<MudStack Row="true" AlignItems="AlignItems.Center">
<MudText Typo="Typo.h5">@T("Tool Selection")</MudText>
@ -15,8 +15,8 @@
</MudStack>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent Style="min-width: 28em; max-height: 60vh; max-width: 48vw; overflow: auto;">
<MudText Typo="Typo.body1" Class="mb-3">
<MudCardContent Class="pa-2" Style="min-width: 22em; max-height: 60vh; max-width: 34vw; overflow: auto;">
<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.")
</MudText>
@if (!this.SupportsTools)
@ -25,7 +25,7 @@
}
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.")
</MudAlert>
}
@ -36,56 +36,62 @@
@if (this.SupportsTools && this.catalog.Count > 0)
{
@foreach (var item in this.catalog)
{
var isSelected = this.SelectedToolIds.Contains(item.Definition.Id);
var isConfigured = item.ConfigurationState.IsConfigured;
var providerConfidenceHint = this.GetProviderConfidenceHint(item);
<MudPaper Class="pa-2 mb-2 border rounded-lg">
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween">
@*
Everything but the settings button switches the tool, so aiming for the
small switch is optional. The button spans that part of the row, which
keeps the settings button outside of it without any event plumbing.
*@
<MudButton Variant="Variant.Text" Color="Color.Default" Class="px-2 py-1 justify-start"
Style="min-width:auto; text-transform:none; flex-grow:1;"
Disabled="@this.IsRowDisabled(item)" OnClick="@(async () => await this.ToggleToolFromRow(item))">
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
@*
The switch only shows the state; the surrounding button does the switching.
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.
*@
<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" />
@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" />
@*
The striping sits on this wrapper: the rows share their parent with the
introduction and the occasional alert, which would shift the parity.
*@
<div class="tool-selection-rows">
@foreach (var item in this.catalog)
{
var isSelected = this.SelectedToolIds.Contains(item.Definition.Id);
var isConfigured = item.ConfigurationState.IsConfigured;
var providerConfidenceHint = this.GetProviderConfidenceHint(item);
<div class="tool-selection-row">
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Spacing="1">
@*
Everything but the settings button switches the tool, so aiming for the
small switch is optional. The button spans that part of the row, which
keeps the settings button outside of it without any event plumbing.
*@
<MudButton Variant="Variant.Text" Color="Color.Default" Class="px-1 py-0 justify-start"
Style="min-width:auto; text-transform:none; flex-grow:1;"
Disabled="@this.IsRowDisabled(item)" OnClick="@(async () => await this.ToggleToolFromRow(item))">
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
@*
The switch only shows the state; the surrounding button does the switching.
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.
*@
<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 Text="@item.Implementation.GetDescription()">
<MudText Typo="Typo.body1">@item.Implementation.GetDisplayName()</MudText>
</MudTooltip>
</MudStack>
</MudButton>
<MudIconButton Icon="@Icons.Material.Filled.Settings" OnClick="@(async () => await this.OpenSettings(item.Definition.Id))" />
</MudStack>
@if (!isConfigured)
{
<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>
}
@if (!item.IsActive)
{
<MudText Typo="Typo.caption" Color="Color.Warning">@T("This tool has been disabled by your organization.")</MudText>
}
@if (!string.IsNullOrWhiteSpace(providerConfidenceHint))
{
<MudText Typo="Typo.caption" Color="Color.Warning">@providerConfidenceHint</MudText>
}
</MudPaper>
}
</MudStack>
</MudButton>
<MudIconButton Icon="@Icons.Material.Filled.Settings" Size="Size.Small" OnClick="@(async () => await this.OpenSettings(item.Definition.Id))" />
</MudStack>
@if (!isConfigured)
{
<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>
}
@if (!item.IsActive)
{
<MudText Typo="Typo.caption" Color="Color.Warning" Class="ml-2">@T("This tool has been disabled by your organization.")</MudText>
}
@if (!string.IsNullOrWhiteSpace(providerConfidenceHint))
{
<MudText Typo="Typo.caption" Color="Color.Warning" Class="ml-2">@providerConfidenceHint</MudText>
}
</div>
}
</div>
}
</MudCardContent>
<MudCardActions>

View File

@ -470,3 +470,25 @@ tr:has(> .provider-group-header) .mud-icon-button {
padding-top: 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;
}