Skip to content

chore: bring v4 up to date with develop (second pass) - #526

Merged
mathewtaylor merged 16 commits into
v4from
chore/align-v4-with-develop-2
Sep 13, 2026
Merged

mathewtaylor merged 16 commits into
v4from
chore/align-v4-with-develop-2

Conversation

@mathewtaylor

Copy link
Copy Markdown
Contributor

Merges develop into v4 again, after the 3.17.0 release and the work that followed it.

Brought across from develop

#507 survived this time

Worth recording, because last time it did not. develop carries fb132fb7, the revert that took the Drawer trigger change off it to keep the release non-breaking — and the previous merge brought that revert along and quietly undid #507 on this branch.

It did not recur because a42ce546, the revert-of-that-revert, is now an ancestor here, so git knows the current state is the newer decision. Checked rather than assumed, same as last time.

Verified after the merge

BbDrawerTrigger renders <button type="button">, AsChild present — #507 intact
BbTooltipTrigger AsChild still defaults to false#428 intact
V4-MIGRATION-GUIDE.md present
CopyTextFailure.cs, native-dialog.js, theme-init.js all arrived from develop
CHANGELOG.md sections in date order, no duplicated headings in any recent section

No conflicts this time. Builds clean, 178/178 tests pass.

Note on the changelog

There are duplicated ### Fixed / ### Added headings inside the 2026-01-15, 2026-01-25 and 2026-02-12 sections. Those are pre-existing and not from this merge — flagging so nobody attributes them to it.

manuel-rw and others added 16 commits September 4, 2026 20:41
Review of README.md before cutting a release.

The primitives table listed 26 of the 29 primitive folders that actually ship
components. Menubar (8 components) and NavigationMenu (6) were missing, though
both have styled counterparts listed under Components — so the README named the
styled version and denied the primitive existed. Added, and the count corrected
to 28.

Floating is deliberately still absent. It holds BbFloatingPortal, which is
positioning infrastructure the overlays use internally rather than a primitive
anyone picks up on its own.

The Render Modes guide link returned 404. So does every /guides path on the
site — the section is missing from the deployed build, which is the same stale
deployment #477's reporter hit and #494 chose to leave alone a month ago. It
now points at the guide in this repository, which resolves today and needs no
deployment. Worth putting back to the site URL once the site is redeployed.

Checked and found correct, so left alone: the 112 component count (the table
has 122 rows, but 10 components appear in two categories), 11 chart types,
every named service and both registration methods, the demo run commands, and
all four relative links. The setup section already carries theme-init.js
from #477.
docs: correct the primitives count and repoint a dead guide link
3.16.1 was published as a patch, but the release adds three features —
theme-init.js, BbFileUpload.AllowPaste, and the chart click events — alongside
the fixes. 3.17.0 is the honest number. 3.16.1 had zero downloads when this was
caught, so it can be unlisted with nothing depending on it.

Retitles both RELEASE_NOTES.md files and bumps the Primitives PackageReference
in BlazorBlueprint.Components.csproj from 3.16.1 to 3.17.0, so Components 3.17.0
depends on Primitives 3.17.0 rather than reaching back to a version about to be
unlisted.

CHANGELOG.md needs no change: its sections are dated rather than versioned, and
the 3.16.0 and 3.15.0 mentions in the prose are historical and still correct.

The components/v3.16.1 and primitives/v3.16.1 tags are deleted separately. They
are not recreated here — the release script tags as part of the run, and the
tag belongs on this commit rather than the one it pointed at before.
chore: prepare 3.17.0 in place of 3.16.1
…vation

Closes #466, the deferred half of #453.

ValueFuncAsync is for text that has to be fetched or computed. Value still wins
when non-empty, then ValueFunc, then this.

It could not be built as an awaited ValueFunc, and that is the whole issue. A
clipboard write requires transient user activation, and awaiting spends it — so
resolving the text first and writing second gets the write refused, Safari most
strictly, while the component showed its copied state and the clipboard stayed
empty. The function is instead invoked from JavaScript inside a ClipboardItem,
handing the browser the promise rather than the result, so the activation
survives however long the callback takes. Where a browser cannot take a promise
there, the value is resolved first and the refusal is reported.

OnCopyFailed carries a CopyTextFailure of Refused or NoValue. Failure used to
be entirely invisible, which is what let this go unnoticed.

The execCommand fallback no longer runs for every failure. It ran whenever
writeText threw, so an expired activation fell through to a path that cannot
rescue one either and success was reported regardless. It now runs only for the
insecure-context case it was written for.

Verified in Chrome: a ValueFuncAsync taking a deliberate 1.5 seconds copies
successfully and OnCopied reports the value, where resolving first would have
been refused. The outcome contract was checked directly — empty string,
non-string and missing reference all return noValue.

NOT verified in Safari or Firefox. Activation semantics differ per engine and
Safari is the strictest, which is the browser this exists for. It needs a manual
pass there before anyone treats it as proven.

API surface is additive — ValueFuncAsync, OnCopyFailed and the CopyTextFailure
enum, nothing removed.
…the write

Follows up the first pass on #466. Safari refused both earlier approaches; this
is what actually works, verified there.

A clipboard write needs transient user activation. Resolving the text and then
writing spends it on the await, so the write is refused — the original bug.
Handing the promise to ClipboardItem is the documented answer and fixed Chrome,
but Safari still refused, and so did a resolve-then-write fallback.

Both attempts missed that Safari objects to WHEN the write is made, not what is
in it. A Blazor click travels C# -> SignalR -> JS, so by the time the write
happens the gesture window has closed. A literal Value copies fine there only
because that hop is fast enough to slip through.

initializeCopy attaches click and keydown listeners to the element and calls
clipboard.write() immediately, inside the real gesture, asking .NET for the text
from inside the ClipboardItem so the callback can take as long as it likes.

The Blazor handlers stand down while JS is in charge and take over again if the
module fails to load or during prerendering, so the component still copies
either way. Enter and Space are wired in JS too, since a span with role=button
gets no native click from them.

Verified in Chrome and Safari: the deliberately slow 1.5s ValueFuncAsync copies
and OnCopied reports the value. The plain literal-value copy was re-checked in
both, because the click path changed for every usage rather than just the async
one.
…-clipboard

feat(copytext): asynchronous value source that survives the user activation
@mathewtaylor
mathewtaylor merged commit faadfb1 into v4 Sep 13, 2026
@mathewtaylor
mathewtaylor deleted the chore/align-v4-with-develop-2 branch September 13, 2026 04:37
pull Bot pushed a commit to russkyc-forked-repos/blazorblueprintui that referenced this pull request Sep 19, 2026
…/align-v4-with-develop-2

chore: bring v4 up to date with develop (second pass)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants