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
16 changes: 6 additions & 10 deletions NET10/BlazorInteractiveServer/Components/Demo/NavigationDemo.razor
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@
<!-- Sidebar Demo -->
<div>
<h3 class="text-xl font-semibold mb-2 text-card-foreground">Sidebar</h3>
<p class="text-xs text-muted-foreground mb-3">Inline mode — <code class="font-mono bg-muted px-1 rounded">Inline="true"</code> keeps the sidebar inside the demo card. For full-viewport usage see <a href="/dashboard" class="underline">/dashboard</a>.</p>
<div class="space-y-4">
<Button OnClick="ToggleSidebar">
@(IsSidebarOpen ? "Close" : "Open") Sidebar
</Button>
<div class="relative border border-border rounded-lg overflow-hidden h-96 bg-background">
<Sidebar IsOpen="@IsSidebarOpen">
<div class="space-y-4">
<Sidebar Inline="true">
<div class="p-4 space-y-4">
<h4 class="font-semibold text-lg">Navigation</h4>
<nav class="space-y-2">
<a href="/dashboard" class="flex items-center space-x-2 px-3 py-2 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors">
Expand All @@ -48,18 +46,16 @@
<span class="material-symbols-outlined text-sm">folder</span>
<span>Components</span>
</a>
<a href="/dashboard" class="flex items-center space-x-2 px-3 py-2 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors">
<a href="#" class="flex items-center space-x-2 px-3 py-2 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors">
<span class="material-symbols-outlined text-sm">settings</span>
<span>Settings</span>
</a>
</nav>
</div>
</Sidebar>
<div class="@(IsSidebarOpen ? "ml-64" : "") transition-all p-6">
<div class="ml-64 p-6">
<h4 class="font-semibold mb-2 text-foreground">Main Content Area</h4>
<p class="text-sm text-muted-foreground">
Toggle the sidebar to see the smooth slide-in animation!
</p>
<p class="text-sm text-muted-foreground">Sidebar respects the bounded container thanks to <code class="font-mono bg-muted px-1 rounded">Inline="true"</code>.</p>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@page "/blocks"
@layout BlazorInteractiveServer.Components.Layout.DashboardLayout
@layout BlazorInteractiveServer.Components.Layout.BlocksLayout
@rendermode InteractiveServer
@using BlazorInteractiveServer.Components.UI

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
@page "/components/form/data-picker"
@layout BlazorInteractiveServer.Components.Layout.DashboardLayout
@rendermode InteractiveServer
@using BlazorInteractiveServer.Components.UI

<PageTitle>DataPicker | ShellUI</PageTitle>

<div class="space-y-8">
<div>
<h1 class="text-3xl font-bold text-foreground">DataPicker</h1>
<p class="text-muted-foreground mt-1">Generic typed picker with search, keyboard navigation, and templated rendering. The typed sibling of Combobox.</p>
</div>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-2 text-card-foreground">Installation</h2>
<div class="flex items-center justify-between gap-2 rounded-md border border-border bg-muted px-4 py-2">
<code class="text-sm font-mono">dotnet shellui add data-picker</code>
<CopyButton Text="dotnet shellui add data-picker" Class="shrink-0" />
</div>
</section>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-4 text-card-foreground">Usage</h2>

<h3 class="text-lg font-medium mb-2 text-card-foreground">Basic — string display, real domain type</h3>
<div class="mb-6 max-w-sm">
<DataPicker TItem="Framework" TKey="string"
Items="_frameworks"
Value="_picked"
ValueChanged="@(f => _picked = f)"
KeySelector="@(f => f.Id)"
DisplaySelector="@(f => f.Name)"
Placeholder="Select framework..." />
@if (_picked is not null)
{
<p class="mt-3 text-xs text-muted-foreground">Picked: <span class="font-mono">@_picked.Name</span> · <span class="font-mono">@_picked.Category</span></p>
}
</div>

