Improved the inner content scrolling to use the entire space available (#263)

This commit is contained in:
Thorsten Sommer 2025-01-21 13:40:47 +01:00 committed by GitHub
parent f50e041640
commit 14caf550ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 509 additions and 486 deletions

View File

@ -1,10 +1,12 @@
@using AIStudio.Chat @using AIStudio.Chat
<MudText Typo="Typo.h3" Class="mb-2 mr-3"> <div class="inner-scrolling-context">
@(this.Title)
</MudText>
<InnerScrolling HeaderHeight="6em"> <MudText Typo="Typo.h3" Class="mb-2 mr-3">
@(this.Title)
</MudText>
<InnerScrolling>
<ChildContent> <ChildContent>
<MudForm @ref="@(this.form)" @bind-IsValid="@(this.inputIsValid)" @bind-Errors="@(this.inputIssues)" FieldChanged="@this.TriggerFormChange" Class="pr-2"> <MudForm @ref="@(this.form)" @bind-IsValid="@(this.inputIsValid)" @bind-Errors="@(this.inputIssues)" FieldChanged="@this.TriggerFormChange" Class="pr-2">
<MudText Typo="Typo.body1" Align="Align.Justify" Class="mb-6"> <MudText Typo="Typo.body1" Align="Align.Justify" Class="mb-6">
@ -128,4 +130,5 @@
} }
</MudStack> </MudStack>
</FooterContent> </FooterContent>
</InnerScrolling> </InnerScrolling>
</div>

View File

@ -3,7 +3,7 @@
@inherits MSGComponentBase @inherits MSGComponentBase
<InnerScrolling FillEntireHorizontalSpace="@true" @ref="@this.scrollingArea" HeaderHeight="12.3em" MinWidth="36em"> <InnerScrolling FillEntireHorizontalSpace="@true" @ref="@this.scrollingArea" MinWidth="36em" Style="height: 100%">
<ChildContent> <ChildContent>
@if (this.ChatThread is not null) @if (this.ChatThread is not null)
{ {

View File

@ -7,17 +7,17 @@
@this.HeaderContent @this.HeaderContent
</div> </div>
} }
<div class="flex-auto overflow-auto"> <div class="flex-auto overflow-auto mb-3">
@this.ChildContent @this.ChildContent
<div @ref="@this.AnchorAfterChildContent"> <div style="max-height: 0.1em;" @ref="@this.AnchorAfterChildContent">
&nbsp; &nbsp;
</div> </div>
</div> </div>
@if (this.FooterContent is not null) @if (this.FooterContent is not null)
{ {
<MudPaper Class="pa-3 border-solid border rounded-lg"> <MudPaper Class="pa-3 mb-3 border-solid border rounded-lg">
@this.FooterContent @this.FooterContent
</MudPaper> </MudPaper>
} }

View File

