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

+224
View File
@@ -0,0 +1,224 @@
@* Styleguide: the Actions components (Button, Dropdown, FAB, Modal, Swap, Theme controller). *@
<div class="grid gap-8 lg:grid-cols-2">
<section class="flex flex-col gap-3 lg:col-span-2">
<h3 class="text-lg font-bold">DButton</h3>
<div class="flex flex-wrap items-center gap-2">
@foreach (var color in Enum.GetValues<DColor>())
{
<DButton Color="color">@color</DButton>
}
</div>
@foreach (var variant in Enum.GetValues<DButtonVariant>().Skip(1))
{
<div class="flex flex-wrap items-center gap-2">
<span class="w-16 text-sm opacity-60">@variant</span>
@foreach (var color in Enum.GetValues<DColor>())
{
<DButton Color="color" Variant="variant">@color</DButton>
}
</div>
}
<div class="flex flex-wrap items-center gap-2">
<DButton Size="DSize.Xs">Xs</DButton>
<DButton Size="DSize.Sm">Sm</DButton>
<DButton>Md</DButton>
<DButton Size="DSize.Lg">Lg</DButton>
<DButton Size="DSize.Xl">Xl</DButton>
</div>
<div class="flex flex-wrap items-center gap-2">
<DButton Shape="DButtonShape.Wide" Color="DColor.Primary">Wide</DButton>
<DButton Shape="DButtonShape.Square"><i class="ion-md-heart"></i></DButton>
<DButton Shape="DButtonShape.Circle" Color="DColor.Secondary"><i class="ion-md-add"></i></DButton>
<DButton Shape="DButtonShape.Circle" Size="DSize.Sm"><i class="ion-md-close"></i></DButton>
<DButton Color="DColor.Accent"><i class="ion-md-mail"></i> With icon</DButton>
</div>
<DButton Shape="DButtonShape.Block">Block</DButton>
<div class="flex flex-wrap items-center gap-2">
<DButton Active="true">Active</DButton>
<DButton Active="true" Color="DColor.Primary">Active primary</DButton>
<DButton Disabled="true">Disabled</DButton>
<DButton Disabled="true" Color="DColor.Primary">Disabled primary</DButton>
<DButton Href="#">Link button</DButton>
<DButton Href="#" Disabled="true">Disabled link</DButton>
<DButton Color="DColor.Info" OnClick="() => buttonClicks++">Clicked @buttonClicks times</DButton>
</div>
</section>
<section class="flex flex-col gap-3">
<h3 class="text-lg font-bold">DDropdown</h3>
<div class="flex flex-wrap items-start gap-2">
<DDropdown @bind-IsOpen="dropdownOpen" CloseOnContentClick="true" TriggerClass="btn" ContentClass="w-52 rounded-box p-2">
<Trigger>Menu (@(dropdownOpen ? "open" : "closed"))</Trigger>
<ChildContent>
<ul class="menu w-full p-0">
<li><a><i class="ion-md-person"></i> Profile</a></li>
<li><a><i class="ion-md-settings"></i> Settings</a></li>
<li><a><i class="ion-md-home"></i> Home</a></li>
</ul>
</ChildContent>
</DDropdown>
<DDropdown Align="DDropdownAlign.End" TriggerClass="btn btn-primary" ContentClass="w-52 rounded-box p-4">
<Trigger>Align end</Trigger>
<ChildContent>Any content: press Escape or click outside to close.</ChildContent>
</DDropdown>
<DDropdown Hover="true" TriggerClass="btn btn-ghost" ContentClass="w-40 rounded-box p-2">
<Trigger>Hover</Trigger>
<ChildContent>
<ul class="menu w-full p-0">
<li><a>One</a></li>
<li><a>Two</a></li>
</ul>
</ChildContent>
</DDropdown>
</div>
<div class="flex flex-wrap items-center gap-2 pt-24">
<DDropdown Placement="DDropdownPlacement.Top" TriggerClass="btn btn-sm" ContentClass="w-32 rounded-box p-2">
<Trigger>Top</Trigger>
<ChildContent>Above</ChildContent>
</DDropdown>
<DDropdown Placement="DDropdownPlacement.Right" TriggerClass="btn btn-sm" ContentClass="w-32 rounded-box p-2">
<Trigger>Right</Trigger>
<ChildContent>Beside</ChildContent>
</DDropdown>
<DDropdown Placement="DDropdownPlacement.Left" Align="DDropdownAlign.End" TriggerClass="btn btn-sm"
ContentClass="w-32 rounded-box p-2" class="ml-auto">
<Trigger>Left</Trigger>
<ChildContent>Beside</ChildContent>
</DDropdown>
</div>
</section>
<section class="flex flex-col gap-3">
<h3 class="text-lg font-bold">DModal</h3>
<div class="flex flex-wrap items-center gap-2">
@foreach (var placement in Enum.GetValues<DModalPlacement>())
{
<DButton OnClick="() => OpenModal(placement)">@placement</DButton>
}
<DButton Color="DColor.Warning" OnClick="() => strictModalOpen = true">No backdrop close</DButton>
</div>
<p class="text-sm opacity-60">Escape and a click outside close the first modal; the second closes only from its buttons or Escape.</p>
<DModal @bind-IsOpen="modalOpen" Placement="modalPlacement">
<Heading>Hello from @modalPlacement</Heading>
<ChildContent>
<p class="py-4">Press Escape or click outside to close.</p>
</ChildContent>
<Actions>
<DButton OnClick="() => modalOpen = false">Close</DButton>
</Actions>
</DModal>
<DModal @bind-IsOpen="strictModalOpen" CloseOnBackdrop="false" BoxClass="w-11/12 max-w-3xl">
<Heading>Confirm</Heading>
<ChildContent>
<p class="py-4">A wider box (BoxClass) that ignores clicks on the backdrop.</p>
</ChildContent>
<Actions>
<DButton Variant="DButtonVariant.Ghost" OnClick="() => strictModalOpen = false">Cancel</DButton>
<DButton Color="DColor.Primary" OnClick="() => strictModalOpen = false">OK</DButton>
</Actions>
</DModal>
</section>
<section class="flex flex-col gap-3">
<h3 class="text-lg font-bold">DSwap</h3>
<div class="flex flex-wrap items-center gap-6 text-4xl">
<DSwap @bind-Active="swapVolume" LabelText="mute">
<On><i class="ion-md-volume-high"></i></On>
<Off><i class="ion-md-volume-off"></i></Off>
</DSwap>
<DSwap @bind-Active="swapTheme" Effect="DSwapEffect.Rotate" LabelText="dark mode">
<On><i class="ion-md-sunny"></i></On>
<Off><i class="ion-md-moon"></i></Off>
</DSwap>
<DSwap Effect="DSwapEffect.Rotate" class="btn btn-circle" LabelText="menu">
<On><i class="ion-md-close"></i></On>
<Off><i class="ion-md-menu"></i></Off>
</DSwap>
<DSwap Effect="DSwapEffect.Flip" class="text-5xl">
<On>😈</On>
<Off>😇</Off>
</DSwap>
<DSwap class="text-base font-bold">
<On>ON</On>
<Off>OFF</Off>
</DSwap>
<DSwap Active="true" Disabled="true" class="text-base">
<On>Disabled on</On>
<Off>Disabled off</Off>
</DSwap>
</div>
<p class="text-sm opacity-60">Volume: @(swapVolume ? "on" : "off"), sun: @(swapTheme ? "on" : "off")</p>
</section>
<section class="flex flex-col gap-3">
<h3 class="text-lg font-bold">DFab</h3>
<p class="text-sm opacity-60">Click or focus the button; these boxes contain the fixed FABs (transform-gpu).</p>
<div class="grid grid-cols-2 gap-3">
<div class="relative h-80 transform-gpu overflow-hidden rounded-box bg-base-200">
<DFab LabelText="Actions">
<Trigger><i class="ion-md-add text-xl"></i></Trigger>
<Close>Close <span class="btn btn-circle btn-lg btn-error"><i class="ion-md-close"></i></span></Close>
<ChildContent>
<div>Camera <DButton Size="DSize.Lg" Shape="DButtonShape.Circle"><i class="ion-md-camera"></i></DButton></div>
<div>Image <DButton Size="DSize.Lg" Shape="DButtonShape.Circle"><i class="ion-md-image"></i></DButton></div>
<div>Mic <DButton Size="DSize.Lg" Shape="DButtonShape.Circle"><i class="ion-md-mic"></i></DButton></div>
</ChildContent>
</DFab>
</div>
<div class="relative h-80 transform-gpu overflow-hidden rounded-box bg-base-200">
<DFab Flower="true" Color="DColor.Secondary" LabelText="Actions">
<Trigger><i class="ion-md-add text-xl"></i></Trigger>
<MainAction>
<DButton Size="DSize.Lg" Shape="DButtonShape.Circle" Color="DColor.Accent"><i class="ion-md-create"></i></DButton>
</MainAction>
<ChildContent>
<div class="tooltip tooltip-left" data-tip="Camera">
<DButton Size="DSize.Lg" Shape="DButtonShape.Circle"><i class="ion-md-camera"></i></DButton>
</div>
<div class="tooltip tooltip-left" data-tip="Image">
<DButton Size="DSize.Lg" Shape="DButtonShape.Circle"><i class="ion-md-image"></i></DButton>
</div>
<div class="tooltip tooltip-left" data-tip="Mic">
<DButton Size="DSize.Lg" Shape="DButtonShape.Circle"><i class="ion-md-mic"></i></DButton>
</div>
</ChildContent>
</DFab>
</div>
</div>
</section>
<section class="flex flex-col gap-3">
<h3 class="text-lg font-bold">DThemeController</h3>
<p class="text-sm opacity-60">Overrides the app theme while checked.</p>
<label class="flex items-center gap-2">
<i class="ion-md-sunny"></i>
<DThemeController Value="neo-dark" @bind-Checked="themeToggle" class="toggle" aria-label="dark theme" />
<i class="ion-md-moon"></i>
</label>
<div class="join">
<DThemeController Radio="true" Value="neo-light" name="styleguide-theme" class="btn join-item" aria-label="neo-light"
Checked="@(themeRadio == "neo-light")" CheckedChanged="@(() => themeRadio = "neo-light")" />
<DThemeController Radio="true" Value="neo-dark" name="styleguide-theme" class="btn join-item" aria-label="neo-dark"
Checked="@(themeRadio == "neo-dark")" CheckedChanged="@(() => themeRadio = "neo-dark")" />
<DButton class="join-item" OnClick="() => themeRadio = null">Reset</DButton>
</div>
</section>
</div>
@code {
int buttonClicks;
bool dropdownOpen;
bool modalOpen;
bool strictModalOpen;
DModalPlacement modalPlacement;
bool swapVolume = true;
bool swapTheme;
bool themeToggle;
string themeRadio;
void OpenModal(DModalPlacement placement)
{
modalPlacement = placement;
modalOpen = true;
}
}