Add D-prefixed Blazor wrappers for every daisyUI 5 component

Components/Daisy/ wraps all 69 components in daisyUI's llms.txt, grouped by
daisyUI's categories (Actions, DataDisplay, Navigation, Feedback, DataInput,
Layout, Mockup), with part components where daisyUI has repeating parts (DTab,
DMenuItem, DTimelineItem, ...).
- Each enum maps to whole literal class names in a switch, so Tailwind's scanner
  generates them. Nothing is concatenated.
- Value-holding fields derive from DInputBase<TValue>, Blazor's InputBase, so
  @bind-Value and EditForm validation work. Invalid fields get the component's
  *-error class.
- Open and active state lives in C# (@bind-IsOpen, @bind-Active) and is rendered
  with daisyUI's *-open modifiers. DDropdown adds an outside-click layer and
  Escape. No component uses JS interop.
- The one exception is DCalendar, which wraps the Cally web component, vendored
  as wwwroot/vendor/cally.js (0.9.2, MIT).

/styleguide (not linked) renders every component in all its colours, sizes and
states, with a theme and hue picker that previews without saving.

neo.css follows what the styleguide showed:
- select keeps daisyUI's arrow;
- skeleton-text isn't sunk;
- the phone mockup and dock are raised;
- active menu items and OTP digits are inset;
- a joined accordion is raised as one block.
The primary, secondary and accent colours are deeper, so they still read as
text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-03 12:01:42 +02:00
1 parent 8e03d12a3e
commit 90e4b9200c
127 files changed
+6962 -17

No files matched your search

