docs: improve stability and usability (#2473)

* 🐛 (docs): correct display abnormalities in Algolia Search

* 📝 : update outdated URLs

* 🆕 (docs): add type switch in components nav

* 📝 : update front matter

* remove a demo

* Update Search.razor
This commit is contained in:
capdiem
2025-07-01 08:45:12 +08:00
committed by GitHub
parent 0dc6931553
commit 77a0ac5b99
27 changed files with 173 additions and 153 deletions

View File

@@ -21,7 +21,7 @@
- breaks:
Convert '\n' in paragraphs into <br>
- linkify:
https://blazor.masastack.com
https://docs.masastack.com
- typographer:
""Smartypants, double quotes"" and 'single quotes'
";

View File

@@ -1,61 +0,0 @@
<MRow>
@for (var i = 0; i < _bars.Count; i++)
{
var bar = _bars[i];
<MCol @key="i"
Cols="12"
Sm="12"
Md="6"
Class="my-4">
<MCard Color="grey lighten-4"
Flat
Height="200">
<MToolbar Color="@bar.Class"
Dark="@bar.Dark">
<MAppBarNavIcon></MAppBarNavIcon>
<MToolbarTitle>Title</MToolbarTitle>
<MSpacer></MSpacer>
<MButton Icon>
<MIcon>mdi-magnify</MIcon>
</MButton>
<MButton Icon>
<MIcon>mdi-heart</MIcon>
</MButton>
<MButton Icon>
<MIcon>mdi-dots-vertical</MIcon>
</MButton>
</MToolbar>
</MCard>
</MCol>
}
</MRow>
@code {
class Bar
{
public string Class { get; set; }
public bool Dark { get; set; }
}
private List<Bar> _bars = new List<Bar>
{
new Bar
{
Class=""
},
new Bar
{
Class="class",
Dark=true
},
new Bar
{
Class="primary",
Dark=true
},
new Bar
{
Class="elevation-0"
}
};
}

View File

@@ -18,7 +18,7 @@
@if (!IsAllComponentsPage)
{
<MTabs Value="IsApiTab.ToString()" Color="primary" BackgroundColor="transparent" Class="default-tabs m-bar--underline mb-9">
<MTabs Value="IsApiTab.ToString()" Color="primary" BackgroundColor="transparent" Class="default-tabs m-bar--underline mb-5">
<MTab Value="@("False")" OnClick="@(() => NavigateToTab(""))">@I18n.T("demo")</MTab>
<MTab Value="@("True")" OnClick="@(() => NavigateToTab("api"))">API</MTab>
</MTabs>

View File

@@ -91,9 +91,3 @@ It is possible to update the appearance of a toolbar in response to changes in a
In this example we offset our card onto the extended content area of a toolbar using the extended prop.
<masa-example file="Examples.components.toolbars.FlexibleAndCardToolbar"></masa-example>
#### Variations
A **MToolbar** has multiple variations that can be applied with themes and helper classes. These range from light and dark themes, colored and transparent.
<masa-example file="Examples.components.toolbars.Variations"></masa-example>

View File

@@ -87,9 +87,3 @@ related:
在本例中,我们使用 `Extended` 属性将卡片偏移到工具栏的扩展内容区域。
<masa-example file="Examples.components.toolbars.FlexibleAndCardToolbar"></masa-example>
#### 变量
**MToolbar** 有多个变量,可以应用主题和辅助类。 这些主题包括浅色和深色的主题、彩色和透明。
<masa-example file="Examples.components.toolbars.Variations"></masa-example>

View File

@@ -18,7 +18,7 @@
}
else if (item.HasChildren())
{
<DefaultListGroup Item="item"/>
<DefaultListGroup Item="item" GroupContent="@GroupContent"/>
}
else if (ItemContent != null)
{
@@ -34,8 +34,6 @@
@code {
[Inject] private IJSRuntime JS { get; set; } = null!;
[Parameter] public List<TItem> Items { get; set; } = new();
[Parameter] public RenderFragment<TItem>? ItemContent { get; set; }
@@ -43,4 +41,6 @@
[Parameter] public bool Routable { get; set; }
[Parameter] public string? Class { get; set; }
[Parameter] public RenderFragment<string?>? GroupContent { get; set; }
}

View File

@@ -16,6 +16,7 @@
<NavItemContent Item="Item"/>
</ActivatorContent>
<ChildContent>
@GroupContent?.Invoke(Item?.Title)
@if (Item?.Title == "ui-components" && ComponentsGroupByType)
{
<TypedList Items="@Item.Children"/>
@@ -58,6 +59,9 @@
[Parameter]
public bool SubGroup { get; set; }
[Parameter]
public RenderFragment<string?>? GroupContent { get; set; }
private List<string?> _group = new();

View File

@@ -1,20 +1,24 @@
<div class="d-flex flex-column align-start mb-2 app-heading">
<h1 class="m-heading text-h3 text-sm-h3" id="@Meta.Title.HashToAnchorString()">@Meta.Title</h1>
@if (!string.IsNullOrWhiteSpace(Meta.Tag))
{
<MChip Class="mt-2 mr-2" Small Color="primary">@Meta.Tag</MChip>
}
@if (AdditionalTags.Any())
{
foreach (string item in AdditionalTags)
{
<MChip Class="mt-2 mr-2" Small Color="primary">@item</MChip>
}
}
</div>
<MMarkdownIt Source="@Meta.Description" NoWrapper Scope="desc"></MMarkdownIt>
<div class="@(string.IsNullOrWhiteSpace(Meta.Description) ? "" : "mt-n3") mb-4">
@if (!string.IsNullOrWhiteSpace(Meta.Tag))
{
<MChip Class="mr-2" Small Color="primary">@Meta.Tag</MChip>
}
@if (AdditionalTags.Any())
{
foreach (var item in AdditionalTags)
{
<MChip Class="mr-2" Small Color="primary">@item</MChip>
}
}
</div>
@ChildContent
@code {

View File

@@ -7,8 +7,8 @@
{
<MDivider Inset Class="mt-3 mb-1"></MDivider>
<MSubheader class="text--primary font-weight-black text-uppercase surface-container"
style="padding-left: 72px; position: sticky; top: 0; z-index: 1;">
<MSubheader class="text--primary font-weight-black text-uppercase typed-list-header">
<MIcon>mdi-circle-small</MIcon>
@I18n.T("component-type." + groupItem.Key)
</MSubheader>
}

View File

@@ -1,3 +1,3 @@
namespace Masa.Docs.Shared.Models;
namespace Masa.Docs.Core.Models;
public record Config(bool NavComponentsGroupByType);

View File

@@ -1,3 +1,6 @@
namespace Masa.Docs.Core.Models;
public record Project(string Name, string? Repo, string IconUrl, string RepoUrl, string? Path = null);
public record Project(string? Key, string Name, string? Repo, string IconUrl, string RepoUrl, string? Path = null)
{
public bool IsValid => Key is not null;
}

View File

@@ -3,28 +3,38 @@
@inject IJSRuntime Js
@inject I18n I18n
<div id="docsearch" style="@Style" class="@Class"></div>
<div id="docsearch" class="mr-2 @Display"></div>
@code {
[CascadingParameter(Name = "project")]
public string? Project { get; set; }
[CascadingParameter(Name = "Env")]
public string? Env { get; set; }
[Parameter]
public Project? Project { get; set; }
[Parameter]
public string? Class { get; set; }
[Parameter]
public string? Style { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
private Project? _prevProject;
private string Display => Project?.IsValid is not true ? "d-none" : string.Empty;
protected override void OnParametersSet()
{
if (firstRender)
base.OnParametersSet();
if (_prevProject != Project)
{
await InitDocSearchAsync();
_prevProject = Project;
if (Project?.IsValid is true)
{
_ = InitDocSearchAsync();
}
}
}
@@ -32,9 +42,9 @@
{
try
{
if (Project is null) return;
if (Project?.IsValid is not true) return;
var currentLanguage = I18n!.Culture.TwoLetterISOLanguageName;
var indexName = Env + I18n.Culture.TwoLetterISOLanguageName + "_" + Project;
var indexName = Env + I18n.Culture.TwoLetterISOLanguageName + "_" + Project.Key;
await Js.InvokeVoidAsync("addDocSearch", indexName, currentLanguage, I18n.T("Search"));
}
catch
@@ -42,4 +52,5 @@
// ignored
}
}
}
}

View File

@@ -37,9 +37,6 @@
[Parameter]
public Project? ProjectInfo { get; set; }
[Parameter]
public Config? Config { get; set; }
[Parameter]
public EventCallback<string> OnCultureChanged { get; set; }

View File

@@ -14,10 +14,7 @@
<MSpacer/>
}
@if (ProjectInfo != null)
{
<Search @ref="_algoliaSearch" Class="mr-2"/>
}
<Search @ref="_algoliaSearch" Project="@ProjectInfo"/>
<LanguageMenu OnCultureChanged="OnCultureChangedLocal"/>

View File

@@ -23,18 +23,17 @@
OnDotClick="@HandleOnDotClick"
OnSettingsClick="@HandleSettingsClick"
HideAppBarNavIcon="@_hideAppBarNavIcon"
ProjectInfo="@_projectInfo"
Config="@_config"/>
ProjectInfo="@_projectInfo"/>
</CascadingValue>
<CascadingValue Value="this" IsFixed>
<CascadingValue Value="@(_config?.NavComponentsGroupByType ?? true)"
<CascadingValue Value="@(Config?.NavComponentsGroupByType ?? true)"
Name="ComponentsGroupByType">
@Body
</CascadingValue>
</CascadingValue>
<Settings @bind-Value="_showSettings" @bind-Config="@_config"/>
<Settings @bind-Value="_showSettings" Config="@Config" ConfigChanged="@OnConfigChanged"/>
<MobileMenuList @bind-Value="_showMobileMenuList"/>
</ChildContent>

View File

@@ -14,9 +14,9 @@ public partial class BaseLayout
private Project? _projectInfo;
private CultureInfo? _culture;
private Dictionary<string, Project> _projectMap = new();
private Config? _config;
internal Action? OnAppBarNavIconClick { get; set; }
internal Config? Config { get; set; }
protected override void OnInitialized()
{
@@ -89,7 +89,8 @@ public partial class BaseLayout
private async Task InitConfig()
{
_config = await LocalStorage.GetItemAsync<Config>("masablazor@config");
Config = await LocalStorage.GetItemAsync<Config>("masablazor@config")
?? new Config(false);
}
private void NavigationManagerOnLocationChanged(object? sender, LocationChangedEventArgs e)
@@ -109,7 +110,8 @@ public partial class BaseLayout
if (_project is not null && _projectMap.TryGetValue(_project, out _projectInfo)) return;
_projectInfo = new Project(
"MASA Stack",
Key: null,
"MASA Docs",
null,
"https://cdn.masastack.com/stack/images/logo/MASAStack/logo.png?x-oss-process=image/resize,h_24,m_lfit",
"https://github.com/masastack");
@@ -169,14 +171,19 @@ public partial class BaseLayout
StateHasChanged();
}
internal void OnConfigChanged(Config? config)
{
Config = config;
_ = LocalStorage.SetItemAsync("masablazor@config", Config);
}
private void SetEnv()
{
var uri = NavigationManager.BaseUri.Replace("http://", "").Replace("https://", "").TrimEnd('/');
_env = uri switch
{
"docs.masastack.com" or "blazor.masastack.com" => "prd_",
"blazor-dev.masastack.com" or "docs-dev.masastack.com" => "dev_",
_ => "local_"
"docs.masastack.com" => "prd_",
_ => "local_"
};
}
@@ -201,4 +208,4 @@ public partial class BaseLayout
{
NavigationManager.LocationChanged -= NavigationManagerOnLocationChanged;
}
}
}