<h3 class="text-lg font-medium mb-2 text-card-foreground">With templates — rich rows</h3>
<div class="mb-6 max-w-sm">
<DataPicker TItem="Framework" TKey="string"
Items="_frameworks"
Value="_pickedTemplated"
ValueChanged="@(f => _pickedTemplated = f)"
KeySelector="@(f => f.Id)"
DisplaySelector="@(f => f.Name)"
Placeholder="Pick with details...">
<OptionTemplate>
<div class="flex flex-col">
<span class="font-medium">@context.Name</span>
<span class="text-xs text-muted-foreground">@context.Category</span>
</div>
</OptionTemplate>
</DataPicker>
</div>

<h3 class="text-lg font-medium mb-2 text-card-foreground">Disabled</h3>
<div class="max-w-sm">
<DataPicker TItem="Framework" TKey="string"
Items="_frameworks"
KeySelector="@(f => f.Id)"
DisplaySelector="@(f => f.Name)"
Disabled="true"
Placeholder="Disabled..." />
</div>
</section>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-4 text-card-foreground">API Reference</h2>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-border">
<th class="text-left py-2 font-medium">Parameter</th>
<th class="text-left py-2 font-medium">Type</th>
<th class="text-left py-2 font-medium">Default</th>
<th class="text-left py-2 font-medium">Description</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-border"><td class="py-2">Items</td><td>IEnumerable&lt;TItem&gt;</td><td>—</td><td>Source list (required)</td></tr>
<tr class="border-b border-border"><td class="py-2">Value</td><td>TItem?</td><td>null</td><td>Currently selected item</td></tr>
<tr class="border-b border-border"><td class="py-2">ValueChanged</td><td>EventCallback&lt;TItem?&gt;</td><td>—</td><td>Fired when selection changes</td></tr>
<tr class="border-b border-border"><td class="py-2">KeySelector</td><td>Func&lt;TItem, TKey&gt;</td><td>—</td><td>Extract stable identity (required)</td></tr>
<tr class="border-b border-border"><td class="py-2">DisplaySelector</td><td>Func&lt;TItem, string&gt;?</td><td>ToString</td><td>Default row display</td></tr>
<tr class="border-b border-border"><td class="py-2">SearchPredicate</td><td>Func&lt;TItem, string, bool&gt;?</td><td>DisplaySelector Contains</td><td>Custom filter</td></tr>
<tr class="border-b border-border"><td class="py-2">SelectedTemplate</td><td>RenderFragment&lt;TItem&gt;?</td><td>—</td><td>Custom render for selected value in the trigger</td></tr>
<tr class="border-b border-border"><td class="py-2">OptionTemplate</td><td>RenderFragment&lt;TItem&gt;?</td><td>—</td><td>Custom render for each option row</td></tr>
<tr class="border-b border-border"><td class="py-2">Placeholder</td><td>string</td><td>"Select..."</td><td>Trigger placeholder</td></tr>
<tr class="border-b border-border"><td class="py-2">Disabled</td><td>bool</td><td>false</td><td>Disables the trigger</td></tr>
</tbody>
</table>
</div>
</section>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-2 text-card-foreground">Keyboard</h2>
<ul class="list-disc list-inside text-sm text-muted-foreground space-y-1">
<li><kbd class="rounded border border-border bg-muted px-1 font-mono text-xs">↑</kbd> / <kbd class="rounded border border-border bg-muted px-1 font-mono text-xs">↓</kbd> move highlighted row</li>
<li><kbd class="rounded border border-border bg-muted px-1 font-mono text-xs">Enter</kbd> select highlighted row</li>
<li><kbd class="rounded border border-border bg-muted px-1 font-mono text-xs">Esc</kbd> close</li>
</ul>
</section>
</div>

