Skip to content

fix(layer-dialog): hide empty native scrollbar tracks - #897

Merged
nandanmen merged 3 commits into
cloudflare:mainfrom
khoinguyenpham04:noah/layer-dialog-scrollbar-bug-723260
Oct 27, 2026
Merged

nandanmen merged 3 commits into
cloudflare:mainfrom
khoinguyenpham04:noah/layer-dialog-scrollbar-bug-723260

Conversation

@khoinguyenpham04

@khoinguyenpham04 khoinguyenpham04 commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

On kumo-ui.com, the LayerDialog body shows empty grey scrollbar tracks along its right and bottom edges when scrollbars are set to always show (macOS "Show scroll bars: Always" or with a mouse attached, Windows, Linux). Sidebar.Content has the same problem.

Before and after

Both shots use the same steps in Chrome with always-visible scrollbars: open the "Choose a Worker" demo, leave the page through the sidebar, come back, and open it again.

Before (kumo-ui.com) After (this branch)
Before: the Choose a Worker dialog with empty grey scrollbar tracks along the right and bottom of its body After: the same dialog with no scrollbar tracks

Cause

Base UI's ScrollArea.Viewport sets overflow: scroll and hides the native scrollbars only through a <style> that React hoists into <head> once per document. The docs site's Astro <ClientRouter /> removes every <head> style the incoming page doesn't ship, and React never re-inserts a hoisted style it has already inserted. So after any soft navigation the rule is gone and the native tracks appear. A hard refresh hides them until the next navigation.

Outside the docs site, any app that swaps <head> or blocks inline styles with a CSP would hit the same thing. In Kumo, only LayerDialog and Sidebar depend on that style. Base UI also uses it for Select's scroll arrows, which Kumo doesn't render.

Changes

  • LayerDialog.Body and Sidebar.Content viewports also get Kumo's existing no-scrollbar utility, so they no longer depend on Base UI's injected style.
  • Regression tests for both components and a patch changeset.

The docs site is unchanged on purpose. With this fix nothing there needs Base UI's style anymore, and leaving the site as-is means it would still surface the problem if another component ever depends on that style.

Testing

  • Browser check with the steps above. Before: the soft navigation removes Base UI's style from <head>, and the native scrollbars take 15px on each axis. After: the style is still removed, but the scrollbars take 0px.
  • Full kumo unit suite: 1507/1507 pass, including the 2 new tests.
  • tsc --noEmit (kumo): 0 errors. vp lint and vp fmt --check on the changed files: clean.

  • Reviews
    • bonk has reviewed the change
    • automated review not possible because: this PR is opened from a fork, and the bonk review workflow only runs on same-repo PRs
  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:

Base UI's ScrollArea viewport sets `overflow: scroll` and hides the
native scrollbars only with a <style> that React hoists into <head>
once per document. Astro's ClientRouter removes that style on every
soft navigation and React never re-inserts it, so the docs site showed
empty scrollbar tracks along the LayerDialog body wherever scrollbars
are always visible.

- Give the LayerDialog body and Sidebar content viewports Kumo's own
  `no-scrollbar` rule so they no longer depend on the injected style.
- Keep React-hoisted styles across ClientRouter swaps on the docs site.
@clanky-the-clanker

Copy link
Copy Markdown

This pull request was not reviewed automatically because its author does not have write access to this repository. A maintainer with write access can start a review by commenting clanky review (or clanker review or @clanky-the-clanker review), optionally followed by instructions (e.g. clanky review focus on the retry logic).

@pkg-pr-new

pkg-pr-new Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
npm i https://pkg.pr.new/@cloudflare/kumo@897

commit: 98afe05

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Docs Preview

View docs preview

Commit: 98afe05

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Visual contracts

Linux Chromium references exercised by the PR's visual-contracts job.

1 curated contract

truncating text trigger

truncating text trigger

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

📐 Bundle Size

Consumer fixtures bundled against packages/kumo/dist (peers external, minified ESM).

Fixture Raw Gzip Brotli
Button (root) 166.6 KB 50.9 KB 44.3 KB
Button (components/button) 166.5 KB 50.9 KB 44.2 KB
Button + Dialog + Select (root) 293.4 KB 87.5 KB 73.6 KB
Button + Dialog + Select (component subpaths) 293.5 KB 87.6 KB 73.6 KB
Chart (root) 238.5 KB 71.9 KB 61.9 KB
Chart (components/chart) 238.5 KB 71.9 KB 61.9 KB
Badge (components/badge) 36.5 KB 12.7 KB 11.1 KB
Flow (components/flow) 200.7 KB 59.2 KB 51.8 KB
Button (primitives/button) 12.4 KB 4.5 KB 4.0 KB
Primitives barrel 718.4 KB 198.5 KB 154.5 KB
Code highlighting (code) 2.07 MB 469.2 KB 350.6 KB

npm tarball: 564 files, 1.56 MB packed, 7.30 MB unpacked.

⚠️ 24 flagged files in tarball (tests / raw scripts)
  • dist/blocks-source/delete-resource/delete-resource.test.tsx
  • dist/blocks-source/resource-list/resource-list.test.tsx
  • scripts/component-registry/cache.ts
  • scripts/component-registry/discovery.ts
  • scripts/component-registry/example-cleanup.ts
  • scripts/component-registry/index.test.ts
  • scripts/component-registry/index.ts
  • scripts/component-registry/markdown-generator.ts
  • scripts/component-registry/metadata.ts
  • scripts/component-registry/props-filter.ts
  • scripts/component-registry/schema-generator.ts
  • scripts/component-registry/sub-components.ts
  • scripts/component-registry/types.ts
  • scripts/component-registry/utils.ts
  • scripts/component-registry/variant-parser.ts
  • scripts/css-build.ts
  • scripts/generate-globe-land-mask.mjs
  • scripts/generate-primitives.ts
  • scripts/theme-generator/config.ts
  • scripts/theme-generator/generate-css.test.ts
  • scripts/theme-generator/generate-css.ts
  • scripts/theme-generator/index.ts
  • scripts/theme-generator/migrate.ts
  • scripts/theme-generator/types.ts

Report-only: no size thresholds are enforced yet.

Commit: 98afe057

@khoinguyenpham04

Copy link
Copy Markdown
Contributor Author

clanky review

With LayerDialog and Sidebar hiding native scrollbars through Kumo's own
CSS, nothing on the docs site needs Base UI's injected style anymore.
The workaround leaned on undocumented Astro head-swap behavior, and
leaving the site as-is keeps it exposing the problem if another
component starts depending on that style.
@nandanmen
nandanmen merged commit 3aa0d59 into cloudflare:main Oct 27, 2026
16 checks passed
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