using Htmx.ApiDemo.Templates.Components; using Immediate.Apis.Shared; using Immediate.Handlers.Shared; using Microsoft.AspNetCore.Http; namespace Htmx.ApiDemo.Templates; public sealed class UiDemo : UiDemoBase { // ── Buttons ────────────────────────────────────────────────────────── public IHtmxComponent BtnDefault { get; } public IHtmxComponent BtnDestructive { get; } public IHtmxComponent BtnOutline { get; } public IHtmxComponent BtnSecondary { get; } public IHtmxComponent BtnGhost { get; } public IHtmxComponent BtnLink { get; } public IHtmxComponent BtnSm { get; } public IHtmxComponent BtnLg { get; } // ── Inputs ─────────────────────────────────────────────────────────── public IHtmxComponent InputText { get; } public IHtmxComponent InputEmail { get; } public IHtmxComponent InputPassword { get; } public IHtmxComponent InputSearch { get; } // ── Select / Calendar / TimePicker ─────────────────────────────────── public IHtmxComponent SelectDemo { get; } public IHtmxComponent CalendarDemo { get; } public IHtmxComponent CalendarRangeDemo { get; } public IHtmxComponent TimePickerDemo { get; } public IHtmxComponent TimePicker12hDemo { get; } // ── Badge ───────────────────────────────────────────────────────────── public IHtmxComponent BadgeDefault { get; } public IHtmxComponent BadgeSecondary { get; } public IHtmxComponent BadgeDestructive { get; } public IHtmxComponent BadgeOutline { get; } // ── Card ────────────────────────────────────────────────────────────── public IHtmxComponent CardDemo { get; } // ── Separator ───────────────────────────────────────────────────────── public IHtmxComponent SeparatorH { get; } public IHtmxComponent SeparatorV { get; } // ── Skeleton ────────────────────────────────────────────────────────── public IHtmxComponent SkeletonTitle { get; } public IHtmxComponent SkeletonLine1 { get; } public IHtmxComponent SkeletonLine2 { get; } public IHtmxComponent SkeletonAvatar { get; } // ── Avatar ──────────────────────────────────────────────────────────── public IHtmxComponent AvatarSm { get; } public IHtmxComponent AvatarDefault { get; } public IHtmxComponent AvatarLg { get; } public IHtmxComponent AvatarImg { get; } // ── Progress ────────────────────────────────────────────────────────── public IHtmxComponent Progress25 { get; } public IHtmxComponent Progress60 { get; } public IHtmxComponent Progress100 { get; } // ── Alert ───────────────────────────────────────────────────────────── public IHtmxComponent AlertDefault { get; } public IHtmxComponent AlertDestructive { get; } // ── Breadcrumb ──────────────────────────────────────────────────────── public IHtmxComponent BreadcrumbDemo { get; } // ── Checkbox ────────────────────────────────────────────────────────── public IHtmxComponent CheckboxAccept { get; } public IHtmxComponent CheckboxChecked { get; } // ── RadioGroup ──────────────────────────────────────────────────────── public IHtmxComponent RadioGroupCol { get; } public IHtmxComponent RadioGroupRow { get; } // ── Switch ──────────────────────────────────────────────────────────── public IHtmxComponent SwitchOff { get; } public IHtmxComponent SwitchOn { get; } // ── Textarea ────────────────────────────────────────────────────────── public IHtmxComponent TextareaDemo { get; } // ── Slider ──────────────────────────────────────────────────────────── public IHtmxComponent SliderDemo { get; } // ── FileInput ───────────────────────────────────────────────────────── public IHtmxComponent FileInputDemo { get; } // ── Table ───────────────────────────────────────────────────────────── public IHtmxComponent TableDemo { get; } // ── Pagination ──────────────────────────────────────────────────────── public IHtmxComponent PaginationDemo { get; } // ── Tabs ────────────────────────────────────────────────────────────── public IHtmxComponent TabsDemo { get; } // ── Accordion ───────────────────────────────────────────────────────── public IHtmxComponent AccordionDemo { get; } // ── Tooltip ─────────────────────────────────────────────────────────── public IHtmxComponent TooltipTop { get; } public IHtmxComponent TooltipBottom { get; } public IHtmxComponent TooltipRight { get; } // ── Dialog ──────────────────────────────────────────────────────────── public IHtmxComponent DialogDemo { get; } // ── Dropdown ────────────────────────────────────────────────────────── public IHtmxComponent DropdownDemo { get; } // ── Toast Viewport ──────────────────────────────────────────────────── public IHtmxComponent ToastViewportDemo { get; } public UiDemo() { // Buttons BtnDefault = new Button("Default"); BtnDestructive = new Button("Destructive", variant: "destructive"); BtnOutline = new Button("Outline", variant: "outline"); BtnSecondary = new Button("Secondary", variant: "secondary"); BtnGhost = new Button("Ghost", variant: "ghost"); BtnLink = new Button("Link", variant: "link"); BtnSm = new Button("Small", size: "sm"); BtnLg = new Button("Large", size: "lg"); // Inputs InputText = new Input("username", label: "Username", placeholder: "Enter username"); InputEmail = new Input("email", inputType: "email", label: "Email", placeholder: "you@example.com"); InputPassword = new Input("password", inputType: "password", label: "Password", placeholder: "••••••••"); InputSearch = new Input("search", inputType: "search", label: "Search", placeholder: "Search…", hxAttrs: "hx-get=\"/search\" hx-trigger=\"keyup changed delay:300ms\" hx-target=\"#search-results\""); // Select / Calendar / TimePicker SelectDemo = new Select( id: "framework", label: "Framework", options: [("htmx", "HTMX"), ("react", "React"), ("vue", "Vue"), ("svelte", "Svelte")], selectedValue: "htmx", description: "Choose your preferred framework"); CalendarDemo = new Calendar(id: "demo-cal", name: "demo-date"); CalendarRangeDemo = new CalendarRange(id: "demo-calr", name: "demo-range"); TimePickerDemo = new TimePicker(name: "time-24h", label: "Time (24h)"); TimePicker12hDemo = new TimePicker(name: "time-12h", label: "Time (12h)", use12h: true); // Badge BadgeDefault = new Badge("Default"); BadgeSecondary = new Badge("Secondary", variant: "secondary"); BadgeDestructive = new Badge("Destructive", variant: "destructive"); BadgeOutline = new Badge("Outline", variant: "outline"); // Card CardDemo = new Card( title: "Component Card", description: "A reusable card surface with header and footer.", content: "

Cards group related content and provide a contained, elevated surface for information.

", footer: ""); // Separator SeparatorH = new Separator(); SeparatorV = new Separator(orientation: "vertical"); // Skeleton SkeletonTitle = new Skeleton("h-5 w-48"); SkeletonLine1 = new Skeleton("h-4 w-full"); SkeletonLine2 = new Skeleton("h-4 w-3/4"); SkeletonAvatar = new Skeleton("h-10 w-10 rounded-full"); // Avatar AvatarSm = new Avatar("SM", size: "sm"); AvatarDefault = new Avatar("JD"); AvatarLg = new Avatar("AB", size: "lg"); AvatarImg = new Avatar("GitHub", src: "https://github.com/github.png", size: "default"); // Progress Progress25 = new Progress(25); Progress60 = new Progress(60); Progress100 = new Progress(100); // Alert AlertDefault = new Alert("Information", description: "This is an informational alert with a default style."); AlertDestructive = new Alert("Error", description: "Something went wrong. Please check your input.", variant: "destructive"); // Breadcrumb BreadcrumbDemo = new Breadcrumb([ ("Home", "/"), ("Components", "/components"), ("UI Demo", ""), ]); // Checkbox CheckboxAccept = new Checkbox("accept-terms", label: "Accept terms and conditions"); CheckboxChecked = new Checkbox("newsletter", label: "Subscribe to newsletter", @checked: true); // RadioGroup RadioGroupCol = new RadioGroup( name: "plan-v", label: "Plan (vertical)", options: [ ("starter", "Starter", true), ("pro", "Pro", false), ("enterprise", "Enterprise", false), ]); RadioGroupRow = new RadioGroup( name: "size-h", label: "Size (horizontal)", direction: "flex-row", options: [ ("sm", "SM", true), ("md", "MD", false), ("lg", "LG", false), ]); // Switch SwitchOff = new Switch("notif-off", label: "Notifications"); SwitchOn = new Switch("darkmode", label: "Dark mode", isChecked: true); // Textarea TextareaDemo = new Textarea( id: "bio", label: "Bio", placeholder: "Tell us about yourself…", description: "Max 200 characters."); // Slider SliderDemo = new Slider(id: "volume", label: "Volume", value: 40, description: "Drag to adjust"); // FileInput FileInputDemo = new FileInput( id: "avatar-upload", label: "Profile picture", accept: "image/*", description: "PNG, JPG or GIF up to 2 MB."); // Table TableDemo = new Table( headers: ["Name", "Role", "Status"], rows: [ ["Alice", "Admin", "Active"], ["Bob", "Editor", "Active"], ["Charlie", "Viewer", "Inactive"], ], caption: "Team members"); // Pagination PaginationDemo = new Pagination(current: 3, total: 7, urlPattern: "/ui-demo?page={0}"); // Tabs TabsDemo = new Tabs("demo", [ ("overview", "Overview", "

This is the overview tab content.

"), ("settings", "Settings", "

Manage your settings here.

"), ("billing", "Billing", "

View billing information.

"), ]); // Accordion AccordionDemo = new Accordion("demo-acc", [ ("What is htmx?", "htmx allows you to access AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML."), ("Is it production ready?", "Yes — htmx is used by thousands of projects in production worldwide."), ("Does it replace React?", "htmx is a different tool suited to server-driven UIs. Use whatever fits your team best."), ], openIndex: 0); // Tooltip TooltipTop = new Tooltip("Top tooltip", new Button("Hover me"), position: "top"); TooltipBottom = new Tooltip("Bottom tooltip", new Button("Bottom", variant: "secondary"), position: "bottom"); TooltipRight = new Tooltip("Right tooltip", new Button("Right", variant: "outline"), position: "right"); // Dialog DialogDemo = new Dialog( id: "demo-dialog", title: "Are you sure?", description: "This action cannot be undone.", content: "Please confirm that you want to proceed with this operation.", footer: "" + ""); // Dropdown DropdownDemo = new DropdownMenu( trigger: new Button("Options ▾", variant: "outline"), items: [ ("Edit", "/edit", false), ("Duplicate", "/dup", false), ("", "", true), // separator ("Delete", "/delete", false), ]); // Toast Viewport ToastViewportDemo = new ToastViewport(); } protected override void RenderBtnDefault(HtmxRenderContext ctx) => BtnDefault.Render(ctx); protected override void RenderBtnDestructive(HtmxRenderContext ctx) => BtnDestructive.Render(ctx); protected override void RenderBtnOutline(HtmxRenderContext ctx) => BtnOutline.Render(ctx); protected override void RenderBtnSecondary(HtmxRenderContext ctx) => BtnSecondary.Render(ctx); protected override void RenderBtnGhost(HtmxRenderContext ctx) => BtnGhost.Render(ctx); protected override void RenderBtnLink(HtmxRenderContext ctx) => BtnLink.Render(ctx); protected override void RenderBtnSm(HtmxRenderContext ctx) => BtnSm.Render(ctx); protected override void RenderBtnLg(HtmxRenderContext ctx) => BtnLg.Render(ctx); protected override void RenderInputText(HtmxRenderContext ctx) => InputText.Render(ctx); protected override void RenderInputEmail(HtmxRenderContext ctx) => InputEmail.Render(ctx); protected override void RenderInputPassword(HtmxRenderContext ctx) => InputPassword.Render(ctx); protected override void RenderInputSearch(HtmxRenderContext ctx) => InputSearch.Render(ctx); protected override void RenderSelectDemo(HtmxRenderContext ctx) => SelectDemo.Render(ctx); protected override void RenderCalendarDemo(HtmxRenderContext ctx) => CalendarDemo.Render(ctx); protected override void RenderCalendarRangeDemo(HtmxRenderContext ctx) => CalendarRangeDemo.Render(ctx); protected override void RenderTimePickerDemo(HtmxRenderContext ctx) => TimePickerDemo.Render(ctx); protected override void RenderTimePicker12hDemo(HtmxRenderContext ctx) => TimePicker12hDemo.Render(ctx); protected override void RenderBadgeDefault(HtmxRenderContext ctx) => BadgeDefault.Render(ctx); protected override void RenderBadgeSecondary(HtmxRenderContext ctx) => BadgeSecondary.Render(ctx); protected override void RenderBadgeDestructive(HtmxRenderContext ctx) => BadgeDestructive.Render(ctx); protected override void RenderBadgeOutline(HtmxRenderContext ctx) => BadgeOutline.Render(ctx); protected override void RenderCardDemo(HtmxRenderContext ctx) => CardDemo.Render(ctx); protected override void RenderSeparatorH(HtmxRenderContext ctx) => SeparatorH.Render(ctx); protected override void RenderSeparatorV(HtmxRenderContext ctx) => SeparatorV.Render(ctx); protected override void RenderSkeletonTitle(HtmxRenderContext ctx) => SkeletonTitle.Render(ctx); protected override void RenderSkeletonLine1(HtmxRenderContext ctx) => SkeletonLine1.Render(ctx); protected override void RenderSkeletonLine2(HtmxRenderContext ctx) => SkeletonLine2.Render(ctx); protected override void RenderSkeletonAvatar(HtmxRenderContext ctx) => SkeletonAvatar.Render(ctx); protected override void RenderAvatarSm(HtmxRenderContext ctx) => AvatarSm.Render(ctx); protected override void RenderAvatarDefault(HtmxRenderContext ctx) => AvatarDefault.Render(ctx); protected override void RenderAvatarLg(HtmxRenderContext ctx) => AvatarLg.Render(ctx); protected override void RenderAvatarImg(HtmxRenderContext ctx) => AvatarImg.Render(ctx); protected override void RenderProgress25(HtmxRenderContext ctx) => Progress25.Render(ctx); protected override void RenderProgress60(HtmxRenderContext ctx) => Progress60.Render(ctx); protected override void RenderProgress100(HtmxRenderContext ctx) => Progress100.Render(ctx); protected override void RenderAlertDefault(HtmxRenderContext ctx) => AlertDefault.Render(ctx); protected override void RenderAlertDestructive(HtmxRenderContext ctx) => AlertDestructive.Render(ctx); protected override void RenderBreadcrumbDemo(HtmxRenderContext ctx) => BreadcrumbDemo.Render(ctx); protected override void RenderCheckboxAccept(HtmxRenderContext ctx) => CheckboxAccept.Render(ctx); protected override void RenderCheckboxChecked(HtmxRenderContext ctx) => CheckboxChecked.Render(ctx); protected override void RenderRadioGroupCol(HtmxRenderContext ctx) => RadioGroupCol.Render(ctx); protected override void RenderRadioGroupRow(HtmxRenderContext ctx) => RadioGroupRow.Render(ctx); protected override void RenderSwitchOff(HtmxRenderContext ctx) => SwitchOff.Render(ctx); protected override void RenderSwitchOn(HtmxRenderContext ctx) => SwitchOn.Render(ctx); protected override void RenderTextareaDemo(HtmxRenderContext ctx) => TextareaDemo.Render(ctx); protected override void RenderSliderDemo(HtmxRenderContext ctx) => SliderDemo.Render(ctx); protected override void RenderFileInputDemo(HtmxRenderContext ctx)=> FileInputDemo.Render(ctx); protected override void RenderTableDemo(HtmxRenderContext ctx) => TableDemo.Render(ctx); protected override void RenderPaginationDemo(HtmxRenderContext ctx)=> PaginationDemo.Render(ctx); protected override void RenderTabsDemo(HtmxRenderContext ctx) => TabsDemo.Render(ctx); protected override void RenderAccordionDemo(HtmxRenderContext ctx)=> AccordionDemo.Render(ctx); protected override void RenderTooltipTop(HtmxRenderContext ctx) => TooltipTop.Render(ctx); protected override void RenderTooltipBottom(HtmxRenderContext ctx) => TooltipBottom.Render(ctx); protected override void RenderTooltipRight(HtmxRenderContext ctx) => TooltipRight.Render(ctx); protected override void RenderDialogDemo(HtmxRenderContext ctx) => DialogDemo.Render(ctx); protected override void RenderDropdownDemo(HtmxRenderContext ctx) => DropdownDemo.Render(ctx); protected override void RenderToastViewportDemo(HtmxRenderContext ctx) => ToastViewportDemo.Render(ctx); } [Handler] [MapGet("/ui-demo")] public static partial class GetUiDemoHandler { public class Query; private static ValueTask HandleAsync( Query query, IHttpContextAccessor httpContextAccessor, CancellationToken token) { var context = httpContextAccessor.HttpContext ?? throw new InvalidOperationException("HttpContext is not available."); var page = new UiDemo(); return ValueTask.FromResult(context.WriteHtmxPage(page, title: "UI Demo", appName: "HtmxApp", pageTitle: "UI Components")); } }