Coder Dad
Coder Dad

Reputation: 55

Add text inside slider thumb with shadcn Svelte

I am currently working on customizing a slider thumb for the shadcn svelte slider. I have tried adding a span within the SliderPrimitive.Thumb element, however, it seems like the span gets stripped before going live in the browser. I'm working with svelte, typescript, and tailwind css, and I'm fairly new to these languages and the shadcn svelte components. Any input and solutions are greatly appreciated!

<script lang="ts">
  import { Slider as SliderPrimitive } from "bits-ui";
  import { cn } from "$lib/utils.js";

  type $$Props = SliderPrimitive.Props;

  let className: $$Props["class"] = undefined;
  export let value: $$Props["value"] = [0];
  export { className as class };
</script>

<SliderPrimitive.Root
  bind:value
  class={cn("flex w-full touch-none select-none items-center", className)}
  {...$$restProps}
  let:thumbs
>
  <span
    class="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary"
  >
    <SliderPrimitive.Range class="absolute h-full bg-primary" />
  </span>
  {#each thumbs as thumb}
    <SliderPrimitive.Thumb
      {thumb}
      class="block h-8 w-24 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
    />
  {/each}
</SliderPrimitive.Root>

Without adding a span within the SliderPrimitive.Thumb, this span is visible within the web-dev tools, and if I add the text "Drag" within it, it works as expected:

<span role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" aria-orientation="horizontal" data-melt-part="thumb" data-value="0" tabindex="0" data-melt-slider-thumb="" data-slider-thumb="" class="block h-8 w-24 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" style="position: absolute; left: 0%; translate: -50%;"></span>

However, if I search for that span within my files, it doesn't appear, unless I'm being dumb and missing something. I tried adding a span within the SliderPrimitive.Thumb like this, and the span is nowhere to be found in the web-dev tools:

<SliderPrimitive.Root
  bind:value
  class={cn("flex w-full touch-none select-none items-center", className)}
  {...$$restProps}
  let:thumbs
>
  <span
    class="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary"
  >
    <SliderPrimitive.Range class="absolute h-full bg-primary" />
  </span>
  {#each thumbs as thumb}
    <SliderPrimitive.Thumb
      {thumb}
      class="block h-8 w-24 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
      ><span class="z-10 text-black">Drag</span></SliderPrimitive.Thumb
    >
  {/each}
</SliderPrimitive.Root>

Upvotes: 0

Views: 985

Answers (1)

philr
philr

Reputation: 1940

If the SliderPrimitive.Thumb component doesn't have a <slot /> then you can't pass it a child component. you'd be better off wrapping a div around the Thumb and text, and use styles to get it centered.

EDIT: just tested my code and it didn't work, here's an updated version using styles as well

{#each thumbs as thumb}
    <SliderPrimitive.Thumb
        {thumb}
        class="long-thumb-class"
    />
    <span
        style={`left: ${(value?.[0] / ($$restProps.max)) * 100}%`}
        class="absolute translate-y-[-50%] translate-x-[-50%] z-10 text-black"
        >Drag</span
    >
{/each}

Upvotes: 0

Related Questions