View File

@@ -4,7 +4,9 @@
@using Masa.Blazor.Extensions
<NavDrawer @bind-Value="_showDrawer"
RTL="MasaBlazor.RTL" />
RTL="MasaBlazor.RTL"
Config="@BaseLayout.Config"
ConfigChanged="@BaseLayout.OnConfigChanged"/>
<MScrollToTarget RootMarginTop="@($"-{Offset + 4}px")"
AutoRootMargin="AutoRootMargin.Bottom"
@@ -14,11 +16,19 @@
</MMain>
<Toc RTL="@MasaBlazor.RTL"
ActiveItem="@context.ActiveTarget" />
ActiveItem="@context.ActiveTarget"/>
</MScrollToTarget>
<FabTransition>
<MButton Show="_showBackTop" Large Fab Fixed Bottom Right Class="transition-swing" Color="primary" OnClick="ToTopAsync">
<MButton Show="_showBackTop"
Large
Fab
Fixed
Bottom
Right
Class="transition-swing"
Color="primary"
OnClick="@ToTopAsync">
<MIcon>mdi-chevron-up</MIcon>
</MButton>
</FabTransition>

View File

@@ -0,0 +1,29 @@
<MSwitch Inset
HideDetails="@true"
Value="@(Config?.NavComponentsGroupByType ?? false)"
ValueChanged="@OnGroupByTypeChange"
TValue="bool"
Class="mt-0"
Dense="@Dense"
></MSwitch>
@code {
[Parameter]
public bool Dense { get; set; }
[Parameter]
public Config? Config { get; set; }
[Parameter]
public EventCallback<Config?> ConfigChanged { get; set; }
private async Task OnGroupByTypeChange(bool value)
{
var newConfig = Config is null
? new Config(value)
: Config with { NavComponentsGroupByType = value };
await ConfigChanged.InvokeAsync(newConfig);
}
}

