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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="QRCoder" Version="1.8.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.9" />
<PackageReference Include="Blazor-ApexCharts" Version="6.0.2" />
</ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions NET10/BlazorInteractiveServer/Components/App.razor
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#blazor-error-ui a { color: inherit; text-decoration: underline; }
#blazor-error-ui .dismiss { cursor: pointer; margin-left: 1rem; }
</style>
<link href="css/charts.css" rel="stylesheet" />
</head>

<body class="bg-background text-foreground">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,47 +41,24 @@
<!-- Loading Demo -->
<div>
<h3 class="text-xl font-semibold mb-2 text-card-foreground">Loading Components</h3>
<div class="flex flex-wrap gap-8 items-center">
<div class="text-center">
<Loading Variant="spinner" Size="sm" />
<p class="text-xs mt-2">Spinner SM</p>
</div>
<div class="text-center">
<Loading Variant="spinner" />
<p class="text-xs mt-2">Spinner</p>
</div>
<div class="text-center">
<Loading Variant="dots" />
<p class="text-xs mt-2">Dots</p>
</div>
<div class="text-center">
<Loading Variant="ring" />
<p class="text-xs mt-2">Ring</p>
</div>
<div class="text-center">
<Loading Variant="pulse" />
<p class="text-xs mt-2">Pulse</p>
</div>
<div class="text-center">
<Loading Variant="bars" />
<p class="text-xs mt-2">Bars</p>
</div>
<div class="text-center">
<Loading Variant="bars-vertical" />
<p class="text-xs mt-2">Bars Vertical</p>
</div>
<div class="text-center">
<Loading Variant="bars-pulse" />
<p class="text-xs mt-2">Bars Pulse</p>
</div>
<div class="text-center">
<Loading Variant="grid" />
<p class="text-xs mt-2">Grid</p>
</div>
<div class="text-center">
<Loading Variant="orbit" />
<p class="text-xs mt-2">Orbit</p>
</div>
<div class="grid grid-cols-3 gap-3 sm:grid-cols-5">
@foreach (var (variant, label) in _loadingVariants)
{
<div class="flex h-24 flex-col items-center justify-between rounded-lg border border-border bg-background p-3">
<div class="flex h-12 w-full items-center justify-center">
<Loading Variant="@variant" Text="@(variant == "shimmer" ? "Thinking..." : null)" />
</div>
<p class="text-xs text-muted-foreground">@label</p>
</div>
}
</div>
<div class="mt-4 flex flex-wrap items-center gap-6">
<Loading Variant="logo" Size="lg" />
<Loading Variant="rows" Size="lg" />
<Loading Variant="sequence" Size="lg" />
<Loading Variant="snake" Size="lg" />
<Loading Variant="ring" Size="lg" Class="text-emerald-500" />
<Loading Variant="wave" Class="text-muted-foreground" />
</div>
</div>

Expand Down Expand Up @@ -189,7 +166,12 @@
Title="No files found"
Description="Get started by uploading your first file.">
<Action>
<Button>Upload File</Button>
<label for="empty-state-upload" class="inline-flex h-10 cursor-pointer items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90">Upload File</label>
<InputFile id="empty-state-upload" class="hidden" OnChange="OnEmptyStateFileSelected" />
@if (_emptyStateFile != null)
{
<p class="mt-2 text-sm text-muted-foreground">Selected: @_emptyStateFile</p>
}
</Action>
</EmptyState>
</div>
Expand Down Expand Up @@ -374,6 +356,15 @@
</section>

@code {
private readonly (string Variant, string Label)[] _loadingVariants =
{
("logo", "ShellUI Logo"), ("spinner", "Spinner"), ("ring", "Ring"), ("dual-ring", "Dual Ring"), ("activity", "Activity"), ("chase", "Chase"),
("orbit", "Orbit"), ("ripple", "Ripple"), ("dots", "Dots"), ("typing", "Typing"), ("wave", "Wave"),
("bars", "Bars"), ("bars-vertical", "Bars Vertical"), ("bars-pulse", "Bars Pulse"), ("grid", "Grid"), ("snake", "Snake"),
("rows", "Rows"), ("columns", "Columns"), ("sequence", "Sequence"), ("twinkle", "Twinkle"), ("pulse", "Pulse"),
("progress", "Progress"), ("shimmer", "Shimmer")
};

private bool _showCommand = false;
private bool _collapsibleOpen = false;
private bool _stepperSubmitted = false;
Expand Down Expand Up @@ -437,6 +428,10 @@
await ShowCommandChanged.InvokeAsync(value);
}

