diff --git a/.changeset/twenty-zebras-kick.md b/.changeset/twenty-zebras-kick.md
new file mode 100644
index 000000000..3c7a62d07
--- /dev/null
+++ b/.changeset/twenty-zebras-kick.md
@@ -0,0 +1,5 @@
+---
+"bits-ui": patch
+---
+
+Improve runtime performance with optimized internal `mergeProps` and `boxWith` implementations, less reactive work in Select/Tooltip/Menu, and smarter body scroll locking when a dialog overlay handles pointer blocking.
diff --git a/eslint.config.js b/eslint.config.js
index b9e23c6ad..8e5d706bc 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -29,6 +29,7 @@ export default tseslint.config(
},
rules: {
"svelte/no-navigation-without-resolve": "off",
+ "svelte/no-unused-svelte-ignore": "off",
},
},
{
diff --git a/packages/bits-ui/src/lib/bits/accordion/accordion.svelte.ts b/packages/bits-ui/src/lib/bits/accordion/accordion.svelte.ts
index 04e03726a..feb79ddf2 100644
--- a/packages/bits-ui/src/lib/bits/accordion/accordion.svelte.ts
+++ b/packages/bits-ui/src/lib/bits/accordion/accordion.svelte.ts
@@ -1,11 +1,11 @@
import {
afterTick,
attachRef,
- boxWith,
type Box,
type ReadableBoxedValues,
type WritableBoxedValues,
} from "svelte-toolbelt";
+import { boxWith } from "$lib/internal/box.svelte.js";
import { Context, watch } from "runed";
import type {
BitsKeyboardEvent,
diff --git a/packages/bits-ui/src/lib/bits/accordion/components/accordion-content.svelte b/packages/bits-ui/src/lib/bits/accordion/components/accordion-content.svelte
index 5b72457d2..8ffcbd3e8 100644
--- a/packages/bits-ui/src/lib/bits/accordion/components/accordion-content.svelte
+++ b/packages/bits-ui/src/lib/bits/accordion/components/accordion-content.svelte
@@ -1,5 +1,6 @@
{#if contentState.shouldRender || forceMount}
@@ -83,14 +89,18 @@
>
{#if child}
{#if contentState.root.opts.open.current}
-
+
{/if}
{@render child({
props: mergeProps(mergedProps, focusScopeProps),
...contentState.snippetProps,
})}
{:else}
-
+
{@render children?.()}
diff --git a/packages/bits-ui/src/lib/bits/alert-dialog/components/alert-dialog.svelte b/packages/bits-ui/src/lib/bits/alert-dialog/components/alert-dialog.svelte
index e9fd9b480..8c213e244 100644
--- a/packages/bits-ui/src/lib/bits/alert-dialog/components/alert-dialog.svelte
+++ b/packages/bits-ui/src/lib/bits/alert-dialog/components/alert-dialog.svelte
@@ -1,5 +1,5 @@
{#if contentState.shouldRender || forceMount}
@@ -75,14 +80,18 @@
>
{#if child}
{#if contentState.root.opts.open.current}
-
+
{/if}
{@render child({
props: mergeProps(mergedProps, focusScopeProps),
...contentState.snippetProps,
})}
{:else}
-
+
{@render children?.()}
diff --git a/packages/bits-ui/src/lib/bits/dialog/components/dialog-description.svelte b/packages/bits-ui/src/lib/bits/dialog/components/dialog-description.svelte
index aa6898125..f09abf9e6 100644
--- a/packages/bits-ui/src/lib/bits/dialog/components/dialog-description.svelte
+++ b/packages/bits-ui/src/lib/bits/dialog/components/dialog-description.svelte
@@ -1,5 +1,6 @@
diff --git a/packages/bits-ui/src/lib/bits/utilities/escape-layer/escape-layer.svelte b/packages/bits-ui/src/lib/bits/utilities/escape-layer/escape-layer.svelte
index 0fe91e50a..6b0767ebb 100644
--- a/packages/bits-ui/src/lib/bits/utilities/escape-layer/escape-layer.svelte
+++ b/packages/bits-ui/src/lib/bits/utilities/escape-layer/escape-layer.svelte
@@ -1,5 +1,5 @@
diff --git a/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-anchor.svelte b/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-anchor.svelte
index bd1c2c90d..14d4c9851 100644
--- a/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-anchor.svelte
+++ b/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-anchor.svelte
@@ -1,5 +1,5 @@
diff --git a/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-arrow.svelte b/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-arrow.svelte
index 027636255..a04d89f2d 100644
--- a/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-arrow.svelte
+++ b/packages/bits-ui/src/lib/bits/utilities/floating-layer/components/floating-layer-arrow.svelte
@@ -1,5 +1,6 @@
diff --git a/packages/bits-ui/src/lib/bits/utilities/hidden-input.svelte b/packages/bits-ui/src/lib/bits/utilities/hidden-input.svelte
index 89504af55..a2bc99a94 100644
--- a/packages/bits-ui/src/lib/bits/utilities/hidden-input.svelte
+++ b/packages/bits-ui/src/lib/bits/utilities/hidden-input.svelte
@@ -1,5 +1,6 @@
diff --git a/packages/bits-ui/src/lib/bits/utilities/scroll-lock/scroll-lock.svelte b/packages/bits-ui/src/lib/bits/utilities/scroll-lock/scroll-lock.svelte
index 2fbdb4e4b..14363cc12 100644
--- a/packages/bits-ui/src/lib/bits/utilities/scroll-lock/scroll-lock.svelte
+++ b/packages/bits-ui/src/lib/bits/utilities/scroll-lock/scroll-lock.svelte
@@ -2,9 +2,18 @@
import type { ScrollLockProps } from "./index.js";
import { BodyScrollLock } from "$lib/internal/body-scroll-lock.svelte.js";
- let { preventScroll = true, restoreScrollDelay = null }: ScrollLockProps = $props();
+ type ScrollLockImplProps = ScrollLockProps & {
+ shouldBlockPointerEvents?: () => boolean;
+ };
+ let {
+ preventScroll = true,
+ restoreScrollDelay = null,
+ shouldBlockPointerEvents,
+ }: ScrollLockImplProps = $props();
+
+ // svelte-ignore state_referenced_locally
if (preventScroll) {
- new BodyScrollLock(preventScroll, () => restoreScrollDelay);
+ new BodyScrollLock(preventScroll, () => restoreScrollDelay, shouldBlockPointerEvents);
}
diff --git a/packages/bits-ui/src/lib/bits/utilities/text-selection-layer/text-selection-layer.svelte b/packages/bits-ui/src/lib/bits/utilities/text-selection-layer/text-selection-layer.svelte
index 4b85a14ce..f75d3adb7 100644
--- a/packages/bits-ui/src/lib/bits/utilities/text-selection-layer/text-selection-layer.svelte
+++ b/packages/bits-ui/src/lib/bits/utilities/text-selection-layer/text-selection-layer.svelte
@@ -1,5 +1,5 @@
diff --git a/packages/bits-ui/src/lib/bits/utilities/visually-hidden/visually-hidden.svelte b/packages/bits-ui/src/lib/bits/utilities/visually-hidden/visually-hidden.svelte
index 173d00189..6d43f6bc6 100644
--- a/packages/bits-ui/src/lib/bits/utilities/visually-hidden/visually-hidden.svelte
+++ b/packages/bits-ui/src/lib/bits/utilities/visually-hidden/visually-hidden.svelte
@@ -1,5 +1,5 @@