View File

@@ -1,8 +1,8 @@
@inject DocService DocService
@inject MasaBlazor MasaBlazor
@inherits NextTickComponentBase
@implements INavDrawer
@inject IJSRuntime JSRuntime
@inject I18n I18n
<MNavigationDrawer Value="Value"
ValueChanged="ValueChanged"
@@ -16,11 +16,22 @@
<CascadingValue Value="this" IsFixed>
<DefaultList Class="doc-list-nav"
Routable
Items="Navs"/>
Items="Navs">
<GroupContent>
@if (context == "ui-components")
{
<div class="d-flex align-center justify-space-between"
style="margin-left: 72px; margin-right: 16px; margin-bottom: 8px;">
<span class="text--secondary text-caption">@I18n.T("nav-component-group-by-type")</span>
<NavComponentsTypeSwitch Config="@Config" ConfigChanged="@ConfigChanged" Dense/>
</div>
}
</GroupContent>
</DefaultList>
</CascadingValue>
</ChildContent>
<AppendContent>
<NavDrawerAppend />
<NavDrawerAppend/>
</AppendContent>
</MNavigationDrawer>
@@ -41,6 +52,12 @@
[Parameter]
public EventCallback<bool?> ValueChanged { get; set; }
[Parameter]
public Config? Config { get; set; }
[Parameter]
public EventCallback<Config?> ConfigChanged { get; set; }
private string? _lastProject;
private List<NavItem> Navs { get; set; } = new();
@@ -61,14 +78,24 @@
Navs = await DocService.ReadNavsAsync(Project);
// delay 500ms in docs.js
NextTick(() => ScrollIntoView("#nav-drawer"));
_ = Task.Run(async () =>
{
await Task.Delay(500);
await ScrollIntoView("#nav-drawer");
});
}
}
private async Task ScrollIntoView(string ancestorSelector)
{
await JSRuntime.InvokeVoidAsync("activeNavItemScrollIntoView", ancestorSelector);
var target = $"{ancestorSelector} .m-list-item--active:not(.m-list-group__header)";
var container = $"{ancestorSelector} .m-navigation-drawer__content";
await JSRuntime.InvokeVoidAsync(
JsInteropConstants.ScrollToTarget,
target,
container,
Config?.NavComponentsGroupByType is true ? 48 : 0,
"smooth");
}
}

