Files
Htmx/Htmx.ApiDemo/Templates/Components/DropdownMenu.htmx.cs
T
2026-05-04 18:58:48 +05:00

56 lines
2.4 KiB
C#

namespace Htmx.ApiDemo.Templates.Components;
/// <summary>
/// CSS-native DropdownMenu using &lt;details&gt;/&lt;summary&gt;.
/// Position: "left-0 top-full mt-1" (default) | "right-0 top-full mt-1" | etc.
/// Items: pre-built HTML — use BuildItem() helper for consistent styling.
/// </summary>
public sealed class DropdownMenu : DropdownMenuBase
{
private const string ItemClasses =
"relative flex w-full cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm " +
"outline-none transition-colors hover:bg-accent hover:text-accent-foreground " +
"focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50";
private readonly byte[] _triggerClassesData;
private readonly byte[] _triggerData;
private readonly byte[] _positionData;
private readonly byte[] _itemsData;
public DropdownMenu(
IHtmxComponent trigger,
IEnumerable<(string Label, string Href, bool IsSeparator)> items,
string position = "left-0 top-full mt-1")
{
// Render trigger to bytes
var writer = new System.Buffers.ArrayBufferWriter<byte>();
trigger.Render(new HtmxRenderContext(writer));
_triggerData = writer.WrittenSpan.ToArray();
_triggerClassesData = []; // trigger already supplies its own classes
_positionData = position.ToUtf8Bytes();
var sb = new System.Text.StringBuilder();
foreach (var (label, href, isSeparator) in items)
{
if (isSeparator)
{
sb.Append("""<div class="-mx-1 my-1 h-px bg-border"></div>""");
}
else if (string.IsNullOrEmpty(href))
{
sb.Append($"""<button type="button" class="{ItemClasses}">{label}</button>""");
}
else
{
sb.Append($"""<a href="{href}" class="{ItemClasses}">{label}</a>""");
}
}
_itemsData = sb.ToString().ToUtf8Bytes();
}
protected override void RenderTriggerClasses(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_triggerClassesData);
protected override void RenderTrigger(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_triggerData);
protected override void RenderPosition(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_positionData);
protected override void RenderItems(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_itemsData);
}