private string? _emptyStateFile;

private void OnEmptyStateFileSelected(InputFileChangeEventArgs e) => _emptyStateFile = e.File.Name;

private async Task HandleCommandSelected(CommandItem command)
{
await OnCommandSelected.InvokeAsync(command);
Expand Down
168 changes: 168 additions & 0 deletions NET10/BlazorInteractiveServer/Components/Demo/NewComponentsDemo.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<section class="border border-border rounded-lg p-6 bg-card">
<h2 class="text-2xl font-semibold mb-1 text-card-foreground">Stat Card</h2>
<p class="text-sm text-muted-foreground mb-4">KPI tiles with a trend badge.</p>
<div class="grid gap-4 sm:grid-cols-3">
<StatCard Title="Revenue" Value="$45,231" Change="+20.1%" Trend="up" Description="vs last month" />
<StatCard Title="Error rate" Value="0.42%" Change="-0.8%" Trend="down" Description="last 24 hours" />
<StatCard Title="Active users" Value="2,350" Description="right now" />
</div>
</section>

<section class="border border-border rounded-lg p-6 bg-card mt-6">
<h2 class="text-2xl font-semibold mb-1 text-card-foreground">Chat</h2>
<p class="text-sm text-muted-foreground mb-4">Enter sends, Shift+Enter adds a new line. Replies are simulated.</p>
<Chat Height="380px">
<Header>
<div class="flex items-center justify-between">
<span class="text-sm font-medium text-foreground">Assistant</span>
<span class="text-xs text-muted-foreground">@_messages.Count messages</span>
</div>
</Header>
<ChildContent>
@foreach (var message in _messages)
{
<ChatMessage Role="@message.Role" Name="@(message.Role == "user" ? "You" : "ShellUI")" Text="@message.Text" />
}
@if (_thinking)
{
<ChatMessage Role="assistant" Name="ShellUI" IsStreaming="true" />
}
</ChildContent>
<Footer>
<ChatInput @bind-Value="_draft" OnSubmit="SendAsync" IsLoading="_thinking" />
</Footer>
</Chat>
</section>

<section class="border border-border rounded-lg p-6 bg-card mt-6">
<h2 class="text-2xl font-semibold mb-4 text-card-foreground">Toggle Group &amp; Button Group</h2>
<div class="space-y-4">
<div class="flex flex-wrap items-center gap-4">
<ToggleGroup @bind-Value="_align">
<ToggleGroupItem Value="left">Left</ToggleGroupItem>
<ToggleGroupItem Value="center">Center</ToggleGroupItem>
<ToggleGroupItem Value="right">Right</ToggleGroupItem>
</ToggleGroup>
<span class="text-sm text-muted-foreground">Single: @(_align ?? "none")</span>
</div>
<div class="flex flex-wrap items-center gap-4">
<ToggleGroup Multiple="true" @bind-Values="_formats">
<ToggleGroupItem Value="bold"><span class="font-bold">B</span></ToggleGroupItem>
<ToggleGroupItem Value="italic"><span class="italic">I</span></ToggleGroupItem>
<ToggleGroupItem Value="underline"><span class="underline">U</span></ToggleGroupItem>
</ToggleGroup>
<span class="text-sm text-muted-foreground">Multiple: @(_formats.Count == 0 ? "none" : string.Join(", ", _formats))</span>
</div>
<div class="flex flex-wrap items-start gap-6">
<ButtonGroup>
<Button Variant="ButtonVariant.Outline">Day</Button>
<Button Variant="ButtonVariant.Outline">Week</Button>
<Button Variant="ButtonVariant.Outline">Month</Button>
</ButtonGroup>
<ButtonGroup Orientation="vertical">
<Button Variant="ButtonVariant.Outline">Top</Button>
<Button Variant="ButtonVariant.Outline">Middle</Button>
<Button Variant="ButtonVariant.Outline">Bottom</Button>
</ButtonGroup>
</div>
</div>
</section>

<section class="border border-border rounded-lg p-6 bg-card mt-6">
<h2 class="text-2xl font-semibold mb-4 text-card-foreground">Input Group &amp; Number Input</h2>
<div class="grid gap-4 sm:grid-cols-2">
<div class="space-y-2">
<InputGroup @bind-Value="_website" Placeholder="example">
<Prefix>https://</Prefix>
<Suffix>.com</Suffix>
</InputGroup>
<InputGroup @bind-Value="_price" Placeholder="0.00" Type="number">
<Prefix>$</Prefix>
<Suffix>USD</Suffix>
</InputGroup>
</div>
<div class="space-y-2">
<NumberInput @bind-Value="_quantity" Min="0" Max="10" />
<p class="text-sm text-muted-foreground">Quantity: @_quantity (0 to 10)</p>
</div>
</div>
</section>

<section class="border border-border rounded-lg p-6 bg-card mt-6">
<h2 class="text-2xl font-semibold mb-4 text-card-foreground">Tree View &amp; Timeline</h2>
<div class="grid gap-8 sm:grid-cols-2">
<div>
<TreeView @bind-SelectedValue="_selectedFile">
<TreeViewItem Label="src" DefaultExpanded="true">
<TreeViewItem Label="Components" DefaultExpanded="true">
<TreeViewItem Label="Button.razor" />
<TreeViewItem Label="Chat.razor" />
</TreeViewItem>
<TreeViewItem Label="Program.cs" />
</TreeViewItem>
<TreeViewItem Label="README.md" />
</TreeView>
<p class="mt-2 text-sm text-muted-foreground">Selected: @(_selectedFile ?? "none")</p>
</div>
<Timeline>
<TimelineItem Title="v0.3.0-rc.2 released" Time="Today" Active="true">Published to NuGet and GitHub.</TimelineItem>
<TimelineItem Title="Charts restyled" Time="2 weeks ago">Donut, radar and radial charts added.</TimelineItem>
<TimelineItem Title="Moved to .NET 10" Time="1 month ago" />
</Timeline>
</div>
</section>

<section class="border border-border rounded-lg p-6 bg-card mt-6">
<h2 class="text-2xl font-semibold mb-4 text-card-foreground">QR Code, Image Viewer &amp; Aspect Ratio</h2>
<div class="grid items-start gap-6 sm:grid-cols-3">
<div class="space-y-2">
<QrCode Value="https://github.com/shellui-dev/shellui" Size="140" />
<p class="text-xs text-muted-foreground">Scan to open the repo</p>
</div>
<div class="space-y-2">
<ImageViewer Src="@SampleImage" Alt="Sample landscape" Class="h-32 w-full" />
<p class="text-xs text-muted-foreground">Click to open, then zoom</p>
</div>
<div class="space-y-2">
<AspectRatio Ratio="1.7777" Class="rounded-md bg-muted">
<div class="flex items-center justify-center text-sm text-muted-foreground">16 : 9</div>
</AspectRatio>
<p class="text-xs text-muted-foreground">Keeps its ratio at any width</p>
</div>
</div>
</section>

<section class="border border-border rounded-lg p-6 bg-card mt-6">
<h2 class="text-2xl font-semibold mb-4 text-card-foreground">Kbd</h2>
<p class="text-sm text-muted-foreground">
Open the command palette with <Kbd>Ctrl</Kbd> <Kbd>K</Kbd>, or toggle the sidebar with <Kbd>Ctrl</Kbd> <Kbd>B</Kbd>.
</p>
</section>

@code {
private readonly List<(string Role, string Text)> _messages = new()
{
("assistant", "Hi! I'm a ShellUI chat demo. Ask me anything."),
};

private string? _draft;
private bool _thinking;
private string? _align = "center";
private List<string> _formats = new() { "bold" };
private string? _website;
private string? _price;
private decimal? _quantity = 1;
private string? _selectedFile = "Chat.razor";

private const string SampleImage = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='800' height='500'><defs><linearGradient id='s' x1='0' y1='0' x2='0' y2='1'><stop offset='0' stop-color='%2393c5fd'/><stop offset='1' stop-color='%23fde68a'/></linearGradient></defs><rect width='800' height='500' fill='url(%23s)'/><circle cx='620' cy='140' r='60' fill='%23fbbf24'/><path d='M0 380 L200 220 L360 360 L520 240 L800 400 L800 500 L0 500 Z' fill='%2334d399'/><path d='M0 430 L260 300 L460 440 L800 330 L800 500 L0 500 Z' fill='%23059669'/></svg>";

private async Task SendAsync(string text)
{
_messages.Add(("user", text));
_thinking = true;
StateHasChanged();
await Task.Delay(800);
_messages.Add(("assistant", $"You said:\n{text}"));
_thinking = false;
}
}
Loading
Loading