View File

@@ -59,13 +59,7 @@
</MBadge>
<div class="m-messages">@I18n.T("nav-component-group-by-type-desc")</div>
</div>
<MSwitch Inset
HideDetails="@true"
Value="@(Config?.NavComponentsGroupByType ?? true)"
ValueChanged="@OnGroupByTypeChange"
TValue="bool"
Class="mt-0"
></MSwitch>
<NavComponentsTypeSwitch Config="@Config" ConfigChanged="@ConfigChanged"/>
</div>
}
</MContainer>
@@ -87,15 +81,7 @@
public Config? Config { get; set; }
[Parameter]
public EventCallback<Config> ConfigChanged { get; set; }
private async Task OnGroupByTypeChange(bool value)
{
var newConfig = Config is null ? new Config(value) : Config with { NavComponentsGroupByType = value };
await ConfigChanged.InvokeAsync(newConfig);
_ = LocalStorage.SetItemAsync("masablazor@config", newConfig);
}
public EventCallback<Config?> ConfigChanged { get; set; }
private void ToggleRtl(bool rtl)
{

View File

@@ -11,4 +11,5 @@
@using Masa.Docs.Core
@using Masa.Docs.Core.Shared
@using Masa.Docs.Core.Components
@using Masa.Blazor.Core.I18n
@using Masa.Blazor.Core.I18n
@using Masa.Docs.Core.Models

View File

@@ -626,4 +626,19 @@ app-alert p {
.theme--dark.typography-active-item {
background-color: rgba(var(--m-theme-surface-container));
border-color: rgba(var(--m-theme-surface-container));
}
.typed-list-header {
padding-left: 48px;
position: sticky;
top: 0;
z-index: 1;
background-color: rgba(var(--m-theme-surface-container));
color: rgba(var(--m-theme-on-surface));
}
.theme--dark .typed-list-header,
.theme--light .typed-list-header {
background-color: rgba(var(--m-theme-surface));
color: rgba(var(--m-theme-on-surface));
}

View File

@@ -1,5 +1,6 @@
{
"blazor": {
"key": "blazor",
"name": "MASA Blazor",
"path": "Masa.Blazor.Docs",
"repo": "Masa.Blazor",
@@ -7,6 +8,7 @@
"repoUrl": "https://github.com/masastack/MASA.Blazor"
},
"framework": {
"key": "framework",
"name": "MASA Framework",
"path": "Masa.Framework.Docs",
"repo": "Masa.Framework",
@@ -14,6 +16,7 @@
"repoUrl": "https://github.com/masastack/MASA.Framework"
},
"stack": {
"key": "stack",
"name": "MASA Stack",
"path": "Masa.Stack.Docs",
"repo": "Masa.Stack",

View File

@@ -565,7 +565,7 @@
"services": "Services",
"misc": "Miscellaneous"
},
"nav-component-group-by-type": "Components grouped by type",
"nav-component-group-by-type": "Grouped by type",
"nav-component-group-by-type-desc": "Group the components in the left navigation by type"
}

View File

@@ -654,6 +654,6 @@
"services": "服务",
"misc": "其他"
},
"nav-component-group-by-type": "组件按类型分",
"nav-component-group-by-type-desc": "左侧导航的组件列表按类型分"
"nav-component-group-by-type": "按类型分",
"nav-component-group-by-type-desc": "左侧导航的组件列表按类型分"
}