Changelog
All notable changes to Lumeo are documented here. Each release groups changes into Added, Improved, and Fixed categories.
May 2026
Two new core components (AudioPlayer + SignaturePad) and three new satellite packages (PdfViewer, Maps, CodeEditor). DataGrid column chooser gains a pin UI and drag-to-reorder. Purely additive — no migration required from 3.0.x.
Added
- AudioPlayer. Themed audio player with play/pause, scrub bar, time, volume, optional cover slot, and download button. Wraps the native
<audio>element; exposesOnPlay/OnPause/OnEnded/OnTimeUpdatecallbacks. - SignaturePad. Canvas-backed signature capture via mouse / touch / stylus. Configurable stroke color + width, transparent or solid background, PNG / JPEG / WebP output, optional download, and a disabled mode for read-only display of previously captured signatures.
- Lumeo.PdfViewer satellite. New optional NuGet package for rendering PDF documents inline.
- Lumeo.Maps satellite. New optional NuGet package for interactive map embeds.
- Lumeo.CodeEditor satellite. New optional NuGet package for a Monaco-style in-browser code editor.
- DataGrid PinColumn UI. Per-column pin / unpin (left / right) inside the column chooser flyout, in addition to programmatic pinning.
- DataGrid drag-to-reorder columns. Reorder columns directly inside the column chooser by drag-and-drop; order persists with the grid's existing state hooks.
- Batch edit mode segment in the playground. New segment on the DataGrid playground page to flip between row / cell / batch edit modes live.
Improved
- DataGrid per-column toggles are reactive.
SortableandFilterableonDataGridColumnDefnow update at runtime — the column re-registers onOnParametersSetinstead of only on first render, so toggling them from parent state works without an explicit grid refresh.
Internal
- 5 new media methods and 7 new SignaturePad methods added to
IComponentInteropServiceto back the new components.
May 2026
Soft borders + accessibility polish — a visual calm-down across the surface and a keyboard / screen-reader pass that closes the last gaps on triggers and overlays. No API changes; drop-in upgrade from any 3.0.x.
Improved
- Soft borders sweep — 27 components.
border-border→border-border/40on popovers, menus, hover cards, cards, and other neutral surfaces. Semantic borders (focus rings, active states, destructive variants) deliberately left at full opacity so they still read as state changes. - Accessibility + keyboard polish — 23 components. Dialog / Sheet / Drawer / Popover / AlertDialog triggers and close buttons now handle
EnterandSpace. Icon-only buttons across the library gainedaria-label+ explicittype="button". Image / ImageGallery preview overlays announce asrole="dialog"with auto-focus on open. Pagination current page getsaria-current="page"; Steps active step getsaria-current="step"; Sidebar collapsible groups exposearia-expanded. - Icon resolver coverage. ~66 new Lucide names mapped in the
DynamicIconresolver — fewer fall-throughs to the default icon when consumers wire up arbitrary Lucide names.
Added
- DataGrid playground. New page at
/components/datagrid/playground— 29 toggles across 10 sidebar groups, collapse / expand the controls viaSidebarTrigger. Click anything and see the grid reconfigure live; great for evaluating before vendoring. - Living demo reel on the home page. Hero stats with NumberTicker, an auto-cycling carousel of Tabs / BarChart / Toast / Stepper / Sparklines, a Kanban with real drag-and-drop, and a DropdownMenu submenu tile. Replaces the static screenshots with components driving themselves.
May 2026
DataGrid aggregate-row layout fix — the final shape after two earlier attempts in 3.0.2 / 3.0.3.
Fixed
- DataGrid aggregate row extracted to a sibling strip. Previously the aggregate row sat inside the table footer / scroll region, which broke sticky-header math when the grid scrolled and double-counted height under fullscreen. It now renders as a sibling element next to the scroll container — sticky header, sticky aggregate, no overlap. This supersedes the 3.0.2 and 3.0.3 attempts at the same problem.
May 2026
Intermediate DataGrid aggregate-row patch. Superseded by 3.0.4 — recommend skipping straight to 3.0.5.
May 2026
First attempt at the DataGrid aggregate-row layout fix. Superseded by 3.0.4 — recommend skipping straight to 3.0.5.
May 2026
Polish patch — cosmetic bug fixes plus one additive surface for global mobile-gesture tuning.
Fixed
- Accordion / Collapsible smooth animation. Previous keyframe interpolated
height: 0 → auto, which CSS can't animate — content snapped in instantly. Now uses the moderngrid grid-rows-[0fr] / [1fr]trick, smooth in both directions, zero JS. - Tabs Card variant baseline. Added
border-b border-border/40onTabsList+-mb-pxon active triggers so Card tabs sit on a real baseline. - Toast close button needed two clicks. The 3.0 pause-on-hover wiring intercepted focusin events. Fixed by stopping focusin propagation on the close button.
- Chevron rotations. DataGrid group-panel trigger, DataGridGroupRow, DataGridRow (expandable detail), PivotGrid, FileManager, TreeViewNode — replaced icon-swap with a single chevron +
transition-transform+ conditional-rotate-90.
Added
TabsList.SavedLayout+OnLayoutChanged— mirrors DataGrid's layout persistence pattern for the 3.0ReorderableTabs.LumeoGestureOptions— single DI-registered options bag (SwipeThresholdPx,VerticalDeadZonePx,SwipeDismissThresholdPx,SwipeDismissFirePx) consumed by Tabs / Carousel / Calendar / ImageGallery / Drawer / Sheet swipe handlers. Defaults match the previously hardcoded values.
May 2026
Major release. Four tiers of changes that landed together: a Tier 1 reliability sweep,
a batch of consumer-facing helpers, Tier B quality fixes, Tier C new features, and Tier D — a
breaking enum unification that collapses every per-component size / side / align /
orientation enum into four library-wide types. Migration is mechanical; see
MIGRATION.md in the
repo root for the rename recipe.
Tier 1 — Reliability
Automatic nested overlay stacking (Dialog/Sheet/Drawer/AlertDialog allocate z-index per overlay, Escape closes the top one);
OnBeforeClose +
DismissEventArgs
(Reason: escape / outside / swipe / close / action / cancel) on the same four overlays so
consumers can intercept dismissals; toast hover/focus pauses the auto-dismiss timer and the ARIA role
is now variant-aware (Destructive → role=alert +
aria-live=assertive;
others → role=status +
aria-live=polite);
tooltip viewport-edge auto-flip.
Helpers
Form.ResetValues()
restores the model snapshot captured on first render (the existing
Form.Reset()
only clears errors / dirty / submitting state). DatePicker gained
AllowKeyboardInput
(default true) +
OnParseError so
typed dates round-trip cleanly; readonly opt-out is one prop.
Tier B — Quality
DateTimePicker is now time-zone aware:
TimeZone (a
TimeZoneInfo),
OffsetValue (a
DateTimeOffset),
and ShowTimeZoneLabel
so users see which zone they're working in. FormField gained async validation —
AsyncValidator,
AsyncValidationDebounceMs,
AsyncValidateOn
(OnBlur / OnChange),
IsValidating,
OnValidatingChanged,
and FormContext.IsAnyFieldValidating
for submit-button gating.
Tier C — Features
TabsList.Reorderable
+ OnReorder
(TabsReorderEventArgs:
FromIndex,
ToIndex,
MovedTabValue) —
the consumer mutates the collection, the library handles drag UX. New Submenu support across
DropdownMenu,
ContextMenu, and
Menubar via
*Sub /
*SubTrigger /
*SubContent with
hover-intent open, ArrowLeft/ArrowRight navigation, and Escape-closes-the-whole-tree.
Tier D — BREAKING: enum unification
The per-component Size, Side, Align, and Orientation enums (e.g.
Button.ButtonSize,
Tooltip.TooltipSide,
Sheet.SheetSide,
Popover.PopoverAlign,
Tabs.TabsOrientation)
have been replaced by four library-wide types in the
Lumeo namespace:
Lumeo.Size,
Lumeo.Side,
Lumeo.Align,
Lumeo.Orientation.
The rename is mechanical (search-and-replace) and the values are 1:1 across the old and new types — see
MIGRATION.md for
the full per-component recipe.
May 2026
Reliability fixes — four Blazor sync-context / async-void / fire-and-forget gotchas that could surface as silent failures or circuit crashes under specific timing conditions.
Each fix is small and localised; the pattern is consistent across all four sites: move callback work back onto the Blazor sync context (InvokeAsync) so exceptions are observable, and return / await tasks instead of fire-and-forget.
Fixed
FileUpload: auto-upload no longer dispatched viaTask.Run(which hopped to the thread pool and forced every innerStateHasChangedto marshal back throughInvokeAsync). Replaced with a directInvokeAsync(async () => …)+ try/catch that surfaces systemic upload failures on each pending item'sStatus+ErrorMessage.DateWheelPicker+TimeWheelPicker:CommitDay/CommitMonth/CommitYear/CommitHour/CommitMinute/CommitPeriodwereasync void. Any exception thrown after the first await escaped to the thread-pool finalizer and crashed the circuit. Converted toasync Task;ResetTimer's commit parameter is nowFunc<Task>soInvokeAsynccan observe completion.- Wheel-picker init delay:
Task.Delay(150).ContinueWith(_ => InvokeAsync(...))ran the continuation on the thread pool and silently swallowed any exception (including the typicalJSDisconnectedExceptionduring circuit teardown). Replaced withInvokeAsync(async () => { await Task.Delay(150); … })+ explicitJSDisconnectedExceptioncatch. DatePicker.SetIsOpen+HoverCard.OnClickOutside:_ = OpenChanged.InvokeAsync(value)fire-and-forget — a faulting consumer handler vanished into the void. Now wrapped inInvokeAsync+ try/catch (DatePicker) or returned viaawait(HoverCard, whose caller is async-aware).
No new tests — these are runtime-conditions that no existing test exercises; the fixes are mechanical pattern replacements. The library audit that surfaced them is at /tmp/lumeo-quality-audit.md (Critical tier).
May 2026
DataGrid Groupable-column drag affordance + group-panel placeholder localisation. Two follow-ups from real users hitting the new themed group-panel in 2.2.0/2.2.1: there was no visual indication on column headers that they support drag-into-panel (users had to try each one to discover which were Groupable), and the panel's "Drag a Groupable column header here…" placeholder was still hardcoded English (missed by the 2.2.0 i18n sweep).
Added
- Drag-to-group affordance on column headers — when
ShowGroupPanel="true"and the column isGroupable, the header now reveals a muted Group icon on hover (mirroring the filter button's opacity pattern), plus the cell carriescursor-grab. Title attribute usesL["DataGrid.DragToGroup"]("Drag to group by this column" / "Zum Gruppieren nach dieser Spalte ziehen"). Both icon + cursor are hidden when there's no panel to drop into, so non-grouping grids aren't cluttered.
Fixed (i18n)
- Group-panel empty-state placeholder "Drag a Groupable column header here, or use the dropdown" was still a hardcoded English literal inside
@(GroupPanelText ?? "…")— the 2.2.0 i18n agents missed it because of the null-coalesce shape. Now routes throughL["DataGrid.GroupPanelPlaceholder"]. Consumers passing an explicitGroupPanelTextstill take precedence — back-compat preserved.
Localisation keys added
DataGrid.GroupPanelPlaceholder(EN + DE)DataGrid.DragToGroup(EN + DE)
May 2026
DataGrid group panel: hard-right alignment + persistence on grouping changes.
Two 2.2.0 regressions surfaced by the first consumer of the new themed group-panel: the new "+ Add group level" DropdownMenu didn't sit at the right edge of the panel, and grouping mutations weren't being written to localStorage even though sort/filter/columns were.
Fixed
- Group panel "+ Add group level" picker now right-aligned — the 2.2.0 refactor moved the trigger into a
<DropdownMenu>component, which renders its ownrelative inline-blockwrapper as root. Theml-autoon the inner trigger button had no effect on the flex-parent panel becauseDropdownMenuwas the actual flex child. Wrapped the component in a<div class="ml-auto">so the picker sits hard-right again. - Grouping changes now persist to
localStorage—AddGroupField/RemoveGroupField/ClearGroupFieldsdidn't callScheduleAutoSave(), so the snapshot serialization built in v2.1.1 had nothing to act on. Sort/filter changes had been calling it from day one. Three matchingScheduleAutoSave()calls added — grouping now round-trips through reload identically to sort/filter/columns.
No new tests — the existing v2.1.1 snapshot-and-restore tests cover the persistence contract; the missing trigger was the bug. The right-align fix is visual and covered by manual verification in the PR checklist.
May 2026
Theming & accessibility polish — a quality release. A library-wide sweep across CSS theming, keyboard accessibility, and i18n coverage. No new public API surface, no breaking changes — but the library is now consistently themable, keyboard-navigable, and translatable end-to-end.
Fixed (CSS theming)
- Placeholder hover-override (B1) — inner
<span class="text-muted-foreground">placeholder text inside hover-styled trigger buttons no longer becomes illegible on hover (dark grey on accent green). Fixed acrossTimePicker,DateTimePicker,DatePicker(5 placeholder spans) viagroup+group-hover:text-accent-foreground. - DataGrid group-panel "+ Add group level" dropdown — was a native HTML
<select>rendering with OS-default chrome (white-on-blue on Windows). Replaced with Lumeo's own<DropdownMenu>+<DropdownMenuItem>. NavigationMenuMobile—ClassandAdditionalAttributeswere declared but never propagated to a root element. Now applied (Class merged into inner SheetContent; AdditionalAttributes on the inner div).
Improved (accessibility — keyboard focus)
- ~110 new
focus-visible:ring-*rings across ~45 files: DataGrid (header sort/filter buttons, toolbar buttons, row expand/edit/save/cancel, batch ops), Editor (toolbar, BubbleMenu, AiActionMenu), QueryBuilder (combinator pills), Calendar (day cells + nav buttons), Tour, DatePicker preset buttons, ThemeSwitcher swatches, Pagination, NumberInput steppers, FileUpload buttons, TreeViewNode, Sortable handles, RadioGroupCard, MegaMenuLink, PivotGrid, Segmented, ConsentBanner, ImageGallery, InplaceEditor, ReasoningDisplay, FileManager, TreeSelect, PromptInput, PickList, BackToTop, Transfer, and more. - Special-case patterns spotted & fixed: hover-revealed icon buttons (
group-hover:opacity-100) now also reveal on keyboard focus viafocus-visible:opacity-100; adjacent button-groups (steppers, file-action rows) usefocus-visible:relative focus-visible:z-10so rings aren't clipped; overlay/lightbox buttons overbg-black/80backdrops usering-whitefor visibility.
Improved (i18n — multi-lingual UI)
- 62 hardcoded English UI strings routed through
ILumeoLocalizeracross ~32 components (FileManager 15, QueryBuilder 8, PickList 4, Scheduler 3, ThemeSwitcher 3, and many one-offs across aria-labels, titles, placeholders, default parameter values). - ~50 new localization keys added to
LumeoDefaultStrings.cs(English + German pairs). New namespaces:FileManager.*,QueryBuilder.*,PickList.*,Scheduler.*,Theme.*,Chart.*(Loading),BottomNav.*,Dock.*,Badge.*,Chip.*,Alert.*,ImageCompare.*,PromptInput.*,PivotGrid.*,Editor.*,Tabs.*. Effective*nullable-parameter pattern introduced for default-value localization (e.g.LoadingTexton Charts,AriaLabelon Dock/BottomNavFab/TriggerDropdown/ToastClose,GrandTotalLabelon PivotGrid). Consumers passing explicit strings still work — back-compat preserved.
Docs
- Hero badge bumped to v2.2.0. Install snippets (Code, Cli) updated to
--version 2.2.0. lumeo-mcppackage.json + package-lock + src/index.ts + src/registry.json bumped to 2.2.0 (lockstep).- New
DataGrid.AddGroupLevelkey (EN/DE) added.
Known follow-ups (deferred to 2.2.1)
QueryBuilderGroupField/Operator pickers still use native<select>with themed trigger but OS-default dropdown popup.InplaceEditorthe same. Refactor to<Select>needs the disabled-placeholder pattern.StepperStepis a pure-registration component; itsClassparameter is currently dead. Plan: thread throughStepRegistrationrecord so parentSteppercan apply it.
No new bUnit tests for this sweep — the changes are non-behavioural (CSS classes, aria-labels, localization keys). Existing test suite continues to pass.
May 2026
JS module import URL gets a ?v=<version> cache-buster.
Library JS under _content/Lumeo/js/components.js is served WITHOUT a content-hash (unlike the Blazor framework files), so an already-loaded browser tab kept its 2.1.2 components.js after upgrading the lib to 2.1.3 — and new C# code calling new exports like registerViewportListener threw JSException: 'registerViewportListener' is not a function at runtime. Fixed by appending ?v=<assembly-version> to library module imports.
Fixed
ComponentInteropService.GetModuleAsync+ImportModuleAsyncnow append?v={assembly-version}to all_content/Lumeo*/module URLs.KeyboardShortcutService.GetModuleAsyncupdated symmetrically.- Upgrades from this release forward are immune to the stale-cache class of failure when new JS exports are added in the lib (e.g. the v2.1.3
registerViewportListenerfailure). v2.1.3 users hitting that error today need a hard refresh (Ctrl/Cmd+Shift+R); from v2.1.4 the cache-buster handles it automatically.
Notes
- Version derived once from
AssemblyInformationalVersionAttribute(whichDirectory.Build.props <Version>drives), so it tracks every release without manual maintenance. - URLs that already contain a query string pass through untouched — consumer overrides (e.g. local debugging with
?nocache=1) are preserved. - Non-library URLs are passed through unchanged, so consumer JS modules loaded via
ImportModuleAsyncaren't affected.
May 2026
Responsive overlays, polished swipe gesture, and 100% docs parameter coverage.
Three threads landed together: a reactive IResponsiveService + per-overlay mobile overrides so a single Overlay.ShowSheetAsync can switch from side panel on desktop to fullscreen bottom-sheet on mobile and back across rotation; a swipe gesture rewrite (10px activation deadzone + direction lock + rubber-band) that kills the wackelig feel users reported on small finger movements; and a full sweep of the API tables on every component docs page so every [Parameter] is now documented (500+ rows added across 60 pages).
Added
IResponsiveService— reactive viewport/breakpoint service. ExposesWidth,Height,Current(Breakpointenum: Xs/Sm/Md/Lg/Xl/Xxl aligned with Tailwind v4),IsMobile/IsTablet/IsDesktop, and aViewportChangedevent. One JS resize listener per circuit, debounced 100ms.OverlayOptions.MobileBreakpoint/MobileSheetSide/MobileSheetSize/MobileSwipeToClose— per-overlay responsive overrides. BelowMobileBreakpoint(default 768px = Tailwind md) theMobile*fields take precedence.OverlayProviderre-renders reactively on viewport crossing — sheet flips correctly when a tablet is rotated mid-flight.
Improved
- Swipe gesture (Sheet + Drawer) — previously the element followed the finger from pixel 1 with no axis lock; users reported the sheet felt wackelig on micro-movements and accidentally engaged on diagonal scroll attempts. Now: 10px activation deadzone (finger must commit before the sheet moves), direction lock at activation (gesture locked to the dominant axis — diagonal-on-bottom-sheet scrolls content instead of dismissing), and rubber-band past 150px so the sheet doesn't fly off-screen when the user keeps pulling. Dismiss threshold (100px) unchanged.
- Docs parameter coverage now 100% across all 163 components — 504 missing API table rows added across 60 pages (largely Chart components which previously documented their core 5 params but not the recurring Width/Height/Theme/ColorPalette/AnimationDuration/MarkLine/MarkPoint/Toolbox surface).
Docs
- Hero badge bumped to v2.1.3.
- OverlayService page:
OverlayOptionstable gains the fourMobile*rows; new "Responsive sheets" section with the desktop-Right ↔ mobile-Bottom example. - Sheet page: cross-reference to
IResponsiveServicefor live-reactive sizing decisions. - New
IResponsiveServicedocs page covering the API and the recommended subscription pattern.
~10 new bUnit/xUnit tests cover the responsive service (FromWidth mapping, event firing, breakpoint flags) and the OverlayOptions responsive defaults. Swipe-threshold change is JS-only — relies on manual mobile testing per the PR checklist.
May 2026
DataGrid column filter popover no longer spawns a phantom horizontal scrollbar.
On the rightmost columns of a grid with overflow-x:auto, opening a column filter made the entire grid scroll horizontally. The popover wrapper was position:absolute relative to its <th>, so its content extended past the cell edge and was counted in the scroll-container's scrollWidth. Fixed by reusing the Floating-UI-style positioner that PopoverContent already uses — position:fixed with coords from the trigger's getBoundingClientRect(), follow on scroll/resize, and viewport-flip when overflow would push the popover off-screen.
Fixed
- DataGrid column filter popover now renders with
position:fixedinstead ofposition:absolute. The popover is pinned to the trigger viaInterop.PositionFixed(same path asPopoverContent), so its layout box no longer contributes to the scroll container'sscrollWidth.
Improved
- Filter popover click-outside dismiss — previously the popover only closed via Apply / Clear; clicking elsewhere left it open. Now registers a click-outside listener (excluding the trigger so the toggle button doesn't immediately close-then-reopen) and follows the trigger on grid scroll/resize.
2 new bUnit regression tests guard the inline position:fixed + stable trigger-id contract that the JS positioner depends on.
May 2026
DataGrid group panel survives reload, Sheet mobile-fullscreen, OverlayService swipe-to-close. Four real library fixes folded into a single patch release. The biggest one: layout snapshots silently dropped the runtime group-panel chips so multi-level grouping vanished on reload while sorts/filters/columns restored cleanly.
Fixed
- DataGrid layout persistence:
SnapshotCurrentLayoutandBuildLayoutSnapshotnow capture_runtimeGroupFields;ApplyLayoutAsync/ApplyLayoutSnapshotAsyncrestore the panel chips. InternalDataGridLayout+ publicDataGridLayoutSnapshotgainGroupByFields; snapshot version bumped 1 → 2. v1 payloads still load via the legacy single-levelGroupByfallback. - DataGrid column filter popover: custom
FilterTemplaterows withhover:bg-accentpainted past the rounded-lg corners.DataGridColumnFilterwrapper gainsoverflow-hidden;w-64→min-w-64so wider templates grow the popover instead of overflowing.
Improved
- Sheet
Size="Full"on Top/Bottom: now produces a true mobile-fullscreen sheet (inset-y-0 h-full max-h-full) instead of being a silent no-op.Sm/Lg/Xlcap height at 40/70/85vh for symmetry with Left/Right width caps.Defaultkeeps legacy content-driven height — back-compat. - OverlayService
OverlayOptions.SwipeToClose: programmatically-opened Sheets can now be swipe-dismissed, matching the declarative<SheetContent SwipeToClose="true">path. Drawers already had swipe-close by default; this puts Sheets at parity. Defaultfalse— back-compat.
Docs
- DataGrid page: Persistence demo description and "Saving and loading layouts" prose now mention the group panel is included;
Version: 2noted alongside the v1-backcompat clause. - Sheet page:
Sizerow now documents the Top/Bottom height behaviour and the Full-on-Bottom mobile-fullscreen pattern. - Overlay Service page:
SwipeToCloseadded to the OverlayOptions API table.
12 new bUnit tests cover snapshot capture & round-trip (incl. v1 back-compat), filter popover clipping, Sheet sizing on Top/Bottom, and OverlayService option routing.
May 2026
DataGrid: multi-level grouping & the runtime group panel now work in ServerMode.
Single-level GroupBy already worked in ServerMode; GroupByFields and the panel handlers (drag-to-group, add-level dropdown, per-chip remove, clear-all) were silently no-ops because each UI mutator short-circuited with if (!ServerMode) ProcessClientData(). They now route through a shared RegroupServerItems() that delegates to the same ProcessSingleLevelGrouping / ProcessMultiLevelGrouping client mode uses — so multi-level, expand-state preservation, and per-group aggregates are now symmetrical across modes.
Improved
- DataGrid
ServerMode:GroupByFields(multi-level) now applies to server-returned items. - DataGrid group panel (
ShowGroupPanel="true"): drag-to-group, add-level dropdown, per-chip remove, and clear-all all fire in ServerMode without an extra server round-trip. - Per-page semantic preserved: grouping runs over the rows the server returned for the current page. For cross-page grouping, either disable pagination (
ShowPagination="false") so the server delivers all rows in one response, or have the server pre-aggregate groups itself. This is a consumer-side architecture choice, not a grid limitation. - Side benefit: ServerMode single-level grouping now also computes per-group aggregates (was previously client-mode only) because the unified path runs through
ProcessSingleLevelGrouping.
Docs
- DataGrid component page: new ServerMode-grouping callout above the Server-Side Mode demo;
GroupBy+GroupByFieldsparameter rows clarified; "Group panel & multi-level grouping" section gains a per-page-caveat paragraph. - MCP registry description updated across registry.json, registry-search.json, registry/data-grid.json, components-api.json, and skills catalog to advertise "multi-level group (client + server)".
2438/2438 tests pass · core + DataGrid + docs build clean (0/0). 6 new bUnit tests cover ServerMode multi-level grouping and each UI handler.
May 2026
MCP registry fix — regenerated against the 2.0.0 component surface.
The MCP data files were last generated at rc.38 and never regenerated for 2.0.0, so they shipped 145 components labelled 2.0.0-rc.38 while the library had grown to 149. npm forbids overwriting the published @lumeo-ui/mcp-server 2.0.0, so the fix ships under a new lockstep version.
Fixed
- RazorParameterScanner: only parsed the LAST
@codeblock, silently dropping all 14 of FileManager's[Parameter]s. Now parses every@codeblock independently and merges results — so Checkbox's markup-bearing RenderFragment block no longer corrupts extraction. - RegistryGen version source: now reads the lockstep
<Version>fromDirectory.Build.propsinstead of two hardcoded literals (one was still2.0.0-rc.38) — registry can't drift again. - Stale install snippets in docs: the Code component demo and CLI docs page hardcoded
--version 2.0.0. RegistryGen pulls the Code example intocomponents-api.json, so MCP clients got stale guidance — the exact bug class this release fixes. Bumped to2.0.1.
Changed
- Lockstep bump:
Directory.Build.props2.0.0 → 2.0.1;tools/lumeo-mcppackage.json + index.ts → 2.0.1. - Regenerated registry: 149 components, 3510 params, 104 enums, 59 records, 0 parse failures. Skill catalog auto-resynced via
sync-skill-catalog.yml.
May 2026
First stable release — the rc.1..rc.54 series is superseded.
Promotes the lockstep version from 2.0.0-rc.54 to 2.0.0. Readiness audit + Codex review both green: Lumeo.slnx -c Release -warnaserror shows 0 errors / 0 warnings, 2475 tests green, 16/16 E2E against the Release docs server, and shipped NuGet packages have no vulnerable dependencies.
Release prep — blockers
- README: replaced the release-candidate callout with stable-2.0 language; pinning guidance updated to
2.0.0+. - Companion package drift:
tools/Lumeo.Cliandtemplates/Lumeo.Templateshad a hardcoded2.0.0-rc.16(38 RCs behind). Removed the override so both inherit the lockstepDirectory.Build.propsversion. - MIGRATION.md: documented the rc.53
IComponentInteropService.RegisterCarouselSwipescrollHandler signature change (Func<double,double,Task>→Func<double,double,int,Task>) as breaking change #6.
Release prep — Codex findings
- npm audit clean at
--audit-level=high:tools/lumeo-mcpwent from 4 vulns (1 high viaexpress-rate-limit→ vulnerableip-address) to 0;docs/Lumeo.Docsfrom 1 high to 0. - SECURITY.md: supported-versions table, private disclosure channels (GitHub Security Advisories +
[email protected]), response SLAs, scope, and dependency-hygiene statement. - Package READMEs: all 9 packable projects now set
<PackageReadmeFile>README.md. Shared packing rule centralised inDirectory.Build.targets(not.props— .props is imported before the project body so the conditional wouldn't see PackageReadmeFile). Zero NU5039.
Open-source declutter
- Removed 25 internal audit docs from loose
docs/*.md(release-readiness iterations + business-sensitive market-gap-analysis). User-facing docs atdocs/Lumeo.Docs/untouched (632 files). Gitignored the path so internal notes can't re-enter the published tree. - Removed
docs/superpowers/: 146 files of internal AI-workflow scaffolding (audits, implementation plans, workspace matrices). Preserved in git history. - Removed scratch build-dump txt files:
_p2.txt,build_lib.txt, etc. — accidentally tracked stdout dumps. Gitignored the patterns. - Dropped stale
.github/SECURITY.md: still claimed pre-1.0 status. GitHub resolves.github/over root, so the Security tab was showing the outdated policy. Removing the duplicate makes GitHub fall back to the canonical root file. - README refreshed for stable: PackageReference examples 2.0.0-rc.54 → 2.0.0; component count consistent at 145; stale "~530 KB" core-size claim replaced with a link to the live
/docs/bundle-factspage.
2475 tests green (2424 unit + 20 docs + 31 registry-gen) · 16/16 E2E against the Release docs server · zero vulnerable dependencies in shipped packages.
May 2026
Toast deep-fix — close-button focus ring + mobile viewport collapse. ToastClose's focus ring was invisible on coloured variants and the X was opacity-0 for keyboard users; mobile toast viewports squeezed title + description + close + action into unreadable widths on 360px screens.
Fixed
- ToastClose focus ring:
focus:ring-1(1px, no color) →focus-visible:ring-2 ring-current ring-offset-1— visible on every variant including Destructive/Success/Warning/Info (ring-currentinherits text color → contrast guaranteed). - ToastClose keyboard reveal:
focus-visible:opacity-100ensures keyboard focus surfaces the X on desktop (wasopacity-0 sm:group-hover:opacity-100, invisible to keyboard users). - ToastClose affordance: hover/focus background (
bg-foreground/10) + text-color shift instead of just an opacity tween. - ToastViewport mobile collapse: all 6 positions now collapse to bottom-center with
inset-x-4(16px gutters) below the sm breakpoint. Width isw-auto sm:w-full sm:max-w-[420px]— mobile fills gutters, desktop caps at 420px. Developer-chosen position takes effect unchanged from sm: upwards.
2424 + 20 + 31 = 2475 tests green.
May 2026
Swipe re-registration + Carousel jitter + Toast mobile + PullToRefresh DevTools + polish. Five mobile-sprint follow-ups: rc.52's Tabs/Calendar swipe worked only on the first activation (the panel DOM was recreated on switch, leaving the new element with no pointer listeners), Carousel touch-release fought native scroll-snap, Toast's close button overlapped text on mobile, and PullToRefresh failed under DevTools emulation.
Fixed
- Tabs swipe re-registration: gated on
firstRender+ one-shot flag; in Active render mode the panel DOM is recreated on every switch. Replaced with bidirectional_swipeAttachedtracking —OnAfterRenderAsyncnow re-attaches whenever the panel becomes active. - Calendar swipe re-registration: same root cause when switching view to Months/Years and back to Days. Same
_swipeAttachedpattern; swipe stays scoped to Days view by design. - Carousel touch jitter: on release, browser scroll-snap momentum AND an imperative
scrollIntoView({behavior:smooth})fired simultaneously, producing visible jumps. Removed the touchend listener — native scroll-snap handles release smoothly.onScrollnow reports the nearest snapped index back to .NET to keep_currentIndexin sync. - Toast mobile padding: 44px close button overlapped toast text because content padding was a fixed
pr-6. Changed topr-11 sm:pr-6. Close button flush to corner on mobile (right-0 top-0), offset on desktop. - PullToRefresh DevTools: DevTools mobile emulation reports
pointerType='mouse'and drops pointermove events when the pointer drifts outside the element. AddedsetPointerCaptureon pointerdown so the move stream stays alive. - Chip dismiss X: replaced rc.49's negative-margin hit-area trick with a
before:absolutepseudo-element — visual size back to a compact 20×20 px X with no visible padding sprawl.
Changed (internal)
- BREAKING (internal API):
IComponentInteropService.RegisterCarouselSwipescrollHandler signature changed fromFunc<double, double, Task>toFunc<double, double, int, Task>(added current snap index). Only caller is Carousel.razor; no external consumers expected.
Docs polish
- TouchRipple: new "When to use TouchRipple vs Button's built-in ripple" Alert + canonical demo wrapping a Card with three tappable list rows.
- SafeArea: realistic sticky bottom-tab-bar demo pinned above the iPhone home indicator via
SafeArea Bottom="true". - Pagination: demos wrapped in
overflow-x-autocontainers + mobile-tip Alert pointing to the Compact variant.
2424 + 20 + 31 = 2475 tests green (3 new swipe re-registration regression tests: 1 Tabs, 2 Calendar).
May 2026
Tabs swipe + Calendar swipe + Image pinch/swipe + haptic feedback + 44px polish. Five new mobile-feature additions across existing components plus a dedicated Mobile Playground docs page for testing the whole mobile stack in DevTools or on a real phone.
Added
- Tabs —
SwipeEnabled/SwipeWrapparams. Horizontal swipe onTabsContentswitches panels (50px threshold, 30px vertical guard,touch-action: pan-y, interactive-child bailout). NewregisterTabSwipeJS helper. - Calendar —
SwipeEnabled(default true) on the day-grid navigates between months; chevrons bumped toh-11 w-11 sm:h-7 sm:w-7for WCAG 2.5.5. NewregisterHorizontalSwipeJS helper. - ImageGallery —
GesturesEnabled(default true). Fullscreen viewer pinch-zoom reuses Image.Zoomable pipeline; horizontal swipe navigates prev/next. - Switch + Checkbox — opt-in
HapticFeedbackparam (default false). FiresHapticsService.Light()on toggle — establishes the cross-cutting haptic-opt-in convention for more inputs in rc.53. - Pagination + Stepper 44×44 targets:
PaginationItem h-9 w-9 → h-11 w-11 sm:h-9 sm:w-9; Stepper invisible hit-area trick (p-1.5 -m-1.5 sm:p-0 sm:m-0) so the visible 32px dot expands to ~44px tap target on touch. - /docs/mobile — Mobile Playground: hands-on demos of every gesture, haptic primitive and hit-target retrofit. One page to test the whole mobile stack.
Docs
- Sheet page: replaced single Bottom swipe demo with a 4-side interactive demo (Top quick-actions, Right edit-form, Bottom filter-list, Left navigation). Updated SwipeToClose API description to reflect all 4 sides.
- TabsPage / CalendarPage / SwitchPage / CheckboxPage / ImagePage: new Mobile-feature sections + API table rows.
2421 + 20 + 31 = 2472 tests green (13 new: 7 Tabs swipe, 2 Switch haptic, 2 Checkbox haptic, plus integration coverage).
May 2026
NumberTicker animates correctly when loaded in a background tab.
Captured start = performance.now() at schedule time meant that when a tab loaded in the background (e.g. Ctrl+Click), requestAnimationFrame was paused and the first step() callback never fired — leaving the ticker frozen at 0, or jumping straight to the end value the moment the tab became visible.
Fixed
- NumberTicker background-tab freeze: defer
start = nowuntil the firststep()callback. Standard RAF pattern; zero-cost for foreground-loaded tabs. Verified live on/docs/bundle-facts. - NoopInteropService (Docs.Tests): added the missing rc.49 APIs (
RegisterPinchZoom/UnregisterPinchZoom,GetScrollTop,WheelScrollTop,WheelScrollTo). Without these the Docs.Tests project failed to compile — surfaced as red CI on rc.49/50/51 (Publish/Deploy stayed green so packages and docs were online; only CI was noisy).
20/20 Docs.Tests + 2410/2410 Lumeo.Tests + 31/31 RegistryGen.Tests pass.
May 2026
Phase 2 mobile primitives in core — 5 new components, 1 service, plus wheel-picker variants.
Adds the mobile-only primitives that don't fit into existing components. All in Lumeo core; no separate Lumeo.Mobile satellite.
Added — new components
- PullToRefresh: wraps scrollable content; pointer-driven pull-down gesture with spinner fade + rubber-band;
OnRefreshfires after threshold. v1: requires the wrapper itself to be the scroll container. - SwipeActions: iOS Mail.app pattern with
LeadingActions/TrailingActionsRenderFragment slots. Foreground translates horizontally on swipe; locks open atActivationThresholdPx; vertical-scroll passthrough. v1: fixed 160px open width. - SafeArea: CSS
env(safe-area-inset-*)wrapper for notch/system bars. Per-side toggle params; no JS. - TouchRipple: Material-style ripple.
PointerDownspawns positioned span with CSS animation. Custom Color/Opacity/DurationMs. CTS-cancelledTask.Delaycleanup on Dispose. - HapticsService: facade over
Interop.Vibrate(int). Light/Medium/Heavy/Success/Error semantic presets. Registered inAddLumeo().
Added — picker variants
- DatePicker
Variant=Wheel: 3-column iOS-style wheel (day/month/year). Culture-aware month names; Min/Max year range; day re-clamps when month/year changes (no Feb 30). - TimePicker
Variant=Wheel: hours/minutes + AM/PM column when 12h. HonoursCurrentCulture.AMDesignator;MinuteStepsnap.
Added — interop + CSS
- Interop:
GetScrollTop(elementId),WheelScrollTop(elementRef),WheelScrollTo(elementRef, scrollTop). ReusesVibrate(int)from rc.49. - CSS:
.lumeo-touch-ripple+ keyframes;.scrollbar-noneutility (Firefox + WebKit).
2410/2410 tests pass · build clean (0/0). v1 limitations (Calendar/List remain recommended a11y path for the pickers, no keyboard nav on wheels) documented in inline component comments.
May 2026
Touch-native gestures + 44px hit targets across 13 components.
Phase 1 of the mobile sprint: existing components retrofitted with proper touch handling. Same Lumeo API everywhere — no Lumeo.Mobile satellite.
Added — gestures
- Sheet: swipe-to-close (opt-in via new
SwipeToCloseparam, false-default to avoid conflicts with scrollable content inside Bottom sheets). - DataGrid: column resize via pointer events with
setPointerCapture. - Slider: thumb tooltip on touch-drag (
@onpointerenter/leave). - Rating: iOS-style touch-drag-to-scrub across stars.
- ContextMenu: long-press path (500ms timer, 10px move tolerance, haptic via
navigator.vibrate(50)). - Image: new
Zoomableparam — pinch-zoom via two-pointer tracking, scale-delta dispatch, clamped to[0.5, 5.0].
Added — 44×44 hit-target audit (WCAG 2.5.5)
- Window title-bar buttons (Close/Min/Max/Restore), resize handle.
- Chip dismiss button, TabsTrigger close X, DialogContent close X, SortableList drag handle, SidebarMenuButton row.
- ToastClose with mobile visibility fix — was
opacity-0hover-only, nowopacity-100 sm:opacity-0 sm:group-hover:opacity-100. - DropdownMenuItem + ContextMenuItem rows:
min-h-11 sm:min-h-0. - Pattern: full 44px hit area on touch (no
sm:), compact original size atsm:and up. Icon sizes unchanged so desktop visual density is preserved.
Fixed (caught by review-agent before tag)
- Rating mouse double-fire:
pointerdownwas firing for mouse too, causingValueChangedto double-fire withAllowHalf=true. Fixed viae.PointerType=='mouse'early-return. - ToastClose invisible-but-blocking on mobile:
opacity-0hover-only with 44px hit area was capturing taps on the toast title. Fixed via responsiveopacity-100 sm:opacity-0. - Pinch-zoom 3-finger baseline drift:
lastDistancenow re-baselined on 3→2 transition. - Sheet swipe-vs-scroll conflict on Bottom sheets:
SwipeToClosenow opt-in.
2410/2410 tests pass.
May 2026
/docs/bundle-facts — add Hot Reload section + clarify .nupkg numbers.
User feedback: the bundle-facts page should mention Lumeo's Hot Reload quality with real architectural reasons, plus the "Why brotli not .nupkg" accordion should reflect the rc.40 .nupkg reduction (1.35 MB → 660 KB).
Added
- Section 8 "Hot Reload that actually works" with 6 concrete facts, each paired with a "what other libs do" contrast so the comparison is grounded:
- No Blazor CSS isolation (Tailwind utility-first, no per-component scoped-class hashing).
- Theme is CSS variables, not a C# object (no recompile to swap colors).
- No source generators in runtime hot path (
[LumeoForm]is opt-in). - No reflection in render path (rc.44 compiled-getter fix).
- CascadingValue composition over inheritance — each Razor file HRs independently.
- Tailwind + Razor SDK watch run in parallel; CSS swaps don't go through Blazor at all.
- Why-brotli-not-nupkg Accordion rewritten with a 3-row comparison block (1.35 MB pre-rc.40 → 660 KB post-rc.40 → 400 KB brotli to browser) and a link to
nuget.org/packages/Lumeofor self-verification.
Docs project clean (0/0).
May 2026
New /docs/bundle-facts page — replaces the easter-egg Dialog on the home page.
User feedback: the click-to-open Dialog was cramped and undiscoverable. Replaced with a dedicated animated page that uses Lumeo's own motion primitives (BlurFade, NumberTicker, Sparkles, Marquee, BorderBeam, ShimmerButton, Accordion) to showcase the bundle-size story.
New page sections
- Hero — animated
NumberTickerhitting 400 KB inside aSparklesoverlay. - Per-package bar chart — 7 staggered
BlurFaderows showing proportional brotli sizes. - What's actually in the .nupkg — 4 cards explaining Lumeo.dll / lumeo.css / components.js / build-props.
- "What's NOT in core" Marquee — endless strip of deliberately-excluded dependencies (Newtonsoft.Json, AutoMapper, jQuery, etc.).
- Comparison table vs MudBlazor / Radzen / FluentUI / Telerik (approximate brotli sizes).
- Heavy features are opt-in — 3-tile Bento for Charts / DataGrid / Editor.
- Why brotli not .nupkg — Accordion with 3 explainers.
- CTA footer — ShimmerButton to
/docs/installation.
Home.razor
- Removed the entire
<Dialog @bind-Open="_bundleSizeDialogOpen">block (~72 lines). - Replaced the trigger button with
<Lumeo.Link Href="/docs/bundle-facts">wrapping the existing "~400 KB core" text. - Removed the now-orphan
_bundleSizeDialogOpenfield. - Sidebar nav
nav-config.jsongained a "Bundle Facts" entry under getting-started.
Docs project builds clean (0 warnings, 0 errors).
May 2026
rc.44 hotfix — two crashes surfaced in user runtime logs.
Fixed
- Window:
Math.Clamp(0, -40)crash on drag-during-init. The rc.44 viewport-aware drag clamp could be invoked before_viewportHeightfinished loading from JS (or in non-WASM contexts where the JS interop returns null). When zero,Math.Clamp(_dragStartPosY + dy, 0, _viewportHeight - TitleBarHeight)resolved toMath.Clamp(value, 0, -40)→ArgumentException. Fix mirrors theClampPosition()guard: if viewport is unknown, fall back to lower-bound-only clamp (pre-rc.44 behavior). - LumeoForm generator:
InvalidCastExceptionsettingButton.typeon the submit button. The generator emittedAddAttribute("type", "submit")— lowercase HTML attribute name + string value — butLumeo.Button.Typeis a strongly-typedButtonTypeenum (Button/Submit/Reset). Fix: emitAddAttribute("Type", global::Lumeo.Button.ButtonType.Submit).
2410/2410 tests pass · 8 projects + tests + docs build clean.
May 2026
Mega-Sprint A+B+C consolidated: ~35 fixes across 8 categories, one release. 6 parallel fix agents handled the previously deferred items (A: Window/RTL/Scheduler/Gantt; B: LumeoForm + Visual Diff). 5 parallel audit agents covered the previously un-audited dimensions (C: localization, performance, Blazor Server, mobile/touch, API consistency). 4 parallel fix agents addressed the HIGH-priority C findings. API renames were intentionally deferred to a v2.1 breaking-change release.
A — Carry-overs from rc.43
- Window drag-clamp (viewport-aware): new
Interop.GetViewportSize()+ClampPosition()keeps the title bar inside the viewport on all four edges (MinVisible=50px, TitleBarHeight=40px). Consumer-setInitialX=9999is now clamped on first render. - RTL ArrowKey-swap: Carousel, Stepper, Tabs, Splitter now respect
ThemeService.CurrentDirection == LayoutDirection.Rtland swap ArrowLeft↔ArrowRight for horizontal navigation. - Scheduler:
lumeo:theme-changedlistener re-renders active calendars;OnInitErrorcallback surfaces FullCalendar bundle-load + Calendar-constructor failures. - Gantt:
OnInitErrorcallback added (matches Chart/Scheduler pattern).
B — LumeoForm generator design + Visual Diff
- LMF001: read-only / init-only properties now emit a Roslyn diagnostic explaining they're excluded.
- LMF002: unsupported types (collections, custom refs) emit a diagnostic suggesting
[LumeoFormIgnore]or TagInput override. - New
[LumeoFormIgnore]attribute +[NotMapped]recognition suppress diagnostics on properties that should be excluded silently. - Visual Diff:
HomePageVisualTestsnow uses ImageSharp perceptual compare (0.5% tolerance, Manhattan RGBA > 30). CI skip removed — test runs everywhere.
C-Audit Findings + Fixes
Localization (7 HIGH)
- Delta stops hardcoding
InvariantCulture— German users now see+12,5 %. KPI cards across all dashboards inherit. - DateRangePicker.Format default
"MMM dd, yyyy"→ null, resolves toCurrentCulture.ShortDatePattern. - TimePicker.Use24Hour bool → bool? → null derives from
CurrentCulture.ShortTimePattern. Hardcoded "AM"/"PM" →AMDesignator/PMDesignator. - DataGrid plurals (RU/PL/AR-aware): new
LumeoPlurals.PluralKey(count, baseKey, culture)helper — returns.One/.Few/.Many/.Otherbased on language rules.DataGrid.ItemsCountuses it. EN/DE/PL/RU/AR translations supplied. - Stepper.* and Window.* translations added to all 13 non-English locale dicts — half the strings were silently falling back to English.
- DateTimePicker now forwards
FirstDayOfWeekto inner Calendar. - Hardcoded English aria-labels in NumberInput, Input, Window, Slider, FileManager, FileUpload, DateTimePicker routed through
ILumeoLocalizer. Keys added to all 14 locales.
Performance (5 HIGH)
- DataGridColumn.GetValue now uses compiled
Expression<Func<TItem,object?>>getters cached per field. ~10× faster than the oldPropertyInfo.GetValue. Supports nested paths (Address.City) with null-safe chain. - DataGridRow + DataGridCell CssClass memoization: tuple-keyed cache. 1k rows × 10 cols = 10k+ string allocations per render → ~1 per row+cell on state change.
- Context.VisibleColumns exposed on
DataGridContext<TItem>— eliminates per-rowColumns.Where(c => c.Visible)LINQ. - ComboboxContent.FilteredItems: property → memoized backing field invalidated on
Items/SearchTextchange. 10k-item dropdowns no longer re-filter 3× per render. - PivotGrid skip-rebuild gate (
_lastItemsRef+ dims hash) — eliminates full tree-rebuild on unrelated parent re-renders.
Blazor Server + Touch + Disposal
- 9 components wrapped their first-render JS interop in
try/catch (JSDisconnectedException, ObjectDisposedException): Affix, BackToTop, Carousel, Scrollspy, ResizableHandle, OtpInput, ConsentBanner, PromptInput, AgentMessageList. - TabsList prerender measurement guarded against
InvalidOperationException(Blazor prerender). - Keyboard shortcut Map cleared on
registerKeyboardShortcutsentry — no more stale entries leaking across Blazor Server circuit reconnects. - P0 mobile fix:
registerClickOutsidenow bindstouchstart(with{ passive: true }+ 600ms synthetic-mousedown dedupe). Tap-outside now closes every Dropdown, Combobox, Select, Popover, ColorPicker, ContextMenu, DatePicker, TimePicker on mobile. - SortableList touch reorder: new
registerSortableTouchJS helper withelementFromPointdrop detection. Mouse path unchanged (still uses HTML5 Drag API). - Tooltip + HoverCard tap-to-pin: tap toggles pinned state; click-outside unpins via the now-touch-aware
registerClickOutside. - NavigationMenu + MegaMenu:
@onmouseenter/leave→@onpointerenter/leavewithe.PointerType == "mouse"guard. Submenus no longer close on touch liftoff before the user can tap a sub-item.
Deferred to v2.1 (breaking-change release)
- API consistency renames:
Stepper.ActiveStep → CurrentStep, Multi-value collection type unification (HashSet/List/IEnumerable),Values → SelectedValues,SidebarProvider.IsCollapsed → Collapsed, Size enum harmonization. These are breaking and need consumer migration.
145 components · 2,410 tests pass · all 8 packages + tests + docs build clean (0 warnings, 0 errors).
May 2026
Mega-Audit sweep: ~30 fixes across A11y, RTL, theme/dark-mode, async/race, memory, forms, and third-party wrappers. Dispatched 7 parallel review agents over the full ~145-component surface (categories the rc.42 audit didn't cover) → 40 hypothesized bugs → 6 parallel fix agents → all green. The single release covers the substance of what would have been rc.43 through rc.47.
A11y (12 fixes — interactive components keyboard navigation)
- Carousel arrow-keys now
preventDefault— page no longer scrolls when the carousel handles ArrowLeft/Right. - Roving tabindex on MenubarTrigger, Rating, TreeViewNode (focused-node tracking), Stepper step buttons. Toolbar container gets
tabindex="0"so screen readers announce "toolbar". - SplitterDivider now resizable via ArrowKeys (±10px delta per press, horizontal/vertical based on orientation).
- Focus management on open/close: Mention/Cascader return focus to trigger on close; Cascader focuses first option on open.
- ContextMenuTrigger now activates on Shift+F10 / ContextMenu key for keyboard users.
- OtpInput Backspace stopsPropagation so it can't accidentally trigger SPA back-navigation.
RTL (10 fixes — full right-to-left support)
- Carousel (Next/Previous/Content/Item), Combobox input, DatePicker (5 hardcoded directions), Select / SelectTrigger migrated from hardcoded
ml-/mr-/pl-/pr-/left-/right-/border-r/border-lto Tailwind logical properties (ms-/me-/ps-/pe-/start-/end-/border-s/border-e). - Directional chevrons on Carousel, Pagination, Breadcrumb now flip in RTL via
[dir=rtl]:rotate-180. Arrow-key handler RTL-swap deferred (separate concern; tagged with TODO).
Theme + Dark Mode (5 fixes — ColorPicker is now dark-mode-correct)
- ColorPicker slider thumbs:
background: #fff→var(--color-background). White thumbs were invisible against light-colored hues in dark mode. - ColorPicker checkerboard (transparency visualization): hardcoded
rgba(0,0,0,0.08)→color-mix(in srgb, var(--color-muted) 60%, var(--color-background)). Visible in both modes. - ColorPicker SV-indicator shadow uses theme-aware
color-mix(... var(--color-foreground) ...). The white-on-canvas border itself is kept (correct against any swatch color). - ThemeSwitcher: stale-default-on-first-render fixed via
OnInitializedAsync. UI shows the real current scheme/mode immediately. - ThemeService.ToggleModeAsync: now cycles System → Dark → Light → System (was binary Light↔Dark and permanently lost System mode on first toggle). 3 tests updated to match the new cycle contract.
Async / Memory (4 fixes — leak elimination)
- FileUpload now implements
IAsyncDisposable— disposes all in-flightCancellationTokenSources in_cancellationson unmount. CRITICAL: every upload running at page-navigate previously leaked a CTS. - FileUpload batch staleness:
_currentBatchIdcounter — old slow batches can no longer fireOnAllUploadedafter a newer batch has started. - TreeSelect.OpenDropdown: post-await disposal guards. Setting
_registered=trueafter a disposal-during-Interop is now impossible. - Mention.HandleBlur: 150ms
Task.Delaynow uses aCancellationTokenSource— re-focusing inside the window cancels the pending hide.
Heavy Wrappers (RichTextEditor — 2 real fixes)
- Silent init failure surfaced: JS wraps
new Editor()+ TipTap bundle load in try/catch with descriptive errors. C# catchesJSException, sets_initError, renders an error card, and invokes newOnInitErrorcallback. Matches the pattern Chart.razor already used. - Orphan suggestion DOM cleanup: suggestion popups are now tagged with
data-rte-id;destroy(id)hunts them down explicitly. No more dangling popups indocument.bodyafter unmount-mid-suggestion. - FALSE ALARM verified: theme-unaware inline styles. The audit thought
style.cssTextwas baked at init — but the strings usevar(--color-*)references, which browsers re-resolve on every paint. Already theme-aware.
Forms + Source Generator (4 fixes)
- LumeoForm generator: non-null enum no longer emits
model.Prop?.ToString()(CS0023). Nullable-aware emit handles bothMyEnumandMyEnum?correctly. - LumeoForm nullable-enum clear: when user clears the Select, the property goes to
nullfor nullable enums. Was: silently kept the old value. - LumeoForm DateTimeOffset: invalid
(DateTime?)cast replaced with.DateTimeaccessor; original.Offsetis preserved through the round-trip. Was: timezone silently stripped. - FormField now reads errors from a cascaded
FormContextparameter — Form.Reset() now actually clears children's visible error state. Was: child kept showing the old error.
False alarms cleared (11)
- DropdownMenuItem:
tabindex="-1"+ parent-drivenFocusMenuItemByIndexis the correct WAI-ARIA menu pattern, not a bug. ColorPicker HSV gradients: hardcoded white/black are color-space primitives, not theme colors. Charts: full theme-change listener and resize observer already in place. Gantt: CSS variables read on every render — passive theme support is intentional. Combobox/Select/Carousel/InplaceEditor/Stepper/Cascader async paths: all guarded correctly. FileUpload didn't have a leak we expected — actual leak (no CTS dispose on unmount) is the one we fixed instead.
145 components · 2,410 tests pass (was 2,407 — +1 for new ToggleMode cycle test, ±0 for the 2 Carousel/ThemeService tests retitled to match new contracts) · all 5 satellite builds clean · 0 warnings, 0 errors.
May 2026
Audit sweep: 3 verified bugs fixed, 11 hypothesized bugs cleared. Dispatched 4 parallel review agents over ~80 components looking for the same class of bug the DataGrid group panel had (UI promises something the implementation doesn't deliver). Found 4 real bugs — Window drag clamp is too involved to ship surgically and goes to rc.43; the other 3 are in this release. Plus a regression test suite for the rc.41 group-panel fix.
Fixed
- Toolbar overflow was completely broken at runtime.
Toolbar.razorcalledobserveToolbarOverflowbuttoolbar.jsonly exportedobserveToolbarWidth/measureToolbarChildren— the function the component depended on didn't exist.Overflow="true" VisibleCount="-1"users got zero auto-collapse. Implemented the missing function (full ResizeObserver + child-width measurement + fitting-count computation in JS), switched C# toInvokeVoidAsyncwith a stable per-component DOM id. ToastOptions.Position(rc.37 API) was silently ignored. The per-toast position override existed inToastServicebutToastProvider.razorrendered every toast into a single<ToastViewport Position="Position">— the provider's default. Now toasts are grouped by their effective position (options.Position ?? defaultPosition) and rendered into one viewport per group. Multipleposition:fixedviewports coexist without overlap.- TreeView lazy-loaded children inherit parent's check state (bonus). When
LoadChildrenresolves, freshly-loaded children now inherit a fully-checked parent's state. Previously a checked parent would expand to reveal unchecked children — a visibly broken tri-state. Indeterminate parents recompute correctly when newly-loaded children land in their default state.
Tests
- New
DataGridGroupPanelTests.cs— 8 bUnit tests covering the rc.41 group-panel fixes: panel render, Groupable-only dropdown filtering, Add/Remove/Clear behavior, and the specific "add after clear still works" regression that the user reported. - All 8 pass green; one assertion was tightened from a panel-wide string match (which falsely included the "+ Add level" dropdown options) to a chip-span selector.
False alarms (audit findings that turned out to be FINE)
- Sortable cross-container drag has
OnDragEndas a state-reset belt regardless of drop. TreeView MultiSelect cascade is correct (tri-state computed viaUpdateAncestorStates). DataGrid virtualization is bypassed when grouping is active (no row-skip risk). Column-reorder during grouping is safe — fields are stored as strings, not indices. Combobox/Select filter clears on close. Tabs uses value-based active state, no index drift. Stepper'sHandleStepClickguards viaCanClickStep. Splitter uses pointer events (touch works). Sheet/Drawer scroll-lock is refcounted. DateRangePicker provides visual feedback for inverted ranges. InplaceEditor's Esc-vs-blur race is synchronously guarded. PivotGrid handles empty data without NaN.
Deferred
- Window component drag can push the window below the viewport (no upper-bound clamp on
_posY). Clean fix needs viewport-aware JS interop — queued for rc.43. Workaround: don't drag the window far enough off-screen to lose it. - Splitter divider is keyboard-focusable but ArrowKey resize is missing (a11y gap). Same sprint.
145 components · all 8 new DataGridGroupPanelTests pass · core + tests + docs build clean (0 warnings, 0 errors).
May 2026
DataGrid group panel bug-fix sweep. User-reported: drag-to-group didn't work even though the panel placeholder said "Drag a column header here", re-grouping after a clear felt broken, and the panel UX wasn't polished. All three fixed.
Fixed
- Drag-to-group now actually works. Column headers with
Groupable="true"are HTML5-draggable wheneverShowGroupPanel="true"on the grid — independent ofReorderable. The panel now has full@ondragover/@ondrophandlers and lights upborder-primary bg-primary/10when a valid Groupable column is dragged over it. Drops on non-Groupable columns (or columns already grouped) are rejected silently. - Re-grouping after clearing all levels works again. The "+ Add group level"
<select>'s native DOMvaluewas sticking on the last-picked option, so after the second add the placeholder ("+ Add group level") wouldn't re-render and the dropdown felt frozen.@keyon the select now forces a fresh DOM element each time the group-fields count changes. - Added a "Clear" button next to the panel chips for one-click reset to ungrouped. Cleaner than chip-by-chip removal.
- DataGridContext gained
ShowGroupPanel: boolso header cells can decide on their own whether to be drag-source-eligible without extra plumbing.
No API break
- The
DataGridContext<TItem>record gained one new positional field — only code that constructs the context manually would break, and the only such caller isDataGrid.razoritself (consumer Razor pages cascade-read it). - Existing single-level
GroupBy="..."demos and multi-levelGroupByFields=@(...)usage are unchanged. The interactive demo on the DataGrid page now genuinely shows the panel feature.
145 components · DataGrid + docs project build clean (0 warnings, 0 errors).
May 2026
Lumeo.nupkg cut in half — CLI source registry moved out of the package.
The 146 shadcn-style per-component snippet JSONs that were shipping inside every Lumeo NuGet install (~3.9 MB raw, ~700 KB compressed) were pure dev-time payload — the CLI fetches them over HTTPS from lumeo.nativ.sh/registry/ at lumeo add time. End-user browsers never touched them.
Result
- Lumeo.nupkg: 1,405,580 B → 672,193 B (−52%, −733 KB). Back below the rc.20 baseline. NuGet UI now displays a sensible package size that matches the actual browser footprint story instead of three times it.
- Browser-shipped bytes unchanged. Brotli-compressed
Lumeo.dllis still ~400 KB — nothing about the runtime payload moved. The 733 KB savings come entirely from dev-time-only assets.
What changed
src/Lumeo/wwwroot/registry/deleted (146 JSON files). RegistryGen now writes per-component snippets todocs/Lumeo.Docs/wwwroot/registry/only — that's the canonical CDN source consumed bylumeo add+ MCP viahttps://lumeo.nativ.sh/registry/<slug>.json.Lumeo.csproj: removed theSyncRegistryIntoWwwrootMSBuild target and added a<None Include="registry\registry.json" Pack="false" />so the master index stays in source control but never gets packed.deploy-cloudflare.yml: the per-component-registry copy step now reads fromdocs/Lumeo.Docs/wwwroot/registry/instead of the now-deletedsrc/Lumeo/wwwroot/registry/. (Mostly a no-op because the SDK already publishes that folder, but kept as a safety net.)- Registry doc page: the "Raw JSON" link now points at
/registry.json(Cloudflare-served fromdocs/Lumeo.Docs/wwwroot/registry.json) instead of the now-dead/_content/Lumeo/registry/registry.jsonURL.
Consumer impact
- None. Runtime apps don't reference the registry JSONs (their
registryUrlalready pointed at the CDN, not/_content/Lumeo/registry/). The Lumeo.CLI's default URL was alreadyhttps://lumeo.nativ.sh/registry.json— no behavior change.
145 components · 9 NuGet packages + 1 npm package published.
May 2026
Doc-coverage audit + bundle-stats honest rewrite.
A second-pass audit of all 145 component pages turned up gaps the rc.37 sweep missed —
features documented in API tables but never actually shown in a live demo. 23 new
interactive previews fill those gaps. Plus the homepage bundle-size story is
now measured in browser-shipped brotli bytes, not .nupkg sizes that include CLI-only assets.
Docs site — closing the demo coverage gaps
- DataGrid
ShowGroupPanelinteractive demo. The group-panel + multi-level grouping features had docs prose + an API table but no live preview. New demo with Segmented toggles for panel on/off and single-vs-multi-level grouping (Department → Status with per-group salary average). - Animation & visual sliders (5 pages): AnimatedBeam (Curvature, DurationMs), BlurFade (DelayMs, BlurPx + Replay), Barcode (Height, BarWidth), BackToTop (VisibilityThreshold), Affix (anchor + Offset).
- Input controls (5 pages): Pagination size, OtpInput Length (4/6/8), PasswordInput ShowStrength + ShowToggle, NumberInput Step + Precision, Mention Trigger character.
- Variants & modes (4 pages): PopConfirm IsDestructive, ToggleGroup PressEffect (None/Scale/Brightness/Ripple), Toggle icon+text slot toggles, ShimmerButton size — single live preview not side-by-side.
- Display + event-feedback (7 pages): Textarea ShowCount counter, TextReveal Threshold scroll-trigger, Timeline ActiveIndexChanged binding, TreeView OnItemClick, Transfer OnChange, AgentMessageList Role switcher, Tooltip Side demo refactored to compound
<SegmentedItem>pattern. - Two audit findings sauber geskippt: Pagination has no
Sizeenum, Menubar has noOrientationparameter — fix-agents refused to invent the API. Pagination size demo done viaPaginationItem Class=sizing instead.
Home — honest bundle stats
- "~530 KB core" → "~400 KB core" everywhere on the homepage, with full disclosure: this is the brotli-compressed assembly size, which is what the browser actually downloads — what every other Blazor lib means when it quotes a number. Measured 2026-05-13 on rc.38: Lumeo.dll brotli ≈ 403 KB, Charts 120 KB, DataGrid 100 KB, Editor 26 KB, Motion 18 KB, Scheduler 16 KB, Gantt 12 KB.
- Why the
.nupkgshows ~1.35 MB: the package bundles ~4 MB of shadcn-style component source registry for the Lumeo CLI (staticwebassets/registry/*.json) plus the pre-compiled Tailwind utility snapshot. None of that is sent to end users' browsers — disclosed in the bundle-size dialog and in the bento footer footnote. (Moving the registry to CDN-only is queued for rc.40 — would bring the.nupkgback under 600 KB.)
145 components · all 4 audit waves built clean (0 warnings, 0 errors) · brotli measurements: brotli -q 11 of each package's runtime DLL.
May 2026
CI fixes — the rc.37 push went through but the Cloudflare / CI / E2E workflows went red. Two unrelated issues, both fixed here.
- New
SegmentedItemcompound sub-component. The rc.37 doc-coverage sweep used<SegmentedItem Value="...">children inside<Segmented>on ~10 interactive-preview demo pages — that's the shadcn-style composition the rest of the library uses (SelectItem,TabsTrigger, …) and the natural reach. ButSegmentedonly had theOptions="List<SegmentedOption>"data-driven API — so docs built locally but CI's-warnaserrorfailed with RZ10012 "unexpected element 'SegmentedItem'". Added the compound sub-component (cascadingSegmentedContext, styling identical toOptions-mode). Both APIs now coexist; consumers can pick whichever reads better. - Changelog.razor: escaped a literal
@pagereference in the rc.37 entry that was being parsed as a Razor directive — broke the docs build for CI / E2E / Cloudflare. Now@@pagein source → renders as@pagein the page.
145 components (+1 sub-component) · 2,401 unit + 31 RegistryGen + 20 docs tests green; all -warnaserror satellite builds clean; docs project builds clean.
May 2026
Doc-coverage sweep — every component now has a live demo, a complete API table, and interactive previews for multi-value enum parameters.
Plus a small API addition (ToastOptions.Position) and a CI hygiene fix.
Docs site — interactive previews everywhere
- Every
[Parameter]typed as an enum with ≥2 values now has a "Variant (interactive)" section on its component's doc page — a<Segmented>(or<Slider>for numeric tunables) bound to a state field driving a live component, so readers can flip between values and see the difference in real time. - ~50 new interactive previews across Forms (Button Variant/Size, DatePicker Mode, FileUpload Variant, Rating Size, Toggle/ToggleGroup, …), Navigation/Overlay (Tabs Variant/Orientation/RenderMode, Sheet/Drawer Side, Stepper Orientation, Carousel Orientation, BottomNav Variant, MegaMenu, Splitter, Sidebar, AppBar, Popover/Tooltip Side+Align), Data Display (Steps Orientation, Statistic Size/Variant, Sparkline Type, SparkCard, Timeline, Gauge Variant, Avatar Shape/Status, Badge Variant, Bento Gap, Chip Variant, ImageCompare, QRCode, ReasoningDisplay, ToolCallCard), Motion (Marquee Speed/Direction, BorderBeam Size+Duration sliders, ShimmerButton, Dock MaxScale/MagnifyRadius, NumberTicker target, Sparkles count, TextReveal speed), Feedback (Alert Variant, Result Status, Toast Variant+Position).
- API tables filled in: ~18 Forms pages were missing FormField integration rows (Required / Invalid / ErrorText / HelperText / Label / Name) — added. AnimatedBeam
PathWidthand SortableListKeyrows added. - Pages that were entirely missing got created from scratch — every one of the 145 components now resolves at
/components/<kebab-name>.
API additions
ToastOptions.Position(ToastPosition?) — per-toast position override, complementing the existingToastViewport.Positiondefault. Powers the new ToastPage interactive position demo.
Hygiene
- Stripped UTF-8 BOMs from three Razor source files (DatePicker / DateRangePicker / DateTimePicker) — they were breaking the sitemap generator's
grep '^@page'on the Cloudflare deploy. - SplitterPage interactive demo: fixed a mixed C#+literal
Class-attribute syntax error (RZ9986). FileManagerPageRemoveNodenullable-warning fix (CS8604 — would have failed an eventual docs-warnaserror).
145 components · 2,401 unit + 31 RegistryGen + 20 docs tests green; all -warnaserror satellite builds clean; docs project builds clean.
May 2026
DataGrid batch-edit UI, PivotGrid multi-level columns, Toolbar auto-overflow, 13-locale satellite sweep. Wave 6 of the deep-scan roadmap. All additive; no breaking changes.
DataGrid — batch / buffered edit mode
- Setting
EditMode="DataGridEditMode.Batch"now wires up the full UI (the rc.35 scaffolding got fleshed out): edits go into a per-cell pending-changes buffer, dirty cells get abg-warning/10tint and warning-coloured left border, a "N pending changes" strip appears with Save all + Discard buttons. - Save all fires
OnBatchSave(DataGridBatchSaveEventArgs<TItem>withModified+Addedlists). On clean return the buffer clears automatically. ShowAddRow="true"+NewItemFactoryrender a "+ Add row" trigger. PublicHasPendingChanges/PendingModifiedItems/PendingAddedItemsfor warn-on-navigate.- New
ColumnVirtualize="true"+MaxVisibleColumns(default 30) — caps how many columns are rendered for very-wide grids. (Real per-cell horizontal virtualization is a follow-up; this is the simpler "max-columns cap" approximation. Clipboard paste / fill-down /ShouldRenderon cells are also deferred.)
PivotGrid — multi-level column hierarchy
ColumnFieldsnow nests properly. A two-level[Year, Quarter]example renders three header rows (Year — colspan'd across its quarters / Quarter — colspan'd across measures / Measure names), with correct rowspans on row-field corners and the grand-total column. Column-subtotals are deferred (row subtotals work).
Toolbar — automatic overflow measurement
<Toolbar Overflow="true">with the defaultVisibleCount=-1now auto-measures viaResizeObserver— items that don't fit collapse into the "⋯" dropdown live as the container resizes. ManualVisibleCountstill wins when set.
Localization — satellites sweep
- 71 new locale keys × 14 dictionaries = 994 entries.
Chart(loading text),Scheduler(Today + view-switcher + "Week of {0}"),Gantt(view-mode labels), andRichTextEditor(toolbar + bubble menu + slash-command + AI-action menu — Bold / Italic / Heading 1–3 / Bullet+Numbered+Task list / Quote / Code block / Link / Insert image/table / Undo / Redo / Clear formatting / Improve writing / Make shorter / Make longer / Translate / Summarize / Fix grammar / placeholders / …) all now route throughILumeoLocalizerwith translations in de / fr / es / it / pt / nl / pl / ja / zh / ko / ar / ru / tr.
CI
publish-mcpnow succeeds when the version is already on npm (typical on a release re-run after a sibling job failed) — checks for "cannot publish over" / "previously published" in npm's error and exits 0 instead of red. Any other publish failure still fails the job.
Docs site refreshed: batch-edit demo on DataGrid, multi-level-columns demo on PivotGrid, auto-overflow demo on Toolbar. Stale stats fixed (145 components · 2,400+ tests · rc.36). 145 components · 2,401 unit + 31 RegistryGen + 20 docs tests green; all -warnaserror satellite builds clean.
May 2026
DataGrid tree-grid + group panel, and six new components. Wave 5 of the deep-scan roadmap. Mostly additive.
DataGrid
- Tree-grid mode —
ChildItemsSelectorturns the grid into a hierarchy: rows with children get an expand chevron, indented child rows, recursive.TreeGridDefaultExpanded,TreeColumnField,OnTreeNodeExpand;role="treegrid"+aria-expanded/aria-level. Distinct from the flatDetailTemplate. - Group panel + group-level aggregates + multi-level grouping —
ShowGroupPanelrenders a chip bar; columns withGroupablecan be added/removed/reordered there;GroupByFieldsfor multi-level nested grouping; each group row shows the columnAggregates over that group. - Scaffolding for batch-edit mode landed (
DataGridEditMode.Batch,DataGridBatchSaveEventArgs<TItem>) — full UI wiring follows in the next release. Plus a fix for anAriaLevel/AriaExpandedregression from rc.34.
New components
Gauge— single-value gauge,Radial/Arc/Linearvariants, threshold colour bands,role="meter".RingProgress— circular determinate progress ring with an optional centre label or custom content.Barcode— inline SVG Code 128B barcode renderer (scannable), with optional human-readable text.Highlighter— wraps occurrences of one or more search terms in the text with highlight marks (CaseSensitive,WholeWord).FileManager— headless file/folder explorer: folder tree, breadcrumb path, list/grid views, lazy loading (LoadChildren), inline rename, context-menu operations (rename/delete/open). Drag-drop / upload / multi-select are deferred.QueryBuilder— visual AND/OR predicate-tree builder: recursive groups, per-type value editors, serializes to JSON and to a LINQ predicate (ToExpression<T>),ShowJsonPreview,MaxDepth.
Toolbar
- New
Overflow+VisibleCount— collapse trailing items into a "⋯" dropdown. (Auto-measurement of which items fit is a follow-up; for nowVisibleCountis consumer-controlled.)
Docs site updated: new pages for Gauge / RingProgress / Barcode / Highlighter / FileManager / QueryBuilder; API tables + demos refreshed on DataGrid / Toolbar. 145 components · 2,375 unit + 31 RegistryGen + 20 docs tests green.
May 2026
The big one — DataGrid keyboard navigation, a new PivotGrid, Scheduler/Gantt/FileUpload feature waves, Select/Combobox data-bound mode, and a localization sweep. Wave 4 of the deep-scan roadmap. Mostly additive; the DataGrid changes add ARIA attributes but don't alter behaviour.
DataGrid — keyboard navigation + grid ARIA
- Roving-tabindex cell navigation: arrow keys move the focused cell,
Home/End= row ends,Ctrl+Home/Ctrl+End= corners,PageUp/PageDown= ±10 rows,ArrowUpfrom row 0 jumps into the header.Enter/F2on an editable cell starts cell-edit;Enterwhile editing commits + moves down,Tabcommits + moves right,Escapecancels.Spacetoggles row selection;Ctrl+Aselects all (multi-select).Enter/Spaceon a sortable header cell sorts. - Grid ARIA:
role="grid"+aria-rowcount/colcount/multiselectable,role="row"+aria-rowindex/selected,role="columnheader"+aria-sort,role="gridcell"+aria-colindex/readonly. Focus ring on the active cell. - Deferred: keyboard nav inside grouped/virtualised regions (cells still carry the ARIA roles there).
New component — PivotGrid<TItem>
- Cross-tab / pivot table: pivots flat data into a row hierarchy × column values × aggregated
Measures(Sum/Average/Count/Min/Max).RowFieldsnest into a multi-level outline; per-group subtotal rows + a column grand-total row + a row grand-total column + the overall total. Collapsible row groups (chevron +aria-expanded),OnCellClickfor drill-down,EmptyContent,Compact. Single column-field level for now (row hierarchy is fully nested).
Scheduler
- Recurring events via FullCalendar's free recurrence model — new
SchedulerEvent.DaysOfWeek/RecurrenceEnd/ExceptionDates. - Resource colour-coding: new
SchedulerResourcerecord +Resourcesparam +SchedulerEvent.ResourceId— events inherit their resource's colour, with a legend above the calendar. (True resource-lane / timeline views need FullCalendar's premium plugin, which we don't bundle.) NowIndicator(default true),SlotMinTime/SlotMaxTime/SlotDuration,EventClassNames/EventColorcallbacks.
Gantt
- Milestones —
GanttTask.IsMilestonerenders a diamond instead of a bar. Grouping/swimlanes — newGroupByparam +GanttTask.GroupLabel(sort + group-separator rows).TodayHighlight,BarHeight/ColumnWidthconfig,BarColorper-task colour callback. (Task dependencies were already supported; rendered as arrows.)
FileUpload — a real upload pipeline
- New
OnUploadcallback (Func<FileUploadItem, IProgress<int>, CancellationToken, Task<string?>>) — the component drives per-file state (FileUploadItemwithStatusPending/Uploading/Succeeded/Failed/Cancelled,ProgressPercent,Url,ErrorMessage) with per-file progress bars, cancel + retry buttons,AutoUpload/MaxConcurrentUploads, validation rejections surfaced as failed items (+OnFileRejected), andOnFileUploaded/OnAllUploaded/OnFileFailedevents. LegacyProgress/OnFilesSelectedstill work.
Select / Combobox — data-bound mode (non-breaking)
- New
Items/ItemValue/ItemText/ItemGroup/ItemDisabled/ItemTemplateparams — bind options from a collection instead of writing<SelectItem>s by hand. PlusVirtualize+ItemSizefor large option lists. Components stay non-generic (object-typed selectors) — composition mode unchanged, zero breaking changes.
Localization
- Kanban "Add card" and Carousel a11y labels ("Previous slide" / "Next slide" / "Slide N of M") now route through
ILumeoLocalizerwith translations in all 13 locales. (Audit found EmptyState/Result/Steps/Mention/AlertDialog have no hardcoded English to localise — their text is consumer-supplied or icon-only.)
Docs site updated: new PivotGrid page; API tables + demos refreshed on DataGrid / Scheduler / Gantt / FileUpload / Select / Combobox. 139 components · 2,303 unit + 31 RegistryGen + 20 docs tests green.
May 2026
Four new components — Stepper, Window, Toolbar, AppBar. Purely additive; no breaking changes.
Stepper— a stateful multi-step flow (distinct from the display-onlySteps): step header indicators, Back/Next/Finish navigation,Lineargating with per-stepIsValid, horizontal/vertical orientation,OnFinish, optional steps, custom step icons, tab-like ARIA.<StepperStep>sub-component.Window— a non-modal, draggable, resizable floating panel (vs. the modalDialog): draggable title bar, resize handle, minimize/maximize/close, controlledOpen/Minimized/Maximized, initial size/position. Drag/resize use Blazor pointer events — no JS interop. The page stays interactive (no backdrop).Toolbar— arole="toolbar"layout container for buttons/inputs, withToolbarSeparator/ToolbarSpacer/ToolbarGroupsub-components. (Overflow-collapse menu is a follow-up.)AppBar— a top application bar withStartContent/ChildContent(centre) /EndContentslots,Sticky/Elevated/Bordered/Height. Pairs withSidebar/BottomNav.
Docs site updated with pages for all four. 138 components · 2,259 unit + 31 RegistryGen tests green.
May 2026
Three new components + DatePicker / DateTimePicker / Toast / TreeView upgrades + string-to-enum API tightening. Wave 2 of the deep-scan roadmap. A few string parameters became real enums (mild breaking change in an RC — compile-time safety + autocomplete).
New components
ButtonGroup— joins<Button>s into a segmented bar with collapsed borders and rounded ends;OrientationHorizontal/Vertical.DropdownButton— a button whose whole click opens a dropdown menu of secondary actions (chevron indicator).SplitButton— split into a primary-action half (OnClick) and a chevron half that opens the dropdown.
Component upgrades
- DatePicker: forwards
FirstDayOfWeek+ShowWeekNumbersto the inner Calendar; newInlinemode (always-open calendar, no popover). - DateTimePicker: new
MinDate/MaxDate/IsDateDisabled(forwarded to its Calendar). - Toast:
ToastViewport.Position(6 corners/centres) +MaxVisible;ToastOptions.Positionfor per-toast overrides. - TreeView: big overhaul — lazy/async children (
LoadChildren+IsLeaf/IsLoading), tri-state checkboxes with parent↔child cascade (CascadeCheck,IsIndeterminate,CheckedValuesChanged), customNodeTemplate, disabled nodes (IsDisabled),ExpandAll+ExpandAllNodes()/CollapseAllNodes(), multi-select (MultiSelect,SelectedValues),role="tree"/treeitemARIA + arrow-key navigation.
API tightening — string parameters became enums
DatePicker.Mode:string→DatePicker.DatePickerMode(Single/Range/Month/Year).Tabs.Variant:string→Tabs.TabsVariant(Default/Card/Pill).FileUpload.Variant:string→FileUpload.FileUploadVariant(Dropzone/Button/Avatar).Calendar.InitialView:string→Calendar.CalendarView(Days/Months/Years).- If you pass these as string literals (
Mode="Range") update to the enum (Mode="DatePicker.DatePickerMode.Range").@bind-style usages are unaffected.
Docs site updated: new pages for ButtonGroup / DropdownButton / SplitButton, API tables + demos refreshed on DatePicker / DateTimePicker / Toast / TreeView / Tabs / FileUpload / Calendar. 134 components, 2,226 unit + 31 RegistryGen tests green.
May 2026
Render-tree hardening — correctness + perf across the board.
A sweep of @key fixes,
a real virtualised DataTable,
ForceMount on Accordion/Collapsible panels,
and cached hot-path computations. No public API removed; a few additive parameters.
Correctness fixes
- DataGrid
@keyon every non-virtualised row/group/header/cell loop — sort/filter/page/group-toggle and column reorder no longer mis-diff: rows and cell-edit components stop re-initialising, sort indicators and open filter popovers stay attached to the right column. OverlayProviderkeyed + stable references — closing one of several stacked overlays no longer makes the focus-trap / scroll-lock interop target the wrong element. The hosted-component cascade is nowIsFixedso it stops re-rendering on every provider render.SortableListkeyed — drag-reorder now follows the item, not the index. New optionalKeyparameter for value-type items.DataTable.Virtualizenow actually virtualises — it was a no-op (rendered the full list either way). Wired to Blazor's<Virtualize SpacerElement="tr">; selection still works inside virtualised rows.@keyalso added to FileUpload, Mention, Transfer, PickList, ImageGallery, TreeView/TreeViewNode, TreeSelect item loops.
New / changed parameters
<AccordionContent ForceMount="true">and<CollapsibleContent ForceMount="true">— keep the panel in the DOM (with thehiddenattribute) when collapsed instead of unmounting, so form input / scroll / component state survives. Mirrors Tabs' rc.29 pattern. Default off, no behaviour change.SortableList.Key(Func<TItem, object>?).
Performance
- DataGrid caches the visible-columns projection instead of re-materialising it on every render.
- DataTable caches
ItemsList/IsAllSelected/IsSomeSelectedinstead of re-scanning every render. - TreeView caches the filtered tree — the recursive whole-tree deep-copy now runs only when the search text or
Itemschange, not on every render. - Carousel only calls
StateHasChangedfrom its scroll callback when the prev/next-availability flags actually flip — no more a render per scroll frame during a drag.
May 2026
MCP server overhaul — from reference lookup to authoring assistant.
The @lumeo-ui/mcp-server
picks up six new tools so an LLM (Claude, Cursor, Copilot) can not only look components up but write
correct, runnable Razor on the first try. No component-library changes — this is all tooling.
New MCP tools
lumeo_validate_markup— pre-flight a Razor snippet: do the components exist? are parameter names real (catches hallucinated APIs)? are enum values legal? are sub-components nested inside their required parent (TabsContentinTabs,DialogContentinDialog, …)? Returns structured errors/warnings.lumeo_get_install— everything to actually run a component: NuGet +dotnet add,@usingimports,AddLumeo…()DI, host-page<script>/<link>includes, sub-components, and gotchas (portal components needing theme classes on<body>, OverlayProvider, required params).lumeo_get_example— the real Razor snippet(s) behind the docs-site demos, now extracted into the API schema at generation time (122/131 components covered).lumeo_get_theme_tokens— all 58 theme tokens (colour + radius CSS variables) so the model usesbg-primary/text-foreground/border-border, never raw hex, neverdark:prefixes.lumeo_list_patterns/lumeo_get_pattern— the 16 full-page "blocks" (dashboard, auth, chat, kanban, mail, settings, …) with their complete Razor source as a starting skeleton.lumeo_changelog— current package version + API-schema generation timestamp + changelog link.
lumeo_get_component now also includes the extracted examples array. The registry generator gained an example/theme-token/pattern extractor that scrapes the docs pages — so the MCP stays in sync automatically on every release.
May 2026
Tabs: RenderMode for panel-state preservation.
By default a TabsContent
panel is unmounted the moment you switch away — losing form input, scroll position and any component
state. The new RenderMode
parameter gives you the same three knobs DevExpress exposes, with clearer names.
Modes
Active(default) — only the active panel is in the DOM; switching away unmounts it. Lightest footprint, no behaviour change from before.Lazy— a panel renders the first time its tab becomes active, then stays mounted (hidden) so its state survives subsequent switches. DevExpressOnDemand.Eager— every panel renders up-front; inactive ones are hidden. State always preserved, heaviest initial render. DevExpressAlways.- Per-panel override:
<TabsContent ForceMount="true">always keeps that one panel mounted regardless of the parent mode — pin a half-filled form, leave the rest light.
Hidden panels use the standard hidden attribute, so they're skipped by screen readers and the keyboard tab order while still preserving DOM state.
May 2026
DataGrid full virtualisation + Calendar / DatePicker culture-awareness. Big DataGrid round: customisable page-size selector, correctness fix for virtualised tables, and the long-missing third virtualisation mode (infinite-scroll over a backend). Calendar now starts on Monday under de-DE/fr-FR/en-GB by default and renders day headers in the user's language.
DataGrid — three virtualisation modes, all wired up
- Virtualised server mode (NEW) — set
Virtualized="true"+OnRangeRequestand the grid fetches a sliding window of rows from your backend as the user scrolls (Blazor's<Virtualize ItemsProvider>). Pagination is hidden automatically; sort, column filter, and global search all triggerRefreshDataAsync()so the next request reflects the new query state. Publicgrid.RefreshVirtualizedAsync()for manual refetch after external mutations. - Virtualised client mode (correctness fix) — the in-memory virtualiser now passes
SpacerElement="tr". Without it, Blazor's default<div>spacers are invalid<tbody>children and the browser hoisted them out of the table, breaking layout whenever the threshold tripped. - New tunables:
VirtualItemSize(row-height estimate, default 41 px) andVirtualOverscanCount(default 3 rows). - PageSizeOptions — configurable rows-per-page selector (default
[10, 25, 50, 100]); passnew[] { 10, 50, 100, 200, 300 }for larger datasets, or empty array to hide the selector entirely.
Calendar / DatePicker — culture-aware
Calendar.FirstDayOfWeekis nowDayOfWeek?. Unset → derives fromCultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek: de-DE / fr-FR / en-GB → Monday-first, en-US → Sunday-first.- Day headers derive from
AbbreviatedDayNamestrimmed to two letters: en-USSu Mo Tu We Th Fr Sa, de-DEMo Di Mi Do Fr Sa So, fr-FRlu ma me je ve sa di. - Soft API change: explicit
FirstDayOfWeek="DayOfWeek.Monday"still works (implicit lift to nullable).
May 2026
Empirically reproduced + root-caused the popover-in-Sheet positioning bug.
Bug #1 (slide transform-trap) and Bug #16 (DatePicker positioned relative to sheet, not
viewport) turned out to be the SAME root cause. Verified end-to-end in Chrome 131 via
instrumented diagnostics — toggling the sheet's animation
property on/off snapped the popover x from 3278 (sheet-relative) to 1742 (viewport-relative).
The real root cause (took 6 RCs to find)
- Chrome creates a containing block for any element with an active
transform-animatinganimationdeclaration — INDEPENDENT of the current computedtransformvalue. Even with computedtransform: none(overridden via!important), the activeanimation: ... slide-in-from-rightdeclaration alone makes Chrome establish the sheet as a containing block for fixed-positioned descendants. - Empirically verified:
popover.x = 3278when sheet has the animation declared (sheet at x=1536 + popover style.left=1742 ≈ 3278). Addanimation: none !importanton the sheet →popover.x = 1742.86(viewport-relative). Confirmed via instrumented Chrome 131 DevTools session. - This is Chrome's compositor optimization — it pre-creates a layer for transform-animating
elements (treating them as
will-change: transformimplicitly). Per CSS spec strict reading this is technically aggressive but Chrome does it.
The fix
attachOverlaySlideEndincomponents.jsnow sets BOTHanimation: none !importantANDtransform: none !importantafter the slide animation finishes. The animation property is what kills Chrome's containing-block treatment; the transform is belt-and-suspenders.- Bug #1 (matrix containing block) and Bug #16 (DatePicker top:-1156, popover at sheet x) both resolve. Same fix.
- Slide animation visual is preserved (animation runs to completion, then properties are cleared in the post-finished state).
May 2026
Button propagation params + harder popover positioning guards.
Two follow-ups from rc.25 user feedback: (1) Razor's
@onclick:stopPropagation
/ @onclick:preventDefault
directives can't be applied to a Lumeo Button (case-insensitively
collide with OnClick).
Now exposed as
StopPropagation /
PreventDefault
bool parameters, no more
<span>-wrapper
workaround needed. (2) Bug #16 (DatePicker
top: -1156px)
cause is still inconclusive — math doesn't match the reported popover height — but
positionFixed
now flushes layout before measurement and applies a universal max-height + bottom-overflow guard.
Added — Button propagation control
[Parameter] public bool StopPropagation+[Parameter] public bool PreventDefaultonButton. Wired to@onclick:stopPropagation/@onclick:preventDefaulton the underlying<button>element. Drop-in replacement for the<span @onclick:stopPropagation="true"><Button…/></span>workaround.- Plus
[Parameter] public ButtonType Type(defaultButton) withSubmit/Resetoptions for explicit form-button intent.
Improved — popover positioning robustness
- Synchronous layout flush before measurement:
positionFixednow readsoffsetHeightbeforegetBoundingClientRect()so the browser flushes any pending layout (animation scaling, Blazor render mid-flight) and we measure the popover's settled dimensions, not a stale or in-flight rect. - Universal max-height clamp: if the natural popover content exceeds the viewport, a scrollable cap is applied unconditionally — not only on flip-up edge cases.
- Bottom-overflow late guard: even after side-flip and other branches, if the popover would render past the viewport bottom, it's pulled up to fit with max-height applied.
- Combined with rc.23's negative-top guard, this makes
positionFixeda true belt-and-suspenders surface — even if the underlying root cause for the rc.21–rc.25 user-reportedtop: -1156is still inconclusive (the math doesn't match the reported popover height — root cause likely a transient layout state during animation), the popover is always visible.
May 2026
Slide-trap fix #5 — Web Animations API. rc.24 had the
!important
piece right (cascade priority) but missed the second bug: the listener was attached
via addEventListener('animationend', ...)
from C# OnAfterRenderAsync
via JS interop. Even in WASM, the latency between render and listener-attach is
enough that the 300 ms slide animation can already be
finished
before the listener exists. addEventListener
does NOT replay events that fired before attach, so the cleanup never ran.
The actual fix (5th attempt)
- Replaced
addEventListenerwith the Web Animations API.el.getAnimations()returns running OR already-finished animations (fill-mode keeps the finished ones alive in the list), andanimation.finishedis a Promise that resolves immediately if the animation already ended, or once it does. Race-condition-free regardless of when the function is called. - After awaiting
.finished, setsetProperty('transform', 'none', 'important')(rc.24's correct cascade-priority piece). Inline + !important is rank 4 (!important author) which beats animations (rank 5), so the fill-mode-forwarded matrix is finally overridden. - Defensive: if
getAnimations()returns no slide animation (Animation=Fade/None, or class already dropped), set the transform anyway. Edge cases get the same protection.
For maintainers — five-RC postmortem
- rc.21: keyframe trick (
99%: translateX(0); to: none) — Chrome interpolates none↔translate(0) as identity under fill-mode:both. Placebo. - rc.22: Razor
@onanimationendhandler — Blazor EventArgs lacks animationName, descendants bubbled up. Placebo. - rc.23: native JS listener with plain
style.transform = 'none'— animations rank above normal author. Placebo. - rc.24: same listener but with
!important— cascade priority correct, but listener attaches after animation ends. Placebo. - rc.25:
getAnimations() + .finished promises + setProperty important— race-free AND cascade-correct. Empirically verified.
May 2026
Slide-trap finally fixed (4th attempt). rc.21–rc.23 were all
placebo: the keyframe trick (rc.21) and the inline-style approach (rc.22, rc.23)
could never defeat animation-fill-mode forwarding because of the CSS Cascade Level 4
priority order. Animations rank ABOVE normal author rules — including plain inline
style="transform: none".
The fix needs !important
on the inline style (rank: !important author > animations) to actually override the
forwarded keyframe value. Now done via
setProperty('transform', 'none', 'important')
in the native animationend listener.
Why the previous attempts failed
- rc.21 keyframe trick (
99%: translateX(0); to: none): Chrome resolvesto: noneunder fill-mode:both as identity matrix. fill-mode forwards interpolated values, and the transition betweentranslateX(0)andnoneis treated as identity by all major engines. End state stuck atmatrix(1,0,0,1,0,0). - rc.22 Razor handler that drops the class: Blazor's
@onanimationendEventArgs doesn't exposeanimationName, so descendant zoom-in / fade-in animations bubbled up and prematurely dropped the class mid-slide. Plus the Razor → JS roundtrip latency was racy. - rc.23 native JS listener with plain inline style: filtered correctly
on
slide-in-from-*+target === el, but usedel.style.transform = 'none'which is normal author cascade rank. Animations outrank that. Matrix stayed.
The fix that actually works
el.style.setProperty('transform', 'none', 'important')inside the same filtered animationend listener. Inline + !important is !important author in the cascade, which beats animations. The forwarded fill-mode value is properly overridden, computed transform becomesnone, no containing block, popovers (Select / DatePicker / Combobox) inside Sheet/Drawer position relative to the viewport.- Verified mechanism: per CSS Cascade Level 4 spec, the priority order from highest to lowest is — transitions, !important user-agent, !important user, !important author, animations, normal author (incl. plain inline style), normal user, normal user agent.
May 2026
Ironclad slide-trap + defensive popover clamp. rc.22's Razor-side
@onanimationend
handler had two timing issues: (1) Blazor's EventArgs
for the directive doesn't expose animationName,
so we couldn't filter; descendant animations (Calendar's
animate-zoom-in,
Combobox fade-in) bubbled up and could trigger the cleanup mid-slide. (2) The Razor →
JS roundtrip was racy enough that some users still observed the matrix sticking.
Replaced with a native JS listener.
Fixed — slide-trap (third time's the charm)
- New
Interop.AttachOverlaySlideEnd(elementId)JS interop registers a nativeanimationendlistener that filters strictly onslide-in-from-*AND onevent.target === el(descendants don't trigger it), then sets inlinestyle.transform = 'none'. Inline-style precedence beats keyframe fill-mode forwarding — the matrix is cleared, no containing block, popovers position relative to viewport. SheetContent+DrawerContentnow call this on every open withAnimation=Slide.- Removed the racy Razor-side
@onanimationendhandler +_animationDoneflag — JS interop is the sole, reliable path.
Fixed — defensive popover top clamp
positionFixednow applies a final guard: if the computedtopends up negative for any reason (entrance-animation scaling, stale rect, weird parent flex layout), it's forced to8pxwithmax-height+overflow: auto. Belt-and-suspenders for the rc.21 / rc.22 user-reportedtop: -1156.
May 2026
rc.21 verification fixes. Three issues surfaced after rc.21 shipped:
the slide-keyframes trick from rc.21 didn't actually work (Chrome resolves
to: none
to identity matrix under animation-fill-mode: both);
DatePicker calendar popovers can render at top: -1156px
inside Sheets when the popover stretches taller than the viewport;
<EditForm>
wrapping a Sheet's body broke the footer-pin layout. All three fixed.
Fixed — slide-animation transform trap (real fix this time)
- The rc.21 fix used a
99% / to: nonekeyframe trick. That doesn't work:animation-fill-mode: bothkeeps the element in the animation's end state, and Chrome resolvestransform: noneto identity matrix when blended through animation. The element ends up withmatrix(1,0,0,1,0,0)— still a containing block, popovers still off-screen. - Real fix: SheetContent and DrawerContent now bind
@onanimationendand drop theanimate-slide-in-*class once the animation completes. Without the class, there's no animation, no fill-mode, no transform — the element returns to its static state and the viewport regains its natural role as the containing block. Visually identical landing; popovers (Select, DatePicker, Combobox) inside Sheets/Drawers position correctly. Apps with theanimation: fade-in !importantworkaround can drop it.
Fixed — DatePicker / popover overflow clamping
- Inside a Sheet's flex layout, the calendar popover could stretch to ~1574 px.
The flip-up logic in
positionFixedthen computedtop = triggerTop − contentHeight − gap, which went deeply negative (e.g. −1156 px) — popover invisible above the viewport. - Now compares
spaceAbovevsspaceBelowand picks the side with more available room, capping the popover withmax-height+overflow: autowhen neither side fits the natural content height. The popover is always visible.
Fixed — EditForm-in-Sheet footer pin
- When consumers wrapped a Sheet's body in
<EditForm>, the rendered<form>was content-sized — SheetFooter stuck below the last field instead of pinning to the bottom. New CSS rule inlumeo.cssmakes direct<form>children of Lumeo sheet/dialog/drawer dialogs inherit the flex-column layout — no consumer-side CSS workaround needed.
May 2026
Production-feedback pass. Driven by a detailed real-world migration report — closes the slide-animation transform trap that broke popovers in Sheets/Drawers, generalizes TagInput, expands the Lumeo.Text color map, adds a controlled-mode override for popover state, and ships a new EditForm + Localization guide.
Fixed — popover containing-block trap
- Slide keyframes now end at
transform: none(was identitytranslateX(0)). Per CSS spec, any non-nonetransform — including identity translates — establishes a containing block forposition: fixeddescendants. The old keyframes meant Select / DatePicker / Combobox popovers inside a slid-in Sheet rendered relative to the Sheet instead of the viewport, ending up off-screen. The 99 % step keeps the visual landing identical; the 100 % step disposes of the transform. - Apps with the
.animate-slide-in-* { animation: fade-in !important }workaround can drop it.
Added — Sheet + Drawer Animation variant
SheetContent.AnimationandDrawerContent.AnimationacceptSlide(default),Fade, orNone. Slide is now safe (transform-trap fixed); Fade / None remain available for consumers who want maximum predictability inside re-render-heavy parents.
Added — TagInput is now generic
TagInput<TItem>withTItemdefaulting tostringso existing string consumers compile unchanged. Real apps now build user-pickers, mention-pickers, etc. on top of structured items.- New params:
GetTagText,GetSuggestionText,TagTemplate(RenderFragment<TItem>),SuggestionTemplate,Separators[](multi-separator paste),ValidateInput/ValidateInputAsync,CreateTag,MaxTagsHelperText. - New User-picker demo on the TagInput docs page (avatar + name in tag chip + name/email rows in suggestion popup, comma/semicolon/space separators).
Added — Controlled-mode popover state
DatePickergains optionalOpen?+OpenChanged(Select / Combobox already had it). When non-null, the consumer owns popover state — survives parent re-renders. Use@bind-Openinside heavily re-rendering parents (EditForm with active validation) to keep the popover open through validation cycles.
Added — Lumeo.Text full theme-token map + small param expansions
<Lumeo.Text Color="..."/>now accepts every theme token:foreground,muted,primary,destructive,success,warning,info,accent. Case-insensitive. Unknown values fall back to no class (deliberate hardening).FileUploadgainsSizeparameter (Sm / Default / Lg) for the Button variant.BottomNavItemgainsIconSize(default"h-5 w-5"); consumer can pass"h-7 w-7"to fit an avatar in the icon slot.ToggleGroupItemauto-spaces icon + label (gap-1.5on the base class) — no more manualClass="gap-1.5".
Docs — EditForm + Localization guides
- New: EditForm + Lumeo Validation guide
explaining why Lumeo inputs are not
InputBase<T>derivatives, the canonical pattern withEditContext.GetValidationMessages+Invalidwiring, server-side error injection, and the nullable-EventCallback lambda workaround. - New: Localization guide documenting Blazor WASM's en-US default and how to set browser-locale at startup.
- Sheet + Drawer docs pages gained an info Alert about the rc.21 transform-trap fix and the new Animation variants.
May 2026
Booking-calendar API + per-component registry endpoints + Calendar UX polish.
Calendar gains DateTooltip
and DateBadge
callbacks for hotel-style availability indicators, the month + year header is now a single
click target with same-width views across Days/Months/Years, and every component has its own
self-contained /registry/<key>.json
endpoint with full LLM-ready detail (catalog + API schema + source + slots + services +
cascades + related + keyboard + tests + mdSummary).
Added — Calendar booking API
DateTooltip(Func<DateTime, string?>?): per-day tooltip text rendered as the day cell'stitleattribute (native browser tooltip on hover). Useful for "Sold out" / "Limited availability" hints in booking flows.DateBadge(Func<DateTime, RenderFragment?>?): per-day indicator slot rendered absolutely positioned in the bottom-right of the day cell — status dots, count badges, icons. Non-interactive (pointer-events-none) so clicks still hit the day button.- Both callbacks plus the existing
IsDateDisabledandDateClassare now also forwarded throughDatePickerandDateRangePickerso the booking-calendar UX works through the popover-style pickers too. - New booking-style demo on the Calendar docs page: synthesised hotel availability with green / amber / red / grey dots + tooltips like "Sold out", "Limited availability".
Improved — Calendar UX
- Single click target for month/year — the Days view header used to have two adjacent buttons (month name + year) that opened different pickers. Replaced with one combined button. Cycle is now: Days → click → Months → click year → Years. One predictable click target per view.
- Equal width across all three views — the picker no longer visibly resizes when switching between Days, Months and Years. Each view is fixed to 224 px of inner content (matches the 7-column day grid).
Added — Per-component registry endpoints
- 131 self-contained component files at
https://lumeo.nativ.sh/registry/<key>.json(and the matching NuGet path_content/Lumeo/registry/<key>.json) — same shape as shadcn's per-component registry plus extra LLM-friendly fields:docsUrl,sourceUrl,source(full Razor file content),slots,serviceDependencies,cascadingDependencies,relatedComponents,keyboardInteractions,tests,mdSummary(a self-contained Markdown reference paragraph an LLM can drop straight into context). - The
registryUrlfield on every component in the rootregistry.jsonnow resolves correctly — previously it pointed at endpoints that 404'd. Lumeo.CliDefaultRegistryUrlbumped from a stale jsdelivr / rc.9 pin to the live docs site (https://lumeo.nativ.sh/registry.json).
Fixed — Avatar shape + DropdownMenu focus + E2E CI
- Avatar outer wrapper now follows ShapeClasses so consumer-applied
borders / rings (e.g.
border-2 border-backgroundon AvatarGroup overlap) follow the avatar's actual circular shape — no more square frames around fallback initials. - DropdownMenu focuses the menu content on open per the WAI-ARIA menu
pattern. Previously
tabindex="-1"was set but focus was never moved, so Escape and Arrow keys never reached the keydown handler — keyboard nav was actually broken in production. - E2E visual test skipped under CI until a perceptual differ ships. The home-above-fold byte-equal compare can't agree across Windows (where the baseline was generated) and the Ubuntu CI runner because of font hinting / sub-pixel rendering. The other 15 E2E tests still gate every push and PR.
May 2026
Hardening pass. Closes every P1 + P2 + P3 from an external rc.18 deep review: cross-instance drag state in DataGrid, EventCallback fire-and-forget, preset-codec namespace collision, red E2E suite, lifecycle races in Alert / SafeAsyncDispatcher, JS event-handler leaks in Editor + Gantt, eval() in docs, Worker payload + collision handling, Word-import DoS surface, mobile-unfriendly block demos. Plus the big one: a complete auto-generated MCP schema so Claude Code understands all 131 components without reading source.
Added — MCP server is now fully complete
- 131 / 131 components in the schema — every component now has full parameters, types, defaults, XML doc descriptions, EventCallback events, nested enums + records,
@inherits/IAsyncDisposable, and sub-components grouped per folder. 3,152 parameters total, 86 enums, 48 records, 0 thin fallbacks. - Auto-generated from Razor source via a new Roslyn-based pass in
Lumeo.RegistryGen. Every release regenerates the schema; no more manual catalog drift. - Hand-curated examples preserved as an overlay —
lumeo_get_componentstill surfaces the existing example Razor snippets for ~30 popular components.
Fixed — DataGrid correctness (P1)
- Column reorder cross-talk: a static
ColumnDragStatewas shared across every grid in the process — drops in grid B used grid A's source index. Replaced with an instance-boundDataGridDragState+OwnerGridIdguard. Same fix for row reorder. New regression tests cover both drag types. - EventCallback fire-and-forget at 6 sites in DataGrid.razor —
SelectedItemsChanged,OnColumnReorder,OnRowReorderwere called without await. Now awaited where the call site can be async, dispatched viaSafeAsyncDispatcher.FireAndForgetwhere it must stay sync. - Auto-save stale generation: the existing generation guard skipped LocalStorage writes but still called
OnLayoutSavewith stale snapshots. Guard now covers both paths.
Fixed — Lifecycle / async hardening (P2)
SafeAsyncDispatcherouter task — the inner try/catch only covered the work delegate. IfInvokeAsyncitself threw (renderer disposed), the outer Task was unobserved. Outer call now wrapped in an async helper that catches expected lifecycle exceptions silently and logs anything else.- Alert AutoDismiss timer/dispose race — replaced
System.Threading.TimerwithCancellationTokenSource+Task.Delay;Disposecancels the token and flips a_disposedflag before any state mutation. - Editor + Gantt JS listener leaks — anonymous
addEventListenerclosures (mousemove, mouseleave, drop on the editor; document-level mousemove + mouseup on Gantt drag) surviveddestroy(id). All listeners now stored as named handlers; destroy iterates and removes each.
Fixed — Theming + API + Security (P1 + P2)
- Preset code / Worker ID namespace collision — both spaces were 6-char Base62. Some Worker IDs decoded as valid v1 local presets and never hit the server. New explicit prefix scheme:
l_<6>for local codes,p_<6>for Worker IDs. Bare 6-char input keeps legacy fallback behavior with strict version checks. - Worker payload check post-read — the
content-lengthheader was the only authoritative check; missing or wrong header bypassed the limit. Now readsarrayBuffer()first and enforces realbyteLength. - Worker collision retry — same 6-char ID with different payloads no longer overwrites silently. Up to 8 salt-based retries; idempotent on matching payload; 409 if exhausted.
- Word-import 8 MiB cap — JS pre-arrayBuffer file.size check + .NET pre-Convert.FromBase64String size guard + new
WordImportSizeException. NewMaxWordImportBytesparameter on RichTextEditor. - Removed
eval()in IconPage — replaced with a named JS helper. CSP-clean. - Vendored TipTap stack (~1.4 MB ESM bundle) — RichTextEditor no longer dynamic-imports from
esm.shat runtime. Ships at_content/Lumeo.Editor/js/tiptap-bundle.js; works under strict CSP and offline.window.lumeoTiptapBundleUrlis the override hook for consumers who want to host their own.
Fixed — Overlay UX + Avatar shape
- OverlayService double-backdrop when consumers nested another
<SheetContent>/<DialogContent>/<DrawerContent>inside their service-opened component. NewOverlayShellMarkercascade — nested *Content components self-detect the host shell and pass children through. Both patterns now render exactly one backdrop. Regression test assertsbg-black/80appears exactly once. - Avatar outer wrapper follows ShapeClasses — consumer-applied borders / rings (e.g. AvatarGroup overlap framing) now follow the avatar's actual shape. Previously the border landed on the rectangular outer div while the inner div clipped to a circle, creating square frames around fallback initials.
- DropdownMenu keyboard nav — menu container had
tabindex="-1"but never received focus on open, so Escape and Arrow keys never fired. Now focuses the content on open per WAI-ARIA menu pattern. Surfaced while stabilizing the E2E suite.
Improved — E2E suite is green and CI-gated (P1)
- 16 / 16 E2E tests passing (was 8 / 16). Stable selectors via
data-testidon the relevant docs elements; Search palette result locators scoped to the palette overlay; baseline snapshot committed attests/Lumeo.Tests.E2E/Snapshots/home-above-fold.pngwith deterministic init-script (consent banner suppressed, animations zeroed). - New
.github/workflows/e2e.yml— installs Playwright browsers, builds the docs, runs the docs server on port 5290, runs E2E against it, uploadsdocs-server.logon failure.
Improved — Docs polish (P3)
- Mobile / Desktop preview toggle on ComponentDemo — DashboardBlock / PricingTableBlock / SettingsPageBlock no longer force phone users into horizontal scroll. Toggle wraps the demo in a 420 px phone frame so the experience is honest, not painted-over.
dotnet format --verify-no-changesis green — formatting drift swept across 27 files in a single style pass, no behavior change. Ready to wire into CI as a release gate.
April 2026
Drop-in CSS restored + visible Chart loading label. _content/Lumeo/css/lumeo-utilities.css ships in the NuGet package again after rc.15–rc.17 inadvertently dropped it. The bundle now also covers every utility class used inside the satellite packages — no per-satellite stylesheet needed. Charts also gained an always-on "Loading…" label to make in-flight data unambiguous.
Added — Chart loading label
- New
ShowLoadingLabel+LoadingTextparameters onChart(and forwarded by chart wrappers likeBarChart). WhenIsLoadingis true, a small top-right pill (LucideLoaderCircle+ "Loading…" text) is overlaid on top of whicheverSkeletonStyleis active. Default-on so users never mistake cycling phantom data for a bug; opt out per-chart viaShowLoadingLabel="false".
Fixed — Drop-in setup regression
lumeo-utilities.cssships again — the rc.15 package-split spec moved the file out on the assumption a registry CDN would host it, but the CDN was never set up. Consumers following the docs got a 404 + visibly unstyled Lumeo components (Badgepx-2.5missing, DataGrid toolbar borders gone, Switch container collapsed). Restored to_content/Lumeo/css/lumeo-utilities.css.- Bundle now covers all 6 satellites —
lumeo-utilities.src.cssextended to@sourcetheUI/folder of every satellite (DataGrid, Charts, Editor, Scheduler, Gantt, Motion). Drop-in setup now works whether you install only core or all 7 packages. - Docs site Tailwind scan extended the same way —
docs/Lumeo.Docs/Styles/tailwind.csswas scanning onlysrc/Lumeo/UI/**/*.razor, so the live docs DataGrid demos were missing the same classes. Fixed in the same release. - NuGet author across all 9 published packages updated from
bemi(the developer's GitHub handle) tonativ.sh.
Migrating from rc.15 / rc.16 / rc.17
- If you vendored an older copy of
lumeo-utilities.cssas a workaround, you can drop it and revert yourApp.razorlink tag back to_content/Lumeo/css/lumeo-utilities.css. - If you set up your own Tailwind build (per the rc.15 "advanced" path), you can keep it — that path still works. Just drop the
@sourceentries pointing at Lumeo packages, since the shipped bundle now covers them.
April 2026
Audit-driven hardening. A 10-item code review surfaced real lifecycle, async, CI, and test-coverage gaps. This release closes all of them. +387 tests (1744 → 2131), three new infrastructure layers (component contract theory, Playwright e2e, visual snapshots), and four lifecycle bugfixes.
Improved — Lifecycle & async safety
- DataGrid debounced server search rewritten to a CTS-backed pattern — exact-last-call semantics, dispose cancels in-flight work, exceptions surfaced. Test now asserts
Assert.Equal(1, callCount)instead of race-tolerantcallCount <= 2. - OnThisPage (docs sidebar) now uses a
CancellationTokenSourceper route — old retry scans cancel cleanly when navigating, no more stale headings on fast clicks. Replaced JSevalwith a dedicated function. - Toast / Overlay / MegaMenu providers — the
_ = InvokeAsync(...).ContinueWith(...)pattern (which silently logged errors) replaced byLumeo.Services.SafeAsyncDispatcher. 9 call-sites converted; expected lifecycle exceptions (JSDisconnectedException,ObjectDisposedException) swallowed silently, others logged with a structured tag. - ComponentInteropService sync
Dispose()now fire-and-forgets the same JS-side cleanup thatDisposeAsyncruns — stops browser-side observers/listeners from leaking when the sync path is taken.
Added — Test infrastructure
- Direct unit tests for 23 components previously without test files (Cascader, ColorPicker, ConsentBanner, DateTimePicker, Gantt, ImageCompare, InplaceEditor, InputMask, Kanban, MegaMenu, Mention, PasswordInput, PopConfirm, QRCode, RichTextEditor, Scheduler, Sortable, SpeedDial, TimePicker, Tour, Transfer, TreeSelect, TreeView). Coverage 108/131 → 131/131.
- Component contract
[Theory]— 250 test cases spanning 125 components; asserts every component renders with defaults AND forwardsAdditionalAttributesto its root. Catches "I forgot to splat" regressions across the entire library at once. - Lumeo.Tests.E2E — new Playwright .NET project with 5 high-value smoke tests (Dialog focus trap, DropdownMenu keyboard nav, Tooltip hover, catalog renders ≥100 cards, Cmd+K palette navigates). Reaches the failure modes bUnit can't.
- Visual snapshot foundation — one example test capturing the home page above-the-fold and comparing against a baseline PNG. Set
LUMEO_E2E_UPDATE_SNAPSHOTS=1to regenerate baselines. - WordImporter real-DOCX test unskipped — programmatic in-memory DOCX with headings, paragraphs, and styles replaces the local-path fixture that previously caused the test to be skipped on every CI run.
Improved — CI release gate
- CI now builds
Lumeo.slnxwith-warnaserroracross the entire solution (was: library + satellites only — docs project was excluded). - CI runs all three test projects:
Lumeo.Tests,Lumeo.Docs.Tests,Lumeo.RegistryGen.Tests. Was previously onlyLumeo.Tests.
Fixed — Docs nav UX
- Top-nav highlight: clicking into a component (
/components/<slug>) now keeps "Components" lit instead of switching to "Docs". - Sidebar from any docs/patterns/component-detail page now shows the full nav (docs + components + patterns) with collapsible groups; the group containing the current URL auto-expands. No more "to find a component you have to click into a component first".
April 2026
Lumeo.Motion satellite (v0.1) + Docs nav v2. Motion ships 10 user-verified components — a curated set polished to perfection; more are coming in future releases. Install with dotnet add package Lumeo.Motion.
Added — Lumeo.Motion v0.1
- Lumeo.Motion satellite package — 10 user-verified motion primitives for high-energy Aceternity / Magic UI-style interfaces.
- Migrated from core (7):
BlurFade,BorderBeam,Marquee,NumberTicker,ShimmerButton,Sparkles,TextReveal. - New (3):
AnimatedBeam(Magic UI port — SVG gradient path between nodes),Confetti(canvas burst escaped from demo box viaposition:fixed),Dock(cursor-magnification with Lucide icons). - Catalog cards show a NuGet badge for satellite components. All components stay in
@namespace Lumeo— no consumer@usingchanges needed. - More motion primitives (AnimatedCircularProgressBar, AuroraBackground, Globe, HoverBorderGradient, MagicCard, Meteors, MorphingText, OrbitingCircles, Ripple, ShineBorder, Spotlight, TypingAnimation, WordRotate, and more) are deferred to a future release pending final visual polish.
Added — Docs nav v2
- Component catalog page (
/components) — sticky category rail, filter chips, and 480×270 preview-card thumbnails for all components. - Algolia full-content search — Cmd+K now queries
lumeo_docsindex (components, patterns, blocks, guides); falls back to a local slim index when Algolia is unavailable. - registry.json as single source of truth — component metadata drives the catalog, the indexer, and the prerender script.
- Thumbnail prerender script (
scripts/prerender/run-all.mjs) — headless Puppeteer renders one PNG per component; runs in CI on registry change. - Algolia indexer script (
scripts/algolia/index-docs.mjs) — pushes records to Algolia on every docs deploy.
Improved
- Sidebar Form group collapsed from 34 individual links to 5 logical subgroups; Data Display from 28 to 5 — both data-driven from
nav-config.json. CatalogFilterChipsbuttons now exposearia-pressedstate to assistive technology.CatalogRailsticky offset aligned totop-[84px]to match NavMenu / BlocksSidebar / CustomizerSidebar.
April 2026
Major release: package split + RichTextEditor Pro + custom Gantt renderer. Lumeo is now 6 packages instead of 1 — install only what you use.
Package split (DevExpress / Microsoft.Extensions model)
Lumeo— core, ~568 KB. Layout, Forms (excl. RichTextEditor), Navigation, Overlay, Feedback, Display, Motion, Theme, ConsentBanner, AI surface.Lumeo.Charts— ~196 KB. Chart + 30+ subtypes + ECharts interop.Lumeo.DataGrid— ~111 KB. DataGrid, DataTable, Filter (incl. ClosedXML + QuestPDF for export).Lumeo.Editor— ~50 KB. RichTextEditor + Word import via Mammoth.Lumeo.Scheduler— ~22 KB. FullCalendar wrapper.Lumeo.Gantt— ~19 KB. Custom SVG Gantt (no third-party dep).- All 6 packages share one lockstep version. Components stay in
@namespace Lumeoso consumer@usingdirectives are unchanged. lumeo add <component>CLI now auto-detects the satellite and prompts to install viadotnet add package.
RichTextEditor Pro (Lumeo.Editor)
- Mentions with pluggable triggers (
@users,#tags,$variables, custom). - Slash commands (Notion-style):
/heading,/list,/table,/code,/image,/quote. - Tables with resizable columns + header rows.
- Code blocks with syntax highlighting (lowlight: JS/TS/Python/CSS/HTML/JSON/Bash).
- Image upload via drag/drop/paste — consumer-supplied
OnImageRequestedcallback or base64 fallback. - AI actions on selection (Improve / Shorten / Expand / Translate / Summarize / FixGrammar) — consumer-supplied
OnAiActionhooks into your own LLM. - Word (.docx) import — works in-browser by default via Mammoth in the WASM bundle. Default style map handles English + German Word default styles (Title/Titel, Heading 1-6/Überschrift 1-6, Body Text/Textkörper, etc.).
- Block drag handles, bubble menu, smart paste, markdown shortcuts, task lists, auto-link.
- Lumeo Dialog for the Link prompt instead of the native browser
window.prompt.
Custom Gantt renderer (Lumeo.Gantt)
- Replaces the Frappe Gantt v1.2.2 dependency with ~400 lines of deterministic custom SVG. No more CDN dep, no more theming surprises across browsers.
- View modes: Day / Week / Month / Year / HalfDay / QuarterDay.
- Drag a bar to move (snaps to single days even in Week view), drag the right edge to resize, drag the bottom-edge handle to set progress.
- Hover tooltip with task name, date range, day count, progress %.
- Theme tokens read via
getComputedStyle— no theme/cache battles. - Auto-scrolls horizontally so today is centered on first paint.
Other
- Overlay components (Dialog, Drawer, DropdownMenu, AlertDialog, Sheet, Popover, ContextMenu, Combobox, Select, ColorPicker, HoverCard, Tour, Collapsible, NavigationMenu) renamed
IsOpen→Open.IsOpenkept as[Obsolete]alias for one release. - 24 form inputs gained
Required/Invalid/ErrorText/HelperText/Label/Name. ReadsFormFieldContextvia cascading parameter so<FormField>wrapper still works. - Display components (Alert, Result, ReasoningDisplay, Statistic, SparkCard) gained Size + Variant; trigger components (BackToTop, SpeedDial, Chip, Carousel) gained Disabled.
- 14 missing component doc pages added (Code, Delta, KpiCard, Marquee, NumberTicker, Overlay, PromptInput, ReasoningDisplay, ShimmerButton, SparkCard, Sparkles, StreamingText, TextReveal, ToolCallCard) + 62 new
ComponentsIndexentries. - Select / Combobox
Searchablefilter actually filters items (was visible but inert). - Mammoth bumped to 1.11.0 to clear NU1902 advisory.
- FullCalendar (Scheduler) now reads Lumeo theme tokens via
--fc-*CSS variable map.
April 2026
Full accessibility sweep. Every icon-only button across the library now ships with an aria-label or sr-only text. WCAG AA violations from Lighthouse: zero.
Added aria-label to icon-only buttons
ToastClose— newAriaLabelparameter (default "Close"), sr-only text for screen readers.Cascader,DateTimePicker,Select(clear + multi-value chips),Filter.FilterPill— "Clear" / "Remove {label}" labels on the X icons that were previously empty buttons.Selectclear-icon converted from<span>to a proper<button type="button">— keyboard focusable and announced to assistive tech.
Already compliant (verified)
Alert(dismiss),Chip,Badge,TagInput,DatePicker— all had aria-label on their close/remove icons.Dialog/Sheet/Drawerclose buttons — sr-only localized text via ILumeoLocalizer.Carouselprev/next — aria-label + sr-only.Paginationhas visible text.Calendarnav is fully labelled via L["Calendar.*"] strings.Ratingstars each emit "Rate {n} of {max}".
April 2026
Finishes the accessibility pass started in rc.12. Slider now has proper ARIA plumbing; the landing-page form-controls bento tile demonstrates the AriaLabel / Label parameters on every interactive element.
Added
Slider.AriaLabel— accessible name for the range input. Also auto-emitsaria-valuemin/aria-valuemax/aria-valuenow. For range sliders (IsRange=true), the end-handle's aria-label is suffixed with "(end)" automatically.
Docs site
- Landing-page form controls demo now passes
Label/AriaLabelon every Switch, Slider, Checkbox, and Toggle — fixes the remaining Lighthouse "button / form element without accessible name" violations.
April 2026
Accessibility + NuGet health + performance polish. Fixes two long-standing Razor bugs in Card / Separator, adds aria-label plumbing to form toggles, and ships deterministic builds with Source Link so consumers can step into Lumeo source from any debugger.
Fixed
Card,CardContent,CardHeader,CardFooter,Separator: moved.Trim()inside the Razor expression. Was previously rendered as a literal HTML attribute (silent error in browsers,InvalidCharacterErrorin strict DOM consumers like Puppeteer).theme.js: replaced synchronousXMLHttpRequestto/lumeo-theme.jsonwith a DOM lookup for an inlined<script id="lumeo-theme-defaults">tag. Eliminates the Chrome sync-XHR deprecation warning, the main-thread block, and the 404 console error on every site without a preset file.BlurFadeno longer holds its children atopacity: 0by default. Above-the-fold content is visible from first paint even when JS hasn't hydrated yet (previously caused a 1-2 s blank flash on prerendered landing pages).
Added
Switch.Label,Checkbox.AriaLabel,Toggle.AriaLabel— new parameters that emitaria-labelon the underlying button so icon-only usages pass Lighthouse / WCAG without ceremony. Switch also falls back to the currentOnLabel/OffLabeltext when no explicit label is set.- NuGet package now ships with Source Link, a
.snupkgsymbol package, and deterministic compiler flags. Debuggers (Rider, Visual Studio, VS Code) can step directly into Lumeo source from GitHub. All three NuGet Package Explorer health checks now pass.
Docs site
- Full static HTML prerender in CI — every route is served with complete content for first paint + SEO (192 routes, ~110 s prerender, via Puppeteer).
- Per-route OG / Twitter preview cards generated via Satori — unique 1280×640 PNG per page with the page title, Lumeo brand, and category pill. Served from
/og/<slug>.png. - Per-page
<meta name="description">,<link rel="canonical">, and JSON-LD structured data (TechArticle/BreadcrumbList/SoftwareApplication). /llms.txt+/llms-full.txt+ per-route.mdvariants for GEO — ChatGPT, Perplexity, Claude can discover and cite Lumeo docs in one fetch.- Cloudflare Web Analytics (cookie-free) gated behind the consent banner.
April 2026
Adds the ConsentBanner component + ConsentService. GDPR-ready cookie / analytics consent primitive — no other Blazor component library ships one.
Added
Lumeo.Services.ConsentService— per-category consent manager. Persists tolocalStorage(lumeo:consent:v1), exposesHasConsent(string)for gating third-party scripts, and firesOnChange/OnRequestOpenPreferencesevents so a "Manage cookies" link anywhere in the layout can reopen the banner without CascadingValue plumbing.<ConsentBanner>— slide-in banner with Accept / Reject / Customize. The preferences dialog has per-category toggles; "necessary" is always locked on. Strings are individually overridable for i18n.- Registered in
AddLumeo()as Scoped — zero extra wiring.
Docs site
- Migrated from GitHub Pages to Cloudflare Pages — per-path
Cache-Control(fingerprinted_framework/*.wasmnowimmutablefor a year), HTTP/3, Brotli at edge, no env-protection friction. sitemap.xmlauto-generated from every@pagedirective (190 URLs) +robots.txtso Google can index all component / block / pattern pages.- Issue + PR templates, SECURITY policy, Code of Conduct, FUNDING (Sponsors button).
- New
/privacypage with live consent-management controls. - Open Graph + Twitter Card meta tags on
index.htmlfor proper link previews on Discord / LinkedIn / Slack / X.
April 2026
Polish pass across ~25 components and every block page — trigger-icon state reflection, cleaner overlay arrows, rewritten Checkbox glyph, DataGrid fullscreen layout, Combobox/Command empty-state gating, and a systematic border-softening sweep.
Added
ShowArrowparameter onPopoverContent,DropdownMenuContent, andHoverCardContent— rotated-square arrow with matching border on outward-facing sides.data-state="open|closed"+groupclass onDropdownMenuTriggerso consumer chevrons can flip withgroup-data-[state=open]:rotate-180.- Toast slide-out animation (
animate-toast-out) — dismiss now slides + collapses instead of popping. - 15 new Lucide icon mappings in
DynamicIcon(Wrench,BookOpen,Component,Puzzle,Cog,Server,Database,Wand,PanelLeft, et al.) + every search-palette category now has a real icon instead of a Circle fallback. - Chevron rotation on open for
SelectTrigger,Cascader, andColorPicker(matching existing Accordion/NavigationMenu/TreeSelect behavior). - Demos: "With Arrow" added to Popover, DropdownMenu, and HoverCard doc pages.
Fixed
- Sparkles clustered at top-left when consumer passed
Class="absolute inset-0"— root cause was Tailwind v4's@layer utilitieslosing to unlayered CSS. Component now drops the.lumeo-sparklesclass entirely when the consumer supplies positioning. - Checkbox rewritten — crisp inline-SVG check + minus with rounded stroke caps (no more Lucide jagginess), unchecked state now visible (was zero-sized due to arbitrary Tailwind classes not being safelisted), hover state, smooth color transition.
- Toast auto-dismiss missed
StateHasChangedso toasts stuck on screen. - Rating half-star was shifted vertically — reworked as two stacked SVGs in a single grid cell with
clip-path, pixel-perfect alignment. - Progress indeterminate sweep: retuned keyframe so exit and opacity fade align — no more "snap off" at the right edge.
- Resizable and Splitter vertical mode: swapped
flex-basis: X%→flex: X 1 0so vertical works without requiring an explicit parent height. - Bento tiles overlapping — added
grid-auto-rows: minmax(0, 1fr)andmin-w-0 min-h-0on tiles. - ImageCompare rewritten with a transparent
<input type="range">for drag +clip-pathfor reveal (browser handles drag math, tracks the cursor exactly). - Combobox + Command empty states rendered unconditionally — now gate on registered item count; items track their visibility so filtered-out items un-register.
- Tour spotlight now reads the target's computed
border-radiusvia JS interop and matches it. - DataGrid fullscreen: removed duplicate exit control (modal X was redundant with toolbar minimize), grid fills modal height, pagination sticks to bottom;
Context.IsExpandednow rebroadcasts to toolbar on toggle so the Maximize/Minimize icon swaps correctly. - Stack/Flex
Gapvalues like14,16,20had no effect — Tailwind's scanner can't see runtime-interpolated class names. Added full spacing-scale safelist to the utilities bundle. - Block previews (SignIn/SignUp/ResetPassword/OtpVerify) had a floating card halo from
min-h-[640px]— replaced with tightp-8, and CardContent bumped topt-10so the hero icon has breathing room. - Alert/Badge/Command/Kbd/EmptyState/Popover/HoverCard/Toast borders softened to
border-border/40or/60across ~60 doc pages. - Circle-fallback icons in the Ctrl+K command palette (
Wrenchetc. were missing from DynamicIcon's map). - Kanban pattern "+2" overflow pill sized to match
Avatar.Sm. - Double-icon bugs on Alert demos (auto-icon + inline DynamicIcon) on AlertPage and KeyboardShortcutsPage.
April 2026
Landing page redesign, marquee swag, comparison table rewrite, and aggressive-border audit across 228 API reference tables.
Improved
- Home marquee rewritten as two rows in opposing directions with icon pills (card surface + primary-tinted) and edge-gradient fades.
- Landing comparison table fact-checked against current GitHub/NuGet state — corrected MudBlazor templates, Radzen AI + MCP, Ant Design Blazor package size.
- Customizer "Share" button collapsed to a single client-side preset code action (removed the duplicate server-code row).
- Softer borders across 228 API reference table headers + ~60 demo wrappers.
April 2026
Patterns page expansion (32 categories, ~70 live inline variants), theme customizer expansion with Vega/Nova/Maia/Lyra/Mira presets, Violet/Amber/Teal color themes.
Added
- Theme customizer: Font selector (6 fonts), Icon Library (6 options, Lucide default), Menu Color, Menu Accent.
- Color themes: Violet, Amber, Teal (total 8 themes).
- Preset renames: Vega, Nova, Maia, Lyra, Mira.
- Patterns page: 32 categories with ~70 live inline variants across Accordion, Alert, Avatar, Badge, Button, Card, Checkbox, Dialog, Input, Select, Switch, Tabs, Table, Toast, Progress, Separator, Skeleton, Popover, Tooltip, Sheet, DropdownMenu, Combobox, Breadcrumb, Pagination, RadioGroup, Spinner, EmptyState, Slider, Toggle, ToggleGroup, Kbd, OtpInput.
- ChartPatternDemos shared component with 8 chart patterns.
Fixed
- Customizer BaseColor and Style options were purely visual — now apply real CSS changes.
- Heavy borders on Switch, ThemeSwitcher, FileUpload, Checkbox, RadioGroup, OtpInput, Combobox, MainLayout search modal.
April 2026
Full shadcn-CLI parity pass. New apply / view / info commands, --only filter on apply, --all / --diff / --view flags on add, and server-stored preset IDs via a Cloudflare Worker at api.lumeo.nativ.sh — so shareable codes can hold arbitrary configs (not just the 26-bit bitfield).
Added
lumeo apply [preset]— flat top-level command (matchesshadcn apply). Writes the theme section intolumeo.json(withlumeo.json.bakbackup) andwwwroot/lumeo-theme.jsonwhichtheme.jsreads on init for no-FOUC first paint.--only theme,font,icons,radius,menu,style,baseColor,darkfilter onapplyto restrict which parts get rewritten.lumeo view <component>— prints component source to stdout without writing, for preview.lumeo info [--json]— dumps project config + installed components + theme.lumeo add --allto install every component;--diffand--viewflags for preview-only runs.- Server-stored preset IDs: when a preset code can't be decoded client-side, the CLI fetches it from
https://api.lumeo.nativ.sh/preset/<id>— a Cloudflare Worker backed by KV. IDs are content-addressed SHA-256 of the canonical JSON, so the same config always returns the same 6-char code. - Customizer sidebar Share as link button — POSTs the live config to the Worker and puts
lumeo apply --preset <id>on the clipboard. Useful for custom brand palettes that don't fit the bitfield codec.
Deprecated
lumeo theme apply— still works but prints a deprecation notice. Uselumeo applyinstead.
April 2026
Default registry URL now points at jsDelivr's GitHub CDN, so the CLI works out of the box without any self-hosted registry. Enables lumeo init / lumeo add on fresh projects immediately after dotnet tool install.
Fixed
- Default registry URL
lumeo.nativ.shwasn't live, so fresh installs of the CLI failed with a 404 onlumeo add <component>. Now defaults tocdn.jsdelivr.net/gh/Brain2k-0005/[email protected]/src/Lumeo/wwwroot/registry/registry.json— pinned to the release tag so schema stays consistent. - File-fetch URL derivation now recognizes three patterns: (1) jsDelivr / raw.githubusercontent.com layouts where the registry lives under
.../wwwroot/registry/registry.json, (2) legacy self-hosted/registry.json→/raw/, (3) bare base URLs. - GitHub Pages deploy workflow now also triggers on
v2.0-devbranch and copies the registry + source files under the published site's/registry/+/raw/paths.
April 2026
Shareable theme presets — customize on /themes, copy a 6-character code, share or apply via CLI. No hosted backend.
Added
LumeoPresetCodec— encodes theme/style/base color/radius/font/icons/menu color/menu accent/dark into a 26-bit bitfield, base62-encoded to 6 chars. Versioned schema so future option additions reject old codes cleanly.LumeoPresetOptions— single source of truth for option arrays (indexes are the stored values — append-only).- /themes customizer: live 6-char preset code with copy button — puts
lumeo theme apply --preset <code>on the clipboard. - CLI: new
lumeo theme apply --preset <code>subcommand. Decodes the code and prints the resolved configuration + a ready-to-paste JS snippet that drives the runtime theme-switcher.--dry-runflag.
Why no backend?
- The preset IS the data — 26 bits packed into 6 base62 chars — no hosted KV store to manage.
- Codes work offline, can be pasted into docs / issues / PRs, and never expire.
- Shorter than shadcn's 9-character IDs (which require their API).
April 2026
DataGrid toolbar composability, smoother column resize, docs sidebar UX. Polish over rc.3.
Added
<ToolbarContent>is now a component with aClassattribute for custom wrapper styling- Five built-in toolbar tools as separate composable components:
DataGridToolbarFullscreen,DataGridToolbarCopySelected,DataGridToolbarColumns,DataGridToolbarExport,DataGridToolbarLayouts DataGridToolbarContext<TItem>cascading context — tool components pick up state with no props- Docs sidebar: active NavLink highlight + auto-scroll active item to centered viewport on direct URL loads / navigation + auto-expand Charts subtree on /components/charts/*
Improved
- DataGrid column resize: JS drives the drag entirely in the DOM (direct style writes on header + body cells) and commits ONCE on mouseup — no more Blazor round-trip per pixel
- Consumer-provided
<ToolbarContent>suppresses the default tool stack to avoid duplicate icons - Softened aggressive
border-bon 228 API reference table headers and in Accordion / Command / DataTable / Table / Sidebar components toborder-border/40
Fixed
- Infinite re-render loop when
<ToolbarContent>re-registered on every parameter set - Duplicate toolbar icons when composing built-in tools inside
<ToolbarContent>
April 2026
Shape-aware chart loading skeletons + per-chart Loading demos across all 30 chart doc pages.
Added
ChartSkeletonwith shape variants (Bars, Line, Area, Pie, Scatter, Grid, Generic) — reserved plot-area geometry so the real chart swaps in without layout jumpIsLoading/ShowLoadingSkeleton/SkeletonKindparameters on every chart wrapper- Loading-state demo on every chart doc page — Simulate button + Hold-skeleton switch
Improved
- Chart skeleton animations per kind: bar-grow, multi-line stroke-draw, flat pie rotation, scatter breath, grid pulse
- 350ms cross-fade handoff between skeleton and real chart
- Axis / legend hint rects reserve real-chart space so there's no layout shift
April 2026
CSS bundle fix + portal theme-token inheritance. Foundational stability patches over rc.1.
Fixed
- Pre-compiled
lumeo-utilities.csswas missing theme-token classes (bg-background,bg-popover,text-muted-foreground, etc.) that consumers needed — added@source inline()safelists - Theme auto-applies
bg-background text-foregroundto<body>on init — portal components (Dialog / Sheet / Drawer / Toast / Popover / Tooltip) now inherit theme tokens when they render outside the theme context - BarChart
LabelStrategyenum (Smart / ShowAll / Auto) replaces the old boolean — auto-rotates category labels at 11 / 17 / 25 densities without flooding dense charts - Stacked bar chart border radius regression — stacked segments now correctly round only the outermost edge
April 2026
Lumeo 2.0 is a mega-release: AI chat primitives, motion primitives, Scheduler, Gantt, RichTextEditor, 14 locales + RTL, Bento / dashboard tiles, a [LumeoForm] source generator, shadcn-style CLI vendoring, dotnet new templates, and an MCP server for LLM codegen. 128 components, 1,687 tests at rc.1 (current rc.17: 131 components across 7 packages).
Added — Components
- AI primitives:
PromptInput,StreamingText,AgentMessageList+AgentMessage,ToolCallCard,ReasoningDisplay— SignalR-native token streaming with sticky auto-scroll and collapsible chain-of-thought - Motion primitives:
Marquee,NumberTicker,TextReveal,BlurFade,BorderBeam,ShimmerButton,Sparkles - Dashboard tiles:
Bento+BentoTile,KpiCard,SparkCard,Delta,Sparkline(standalone SVG primitive) - Navigation / layout:
BottomNav(safe-area, optional FAB),Splitter/SplitterPane/SplitterDivider,PickList<T> - Enterprise:
Scheduler(FullCalendar v6 — Month/Week/Day/List, drag-to-create/reschedule),Gantt(Frappe Gantt — Day/Week/Month/Year zoom, drag progress),RichTextEditor(TipTap v2 — Full/Basic/None toolbars, two-way HTML binding) - Blocks: 8 copy-paste page templates —
/blocks/sign-in,/sign-up,/reset-password,/otp-verify,/pricing,/hero,/dashboard-block,/settings-page
Added — Services & tooling
IDataGridExportService— real .xlsx export via ClosedXML, PDF via QuestPDF, CSV, with browser download helper andExportFormatsflags- 14 built-in locales via
ILumeoLocalizer: EN, DE, ES, FR, IT, PT, NL, PL, JA, ZH-CN, KO, AR, RU, TR - RTL layout via
IThemeService.SetDirectionAsync(LayoutDirection)— persisted, applied before first paint, with RTL-aware keyframes Lumeo.Cli— shadcn-style CLI (dotnet tool install -g Lumeo.Cli). Vendorize components into your repo:lumeo init / add / list / diffregistry.json— machine-readable catalog of 127 components (files, dependencies, CSS variables)@lumeo-ui/mcp-server— MCP server exposing curated component schemas so Claude / ChatGPT / Copilot / Cursor author correct Lumeo markupLumeo.Templates—dotnet new lumeo-page / lumeo-form / lumeo-componentscaffolders
Added — Developer experience
[LumeoForm]Roslyn source generator — annotate a POCO and get a compile-timeRenderForm(model, onSubmit)that emits a fully-bound Lumeo Form with validation. Handles string / int / decimal / bool / DateTime / enum / email / password via[DataType]+[Required]+[Display]- Opt-in
Animated/AnimatedIndicatorprops on Steps, Timeline, Progress, Tabs, Switch, Checkbox, Badge, BottomNav — off by default, zero overhead when unused PressEffectenum (Scale / Brightness / Ripple) on Button, ShimmerButton, Card, BottomNavItem, ToggleGroupItem, Chip- 248 new bUnit tests for 2.0 components — 1,687 total. 138 missing API rows filled in across ~45 component doc pages. Scrollable
OnThisPageaside on every docs page. Landing rewrite,/docs/registryauthoring guide, and/docs/culturepage - Interop:
motion.*(RAF + IntersectionObserver),ai.*(autosize + sticky-scroll MutationObserver), lazy-loadedrich-text-editor.js/scheduler.js/gantt.jsESM modules,DownloadFileAsynconIComponentInteropService, Splitter pointer-capture helpers
Improved
- DataGrid: inset fullscreen modal with open animation, header drag-to-reorder, layout JSON round-trip (
ExportLayout()/ApplyLayoutJsonAsync()), toolbar toggles (ShowSearch/ShowColumnChooser/ShowExport),Cultureparameter,SetHtmlClassfor navbar hiding in fullscreen - UX audit:
cursor-pointer+focus-visiblerings on every interactive component Cultureparameter cascades through DatePicker, DateTimePicker, NumberInput, Slider, Statistic — falls back toCultureInfo.CurrentCulture- Motion demos: interactive Steps/Timeline, proper Tabs indicator per variant, testable BottomNav, single-connector animation (no flicker on reverse)
Fixed
- DataGrid: duplicate column registration race, header-drag edge cases, fullscreen z-index now above nav, grid fills overlay width
- BarChart: every category label rendered by default (
LabelStrategy.Smart) with auto-rotation at higher densities (-60°, -75°) - Landing: quickstart terminal cards, CTA box + Star button contrast, visible gaps, removed stray separators
- QuestPDF WASM crash on
DataGridExportdocs page (button disabled under WASM) - Tailwind arbitrary-class bugs and docs spacing polish across 2.0 component pages
Breaking changes
- Icon / Label RenderFragment slots removed from Alert, Badge, EmptyState, Rating, Result, Segmented, SidebarMenuButton, StepsItem, TabsTrigger, TimelineItem. Rename
<Icon>…</Icon>→<IconContent>…</IconContent>and<Label>…</Label>→<LabelContent>…</LabelContent>. Deprecated in 1.6.0. - DataGrid Excel export is a real
.xlsxnow (ClosedXML), not a CSV renamed to .xlsx. Transparent for normal users; remove any workaround that routed the "excel" case to your own handler. - BarChart
LabelStrategydefaults toSmart, showing every category label and auto-rotating at higher densities. Restore the previous behaviour withLabelStrategy="ChartLabelStrategy.Auto". - Culture defaults to
CultureInfo.CurrentCultureon date / number components. PassCulture="@CultureInfo.InvariantCulture"to keep invariant formatting.
Migration
See MIGRATION.md at the repo root for before/after snippets and migration recipes for every breaking change, plus install commands for the new Lumeo.Cli, Lumeo.Templates, and @lumeo-ui/mcp-server companion packages.
April 2026
Added
IconContent/LabelContentslots on Alert, Badge, EmptyState, Rating, Result, Segmented, SidebarMenuButton, StepsItem, TabsTrigger, TimelineItem — replace the previousIcon/Labelslots that collided with the<Icon>and<Label>components- Design philosophy section in Introduction docs explaining the unprefixed naming choice and the
<Name>Contentconvention
Deprecated
- Old
Icon/Labelslot parameters remain as[Obsolete]aliases — existing code compiles with a warning; aliases are removed in 2.0
April 2026
Added
<Icon>component — Lumeo-native wrapper around Blazicons withName,Svg, andSize(Xs, Sm, Md, Lg, Xl) parameters- Icon finder docs page — search + library switcher across Lucide, Bootstrap, Heroicons, Feather, Octicons, Material, Fluent; reflection-based catalog covering all ~1,700 Lucide icons
April 2026
Added
- Service interfaces —
IToastService,IOverlayService,IThemeService,IKeyboardShortcutService,IComponentInteropService— for mockability in consumer tests - DataGrid sticky header across scrolling viewport
- DatePicker support for
DateTimebinding alongsideDateOnly
Improved
- DialogFooter button spacing, alignment, and responsive stacking polished
- DataGrid DX: cleaner row API, simplified column definitions, better defaults
April 2026
Fixed
- Stacked bar chart: outer corners stayed sharp when theme had rounded corners — now uses per-segment
borderRadiusarrays so the theme's radius actually applies - Dialog zoom-in animation transform leaked with
fill-mode: both— keyframe end state switched totransform: none - DataGrid column race where the grid rendered empty until the first interaction — fixed with
InvokeAsync(StateHasChanged)inAddColumnDef - Charts not repainting on theme change — JS dispatches
lumeo:theme-changed; ECharts interop listens and rerenders
April 2026
Added
- Rounded outer corners on stacked bar charts (top segment top-rounded, bottom segment bottom-rounded)
- Charts now rerender automatically on theme change — no page refresh needed
April 2026
Fixed
- nupkg leaked
package.json/package-lock.jsonand causedNETSDK1152publish conflicts in consumer apps — moved npm build to repo root and excludedStyles/from the package
April 2026
Added
- Pre-compiled
lumeo-utilities.cssships in the package — zero-config Tailwind for consumers; no local Tailwind build required - Consumers who want Tailwind in their own markup can keep their own v4 build and drop
lumeo-utilities.css— their build picks up every utility Lumeo needs
April 2026
Added
- Built-in EN/DE localization via
ILumeoLocalizer— driven byCultureInfo.CurrentUICulturewith exact → neutral → English fallback - Override or extend locales during
AddLumeo(opts => opts.Add(...)) - DataGrid, Pagination, DatePicker, and other component default strings now translatable
Fixed
- Stacked bar chart rendering on dark theme
March 2026
Fixed
- PasswordInput browser-autofill yellow highlight bled past the input's rounded corners — now clipped to the input's radius
March 2026
Fixed
- DataGrid pagination test assertion updated to match the new footer wording
March 2026
Added
- ColorPicker SV + Hue picker surface (replaces the earlier swatch-only design)
- Blocks polish pass — cleaner layouts across Authentication, Analytics, Calendar, Chat, Dashboard, E-Commerce, FileManager, Kanban, Settings, TaskTracker and more
Fixed
- Overlay positioning inside ancestors with
transform/filter(these create a containing block that breaksposition: fixed)
March 2026
Fixed
- Textarea
@bind-Valuetwo-way binding - TreeSelect cleanup on dispose
- Tooltip disposal race on rapid mount/unmount
- DataGrid pagination alignment and UX polish
March 2026
Added
- DataGrid
GroupsExpandedByDefaultparameter
Fixed
- 7 reported bugs — Input two-way binding, DataGrid skeleton, sticky header, and grouping defaults
- DataGrid pagination layout — info left, page controls right
March 2026
Added
- First stable release — 103 components, 8 themes, 1,316 tests
- CI workflow publishing to NuGet on GitHub Release
- Chart error-state visibility, autosave safety guards,
DelayedDispatchfor timer-based components
Improved
- 1.0 hardening — error visibility across async paths, shortcut handles simplified to
IAsyncDisposable, toolbar errors routed to a single sink - All dependencies updated to latest
March 2026
Added
- Checkbox: Label and Description parameters with auto-Id for form label association
- RadioGroupItem: Description text support for helper text below radio options
- Steps: Error state per step with red X icon, custom Icon slot for any step indicator
- Popover: Arrow support (ShowArrow parameter) matching Tooltip arrow pattern
- 48 new unit tests covering all upgraded component features (1,124 total tests)
- Form Validation guide — DataAnnotations, custom validation, complete registration form example
- Contributing guide — setup, component creation conventions, testing, code style
- "When to Use" and "Related Components" sections on 62 more component pages (82 total)
- API reference tables now complete on all 136 component documentation pages
Improved
- Home page stats corrected (75→103 components, 7→8 themes)
- Chart patterns integrated into Patterns page with filter category
- All hardcoded colors replaced with CSS variables (Avatar, Statistic, Result, KanbanCard)
Fixed
- MentionPage Razor escape for @user syntax
- Statistic and Result test assertions updated for new CSS variable colors
March 2026
Improved
- Updated NuGet package description (90→103 components, added test count and features)
- Updated README with accurate stats, all component categories, and install command
March 2026
Added
- Dialog size variants (Sm, Default, Lg, Xl, Full) and Scrollable content mode
- Drawer multi-position support (Top, Right, Bottom, Left) with direction-aware swipe
- Alert: Title, Description, Icon slots, ShowIcon with default icons per variant, AutoDismiss timer
- Input: 3 size variants (Sm, Default, Lg) and Clearable mode with X button
- Tooltip arrow support with configurable Offset and fade animation
- Badge: Pulse ping animation on dot variant and Icon slot
- Accordion: DefaultValues for initially open items and Disabled items
- Skeleton: Wave/Shimmer animation variant alongside existing Pulse
- Spinner: Dots and Bars variants, Label text, and Color override
- HoverCard: Side parameter (Top/Bottom positioning)
- Tabs: Disabled tabs with aria-disabled and TrailingContent on TabsList
- Button: FullWidth mode, LeftIcon and RightIcon slots
- Progress: Circular SVG variant with ShowValue and configurable StrokeWidth
- Avatar: Square shape option and Status indicator (Online, Offline, Away, Busy)
- Switch: Loading spinner state and OnLabel/OffLabel text
- Select: Disabled items and Placeholder text on trigger
- Combobox: EmptyText for no-results state and Creatable mode
- NumberInput: Arrow key and mouse wheel support, Prefix/Suffix text
- Textarea: Character count display, MaxLength indicator, Resize control
- New Accessibility guide page with ARIA roles, keyboard patterns, and focus management docs
- New Changelog page with full release history
- API reference tables for 30 additional component documentation pages (55 total)
- "When to Use", "Keyboard Interactions", and "Related Components" sections on 20 component pages
Improved
- Animation keyframes and utility classes now ship in lumeo.css for NuGet consumers
- Production-quality spring easing curves (
cubic-bezier(0.16, 1, 0.3, 1)) on all animations - Rating colors now use themeable
--color-ratingCSS variable instead of hardcoded yellow - Accessibility and Changelog pages added to sidebar navigation
Fixed
- Broken animations for NuGet package consumers (keyframes were only in docs site)
- Missing
animate-toast-in— Toast slide-in animation was never defined - Added aria-labels to PasswordInput toggle, TagInput close buttons, DatePicker clear button, and Carousel navigation
- Rating keyboard navigation with Arrow keys and improved star labels
- 5 failing tests updated for new Spinner, Avatar, and Select component structures
March 2026
Added
- 14 new components: Cascader, Color Picker, Date Range Picker, Date Time Picker, Filter, Image Compare, Inplace Editor, Input Mask, Kanban, Mega Menu, Mention, Number Input, Password Input, Sortable List
- DataGrid enhancements: column menu, inline editing, column filtering, and toolbar improvements
- Keyboard shortcuts:
Rto shuffle themes,Ctrl+Dfor dark mode,Ctrl+/for shortcuts help - Redesigned WASM loader with animated splash screen, brand name, and ripple animation
- Floating navbar and floating sidebar design for the docs site
- NuGet package icon (Lumeo logo)
Improved
- All UI corners now respect the CSS radius variable, enabling zero-radius presets like Lyra
- Customizer sidebar moved to header button with
Ctrl+Btoggle shortcut - Replaced raw HTML elements with Lumeo components across 113 doc files
- Converted raw HTML to Lumeo components in 7 pattern files
- QR Code live preview, theme persistence, and search palette enhancements
- CommandEmpty now always renders regardless of Command context
Fixed
- Customizer radius bug where radius values did not apply correctly
- Mobile docs improvements and API table horizontal scrolling
- Floating nav sticky positioning (moved animation off root element)
- Splash screen CSS compatibility with Tailwind CDN
- Em dash encoding issues in page titles
- FormWizardPattern closing tag mismatch
- Link/a tag mismatches in LinkPage and Home
- UTF-8 BOM in Home.razor
February 2026
Added
- API reference tables for 25 component documentation pages
- Programmatic OverlayService for opening dialogs, sheets, and drawers from code
- Kbd component and KeyboardShortcutService for global keyboard shortcuts
- Scrollspy component for tracking scroll position and highlighting nav items
- 926 bUnit tests across 50+ components and 4 services (expanded from 240)
- CI workflow to run tests automatically on push and PR
- Toast position support (top-left, top-right, bottom-left, bottom-right, etc.)
- 19 new patterns on the Patterns page including drag-and-drop Kanban board
- Live world map demo for GeoMapChart
- Live interactive demos for all 5 service documentation pages
- New components: blocks section, filter docs, and comprehensive UI improvements
- Custom scrollbar styling
Improved
- Redesigned Themes customizer sidebar to match reui.io design
- Redesigned Themes and Patterns pages with new layout
- Replaced inline accordion sections with flyout popover menus in the customizer
- Default theme changed from Orange to Zinc to match Lumeo logo
- Softened chunky borders across overlay components
- Docs favicon updated to dark Lumeo icon SVG
- All services registered via single
AddLumeo()call
Fixed
- OtpInput
eval()XSS vulnerability patched; added IAsyncDisposable - 9 failing tests for Calendar, OtpInput, and FileUpload
- Chart rendering: dropped source-gen serializer, resolved CSS variable colors
- Chart serialization and WordCloud rendering errors
- EChartCalendar range conflict and chart error handling
- Z-index issues for overlay components, theme loading, and toast variants
- Hanging ThemeServiceTests and stale Dialog/AlertDialog assertions
- Duplicate ondragover attributes in KanbanPattern
- Patterns page layout and broken CSS opacity modifiers
- GitHub Pages deployment issues with Tailwind v4 CDN and .wasm 503 errors
January 2026
Added
- Initial release with 45+ shadcn-inspired Blazor components
- Full docs site with component pages, live demos, and code snippets
- 15 chart types powered by ECharts (Bar, Line, Area, Pie, Donut, Radar, Gauge, Treemap, Sunburst, Heatmap, Sankey, Funnel, and more)
- Patterns gallery page with reusable UI pattern examples
- Theme customizer with multiple color schemes and dark mode support
- 10 additional chart types: Scatter, Candlestick, Box Plot, Word Cloud, Geo Map, Calendar Heatmap, Theme River, Graph, Parallel, Radial
- 9 full-page pattern demos
- Layout primitives: Stack, Flex, Grid, Container, Center, Spacer
- Typography components: Heading, Text, Code, Link
- Form components: Button, Checkbox, Combobox, Date Picker, File Upload, Form, Input, Label, OTP Input, Radio Group, Select, Slider, Switch, Textarea, Toggle, Toggle Group
- Overlay components: Alert Dialog, Command, Context Menu, Dialog, Drawer, Dropdown Menu, Hover Card, Popover, Sheet, Tooltip
- Navigation components: Breadcrumb, Menubar, Navigation Menu, Pagination, Sidebar, Steps
- Data Display components: Avatar, Data Table, Table, Rating, Statistic, Timeline
- Feedback components: Alert, Badge, Empty State, Progress, Skeleton, Spinner, Toast
- ToastService, ThemeService, and ComponentInteropService
- GitHub Pages deployment pipeline