@ -9,14 +9,6 @@ public partial class InnerScrolling : MSGComponentBase
[Parameter] [Parameter]
public bool FillEntireHorizontalSpace { get; set; } public bool FillEntireHorizontalSpace { get; set; }
/// <summary>
/// Set the height of anything above the scrolling content; usually a header.
/// What we do is calc(100vh - HeaderHeight). Means, you can use multiple measures like
/// 230px - 3em. Default is 3em.
/// </summary>
[Parameter]
public string HeaderHeight { get; set; } = "3em";
[Parameter] [Parameter]
public RenderFragment? HeaderContent { get; set; } public RenderFragment? HeaderContent { get; set; }
@ -35,6 +27,9 @@ public partial class InnerScrolling : MSGComponentBase
[Parameter] [Parameter]
public string? MinWidth { get; set; } public string? MinWidth { get; set; }
[Parameter]
public string Style { get; set; } = string.Empty;
[CascadingParameter] [CascadingParameter]
private MainLayout MainLayout { get; set; } = null!; private MainLayout MainLayout { get; set; } = null!;
@ -74,12 +69,14 @@ public partial class InnerScrolling : MSGComponentBase
#endregion #endregion
private string MinWidthStyle => string.IsNullOrWhiteSpace(this.MinWidth) ? string.Empty : $"min-width: {this.MinWidth};"; private string MinWidthStyle => string.IsNullOrWhiteSpace(this.MinWidth) ? string.Empty : $"min-width: {this.MinWidth}; ";
private string Styles => this.FillEntireHorizontalSpace ? $"height: calc(100vh - {this.HeaderHeight} - {this.MainLayout.AdditionalHeight}); overflow-x: auto; min-width: 0; {this.MinWidthStyle}" : $"height: calc(100vh - {this.HeaderHeight} - {this.MainLayout.AdditionalHeight}); flex-shrink: 0; {this.MinWidthStyle}"; private string TerminatedStyles => string.IsNullOrWhiteSpace(this.Style) ? string.Empty : $"{this.Style}; ";
private string Classes => this.FillEntireHorizontalSpace ? $"{this.Class} d-flex flex-column flex-grow-1" : $"{this.Class} d-flex flex-column"; private string Classes => this.FillEntireHorizontalSpace ? $"{this.Class} d-flex flex-column flex-grow-1" : $"{this.Class} d-flex flex-column";
private string Styles => $"flex-grow: 1; overflow: hidden; {this.TerminatedStyles}{this.MinWidthStyle}";
public async Task ScrollToBottom() public async Task ScrollToBottom()
{ {
await this.AnchorAfterChildContent.ScrollIntoViewAsync(this.JsRuntime); await this.AnchorAfterChildContent.ScrollIntoViewAsync(this.JsRuntime);

View File

@ -1,8 +1,9 @@
@attribute [Route(Routes.ABOUT)] @attribute [Route(Routes.ABOUT)]
<MudText Typo="Typo.h3" Class="mb-2">About MindWork AI Studio</MudText> <div class="inner-scrolling-context">
<MudText Typo="Typo.h3" Class="mb-2">About MindWork AI Studio</MudText>
<InnerScrolling HeaderHeight="6em"> <InnerScrolling>
<MudExpansionPanels Class="mb-3" MultiExpansion="@false"> <MudExpansionPanels Class="mb-3" MultiExpansion="@false">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Layers" HeaderText="Versions" IsExpanded="@true"> <ExpansionPanel HeaderIcon="@Icons.Material.Filled.Layers" HeaderText="Versions" IsExpanded="@true">
<MudText> <MudText>
@ -61,4 +62,5 @@
<MudMarkdown Value="@LICENSE" OverrideHeaderTypo="@Markdown.OverrideHeaderTypo"/> <MudMarkdown Value="@LICENSE" OverrideHeaderTypo="@Markdown.OverrideHeaderTypo"/>
</ExpansionPanel> </ExpansionPanel>
</MudExpansionPanels> </MudExpansionPanels>
</InnerScrolling> </InnerScrolling>
</div>

View File

@ -1,11 +1,12 @@
@using AIStudio.Settings.DataModel @using AIStudio.Settings.DataModel
@attribute [Route(Routes.ASSISTANTS)] @attribute [Route(Routes.ASSISTANTS)]
<MudText Typo="Typo.h3" Class="mb-2 mr-3"> <div class="inner-scrolling-context">
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
Assistants Assistants
</MudText> </MudText>
<InnerScrolling HeaderHeight="6em"> <InnerScrolling>
<MudText Typo="Typo.h4" Class="mb-2 mr-3"> <MudText Typo="Typo.h4" Class="mb-2 mr-3">
General General
@ -48,4 +49,5 @@
} }
</MudStack> </MudStack>
</InnerScrolling> </InnerScrolling>
</div>

View File

