diff --git a/.changeset/fresh-gifts-bathe.md b/.changeset/fresh-gifts-bathe.md new file mode 100644 index 000000000..4549162d5 --- /dev/null +++ b/.changeset/fresh-gifts-bathe.md @@ -0,0 +1,5 @@ +--- +"bits-ui": patch +--- + +fix(Slider): update tick position calculation for consistent scaling diff --git a/docs/content/components/slider.md b/docs/content/components/slider.md index f4f0d7558..8a3e1ba12 100644 --- a/docs/content/components/slider.md +++ b/docs/content/components/slider.md @@ -4,7 +4,7 @@ description: Allows users to select a value from a continuous range by sliding a --- @@ -151,11 +151,11 @@ If the `value` prop has more than one value, the slider will render multiple thu {#snippet children({ ticks, thumbs })} - {#each thumbs as index} + {#each thumbs as index (index)} {/each} - {#each ticks as index} + {#each ticks as index (index)} {/each} {/snippet} @@ -164,6 +164,14 @@ If the `value` prop has more than one value, the slider will render multiple thu To determine the number of ticks that will be rendered, you can simply divide the `max` value by the `step` value. + + +{#snippet preview()} + +{/snippet} + + + ## Single Type Set the `type` prop to `"single"` to allow only one accordion item to be open at a time. diff --git a/docs/src/lib/components/demos/index.ts b/docs/src/lib/components/demos/index.ts index e41a189c1..81ca30452 100644 --- a/docs/src/lib/components/demos/index.ts +++ b/docs/src/lib/components/demos/index.ts @@ -57,6 +57,7 @@ export { default as ScrollAreaDemoCustom } from "./scroll-area-demo-custom.svelt export { default as SeparatorDemo } from "./separator-demo.svelte"; export { default as SliderDemo } from "./slider-demo.svelte"; export { default as SliderDemoMultiple } from "./slider-demo-multiple.svelte"; +export { default as SliderDemoTicks } from "./slider-demo-ticks.svelte"; export { default as SwitchDemo } from "./switch-demo.svelte"; export { default as SwitchDemoCustom } from "./switch-demo-custom.svelte"; export { default as TabsDemo } from "./tabs-demo.svelte"; diff --git a/docs/src/lib/components/demos/slider-demo-ticks.svelte b/docs/src/lib/components/demos/slider-demo-ticks.svelte new file mode 100644 index 000000000..2423f6e55 --- /dev/null +++ b/docs/src/lib/components/demos/slider-demo-ticks.svelte @@ -0,0 +1,36 @@ + + +
+ + {#snippet children({ ticks, thumbs })} + + + + {#each thumbs as thumb} + + {/each} + {#each ticks as tick} + + {/each} + {/snippet} + +
diff --git a/packages/bits-ui/src/lib/bits/slider/slider.svelte.ts b/packages/bits-ui/src/lib/bits/slider/slider.svelte.ts index 0623f5458..0bb5c5609 100644 --- a/packages/bits-ui/src/lib/bits/slider/slider.svelte.ts +++ b/packages/bits-ui/src/lib/bits/slider/slider.svelte.ts @@ -305,12 +305,9 @@ class SliderSingleRootState extends SliderBaseRootState { const currValue = this.opts.value.current; return Array.from({ length: count }, (_, i) => { - const tickPosition = i * (step / difference) * 100; + const tickPosition = i * step; - const scale = linearScale( - [this.opts.min.current, this.opts.max.current], - this.getThumbScale() - ); + const scale = linearScale([0, (count - 1) * step], this.getThumbScale()); const isFirst = i === 0; const isLast = i === count - 1; @@ -623,12 +620,15 @@ class SliderMultiRootState extends SliderBaseRootState { const currValue = this.opts.value.current; return Array.from({ length: count }, (_, i) => { - const tickPosition = i * (step / difference) * 100; + const tickPosition = i * step; + + const scale = linearScale([0, (count - 1) * step], this.getThumbScale()); const isFirst = i === 0; const isLast = i === count - 1; const offsetPercentage = isFirst ? 0 : isLast ? -100 : -50; - const style = getTickStyles(this.direction, tickPosition, offsetPercentage); + + const style = getTickStyles(this.direction, scale(tickPosition), offsetPercentage); const tickValue = min + i * step; const bounded = currValue.length === 1