56 lines
2.4 KiB
C#
56 lines
2.4 KiB
C#
namespace Htmx.ApiDemo.Templates.Components;
|
|
|
|
/// <summary>
|
|
/// CSS-native DropdownMenu using <details>/<summary>.
|
|
/// 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);
|
|
}
|