@@ -0,0 +1,46 @@
@inherits DComponentBase
@* daisyUI Accordion: https://daisyui.com/components/accordion/ . Instead of daisyUI's radio group, the open item is an
index in C# (@bind-Active, -1 = none). Each DAccordionItem registers itself through the cascading value and renders a
DCollapse that is open only while its index is Active. The cascading value isn't fixed, so every item re-renders
whenever the accordion does. *@
<div @attributes="AdditionalAttributes" class="@CssClass">
<CascadingValue Value="this">
@ChildContent
</CascadingValue>
</div>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
/// <summary>Index of the open item, in registration order; -1 when all are closed.</summary>
[Parameter] public int Active { get; set; } = -1;
[Parameter] public EventCallback<int> ActiveChanged { get; set; }
[Parameter] public DCollapseIcon Icon { get; set; }
/// <summary>Join the items into one block (join join-vertical, join-item).</summary>
[Parameter] public bool Joined { get; set; }
readonly List<DAccordionItem> items = new();
string CssClass => Cx(Joined ? "join join-vertical rounded-box neo-raised" : "flex flex-col gap-2", Class);
internal int IndexOf(DAccordionItem item) => items.IndexOf(item);
internal void Add(DAccordionItem item)
{
items.Add(item);
StateHasChanged();
}
internal void Remove(DAccordionItem item)
{
items.Remove(item);
StateHasChanged();
}
internal async Task Select(int index)
{
Active = index;
await ActiveChanged.InvokeAsync(index);
StateHasChanged();
}
}
@@ -0,0 +1,32 @@
@inherits DComponentBase
@implements IDisposable
@* One item of a DAccordion: a DCollapse (so collapse + neo-raised, keyboard and aria-expanded come from there) whose
open state is the accordion's Active index. Opening it closes the others; clicking it while open closes it. *@
<DCollapse @attributes="AdditionalAttributes" IsOpen="@IsOpen" IsOpenChanged="OnIsOpenChanged" Icon="@Parent.Icon"
Disabled="@Disabled" HeaderClass="@HeaderClass" ContentClass="@ContentClass" Header="@Header"
Class="@Cx(Parent.Joined ? "join-item shadow-none!" : null, Class)">
@ChildContent
</DCollapse>
@code {
[CascadingParameter] DAccordion Parent { get; set; }
[Parameter] public RenderFragment Header { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public bool Disabled { get; set; }
[Parameter] public string HeaderClass { get; set; }
[Parameter] public string ContentClass { get; set; }
bool IsOpen => Parent.Active >= 0 && Parent.Active == Parent.IndexOf(this);
protected override void OnInitialized()
{
if (Parent is null)
throw new InvalidOperationException($"{nameof(DAccordionItem)} must be inside a {nameof(DAccordion)}.");
Parent.Add(this);
}
Task OnIsOpenChanged(bool isOpen) => Parent.Select(isOpen ? Parent.IndexOf(this) : -1);
public void Dispose() => Parent?.Remove(this);
}
+51
View File
@@ -0,0 +1,51 @@
@inherits DComponentBase
@* daisyUI Aura: https://daisyui.com/components/aura/ . ChildContent must be exactly one element (a btn, card, …).
The light takes the text colour (Color, or any text-* in Class); a bg-* sets its background and duration-* its
speed. daisyUI advises at most one aura per page. *@
<div @attributes="AdditionalAttributes" class="@CssClass">
@ChildContent
</div>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public DAuraVariant Variant { get; set; }
/// <summary>Colour of the light, as text-*; the child inherits it unless it sets its own text colour.</summary>
[Parameter] public DColor Color { get; set; }
[Parameter] public DSize Size { get; set; }
string CssClass => Cx("aura", VariantClass, ColorClass, SizeClass, Class);
string VariantClass => Variant switch
{
DAuraVariant.Dual => "aura-dual",
DAuraVariant.Rainbow => "aura-rainbow",
DAuraVariant.Holo => "aura-holo",
DAuraVariant.Gold => "aura-gold",
DAuraVariant.Silver => "aura-silver",
DAuraVariant.Glow => "aura-glow",
_ => null
};
string ColorClass => Color switch
{
DColor.Neutral => "text-neutral",
DColor.Primary => "text-primary",
DColor.Secondary => "text-secondary",
DColor.Accent => "text-accent",
DColor.Info => "text-info",
DColor.Success => "text-success",
DColor.Warning => "text-warning",
DColor.Error => "text-error",
_ => null
};
string SizeClass => Size switch
{
DSize.Xs => "aura-xs",
DSize.Sm => "aura-sm",
DSize.Lg => "aura-lg",
DSize.Xl => "aura-xl",
_ => null
};
}
@@ -0,0 +1,12 @@
namespace decePubClient.Components.Daisy.DataDisplay;
public enum DAuraVariant
{
Default,
Dual,
Rainbow,
Holo,
Gold,
Silver,
Glow
}
@@ -0,0 +1,36 @@
@inherits DComponentBase
@* daisyUI Avatar: https://daisyui.com/components/avatar/ . Class goes on the inner frame, where daisyUI puts the size
and shape (w-16 rounded-full, mask mask-squircle) and, for a placeholder, the colours (bg-neutral
text-neutral-content); the other attributes go on the outer .avatar. Without Src the frame shows ChildContent. *@
<div @attributes="AdditionalAttributes" class="@CssClass">
<div class="@Class">
@if (Src is not null)
{
<img src="@Src" alt="@Alt" />
}
else
{
@ChildContent
}
</div>
</div>
@code {
[Parameter] public string Src { get; set; }
[Parameter] public string Alt { get; set; } = "";
/// <summary>Shown in the frame when there is no Src, e.g. initials with Placeholder.</summary>
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public DAvatarStatus Status { get; set; }
/// <summary>Centre ChildContent in the frame (avatar-placeholder); give the frame a bg-* in Class.</summary>
[Parameter] public bool Placeholder { get; set; }
string CssClass => Cx("avatar", StatusClass, Placeholder ? "avatar-placeholder" : null);
string StatusClass => Status switch
{
DAvatarStatus.Online => "avatar-online",
DAvatarStatus.Offline => "avatar-offline",
_ => null
};
}
@@ -0,0 +1,8 @@
namespace decePubClient.Components.Daisy.DataDisplay;
public enum DAvatarStatus
{
None,
Online,
Offline
}
@@ -0,0 +1,11 @@
@inherits DComponentBase
@* daisyUI Avatar group: https://daisyui.com/components/avatar/ . Overlap the DAvatar children with a negative
space-x in Class, e.g. -space-x-6. *@
<div @attributes="AdditionalAttributes" class="@Cx("avatar-group", Class)">
@ChildContent
</div>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
}
+44
View File
@@ -0,0 +1,44 @@
@inherits DComponentBase
@* daisyUI Badge: https://daisyui.com/components/badge/ . Without ChildContent it is an empty dot. *@
<span @attributes="AdditionalAttributes" class="@CssClass">@ChildContent</span>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public DColor Color { get; set; }
[Parameter] public DBadgeVariant Variant { get; set; }
[Parameter] public DSize Size { get; set; }
string CssClass => Cx("badge", ColorClass, VariantClass, SizeClass, Class);
string ColorClass => Color switch
{
DColor.Neutral => "badge-neutral",
DColor.Primary => "badge-primary",
DColor.Secondary => "badge-secondary",
DColor.Accent => "badge-accent",
DColor.Info => "badge-info",
DColor.Success => "badge-success",
DColor.Warning => "badge-warning",
DColor.Error => "badge-error",
_ => null
};
string VariantClass => Variant switch
{
DBadgeVariant.Outline => "badge-outline",
DBadgeVariant.Dash => "badge-dash",
DBadgeVariant.Soft => "badge-soft",
DBadgeVariant.Ghost => "badge-ghost",
_ => null
};
string SizeClass => Size switch
{
DSize.Xs => "badge-xs",
DSize.Sm => "badge-sm",
DSize.Lg => "badge-lg",
DSize.Xl => "badge-xl",
_ => null
};
}
@@ -0,0 +1,10 @@
namespace decePubClient.Components.Daisy.DataDisplay;
public enum DBadgeVariant
{
Default,
Outline,
Dash,
Soft,
Ghost
}
+66
View File
@@ -0,0 +1,66 @@
@inherits DComponentBase
@* daisyUI Card: https://daisyui.com/components/card/ . Figure is wrapped in <figure> before the body (after it with
FigureLast); the body renders only when Heading, ChildContent or Actions is set. Give it a background in Class
(bg-base-100). *@
<div @attributes="AdditionalAttributes" class="@CssClass">
@if (Figure is not null && !FigureLast)
{
<figure class="@FigureClass">@Figure</figure>
}
@if (Heading is not null || ChildContent is not null || Actions is not null)
{
<div class="@Cx("card-body", BodyClass)">
@if (Heading is not null)
{
<h2 class="card-title">@Heading</h2>
}
@ChildContent
@if (Actions is not null)
{
<div class="@Cx("card-actions", ActionsClass)">@Actions</div>
}
</div>
}
@if (Figure is not null && FigureLast)
{
<figure class="@FigureClass">@Figure</figure>
}
</div>
@code {
[Parameter] public RenderFragment Figure { get; set; }
[Parameter] public RenderFragment Heading { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public RenderFragment Actions { get; set; }
[Parameter] public DCardVariant Variant { get; set; }
[Parameter] public DSize Size { get; set; }
/// <summary>Figure beside the body instead of above it (card-side).</summary>
[Parameter] public bool Side { get; set; }
/// <summary>Figure as the background behind the body (image-full).</summary>
[Parameter] public bool ImageFull { get; set; }
/// <summary>Put the figure after the body: at the bottom, or on the right with Side.</summary>
[Parameter] public bool FigureLast { get; set; }
[Parameter] public string FigureClass { get; set; }
[Parameter] public string BodyClass { get; set; }
/// <summary>Extra classes on card-actions, e.g. justify-end.</summary>
[Parameter] public string ActionsClass { get; set; }
string CssClass => Cx("card", VariantClass, SizeClass, Side ? "card-side" : null, ImageFull ? "image-full" : null, Class);
string VariantClass => Variant switch
{
DCardVariant.Border => "card-border",
DCardVariant.Dash => "card-dash",
_ => null
};
string SizeClass => Size switch
{
DSize.Xs => "card-xs",
DSize.Sm => "card-sm",
DSize.Lg => "card-lg",
DSize.Xl => "card-xl",
_ => null
};
}
@@ -0,0 +1,8 @@
namespace decePubClient.Components.Daisy.DataDisplay;
public enum DCardVariant
{
Default,
Border,
Dash
}
@@ -0,0 +1,22 @@
@inherits DComponentBase
@* daisyUI Carousel: https://daisyui.com/components/carousel/ . A scroll-snap strip of DCarouselItem children; the
user scrolls or swipes it. Give each item w-full for one slide at a time. *@
<div @attributes="AdditionalAttributes" class="@CssClass">
@ChildContent
</div>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public DCarouselSnap Snap { get; set; }
[Parameter] public DDirection Direction { get; set; }
string CssClass => Cx("carousel", SnapClass, Direction == DDirection.Vertical ? "carousel-vertical" : null, Class);
string SnapClass => Snap switch
{
DCarouselSnap.Center => "carousel-center",
DCarouselSnap.End => "carousel-end",
_ => null
};
}
@@ -0,0 +1,9 @@
namespace decePubClient.Components.Daisy.DataDisplay;
/// <summary>Where each item snaps; <see cref="Start"/> is daisyUI's default, so it renders no class.</summary>
public enum DCarouselSnap
{
Start,
Center,
End
}
@@ -0,0 +1,10 @@
@inherits DComponentBase
@* One slide of a DCarousel. *@
<div @attributes="AdditionalAttributes" class="@Cx("carousel-item", Class)">
@ChildContent
</div>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
}
+32
View File
@@ -0,0 +1,32 @@
@inherits DComponentBase
@* daisyUI Chat: https://daisyui.com/components/chat/ . One line of a conversation: an optional avatar, header and
footer around one DChatBubble (ChildContent). Avatar renders inside <div class="chat-image avatar">, so it takes
the avatar's frame, e.g. <div class="w-10 rounded-full"><img … /></div>. *@
<div @attributes="AdditionalAttributes" class="@CssClass">
@if (Avatar is not null)
{
<div class="chat-image avatar">@Avatar</div>
}
@if (Header is not null)
{
<div class="@Cx("chat-header", HeaderClass)">@Header</div>
}
@ChildContent
@if (Footer is not null)
{
<div class="@Cx("chat-footer", FooterClass)">@Footer</div>
}
</div>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public RenderFragment Avatar { get; set; }
[Parameter] public RenderFragment Header { get; set; }
[Parameter] public RenderFragment Footer { get; set; }
[Parameter] public DChatPlacement Placement { get; set; }
[Parameter] public string HeaderClass { get; set; }
[Parameter] public string FooterClass { get; set; } = "opacity-50";
string CssClass => Cx("chat", Placement == DChatPlacement.End ? "chat-end" : "chat-start", Class);
}
@@ -0,0 +1,27 @@
@inherits DComponentBase
@* daisyUI Chat bubble: https://daisyui.com/components/chat/ . The message of a DChat; one per DChat, since daisyUI
places every bubble in the same grid cell. *@
<div @attributes="AdditionalAttributes" class="@CssClass">
@ChildContent
</div>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public DColor Color { get; set; }
string CssClass => Cx("chat-bubble", ColorClass, Class);
string ColorClass => Color switch
{
DColor.Neutral => "chat-bubble-neutral",
DColor.Primary => "chat-bubble-primary",
DColor.Secondary => "chat-bubble-secondary",
DColor.Accent => "chat-bubble-accent",
DColor.Info => "chat-bubble-info",
DColor.Success => "chat-bubble-success",
DColor.Warning => "chat-bubble-warning",
DColor.Error => "chat-bubble-error",
_ => null
};
}
@@ -0,0 +1,8 @@
namespace decePubClient.Components.Daisy.DataDisplay;
/// <summary>daisyUI requires a placement, so unlike other enums both members render a class.</summary>
public enum DChatPlacement
{
Start,
End
}
@@ -0,0 +1,45 @@
@inherits DComponentBase
@* daisyUI Collapse: https://daisyui.com/components/collapse/ . The open state lives in C# (@bind-IsOpen) and is
rendered with collapse-open / collapse-close; clicking the header (or Enter/Space on it) toggles it. neo-raised
gives it the neumorphic panel look (see Styles/neo.css for why it isn't a @utility override). *@
<div @attributes="AdditionalAttributes" class="@CssClass">
<div class="@Cx("collapse-title", Disabled ? "cursor-not-allowed" : "cursor-pointer", HeaderClass)" role="button"
tabindex="@(Disabled ? "-1" : "0")" aria-expanded="@(IsOpen ? "true" : "false")" aria-disabled="@(Disabled ? "true" : null)"
@onclick="Toggle" @onkeydown="OnKeyDown">
@Header
</div>
<div class="@Cx("collapse-content", ContentClass)">
@ChildContent
</div>
</div>
@code {
[Parameter] public RenderFragment Header { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public bool IsOpen { get; set; }
[Parameter] public EventCallback<bool> IsOpenChanged { get; set; }
[Parameter] public DCollapseIcon Icon { get; set; }
[Parameter] public bool Disabled { get; set; }
[Parameter] public string HeaderClass { get; set; }
[Parameter] public string ContentClass { get; set; }
string CssClass => Cx("collapse neo-raised", IconClass, IsOpen ? "collapse-open" : "collapse-close", Class);
string IconClass => Icon switch
{
DCollapseIcon.Arrow => "collapse-arrow",
DCollapseIcon.Plus => "collapse-plus",
_ => null
};
async Task Toggle()
{
if (Disabled)
return;
IsOpen = !IsOpen;
await IsOpenChanged.InvokeAsync(IsOpen);
}
Task OnKeyDown(KeyboardEventArgs e) => e.Key is "Enter" or " " ? Toggle() : Task.CompletedTask;
}
@@ -0,0 +1,8 @@
namespace decePubClient.Components.Daisy.DataDisplay;
public enum DCollapseIcon
{
None,
Arrow,
Plus
}
@@ -0,0 +1,18 @@
@inherits DComponentBase
@* daisyUI Countdown: https://daisyui.com/components/countdown/ . Shows one number (0-999) that rolls to each new
Value; --value and --digits go in the inner span's style. For a clock, put several side by side with separators. *@
<span @attributes="AdditionalAttributes" class="@Cx("countdown", Class)">
<span style="@ValueStyle" aria-live="polite" aria-label="@Number">@Number</span>
</span>
@code {
/// <summary>The number to show, clamped to 0-999.</summary>
[Parameter] public int Value { get; set; }
/// <summary>Minimum digits shown (1-3); 2 pads 5 to 05.</summary>
[Parameter] public int Digits { get; set; } = 1;
int Number => Math.Clamp(Value, 0, 999);
string ValueStyle => Digits > 1 ? $"--value:{Number}; --digits:{Math.Min(Digits, 3)};" : $"--value:{Number};";
}
+20
View File
@@ -0,0 +1,20 @@
@inherits DComponentBase
@* daisyUI Diff: https://daisyui.com/components/diff/ . Item1 and Item2 overlap, and the resizer handle reveals one over
the other; each slot takes one element (an img, or a div that fills it). Keyboard focus on the figure or on item 1
slides the handle to either end. It has no height of its own: AspectClass (or a height in Class) gives it one. *@
<figure @attributes="AdditionalAttributes" class="@Cx("diff", AspectClass, Class)" tabindex="0">
<div class="diff-item-1" role="img" aria-label="@Item1Alt" tabindex="0">@Item1</div>
<div class="diff-item-2" role="img" aria-label="@Item2Alt">@Item2</div>
<div class="diff-resizer"></div>
</figure>
@code {
[Parameter] public RenderFragment Item1 { get; set; }
[Parameter] public RenderFragment Item2 { get; set; }
/// <summary>Accessible name of item 1 (its role is img, which hides the alt of an img inside).</summary>
[Parameter] public string Item1Alt { get; set; }
[Parameter] public string Item2Alt { get; set; }
/// <summary>An aspect-* class for the figure; null when Class gives it a height instead.</summary>
[Parameter] public string AspectClass { get; set; } = "aspect-16/9";
}
@@ -0,0 +1,24 @@
@inherits DComponentBase
@* daisyUI Hover 3D: https://daisyui.com/components/hover-3d/ . ChildContent must be one non-interactive element (a
<figure>, a card); the eight empty divs after it are the hover zones that tilt it. With Href the whole thing is a
link, the only way to make it clickable. *@
@if (Href is null)
{
<div @attributes="AdditionalAttributes" class="@Cx("hover-3d", Class)">
@ChildContent
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
</div>
}
else
{
<a @attributes="AdditionalAttributes" href="@Href" class="@Cx("hover-3d", Class)">
@ChildContent
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
</a>
}
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public string Href { get; set; }
}
@@ -0,0 +1,21 @@
@inherits DComponentBase
@* daisyUI Hover gallery: https://daisyui.com/components/hover-gallery/ . Shows the first image; moving the pointer
across it shows the others. Up to 10 images of the same size, from Images or as <img> children; cap its width in
Class (max-w-60), or it fills the container. *@
<figure @attributes="AdditionalAttributes" class="@Cx("hover-gallery", Class)">
@if (Images is not null)
{
foreach (var src in Images.Take(10))
{
<img src="@src" alt="@Alt" />
}
}
@ChildContent
</figure>
@code {
[Parameter] public IEnumerable<string> Images { get; set; }
[Parameter] public string Alt { get; set; } = "";
[Parameter] public RenderFragment ChildContent { get; set; }
}
+20
View File
@@ -0,0 +1,20 @@
@inherits DComponentBase
@* daisyUI Kbd: https://daisyui.com/components/kbd/ *@
<kbd @attributes="AdditionalAttributes" class="@CssClass">@ChildContent</kbd>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public DSize Size { get; set; }
string CssClass => Cx("kbd", SizeClass, Class);
string SizeClass => Size switch
{
DSize.Xs => "kbd-xs",
DSize.Sm => "kbd-sm",
DSize.Lg => "kbd-lg",
DSize.Xl => "kbd-xl",
_ => null
};
}
+10
View File
@@ -0,0 +1,10 @@
@inherits DComponentBase
@* daisyUI List: https://daisyui.com/components/list/ . Rows are DListRow children; a plain <li> works as a caption. *@
<ul @attributes="AdditionalAttributes" class="@Cx("list", Class)">
@ChildContent
</ul>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
}
@@ -0,0 +1,11 @@
@inherits DComponentBase
@* One row of a DList. Its second child fills the remaining width; put list-col-grow on another child to change that,
and list-col-wrap on a child to move it to a second line. *@
<li @attributes="AdditionalAttributes" class="@Cx("list-row", Class)">
@ChildContent
</li>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
}
+37
View File
@@ -0,0 +1,37 @@
@inherits DComponentBase
@* One stat of a DStats: ChildContent is the value (stat-value); each slot renders its part only when set. *@
<div @attributes="AdditionalAttributes" class="@Cx("stat", Class)">
@if (Figure is not null)
{
<div class="@Cx("stat-figure", FigureClass)">@Figure</div>
}
@if (Heading is not null)
{
<div class="stat-title">@Heading</div>
}
@if (ChildContent is not null)
{
<div class="@Cx("stat-value", ValueClass)">@ChildContent</div>
}
@if (Desc is not null)
{
<div class="stat-desc">@Desc</div>
}
@if (Actions is not null)
{
<div class="stat-actions">@Actions</div>
}
</div>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public RenderFragment Figure { get; set; }
[Parameter] public RenderFragment Heading { get; set; }
[Parameter] public RenderFragment Desc { get; set; }
[Parameter] public RenderFragment Actions { get; set; }
/// <summary>Extra classes on stat-figure, e.g. text-primary.</summary>
[Parameter] public string FigureClass { get; set; }
/// <summary>Extra classes on stat-value, e.g. text-primary.</summary>
[Parameter] public string ValueClass { get; set; }
}
+14
View File
@@ -0,0 +1,14 @@
@inherits DComponentBase
@* daisyUI Stat: https://daisyui.com/components/stat/ . The container of DStat items; horizontal unless Direction is
Vertical (for a responsive switch add lg:stats-horizontal in Class). *@
<div @attributes="AdditionalAttributes" class="@CssClass">
@ChildContent
</div>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public DDirection Direction { get; set; }
string CssClass => Cx("stats", Direction == DDirection.Vertical ? "stats-vertical" : null, Class);
}
@@ -0,0 +1,45 @@
@inherits DComponentBase
@* daisyUI Status: https://daisyui.com/components/status/ . Give it an aria-label (online, error, …). Ping stacks an
animate-ping copy under the dot, as in daisyUI's ping example; the attributes stay on the visible dot. *@
@if (Ping)
{
<span class="inline-grid *:[grid-area:1/1]">
<span class="@Cx(CssClass, "animate-ping")" aria-hidden="true"></span>
<span @attributes="AdditionalAttributes" class="@CssClass"></span>
</span>
}
else
{
<span @attributes="AdditionalAttributes" class="@CssClass"></span>
}
@code {
[Parameter] public DColor Color { get; set; }
[Parameter] public DSize Size { get; set; }
[Parameter] public bool Ping { get; set; }
string CssClass => Cx("status", ColorClass, SizeClass, Class);
string ColorClass => Color switch
{
DColor.Neutral => "status-neutral",
DColor.Primary => "status-primary",
DColor.Secondary => "status-secondary",
DColor.Accent => "status-accent",
DColor.Info => "status-info",
DColor.Success => "status-success",
DColor.Warning => "status-warning",
DColor.Error => "status-error",
_ => null
};
string SizeClass => Size switch
{
DSize.Xs => "status-xs",
DSize.Sm => "status-sm",
DSize.Lg => "status-lg",
DSize.Xl => "status-xl",
_ => null
};
}
+40
View File
@@ -0,0 +1,40 @@
@inherits DComponentBase
@* daisyUI Table: https://daisyui.com/components/table/ . ChildContent is the <thead>/<tbody>/<tfoot> markup. Class and
the other attributes go on the <table>; with Scroll (the default) it sits in an overflow-x-auto div, whose classes
are WrapperClass (pinned rows need it to have a height, e.g. h-96). *@
@if (Scroll)
{
<div class="@Cx("overflow-x-auto", WrapperClass)">
<table @attributes="AdditionalAttributes" class="@CssClass">@ChildContent</table>
</div>
}
else
{
<table @attributes="AdditionalAttributes" class="@CssClass">@ChildContent</table>
}
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public DSize Size { get; set; }
[Parameter] public bool Zebra { get; set; }
/// <summary>Sticky thead/tfoot rows while the wrapper scrolls vertically.</summary>
[Parameter] public bool PinRows { get; set; }
/// <summary>Sticky &lt;th&gt; columns while the wrapper scrolls horizontally.</summary>
[Parameter] public bool PinCols { get; set; }
/// <summary>Wrap the table in an overflow-x-auto div so it scrolls on narrow screens.</summary>
[Parameter] public bool Scroll { get; set; } = true;
[Parameter] public string WrapperClass { get; set; }
string CssClass => Cx("table", Zebra ? "table-zebra" : null, PinRows ? "table-pin-rows" : null,
PinCols ? "table-pin-cols" : null, SizeClass, Class);
string SizeClass => Size switch
{
DSize.Xs => "table-xs",
DSize.Sm => "table-sm",
DSize.Lg => "table-lg",
DSize.Xl => "table-xl",
_ => null
};
}
@@ -0,0 +1,24 @@
@inherits DComponentBase
@* daisyUI Text rotate: https://daisyui.com/components/text-rotate/ . Loops through 2-6 lines, one at a time, pausing on
hover. The lines are Items, or <span> children in ChildContent (for per-line classes). Set the loop time with a
duration-* in Class (default 10s). *@
<span @attributes="AdditionalAttributes" class="@Cx("text-rotate", Class)">
<span class="@(Centered ? "justify-items-center" : null)">
@if (Items is not null)
{
foreach (var item in Items.Take(6))
{
<span>@item</span>
}
}
@ChildContent
</span>
</span>
@code {
[Parameter] public IEnumerable<string> Items { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
/// <summary>Centre the lines horizontally.</summary>
[Parameter] public bool Centered { get; set; }
}
@@ -0,0 +1,21 @@
@inherits DComponentBase
@* daisyUI Timeline: https://daisyui.com/components/timeline/ . Horizontal unless Direction is Vertical (for a
responsive switch add lg:timeline-horizontal in Class). Every DTimelineItem draws its connecting <hr> on both
sides; the two arbitrary variants here hide the outer ends, so the line runs only between items. *@
<ul @attributes="AdditionalAttributes" class="@CssClass">
@ChildContent
</ul>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public DDirection Direction { get; set; }
/// <summary>Put every item on one side of the line (timeline-compact).</summary>
[Parameter] public bool Compact { get; set; }
/// <summary>Align the icon with the start of the content instead of its middle (timeline-snap-icon).</summary>
[Parameter] public bool SnapIcon { get; set; }
string CssClass => Cx("timeline", Direction == DDirection.Vertical ? "timeline-vertical" : null,
Compact ? "timeline-compact" : null, SnapIcon ? "timeline-snap-icon" : null,
"[&>li:first-child>hr:first-child]:hidden [&>li:last-child>hr:last-child]:hidden", Class);
}
@@ -0,0 +1,36 @@
@inherits DComponentBase
@* One event of a DTimeline: Start and End on either side of the line, Middle (an icon) on it. Each part renders only
when set. The <hr> before and after are the line segments to the neighbouring items; colour them with
LineBeforeClass / LineAfterClass (bg-primary). *@
<li @attributes="AdditionalAttributes" class="@Class">
<hr class="@LineBeforeClass" />
@if (Start is not null)
{
<div class="@Cx("timeline-start", StartBox ? "timeline-box" : null, StartClass)">@Start</div>
}
@if (Middle is not null)
{
<div class="@Cx("timeline-middle", MiddleClass)">@Middle</div>
}
@if (End is not null)
{
<div class="@Cx("timeline-end", EndBox ? "timeline-box" : null, EndClass)">@End</div>
}
<hr class="@LineAfterClass" />
</li>
@code {
[Parameter] public RenderFragment Start { get; set; }
[Parameter] public RenderFragment Middle { get; set; }
[Parameter] public RenderFragment End { get; set; }
/// <summary>Draw Start as a box (timeline-box).</summary>
[Parameter] public bool StartBox { get; set; }
/// <summary>Draw End as a box (timeline-box).</summary>
[Parameter] public bool EndBox { get; set; }
[Parameter] public string StartClass { get; set; }
[Parameter] public string MiddleClass { get; set; }
[Parameter] public string EndClass { get; set; }
[Parameter] public string LineBeforeClass { get; set; }
[Parameter] public string LineAfterClass { get; set; }
}