Repository navigation
release: v4.2.0 into develop - #648
Merged
Merged
Conversation
…s-origin download
A resize drag reports every column's measured width, so a control column with nothing to measure reported zero - stored as the column's width and preferred over the one it declares. table-columns.js now leaves such a column out of the report, OnResizeCompleted refuses a width that is not a width, and the column state treats one as unset where it is stored or restored. Non-pixel lengths (20%, auto, clamp()) pass through untouched.
Runs axe (WCAG 2.0, 2.1 and 2.2 A/AA) on every component, primitive and chart demo, plus a keyboard pass over the main interactive components, against the Server demo in Chromium. Report mode is the default and writes test-results/a11y/report.md; BB_A11Y_MODE=enforce fails on findings.
…its in Floating content is portalled to the body and given z-index 50 (9999 for fixed positioning), whatever its trigger sits inside. A trigger inside a raised container therefore opened its overlay underneath that container: a dropdown in a toast (the toast stack is z-100) rendered behind the toast. computePosition now returns the z-index that clears every raised ancestor of the reference, and applyPosition uses it. Positions that come through C# (PositionResult) carry no zIndex and keep the old values. Unchanged for triggers in normal flow (still 50). A select in a popover in a dialog now sits at 10000 over the popover's 9999 instead of tying with it.
A toast could only hold text. It can now hold any markup or components. - ToastService.Show<TComponent>(parameters, toast) shows a component in a toast, so its content is written as an ordinary .razor component. It works from pages and from plain C# services, and mirrors DialogService.OpenAsync<TComponent>. - IToastReference is cascaded to everything inside a toast; DismissAsync() lets a component close the toast it is shown in. - ToastData.Icon, Content and Actions are RenderFragment slots, named after BbAlert's, for small inline content. Icon replaces the variant icon, Content renders below the title and description, Actions is a row below. - A toast with Content or Actions stops auto-dismissing once the user presses or moves focus inside it (BbToast.OnHold). Hover alone can't keep it open: a menu opened from it renders outside the toast, so moving onto the menu reads as leaving and the toast was dismissed, menu and all. - ToastService docs now say to keep it scoped; a singleton on Blazor Server would share toasts, and their fragments, between users. Demo: a Custom Content section (a ReplyToast component) and an Inline Content section (a dropdown in Actions), with code samples and API reference entries.
feat(Toast): show components and custom content in toasts
test: add accessibility audit to the browser suite
- Rename ColumnWidth to DataGridColumnWidth and mark it [EditorBrowsable(Never)]. It is public only because Components shares it with Primitives, and consumers import this namespace for DataGridState, so a type of their own called ColumnWidth would have become ambiguous (CS0104). - Parse widths with NumberStyles.Float instead of Any. Any accepts thousands separators, so "12,5px" (12.5 in a comma-decimal culture) read as 125 and "0,4px" slipped past the sub-pixel guard as 4. - Test the Gantt's resize guard, which no test covered, and correct its doc comment: the script no longer reports every column.
fix(DataGrid): never store or render a zero column width
The vendored files were the modern, unminified build. It calls Map.prototype.getOrInsertComputed with no polyfill, so documents failed to load on anything older than Chrome/Edge 145, Firefox 144 or Safari 26.2 (iOS 18, Firefox ESR, pinned enterprise browsers). The legacy build carries its own polyfills, and the minified files are 1.8 MB instead of 3.1 MB with no references to source maps that weren't shipped. PDF.js 6 decodes JPEG 2000, JBIG2 and CCITT images only through WebAssembly modules, and none were shipped or located, so scanned documents rendered blank or wrong. openjpeg.wasm, jbig2.wasm and qcms_bg.wasm now ship under lib/pdfjs/wasm/ and every getDocument call passes wasmUrl, resolved from the interop module's own URL like the worker. Their licences are added to the third-party notices. Files are byte-identical to pdfjs-dist 6.3.289 (npm integrity sha512-ZHjSVpDa3D6izMq8...).
dispose() called pdf.destroy(), which PDF.js 6 no longer has; the TypeError
was swallowed, so no document or worker was ever freed. Every Url change,
LoadDataAsync call or disposal left a worker running with a parsed PDF in
it. Only the loading task frees them, so it is now kept and destroyed.
Loads also raced. load/loadData registered the document after awaiting it
without checking whether a newer load had started, and dispose() found
nothing to free while a load was in flight. A slow document could replace
a newer fast one, and a load running at disposal re-registered itself on
the removed canvas. Each canvas now has a generation: a new load or dispose
bumps it and destroys the task in flight, and an overtaken load destroys
its own document and returns { superseded: true }.
The C# side gets the same guarantee: every load takes a version and its
own CancellationTokenSource, passed to the interop call, so a late result
never wins ApplyState or raises OnDocumentLoaded. The explicit token also
replaces Blazor Server's 60-second interop timeout, which reported a large
document on a slow link as failed while it was still loading.
The page, zoom and fit functions return failures in `error` instead of
throwing, and a render only clears its own task, not a newer one's.
OnDocumentLoaded is raised outside the interop error handling, so an
exception from the consumer's handler reaches them instead of showing
"Unable to load".
A byte-loaded document downloaded as a 0-byte file: PDF.js transfers the ArrayBuffer given to getDocument to its worker, which leaves the copy the viewer kept for downloads empty. download() now asks the document for its data (pdf.getData()) for both URL- and byte-loaded documents. A URL-loaded document is no longer fetched a second time, so an expiring signed URL or a server without CORS no longer matters, and the window.open fallback for a failed fetch, which had no noopener, is gone. It returns why a download did not happen instead of throwing.
- Public methods wait for the module import. LoadDataAsync called from a consumer's own OnAfterRenderAsync(firstRender) ran before the viewer's import came back and silently did nothing, the first time per circuit. The import task is kept and awaited, and retried if it failed. - Page, zoom, fit, download and the getters catch interop failures the way loading does and log them. They run from toolbar clicks, and an exception escaping an event handler ends a Blazor Server circuit: a corrupt page, or "Worker was destroyed" while a document was being replaced, did exactly that. A result from before a newer load, or one answered with no document open, is no longer applied, so it can't wipe the viewer or show "Unable to load" while a load is in flight. - A failed load always shows the localized PdfViewer.LoadFailed message. PDF.js's own text was shown as-is: raw English, sometimes with the full URL and its signed query string. It now goes to the log through a source-generated PdfViewerLog, which also replaces Console.Error. - Relative URLs resolve against document.baseURI. PDF.js resolves them against the page's location, so Url="docs/a.pdf" requested /components/docs/a.pdf on a page at /components/pdf-viewer.
…parameter - Height=null is documented to fill the parent, but the root had no height of its own. It now takes h-full and the viewport min-h-0, so the canvas area gets what the toolbar leaves. - ShouldRender ignored MinScale, MaxScale, DefaultScale and AdditionalAttributes, so changing the zoom bounds left the zoom buttons enabled or disabled as before. Attributes compare by content, so a parent re-render's new dictionary alone still doesn't redraw the viewer. - Changing page scrolls back to the top instead of landing wherever the previous page was scrolled to. - The page-input wrapper span no longer carries an aria-label; a label on a generic element is not announced, and the input has its own.
…ds late on Server (#608) (#609) overlay.close reaches the browser ahead of the render that writes data-state="closed", up to a round trip ahead when the portal host is still waiting on its previous batch. hidePosition read data-state to tell a reopen from a close, saw "open", and skipped the hide, leaving the overlay on screen. overlay.close now passes its own token check, so only a real reopen (which takes a new token) cancels the hide. Direct hidePosition callers keep the data-state check.
… (#606) With UpdateTiming.Immediate or Debounced, BbInput, BbTextarea, BbInputGroupInput and BbInputGroupTextarea raised ValueChanged a second time on blur with the value typing had just raised, so a @bind-Value:after handler ran twice for one edit. JsOnChange now raises only when the value differs from the current Value, as BbInputField already does. A pending debounced edit is still flushed on blur.
…r first render (#607) * fix(text-input): apply UpdateTiming and DebounceInterval changes after first render The input handlers read the config captured at initialize, so updateConfig had no effect. They now read state.config. * fix(text-input): drop pending input callbacks when updateConfig changes mode A debounce timer or animation frame queued under the old mode would otherwise send a stale value after the switch.
… dark mode (#611) * fix(inputs): use shadcn's input fill so theme --input colours show in dark mode Input-style fields filled with bg-background; shadcn v4 uses bg-transparent with dark:bg-input/30, so a tweakcn or shadcn theme's --input had no effect on our fields in dark mode. Swap the fill on every field box, add shadow-xs, add dark:hover:bg-input/50 on clickable triggers, and follow shadcn's outline button variant. The outline's light fill uses not-dark:bg-background so an add-on stylesheet that repeats .bb:bg-background (PdfViewer's) can't override the dark fill. Refs discussion #610. * fix(inputs): keep Class background overrides on Outline and tint the editable DatePicker on hover not-dark:bg-background survived cn when Class set a background (bb:bg-primary), because the variants differ, so the light fill won. Use bg-background/100: the same colour, still merged away by a Class background, and not repeated by PdfViewer's stylesheet, so dark:bg-input/30 keeps winning in dark mode. The editable DatePicker wrapper now gets dark:hover:bg-input/50 like the other triggers.
* feat(Dialog): add Position option to Dialog and DialogOpenOptions (#612) Dialog takes a Position parameter (DialogPosition: Center, TopCenter, BottomCenter, CenterLeft, CenterRight, TopLeft, TopRight, BottomLeft, BottomRight). DialogService dialogs take the same value through DialogOpenOptions.Position. Center stays the default, so dialogs that don't set it are unchanged. Adds a demo section, code snippet and API Reference entries, and updates the API surface snapshot. * test(conventions): exempt DialogPositionClasses from logical-direction check DialogPosition names physical sides (CenterLeft, TopRight, ...), the same way ToastPosition does, so its placement classes stay physical.
* feat(Dialog): add enter and exit animations to Dialog and DialogOpenOptions (#613) Dialog and DialogOpenOptions take EnterPreset, ExitPreset (MotionPreset?), EnterKeyframes, ExitKeyframes and AnimationDuration. A closing dialog stays on the page, with data-state="closed", until its exit animation ends. With none set, dialogs open and close as before. Reduced motion skips the animations. * fix(Dialog): keep exit lifetime and modal protection right (#613) - An exit that ends at once now releases the dialog on both controlled and context closes. - A superseded native exit no longer closes a reopened <dialog>. - DialogService dialogs keep the focus trap, scroll lock and Escape handling until their exit ends; a stacked exiting dialog keeps focus until it leaves.
MobileLayout="Stacked" turns each row into a card below MobileBreakpoint (Sm, Md or Lg). The grid writes each body cell's label as data-label, and CSS under the root's data-mobile-stacked attribute does the switch, so no JavaScript is needed. Columns take MobileLabel (defaults to the title; an empty string shows none) and HideOnMobile. Pinned cells drop their sticky offset, full-width rows keep their own layout, and the row groups get an explicit role. A grid left at None renders exactly as before. Co-authored-by: Mathew Taylor <mathew@mac-m5.local>
10.0.12 of Microsoft.AspNetCore.Components.WebAssembly.Server has two high-severity advisories (GHSA-qjpx-jqm5-h2c4, GHSA-g27p-qf6j-c96c), which fail the solution build with NU1903. Both are patched in 10.0.13. Move every Components package in the demos to it together. The src/ libraries reference only Components.Web, which neither advisory covers, so their 10.0.12 floor stays. Co-authored-by: Mathew Taylor <mathew@mac-m5.local>
…623) Selecting a node redrew every node about five times (ten with the Items API), and each draw sorted the node's siblings to find aria-posinset, so a click cost grew with the square of the sibling count. - TreeViewContext: keep each node's sibling index, refreshed once after removals, so GetPosInSet is O(1); IsFirstEnabledRoot no longer sorts. - Primitive BbTreeItem: on a tree state change, re-render only when the node's own state (selected, expanded, checked, focus, position) changed. - Primitive BbTreeView: skip a bound-value callback when the bound parameter already holds the value, so a selection no longer raises ExpandedValuesChanged and re-renders the page for nothing. - Styled BbTreeView: pass OnNodeClick to the primitive only when the app listens for it. - TreeItemNode and styled BbTreeItem: merge node classes once per state instead of per node per render. aria-posinset, aria-setsize, focus and selection are unchanged. Co-authored-by: Mathew Taylor <mathew@mac-m5.local>
…#624) Navigating to a page with another layout disposes the layout's provider and mounts a new one. The scoped ToastService keeps its toasts, but the new provider only started timers on the next change, so toasts already showing stayed until another toast was raised. Start their timers when the provider initialises. Co-authored-by: Mathew Taylor <mathew@mac-m5.local>
…ilwind CLI to v4.3.5 (#639) 10.0.12 and 10.0.13 carry GHSA-g27p-qf6j-c96c, which fails restore under TreatWarningsAsErrors. All Microsoft.AspNetCore.* references, including BlazorBlueprint.PdfViewer, now use 10.0.14. tools/install.sh and install.ps1 now default to Tailwind v4.3.5 (override with TAILWIND_VERSION).
…e for the same key is disposed (#629)
…601) Update the theme switcher radius options to use each radius value for the button border radius instead of a fixed rounded class. This makes the preview better reflect the selected corner style.
… (#619) Co-authored-by: Mathew Taylor <mathew@mac-m5.local>
…itable elements (#634, #632) (#640) fix(Menubar): use one roving tab stop (#634) feat(KeyboardShortcuts): allow shortcuts in editable elements (#632) Both by @ric-ros, resolved against #631, #633 and #635. BbMenubarItem also re-registers its shortcut when AllowShortcutInEditable changes. Co-authored-by: ric-ros <ric.ros@icloud.com>
…ancel buttons (#630, #600) (#641) fix(Toast): announce non-error toasts politely (#630) feat(ColorPicker): add apply/cancel buttons (#600) Resolved against v4.2.0's Toast changes and the #598 presets label fix. Adds ColorPickerActionButtonsTests and the ActionButtons API snapshot. Co-authored-by: ric-ros <ric.ros@icloud.com> Co-authored-by: garrenf <144177629+garrenf@users.noreply.github.com>
… and generate the key docs (#638) (#643) Adds DefaultBbLocalizer.EnglishDefaults and generates the guide's key table from it (#638). Routes hard-coded literals and English parameter defaults through IBbLocalizer with 36 new keys (#637 parts a and b); affected parameters and DialogService option texts now default to null and fall back to the localized text.
BarcodeFormatException gains Error/Arguments (BarcodeFormatError); GanttBuilder throws GanttBuildException (GanttBuildError), an ArgumentException. BbBarcode, BbGantt, BbFormFieldInput and BbDynamicForm show these messages through IBbLocalizer; English output unchanged by default.
BbSheetContent gains ShowOverlay and CloseOnInteractOutside; Primitives BbSheetContent gains NonModal and CloseOnInteractOutside. Non-modal sheets render no overlay, are aria-modal="false", don't trap focus or lock scroll, and close on Escape or an outside pointer-down. Default sheets are unchanged.
CHANGELOG gets a 2026-11-07 (v4.2.0) section with upgrade notes, and the Components and Primitives package notes are rewritten for v4.2.0. Claude-Session: https://claude.ai/code/session_01K3XidR4yZdEDicFv6gUyoq Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings the v4.2.0 release branch into
developso it can be released withrelease.sh(Primitives 4.2.0, Components 4.2.0 and the first BlazorBlueprint.PdfViewer, 1.0.0). The full list of changes is in the2026-11-07 (v4.2.0)section ofCHANGELOG.md.Highlights:
BlazorBlueprint.PdfViewer(BbPdfViewermoved out of Components)data-sloton modal overlaysIBbLocalizerIssues resolved
developisn't the default branch, so this PR's merge closes none of these. They close when the release reachesmain.