Migrate consumers to @workflowbuilder/ui (2/3: consumers) - #45
Open
librowski wants to merge 22 commits into
Open
Migrate consumers to @workflowbuilder/ui (2/3: consumers)#45librowski wants to merge 22 commits into
librowski wants to merge 22 commits into
Conversation
This was referenced Jun 24, 2026
librowski
marked this pull request as ready for review
June 24, 2026 12:31
librowski
requested review from
lukasz-jazwa,
piotrblaszczyk and
szymon-t-sc
as code owners
June 24, 2026 12:31
librowski
force-pushed
the
ui-consumers
branch
6 times, most recently
from
June 30, 2026 10:36
df8c61a to
35613b2
Compare
librowski
force-pushed
the
ui-consumers
branch
4 times, most recently
from
July 31, 2026 15:14
882caa7 to
fab9602
Compare
librowski
force-pushed
the
ui-consumers
branch
3 times, most recently
from
August 10, 2026 20:43
2d5d4a8 to
19ee1f1
Compare
The SDK bundles @workflowbuilder/ui and @base-ui/react into its dist, but
declared them as runtime dependencies - so a published @workflowbuilder/sdk
would 404 on @workflowbuilder/ui (not published) at npm install. Move both to
devDependencies (they are inlined, consumers don't install them).
Add @workflowbuilder/ui to the dts plugin's bundledPackages so its types are
inlined into dist/index.d.ts instead of leaking unresolvable
import('@workflowbuilder/ui') references into the public type surface. Verified:
no real ui/base-ui imports remain in dist/index.d.ts.
Remove the obsolete docs/overflow-ui.md (described the old external
@synergycodes/overflow-ui local-dev flow this migration replaces).
… branch point Rebasing onto current main pulled in commits landed after this branch diverged (WB-339's use-on-connect.tsx, PR #48's language-selector spec, PR #48's ai-studio undo-redo buttons) that still imported the retired @synergycodes/overflow-ui package. Point them at @workflowbuilder/ui like every other already-migrated call site, and regenerate the lockfile for the fully rebased dependency graph.
…undle @workflowbuilder/ui is bundled (not externalized) into the SDK, so @base-ui/react was being inlined transitively into dist/index.js even though the SDK never imports it directly. @phosphor-icons/react was already a direct SDK dependency but was likewise getting bundled a second time on top of the copy demo/ai-studio install directly. Add both to the SDK's Vite external list and move @base-ui/react from devDependencies to dependencies, mirroring the treatment already used for i18next/jsonforms/immer/zustand and matching how packages/ui declares them.
The datepicker z-index fix (index.css) and the variable-suggestions backdrop suppression (variable-text.module.css) both keyed off `.base-Modal-root` and `.mantine-Popover-dropdown`, class names from the retired MUI Base + Mantine modal/popover. Neither selector matched anything after the Base UI migration, silently reintroducing both bugs: a datepicker opened inside a modal rendered behind it, and the variable-suggestions backdrop no longer disappeared when a modal opened on top of it. ModalProvider now toggles a `wb-modal-open` class on <body> whenever the SDK's modal store has a modal open - a stable signal owned by the SDK rather than coupled to @workflowbuilder/ui's internal markup. Both selectors are repointed at it; the datepicker fix additionally keys off Base UI's own `[data-open]` popup attribute, since the DatePicker's popover class is a hashed CSS module class internal to @workflowbuilder/ui.
Update the move-ui-library-in-repo changeset: @base-ui/react is now a regular dependency of the SDK rather than an inlined implementation detail, and note explicitly that internal DOM structure and class names of the bundled UI changed (MUI Base + Mantine -> Base UI), so consumer styles or tests written against internal class names may need updating. Stays a minor bump.
Three SDK stylesheets open @layer ui.component without declaring the ui.base/ui.component order first. Module-graph order currently loads the declaration earlier by luck; an import reorder or dynamic import would register ui.component first and invert the cascade inside the ui layer - react-day-picker's raw defaults would then beat the calendar theming. Duplicate order statements are no-ops, so the prepends are free.
Removing the overflow-ui/MUI subtree left react-is resolvable only from stale transitive copies, and pnpm rewired recharts' react-is peer to 17.0.2 (supplied by a vitest transitive). react-is 17 does not know React 19 element symbols, so isFragment() is always false and fragment children inside charts would be silently dropped. Pinned in the catalog next to react/react-dom (must move in lockstep) and declared by ai-studio to steer the peer resolution.
ModalProvider mounted Dialog.Root conditionally: it appeared with open already true and unmounted on close, so Base UI's transition lifecycle (data-starting-style / data-ending-style) never ran in either direction - on every Base UI version. The root now stays mounted with open driving it, and the last modal content is retained through the exit transition because the store clears it on close.
The 1.4.1 pin guarded against a modal-fade regression attributed to Base UI 1.6; the fade was actually broken by the SDK's own conditional Dialog mounting (fixed in the previous commit) on every version. Caret range in the catalog restores dependency dedupe for npm consumers of the published packages; the workspace stays locked to an exact version via the lockfile.
dist/style.css carried every ui rule twice: once through the explicit @import of ui's index.css and once through the JS module graph (each bundled ui chunk carries a libInjectCss-injected CSS import). The JS graph vector stays - it also tree-shakes CSS of components the SDK does not use; the redundant @import goes. Verified by marker counts halving in the rebuilt bundle (typography 24 -> 12) and a visual pass on demo.
…x token paths The decision log's sections 3-4 describe the overflow-ui Vite alias and import layout as current; the banner now covers the swap to the in-repo library and corrects the disproven CSS-extraction claim. The token doc pointed readers into a node_modules symlink instead of packages/ui/dist.
A caret react next to catalog react-dom is the exact drift the catalog comment warns about - React 19 requires the pair to match (React error 527).
xyflow CSS arrived through two vectors (a bare css @import and a JS-side import in diagram.tsx), both unlayered. Once the ui library's port rules moved into @layer ui.component, unlayered xyflow beat them and node ports rendered as raw 6px dark dots. The stylesheet now joins the declared (and previously unused) ext-lib layer, which the ui layer outranks; the duplicate JS import goes away. Verified in demo: styled ports and the node-as-port connection target both render from the layered rules.
UI chunk CSS arrives through the JS module graph and can parse before index.css; its stamped statement then registered top-level ui first and the SDK's reset/ext-lib/ui declaration could only append, flipping the effective order to [ui, reset, ext-lib] - xyflow beat every component style. Now every stylesheet opens with the identical @layer ui.base, ui.component; statement, xyflow and the SDK resets join ui.base, and no second top-level layer exists to race against. Verified live in demo: only one order statement registers, xyflow's handle defaults sit in ui.base and lose to ui.component, and an unlayered :root override prepended before all component CSS still wins.
The always-mounted portal evaluated createPortal(..., document.body) on every render, so SSR of a closed editor threw ReferenceError.
DatePicker renders Popover.Trigger as the button itself, so the .date-picker > div > button override matched nothing and date/datetime fields lost their 2.5rem trigger height.
README and CHANGELOG promised a validated 1.4.x pin and blamed later versions for transition regressions; the regression was our conditional mounting, and the actual dependency is ^1.7.0. Changeset records the dependency-contract change.
README advertised a scroll-thumb-hover token that does not exist and claimed the html/body/root 100vh sizing ships in the package. The token guide only described monorepo paths and suggested editing generated dist CSS. Both now describe what actually ships and how an npm consumer overrides tokens.
librowski
force-pushed
the
ui-consumers
branch
from
August 11, 2026 10:48
19ee1f1 to
46e0305
Compare
piotrblaszczyk
approved these changes
Aug 12, 2026
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.
Part 2 of 3 of the
@workflowbuilder/uiseries (#44 packages → this PR consumers → #46 docs).Summary
Switches every consumer -
packages/sdk,apps/demo,apps/ai-studio- from the published@synergycodes/overflow-ui@1.0.0-beta.27to the in-repo@workflowbuilder/ui, and removes the overflow-ui dependency tree (~700 lockfile lines). Also bumps@base-ui/reactto the 1.7 line (see history below - the 1.4.1 pin's rationale turned out to be a bug on our side).How to review
packages/sdk/package.json,vite.config.mts):@workflowbuilder/uiis aworkspace:*devDependency, bundled into dist (not external), listed in dtsbundledPackages- a published SDK has zero runtime references to the unpublished package (the historical publish-404 trap is closed; verified against built artifacts).packages/sdk/src/index.css): ui styles arrive through the JS module graph only (the explicit@importof ui's index.css double-bundled ~91 KB and is gone); xyflow's stylesheet now joins the declaredext-liblayer (@import ... layer(ext-lib)) and its duplicate JS-side import is removed - this fixes node ports collapsing to raw 6px xyflow defaults once ui port rules became layered. Three SDK module stylesheets that open@layer ui.componentnow declare the layer order first.packages/sdk/src/features/modals/providers/modal-provider.tsx):Dialog.Rootstays mounted andopendrives it; previously the conditional mount skipped Base UI's enter/exit lifecycle entirely - on every Base UI version. This disproved the "1.6 broke the modal backdrop fade" note that justified the old exact1.4.1pin, so the catalog now holds^1.7.0(workspace stays locked via lockfile).react-ispinned in the catalog next to react (recharts' peer resolution drifted to a React-17-era copy after the MUI subtree vanished -isFragment()silently false under React 19); appreactdeps resolve from the catalog (React 19 requires the react/react-dom pair to match).packages/ui/dist/tokens.cssinstead of a node_modules symlink; root CLAUDE.md notes that app builds consume the prebuilt ui dist (Turborepo adoption tracked separately).Review history
Three-reviewer adversarial pass (SDK migration / apps + tooling / cross-branch stack coherence) after the external #44 review; all findings above landed as individual commits. Import swap verified complete (zero
overflow-uireferences outside changelogs); all 34 ui symbols the SDK imports exist;Select.onChangeandDatePicker.valueFormatsignature changes verified compatible.2026-08-11 - OpenCode (GPT-5.6) adversarial round. 8 findings, all verified on code; the two CRITICALs are fixed here:
uilayer beforeindex.css'sreset, ext-lib, uideclaration, flipping the effective order so xyflow beat every component style. There is now a single top-level layer: xyflow and the SDK resets joinui.base, andindex.cssopens with the same@layer ui.base, ui.component;statement every UI stylesheet carries - load order can no longer invert the cascade. Verified live in demo (one order statement registers; an unlayered:rootoverride prepended before all component CSS still wins).createPortal(..., document.body)during render, so SSR of a closed editor threwReferenceError- the portal now mounts after hydration..date-picker > div > buttonoverride (trigger height restored), the stale "pinned to 1.4.x" claims across README/CHANGELOG (actual dependency:^1.7.0, recorded in a ui changeset), the README's nonexistent scroll token and unshipped 100vh reset, an npm-consumer path in the token guide, and the missing@workflowbuilder/uiinstall step in the custom-node guide (on UI Library docs: page-per-component + source-generated tables (3/3) #46).Verification
build:lib- green after every rebase.minoron@workflowbuilder/sdk, covering the bundling swap, derived type shapes, DOM/class-name churn, and the restored modal fade.Notes