@code {
private record Framework(string Id, string Name, string Category);
private List<Framework> _frameworks = new()
{
new("next", "Next.js", "React"),
new("sveltekit", "SvelteKit", "Svelte"),
new("nuxt", "Nuxt.js", "Vue"),
new("remix", "Remix", "React"),
new("astro", "Astro", "Multi"),
new("qwik", "Qwik", "Fresh"),
new("solidstart", "SolidStart", "Solid"),
new("blazor", "Blazor", ".NET"),
};
private Framework? _picked;
private Framework? _pickedTemplated;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
@page "/components/form/multi-select"
@layout BlazorInteractiveServer.Components.Layout.DashboardLayout
@rendermode InteractiveServer
@using BlazorInteractiveServer.Components.UI

<PageTitle>MultiSelect | ShellUI</PageTitle>

<div class="space-y-8">
<div>
<h1 class="text-3xl font-bold text-foreground">MultiSelect</h1>
<p class="text-muted-foreground mt-1">Generic multi-value picker. Renders selected items as chips with inline remove; toggle rows in the popover to add/remove.</p>
</div>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-2 text-card-foreground">Installation</h2>
<div class="flex items-center justify-between gap-2 rounded-md border border-border bg-muted px-4 py-2">
<code class="text-sm font-mono">dotnet shellui add multi-select</code>
<CopyButton Text="dotnet shellui add multi-select" Class="shrink-0" />
</div>
</section>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-4 text-card-foreground">Usage</h2>

<h3 class="text-lg font-medium mb-2 text-card-foreground">Basic</h3>
<div class="mb-6 max-w-md">
<MultiSelect TItem="Tech" TKey="string"
Items="_stack"
Values="_picked"
ValuesChanged="@(vs => _picked = vs)"
KeySelector="@(t => t.Id)"
DisplaySelector="@(t => t.Name)"
Placeholder="Pick your stack..." />
<p class="mt-3 text-xs text-muted-foreground">Selected: <span class="font-mono">@_picked.Count</span></p>
</div>

<h3 class="text-lg font-medium mb-2 text-card-foreground">With option template</h3>
<div class="max-w-md">
<MultiSelect TItem="Tech" TKey="string"
Items="_stack"
Values="_pickedRich"
ValuesChanged="@(vs => _pickedRich = vs)"
KeySelector="@(t => t.Id)"
DisplaySelector="@(t => t.Name)"
Placeholder="Pick with details...">
<OptionTemplate>
<div class="flex flex-col">
<span class="font-medium">@context.Name</span>
<span class="text-xs text-muted-foreground">@context.Kind</span>
</div>
</OptionTemplate>
</MultiSelect>
</div>
</section>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-4 text-card-foreground">API Reference</h2>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-border">
<th class="text-left py-2 font-medium">Parameter</th>
<th class="text-left py-2 font-medium">Type</th>
<th class="text-left py-2 font-medium">Default</th>
<th class="text-left py-2 font-medium">Description</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-border"><td class="py-2">Items</td><td>IEnumerable&lt;TItem&gt;</td><td>—</td><td>Source list (required)</td></tr>
<tr class="border-b border-border"><td class="py-2">Values</td><td>List&lt;TItem&gt;</td><td>empty</td><td>Currently selected items</td></tr>
<tr class="border-b border-border"><td class="py-2">ValuesChanged</td><td>EventCallback&lt;List&lt;TItem&gt;&gt;</td><td>—</td><td>Fired when selection changes</td></tr>
<tr class="border-b border-border"><td class="py-2">KeySelector</td><td>Func&lt;TItem, TKey&gt;</td><td>—</td><td>Extract stable identity (required)</td></tr>
<tr class="border-b border-border"><td class="py-2">ChipTemplate</td><td>RenderFragment&lt;TItem&gt;?</td><td>—</td><td>Custom render for chips in the trigger</td></tr>
<tr class="border-b border-border"><td class="py-2">OptionTemplate</td><td>RenderFragment&lt;TItem&gt;?</td><td>—</td><td>Custom render for each option row</td></tr>
<tr class="border-b border-border"><td class="py-2">Disabled</td><td>bool</td><td>false</td><td>Disables the trigger</td></tr>
</tbody>
</table>
</div>
</section>
</div>

@code {
private record Tech(string Id, string Name, string Kind);
private List<Tech> _stack = new()
{
new("blazor", "Blazor", "Framework"),
new("tailwind", "Tailwind CSS", "Styling"),
new("net10", ".NET 10", "Runtime"),
new("csharp14", "C# 14", "Language"),
new("apex", "ApexCharts", "Charts"),
new("shadcn", "shadcn/ui", "Inspiration"),
};
private List<Tech> _picked = new();
private List<Tech> _pickedRich = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
@page "/components/form/tag-input"
@layout BlazorInteractiveServer.Components.Layout.DashboardLayout
@rendermode InteractiveServer
@using BlazorInteractiveServer.Components.UI

<PageTitle>TagInput | ShellUI</PageTitle>

<div class="space-y-8">
<div>
<h1 class="text-3xl font-bold text-foreground">TagInput</h1>
<p class="text-muted-foreground mt-1">Free-form tag entry. Enter to confirm, Backspace on empty removes the last, and pasting comma/newline-separated text bulk-adds.</p>
</div>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-2 text-card-foreground">Installation</h2>
<div class="flex items-center justify-between gap-2 rounded-md border border-border bg-muted px-4 py-2">
<code class="text-sm font-mono">dotnet shellui add tag-input</code>
<CopyButton Text="dotnet shellui add tag-input" Class="shrink-0" />
</div>
</section>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-4 text-card-foreground">Usage</h2>

<h3 class="text-lg font-medium mb-2 text-card-foreground">Basic</h3>
<div class="mb-6 max-w-md">
<TagInput Tags="_tags" TagsChanged="@(ts => _tags = ts)" Placeholder="Add tag..." />
<p class="mt-3 text-xs text-muted-foreground">Current: <span class="font-mono">[@string.Join(", ", _tags)]</span></p>
</div>

<h3 class="text-lg font-medium mb-2 text-card-foreground">Max 5 tags, allow duplicates</h3>
<div class="mb-6 max-w-md">
<TagInput Tags="_tagsCapped"
TagsChanged="@(ts => _tagsCapped = ts)"
Placeholder="Max 5..."
MaxTags="5"
AllowDuplicates="true" />
<p class="mt-3 text-xs text-muted-foreground">@_tagsCapped.Count / 5</p>
</div>

<h3 class="text-lg font-medium mb-2 text-card-foreground">Disabled</h3>
<div class="max-w-md">
<TagInput Tags="@(new List<string> { "readonly", "example" })" Disabled="true" />
</div>
</section>

<section class="rounded-lg border border-border bg-card p-6">
<h2 class="text-xl font-semibold mb-4 text-card-foreground">API Reference</h2>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-border">
<th class="text-left py-2 font-medium">Parameter</th>
<th class="text-left py-2 font-medium">Type</th>
<th class="text-left py-2 font-medium">Default</th>
<th class="text-left py-2 font-medium">Description</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-border"><td class="py-2">Tags</td><td>List&lt;string&gt;</td><td>empty</td><td>Current tags</td></tr>
<tr class="border-b border-border"><td class="py-2">TagsChanged</td><td>EventCallback&lt;List&lt;string&gt;&gt;</td><td>—</td><td>Fired when tags change</td></tr>
<tr class="border-b border-border"><td class="py-2">Placeholder</td><td>string</td><td>"Add tag..."</td><td>Placeholder while empty</td></tr>
<tr class="border-b border-border"><td class="py-2">MaxTags</td><td>int?</td><td>null</td><td>Cap the number of tags</td></tr>
<tr class="border-b border-border"><td class="py-2">AllowDuplicates</td><td>bool</td><td>false</td><td>Allow identical tags (case-insensitive by default)</td></tr>
<tr class="border-b border-border"><td class="py-2">Separators</td><td>string[]</td><td>",", ";", "\t", "\n"</td><td>Split chars for paste-to-bulk-add</td></tr>
<tr class="border-b border-border"><td class="py-2">Disabled</td><td>bool</td><td>false</td><td>Disables input and remove buttons</td></tr>
</tbody>
</table>
</div>
</section>
</div>

@code {
private List<string> _tags = new() { "blazor", "shellui" };
private List<string> _tagsCapped = new();
}
Loading
Loading