@ -2,7 +2,9 @@
@using AIStudio.Settings.DataModel @using AIStudio.Settings.DataModel
@inherits MSGComponentBase @inherits MSGComponentBase
<MudText Typo="Typo.h3" Class="mb-2 mr-3"> <div class="inner-scrolling-context">
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
@if (this.chatThread is not null && this.chatThread.WorkspaceId != Guid.Empty) @if (this.chatThread is not null && this.chatThread.WorkspaceId != Guid.Empty)
{ {
@($"Chat in Workspace \"{this.currentWorkspaceName}\"") @($"Chat in Workspace \"{this.currentWorkspaceName}\"")
@ -11,64 +13,51 @@
{ {
@("Temporary Chat") @("Temporary Chat")
} }
</MudText> </MudText>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings"/> <ProviderSelection @bind-ProviderSettings="@this.providerSettings"/>
@if (this.AreWorkspacesVisible) @if (this.AreWorkspacesVisible)
{ {
<MudSplitter Dimension="@this.ReadSplitterPosition" DimensionChanged="this.SplitterChanged" EnableSlide="@this.AreWorkspacesVisible" EnableMargin="@false" StartContentStyle="margin-right: 1em;" BarStyle="" EndContentStyle="margin-left: 1em;"> <MudSplitter Dimension="@this.ReadSplitterPosition" DimensionChanged="this.SplitterChanged" EnableSlide="@this.AreWorkspacesVisible" EnableMargin="@false" StartContentStyle="margin-right: 1em;" BarStyle="" EndContentStyle="margin-left: 1em;">
<StartContent> <StartContent>
@if (this.AreWorkspacesHidden)
{
<MudPaper Class="border border-solid rounded-lg">
<MudTooltip Text="Show your workspaces" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudIconButton Size="Size.Large" Icon="@this.WorkspaceSidebarToggleIcon" OnClick="() => this.ToggleWorkspaceSidebar()"/>
</MudTooltip>
</MudPaper>
}
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES)
{
@if ((this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.TOGGLE_SIDEBAR && this.SettingsManager.ConfigurationData.Workspace.IsSidebarVisible) || this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.SIDEBAR_ALWAYS_VISIBLE)
{
@if (this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.TOGGLE_SIDEBAR && this.SettingsManager.ConfigurationData.Workspace.IsSidebarVisible) @if (this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.TOGGLE_SIDEBAR && this.SettingsManager.ConfigurationData.Workspace.IsSidebarVisible)
{ {
<InnerScrolling HeaderHeight="12.3em" FillEntireHorizontalSpace="@true" Class="border border-solid rounded-lg" MinWidth="26em"> // Case: Sidebar can be toggled and is currently visible
<InnerScrolling FillEntireHorizontalSpace="@true" Class="border border-solid rounded-lg mb-3" MinWidth="26em">
<HeaderContent> <HeaderContent>
<MudTooltip Text="Hide your workspaces" Placement="@TOOLBAR_TOOLTIP_PLACEMENT"> <MudTooltip Text="Hide your workspaces" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudIconButton Size="Size.Large" Icon="@this.WorkspaceSidebarToggleIcon" OnClick="() => this.ToggleWorkspaceSidebar()"/> <MudIconButton Size="Size.Large" Icon="@this.WorkspaceSidebarToggleIcon" OnClick="() => this.ToggleWorkspaceSidebar()"/>
</MudTooltip> </MudTooltip>
</HeaderContent> </HeaderContent>
<ChildContent> <ChildContent>
<Workspaces @ref="this.workspaces" @bind-CurrentChatThread="@this.chatThread" /> <Workspaces @ref="this.workspaces" @bind-CurrentChatThread="@this.chatThread"/>
</ChildContent> </ChildContent>
</InnerScrolling> </InnerScrolling>
} }
else else
{ {
<InnerScrolling HeaderHeight="12.3em" FillEntireHorizontalSpace="@true" Class="border border-solid rounded-lg" MinWidth="26em"> // Case: Sidebar is always visible
<InnerScrolling FillEntireHorizontalSpace="@true" Class="border border-solid rounded-lg mb-3" MinWidth="26em">
<ChildContent> <ChildContent>
<Workspaces @ref="this.workspaces" @bind-CurrentChatThread="@this.chatThread" /> <Workspaces @ref="this.workspaces" @bind-CurrentChatThread="@this.chatThread"/>
</ChildContent> </ChildContent>
</InnerScrolling> </InnerScrolling>
} }
}
}
</StartContent> </StartContent>
<EndContent> <EndContent>
<ChatComponent <ChatComponent
@bind-ChatThread="@this.chatThread" @bind-ChatThread="@this.chatThread"
@bind-Provider="@this.providerSettings" @bind-Provider="@this.providerSettings"
Workspaces="@this.workspaces" Workspaces="@this.workspaces"
WorkspaceName="name => this.currentWorkspaceName = name" /> WorkspaceName="name => this.currentWorkspaceName = name"/>
</EndContent> </EndContent>
</MudSplitter> </MudSplitter>
} }
else if(this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES && this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.TOGGLE_SIDEBAR) else if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES && this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.TOGGLE_SIDEBAR)
{ {
<MudStack Row="@true" Style="width: 100%; overflow: hidden;"> // Case: Sidebar can be toggled and is currently hidden
<MudPaper Class="border border-solid rounded-lg"> <MudStack Row="@true" Style="width: 100%; overflow: hidden; height: 100%; flex-grow: 1; min-height: 0;">
<MudPaper Class="border border-solid rounded-lg mb-3">
<MudTooltip Text="Show your workspaces" Placement="@TOOLBAR_TOOLTIP_PLACEMENT"> <MudTooltip Text="Show your workspaces" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudIconButton Size="Size.Large" Icon="@this.WorkspaceSidebarToggleIcon" OnClick="() => this.ToggleWorkspaceSidebar()"/> <MudIconButton Size="Size.Large" Icon="@this.WorkspaceSidebarToggleIcon" OnClick="() => this.ToggleWorkspaceSidebar()"/>
</MudTooltip> </MudTooltip>
@ -80,20 +69,21 @@ else if(this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not
Workspaces="@this.workspaces" Workspaces="@this.workspaces"
WorkspaceName="name => this.currentWorkspaceName = name"/> WorkspaceName="name => this.currentWorkspaceName = name"/>
</MudStack> </MudStack>
} }
else else
{ {
// Case: Workspaces are disabled or shown in an overlay
<ChatComponent <ChatComponent
@bind-ChatThread="@this.chatThread" @bind-ChatThread="@this.chatThread"
@bind-Provider="@this.providerSettings" @bind-Provider="@this.providerSettings"
Workspaces="@this.workspaces" Workspaces="@this.workspaces"
WorkspaceName="name => this.currentWorkspaceName = name"/> WorkspaceName="name => this.currentWorkspaceName = name"/>
} }
@if ( @if (
this.SettingsManager.ConfigurationData.Workspace.StorageBehavior != WorkspaceStorageBehavior.DISABLE_WORKSPACES this.SettingsManager.ConfigurationData.Workspace.StorageBehavior != WorkspaceStorageBehavior.DISABLE_WORKSPACES
&& this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.TOGGLE_OVERLAY) && this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.TOGGLE_OVERLAY)
{ {
<MudDrawer @bind-Open="@this.workspaceOverlayVisible" Width="40em" Height="100%" Anchor="Anchor.Start" Variant="DrawerVariant.Temporary" Elevation="1"> <MudDrawer @bind-Open="@this.workspaceOverlayVisible" Width="40em" Height="100%" Anchor="Anchor.Start" Variant="DrawerVariant.Temporary" Elevation="1">
<MudDrawerHeader> <MudDrawerHeader>
<MudStack Row="@true" AlignItems="AlignItems.Center"> <MudStack Row="@true" AlignItems="AlignItems.Center">
@ -104,7 +94,8 @@ else
</MudStack> </MudStack>
</MudDrawerHeader> </MudDrawerHeader>
<MudDrawerContainer Class="ml-6"> <MudDrawerContainer Class="ml-6">
<Workspaces @ref="this.workspaces" @bind-CurrentChatThread="@this.chatThread" /> <Workspaces @ref="this.workspaces" @bind-CurrentChatThread="@this.chatThread"/>
</MudDrawerContainer> </MudDrawerContainer>
</MudDrawer> </MudDrawer>
} }
</div>

View File

@ -1,9 +1,10 @@
@attribute [Route(Routes.HOME)] @attribute [Route(Routes.HOME)]
<MudImage Src="svg/banner.svg" /> <div class="inner-scrolling-context">
<MudText Typo="Typo.h3" Class="mt-2 mb-2">Let's get started</MudText> <MudImage Src="svg/banner.svg" Style="max-height: 16em; width: 100%; object-fit: cover;" />
<MudText Typo="Typo.h3" Class="mt-2 mb-2">Let's get started</MudText>
<InnerScrolling HeaderHeight="288px - 8em"> <InnerScrolling>
<MudExpansionPanels Class="mb-3" MultiExpansion="@false"> <MudExpansionPanels Class="mb-3" MultiExpansion="@false">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.MenuBook" HeaderText="Introduction" IsExpanded="@true"> <ExpansionPanel HeaderIcon="@Icons.Material.Filled.MenuBook" HeaderText="Introduction" IsExpanded="@true">
@ -37,4 +38,5 @@
</ExpansionPanel> </ExpansionPanel>
</MudExpansionPanels> </MudExpansionPanels>
</InnerScrolling> </InnerScrolling>
</div>

View File

@ -1,9 +1,10 @@
@attribute [Route(Routes.SETTINGS)] @attribute [Route(Routes.SETTINGS)]
@using AIStudio.Components.Settings @using AIStudio.Components.Settings
<MudText Typo="Typo.h3" Class="mb-12">Settings</MudText> <div class="inner-scrolling-context">
<MudText Typo="Typo.h3" Class="mb-12">Settings</MudText>
<InnerScrolling HeaderHeight="10em"> <InnerScrolling>
<MudExpansionPanels Class="mb-3" MultiExpansion="@false"> <MudExpansionPanels Class="mb-3" MultiExpansion="@false">
<SettingsPanelProviders @bind-AvailableLLMProviders="@this.availableLLMProviders" /> <SettingsPanelProviders @bind-AvailableLLMProviders="@this.availableLLMProviders" />
<SettingsPanelEmbeddings AvailableLLMProvidersFunc="() => this.availableLLMProviders" @bind-AvailableEmbeddingProviders="@this.availableEmbeddingProviders" /> <SettingsPanelEmbeddings AvailableLLMProvidersFunc="() => this.availableLLMProviders" @bind-AvailableEmbeddingProviders="@this.availableEmbeddingProviders" />
@ -28,4 +29,5 @@
<SettingsPanelAssistantBias AvailableLLMProvidersFunc="() => this.availableLLMProviders" /> <SettingsPanelAssistantBias AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
<SettingsPanelAgentContentCleaner AvailableLLMProvidersFunc="() => this.availableLLMProviders" /> <SettingsPanelAgentContentCleaner AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
</MudExpansionPanels> </MudExpansionPanels>
</InnerScrolling> </InnerScrolling>
</div>

View File

@ -1,8 +1,9 @@
@attribute [Route(Routes.SUPPORTERS)] @attribute [Route(Routes.SUPPORTERS)]
<MudText Typo="Typo.h3" Class="mb-2">Supporters</MudText> <div class="inner-scrolling-context">
<MudText Typo="Typo.h3" Class="mb-2">Supporters</MudText>
<InnerScrolling HeaderHeight="6em"> <InnerScrolling>
<div class="border-solid border-2 rounded-lg pa-3 mb-6"> <div class="border-solid border-2 rounded-lg pa-3 mb-6">
<MudText Typo="Typo.h4" Class="mb-2">Our Titans</MudText> <MudText Typo="Typo.h4" Class="mb-2">Our Titans</MudText>
@ -60,4 +61,5 @@
</MudItem> </MudItem>
</MudGrid> </MudGrid>
</InnerScrolling> </InnerScrolling>
</div>

View File

@ -1,14 +1,15 @@
@attribute [Route(Routes.WRITER)] @attribute [Route(Routes.WRITER)]
@inherits MSGComponentBase @inherits MSGComponentBase
<MudText Typo="Typo.h3" Class="mb-2 mr-3"> <div class="inner-scrolling-context">
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
Writer Writer
</MudText> </MudText>
<PreviewExperimental/> <PreviewExperimental/>
<ProviderSelection @bind-ProviderSettings="@this.providerSettings"/> <ProviderSelection @bind-ProviderSettings="@this.providerSettings"/>
<InnerScrolling HeaderHeight="12.3em"> <InnerScrolling>
<ChildContent> <ChildContent>
<MudTextField <MudTextField
@ref="@this.textField" @ref="@this.textField"
@ -54,4 +55,5 @@
FullWidth="@true" FullWidth="@true"
UserAttributes="@USER_INPUT_ATTRIBUTES"/> UserAttributes="@USER_INPUT_ATTRIBUTES"/>
</FooterContent> </FooterContent>
</InnerScrolling> </InnerScrolling>
</div>

View File

@ -210,6 +210,6 @@
"type": "Project" "type": "Project"
} }
}, },
"net8.0/osx-x64": {} "net8.0/osx-arm64": {}
} }
} }

View File

@ -71,7 +71,25 @@
text-decoration-thickness: 2px; text-decoration-thickness: 2px;
} }
/* Fixed for MudBlazor, tooltips inside of navmenu */ /* Fix for MudBlazor, tooltips inside of navmenu */
.mud-navmenu .mud-tooltip-root { .mud-navmenu .mud-tooltip-root {
display: initial !important; display: initial !important;
} }
/* Context div for inner scrolling component */
.inner-scrolling-context {
display: flex;
flex-direction: column;
height: 100vh;
}
/* Fixed MudSplitter inside context div for inner scrolling component */
.inner-scrolling-context > .mud-splitter {
flex-grow: 1;
overflow: hidden;
}
/* Fixed the slider part of MudSplitter inside context div for inner scrolling component */
.inner-scrolling-context > .mud-splitter > .mud-slider > .mud-slider-container {
padding-bottom: 12px;
}

View File

@ -0,0 +1,2 @@
# v0.9.27, build 202 (2025-01-xx xx:xx UTC)
- Improved the inner content scrolling to use the entire space available.