<script lang="ts">
import { ScrollArea } from "$lib/components/ui/scroll-area/index.js";
import { Separator } from "$lib/components/ui/separator/index.js";
const tags = Array.from({ length: 50 }).map(
(_, i, a) => `v1.2.0-beta.${a.length - i}`
);
</script>
<ScrollArea class="h-72 w-48 rounded-md border">
<div class="p-4">
<h4 class="mb-4 text-sm leading-none font-medium">Tags</h4>
{#each tags as tag (tag)}
<div class="text-sm">
{tag}
</div>
<Separator class="my-2" />
{/each}
</div>
</ScrollArea> Installation
pnpm dlx shadcn-svelte@latest add scroll-area Install bits-ui:
pnpm add bits-ui -D Copy and paste the following code into your project.
import Scrollbar from './scroll-area-scrollbar.svelte';
import Root from './scroll-area.svelte';
export {
Root,
Scrollbar,
//,
Root as ScrollArea,
Scrollbar as ScrollAreaScrollbar
};
<script lang="ts">
import { ScrollArea as ScrollAreaPrimitive } from 'bits-ui';
import { cn, type WithoutChild } from '$UTILS$.js';
let {
ref = $bindable(null),
class: className,
orientation = 'vertical',
children,
...restProps
}: WithoutChild<ScrollAreaPrimitive.ScrollbarProps> = $props();
</script>
<ScrollAreaPrimitive.Scrollbar
bind:ref
data-slot="scroll-area-scrollbar"
data-orientation={orientation}
{orientation}
class={cn(
'flex touch-none bg-[#09090b] p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-[#222225] data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-[#222225]',
className
)}
{...restProps}
>
{@render children?.()}
<ScrollAreaPrimitive.Thumb
data-slot="scroll-area-thumb"
class="relative flex-1 rounded-none bg-[#3f3f46] hover:bg-[#d0e891]"
/>
</ScrollAreaPrimitive.Scrollbar>
<script lang="ts">
import { ScrollArea as ScrollAreaPrimitive } from 'bits-ui';
import { Scrollbar } from './index.js';
import { cn, type WithoutChild } from '$UTILS$.js';
let {
ref = $bindable(null),
viewportRef = $bindable(null),
class: className,
orientation = 'vertical',
scrollbarXClasses = '',
scrollbarYClasses = '',
children,
...restProps
}: WithoutChild<ScrollAreaPrimitive.RootProps> & {
orientation?: 'vertical' | 'horizontal' | 'both' | undefined;
scrollbarXClasses?: string | undefined;
scrollbarYClasses?: string | undefined;
viewportRef?: HTMLElement | null;
} = $props();
</script>
<ScrollAreaPrimitive.Root
bind:ref
data-slot="scroll-area"
class={cn('relative [--scrollbar-track:#09090b]', className)}
{...restProps}
>
<ScrollAreaPrimitive.Viewport
bind:ref={viewportRef}
data-slot="scroll-area-viewport"
class="cn-scroll-area-viewport size-full rounded-[inherit] outline-none transition-[color,box-shadow] focus-visible:ring-2 focus-visible:ring-zinc-300/60 focus-visible:outline-1"
>
{@render children?.()}
</ScrollAreaPrimitive.Viewport>
{#if orientation === 'vertical' || orientation === 'both'}
<Scrollbar orientation="vertical" class={scrollbarYClasses} />
{/if}
{#if orientation === 'horizontal' || orientation === 'both'}
<Scrollbar orientation="horizontal" class={scrollbarXClasses} />
{/if}
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
Usage
<script lang="ts">
import { ScrollArea } from '$lib/components/ui/scroll-area/index.js';
</script> <ScrollArea class="h-[200px] w-[350px] rounded-md border p-4">
Jokester began sneaking into the castle in the middle of the night and leaving jokes all over the
place: under the king's pillow, in his soup, even in the royal toilet. The king was furious, but
he couldn't seem to stop Jokester. And then, one day, the people of the kingdom discovered that
the jokes left by Jokester were so funny that they couldn't help but laugh. And once they started
laughing, they couldn't stop.
</ScrollArea> Examples
Horizontal Scrolling
Set the orientation prop to "horizontal" to enable horizontal scrolling.
<script lang="ts">
import { ScrollArea } from "$lib/components/ui/scroll-area/index.js";
type Artwork = {
artist: string;
art: string;
};
const works: Artwork[] = [
{
artist: "Ornella Binni",
art: "https://images.unsplash.com/photo-1465869185982-5a1a7522cbcb?auto=format&fit=crop&w=300&q=80"
},
{
artist: "Tom Byrom",
art: "https://images.unsplash.com/photo-1548516173-3cabfa4607e9?auto=format&fit=crop&w=300&q=80"
},
{
artist: "Vladimir Malyavko",
art: "https://images.unsplash.com/photo-1494337480532-3725c85fd2ab?auto=format&fit=crop&w=300&q=80"
}
];
</script>
<ScrollArea
class="w-96 rounded-md border whitespace-nowrap"
orientation="horizontal"
>
<div class="flex w-max space-x-4 p-4">
{#each works as artwork (artwork.artist)}
<figure class="shrink-0">
<div class="overflow-hidden rounded-md">
<img
src={artwork.art}
alt="Photo by {artwork.artist}"
class="aspect-[3/4] h-fit w-fit object-cover"
width={300}
height={400}
/>
</div>
<figcaption class="text-muted-foreground pt-2 text-xs">
Photo by
<span class="text-foreground font-semibold">
{artwork.artist}
</span>
</figcaption>
</figure>
{/each}
</div>
</ScrollArea>