ScrollShadow

Apply visual shadows to indicate scrollable content overflow with automatic detection of scroll position.

Usage

<script setup lang="ts">
import { ScrollShadow } from '@hareui/vue'
</script>

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

<script setup lang="ts">import { ScrollShadow } from '@hareui/vue'</script><template>  <div class="w-full p-0 sm:max-w-sm">    <ScrollShadow class="max-h-[240px] p-4">      <div class="space-y-4">        <p v-for="idx in 10" :key="`scroll-shadow-lorem-content-${idx}`">          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non          risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.          Morbi accumsan cursus enim, sed ultricies sapien.        </p>      </div>    </ScrollShadow>  </div></template>

Examples

Orientation

Vertical

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Horizontal

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

<script setup lang="ts">import { Card, ScrollShadow } from '@hareui/vue'const images = [  'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/robot1.jpeg',  'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/avocado.jpeg',  'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/oranges.jpeg',]const getRandomImage = (idx: number) => images[idx % images.length]</script><template>  <div class="w-full sm:max-w-sm">    <div class="mb-8 w-full">      <h4 class="mb-2 text-sm font-semibold">        Vertical      </h4>      <Card class="w-full p-0">        <ScrollShadow class="max-h-[240px] p-4" orientation="vertical">          <div class="space-y-4">            <p v-for="idx in 10" :key="`scroll-shadow-lorem-content-${idx}`">              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non              risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.              Morbi accumsan cursus enim, sed ultricies sapien.            </p>          </div>        </ScrollShadow>      </Card>    </div>    <div class="w-full">      <h4 class="mb-2 text-sm font-semibold">        Horizontal      </h4>      <Card class="w-full p-0">        <ScrollShadow class="p-4" orientation="horizontal">          <div class="flex flex-row gap-4">            <Card              v-for="idx in 10"              :key="`scroll-shadow-lorem-cards-${idx}`"              class="flex min-w-[200px] flex-row gap-3 p-1"              :ui="{ content: 'justify-center' }"              variant="transparent"            >              <template #leading>                <img                  alt="Lorem Card"                  class="aspect-square h-16 w-16 shrink-0 rounded-xl object-cover select-none sm:h-20 sm:w-20"                  loading="lazy"                  :src="getRandomImage(idx - 1)"                >              </template>              <h3 class="text-sm leading-6 font-medium text-foreground">                Bridging the Future              </h3>              <p class="text-xs leading-5 text-muted">                Today, 6:30 PM              </p>            </Card>          </div>        </ScrollShadow>      </Card>    </div>  </div></template>

Shadow Size

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

<script setup lang="ts">import { ScrollShadow } from '@hareui/vue'</script><template>  <div class="w-full p-0 sm:max-w-sm">    <ScrollShadow class="max-h-[240px] p-4" :size="80">      <div class="space-y-4">        <p v-for="idx in 10" :key="`scroll-shadow-lorem-content-${idx}`">          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non          risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.          Morbi accumsan cursus enim, sed ultricies sapien.        </p>      </div>    </ScrollShadow>  </div></template>

With Card

Terms and Conditions

Please review before proceeding

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

<script setup lang="ts">import { Button, Card, ScrollShadow } from '@hareui/vue'</script><template>  <Card    class="max-w-[400px]"    description="Please review before proceeding"    title="Terms and Conditions"    :ui="{ content: 'p-0', footer: 'mt-4 flex flex-row gap-2' }"  >    <ScrollShadow class="h-[300px] px-4" :size="80">      <div class="space-y-4">        <p v-for="idx in 10" :key="`scroll-shadow-lorem-content-${idx}`">          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non          risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.          Morbi accumsan cursus enim, sed ultricies sapien.        </p>      </div>    </ScrollShadow>    <template #footer>      <Button class="w-full" variant="secondary">        Cancel      </Button>      <Button class="w-full">        Accept      </Button>    </template>  </Card></template>

Hide Scroll Bar

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

<script setup lang="ts">import { ScrollShadow } from '@hareui/vue'</script><template>  <div class="w-full p-0 sm:max-w-sm">    <ScrollShadow hide-scroll-bar class="max-h-[240px] p-4">      <div class="space-y-4">        <p v-for="idx in 10" :key="`scroll-shadow-lorem-content-${idx}`">          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non          risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.          Morbi accumsan cursus enim, sed ultricies sapien.        </p>      </div>    </ScrollShadow>  </div></template>

Visibility Change

Vertical Shadow State: none

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam. Morbi accumsan cursus enim, sed ultricies sapien.

Horizontal Shadow State: none

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

Lorem Card

Bridging the Future

Today, 6:30 PM

<script setup lang="ts">import type { ScrollShadowVisibility } from '@hareui/vue'import { Card, ScrollShadow } from '@hareui/vue'import { ref } from 'vue'const images = [  'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/robot1.jpeg',  'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/avocado.jpeg',  'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/oranges.jpeg',]const getRandomImage = (idx: number) => images[idx % images.length]const verticalState = ref<ScrollShadowVisibility>('none')const horizontalState = ref<ScrollShadowVisibility>('none')</script><template>  <div class="w-full sm:max-w-sm">    <div class="mb-8 flex flex-col gap-2">      <div class="rounded bg-default p-4">        <p class="text-sm font-semibold">          Vertical Shadow State: {{ verticalState }}        </p>      </div>      <div class="w-full">        <ScrollShadow class="max-h-[240px] p-4" orientation="vertical" @visibility-change="verticalState = $event">          <div class="space-y-4">            <p v-for="idx in 10" :key="`scroll-shadow-lorem-content-${idx}`">              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non              risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.              Morbi accumsan cursus enim, sed ultricies sapien.            </p>          </div>        </ScrollShadow>      </div>    </div>    <div class="flex flex-col gap-2">      <div class="rounded bg-default p-4">        <p class="text-sm font-semibold">          Horizontal Shadow State: {{ horizontalState }}        </p>      </div>      <div class="w-full">        <ScrollShadow class="p-4" orientation="horizontal" @visibility-change="horizontalState = $event">          <div class="flex flex-row gap-4">            <Card              v-for="idx in 10"              :key="`scroll-shadow-lorem-cards-${idx}`"              class="flex min-w-[200px] flex-row gap-3 p-1"              :ui="{ content: 'justify-center' }"              variant="transparent"            >              <template #leading>                <img                  alt="Lorem Card"                  class="aspect-square h-16 w-16 shrink-0 rounded-xl object-cover select-none sm:h-20 sm:w-20"                  loading="lazy"                  :src="getRandomImage(idx - 1)"                >              </template>              <h3 class="text-sm leading-6 font-medium text-foreground">                Bridging the Future              </h3>              <p class="text-xs leading-5 text-muted">                Today, 6:30 PM              </p>            </Card>          </div>        </ScrollShadow>      </div>    </div>  </div></template>

Customization

Tailwind CSS

Reviewed quarterly goals with the design team.

Shipped dark mode tokens to production.

Merged accessibility fixes for form fields.

Published updated component documentation.

Scheduled performance audit for next sprint.

Added scroll shadow demos to the docs site.

<script setup lang="ts">import { ScrollShadow } from '@hareui/vue'const entries = [  'Reviewed quarterly goals with the design team.',  'Shipped dark mode tokens to production.',  'Merged accessibility fixes for form fields.',  'Published updated component documentation.',  'Scheduled performance audit for next sprint.',  'Added scroll shadow demos to the docs site.',]</script><template>  <div class="w-full sm:max-w-sm">    <ScrollShadow      hide-scroll-bar      class="max-h-48 rounded-xl border border-border/80 bg-linear-to-b from-neutral-50/90 to-white p-4 ring-1 ring-black/5 dark:from-neutral-900/80 dark:to-neutral-900 dark:ring-white/10"      :size="48"      variant="fade"    >      <div class="space-y-3">        <p          v-for="entry in entries"          :key="entry"          class="text-sm leading-relaxed text-neutral-600 dark:text-neutral-400"        >          {{ entry }}        </p>      </div>    </ScrollShadow>  </div></template>

Global Configuration

To customize the ScrollShadow classes for the whole app, extend the scrollShadow theme in createHareUI:

app.use(createHareUI({
  ui: {
    scrollShadow: {
      slots: { base: 'rounded-xl border border-default-200' },
      variants: {
        orientation: {
          vertical: { base: 'pr-2' }, // Add padding for custom scrollbar styling
          horizontal: { base: 'pb-2' },
        },
      },
    },
  },
}))

Styling Reference

Slots

  • base → [data-slot="scroll-shadow"] – root container element

Variants

  • orientation="vertical" – vertical scrolling (default)
  • orientation="horizontal" – horizontal scrolling
  • hide-scroll-bar – hides the native scrollbar

The fade masks live in HareUI's stylesheet (styles/scroll-shadow.css) and key on [data-slot="scroll-shadow"] and [data-orientation], so they apply to any element carrying those attributes (Tabs' scrolling list uses the same component).

CSS Variables

The ScrollShadow component uses CSS variables to size the fade mask and reserve space for visible native scrollbars:

VariableDefaultDescription
--scroll-shadow-size40pxControls the fade gradient size. This is set from the size prop.
--scroll-shadow-offset0pxHow far the container must be scrolled before the fade starts. This is set from the offset prop.
--scroll-shadow-scrollbar-size10px (0px when hideScrollBar)Reserves a solid mask gutter for the native scrollbar so the fade does not cover it. Override for wider scrollbars.

Data Attributes

The component uses data attributes to control shadow visibility:

  • Scroll States: [data-top-scroll], [data-bottom-scroll], [data-left-scroll], [data-right-scroll] - Applied when content can be scrolled in that direction
  • Combined States: [data-top-bottom-scroll], [data-left-right-scroll] - Applied when content can be scrolled in both directions
  • Orientation: [data-orientation="vertical"] or [data-orientation="horizontal"] - Indicates scroll direction
  • Size: [data-scroll-shadow-size] - Contains the shadow gradient size value
  • Shadow Mode: [data-scroll-shadow-mode] - "auto" when the fade is derived from the scroll position, "manual" when visibility is controlled or enabled is false

Scroll-Driven Fade

In auto mode, browsers that support scroll-driven animations derive the fade from the scroll position in CSS. The mask is therefore correct on the very first paint, with no measurement and no flash of unfaded content during hydration. Browsers without support fall back to the [data-*-scroll] attributes above, which are written after mount. Two things to keep in mind when customizing:

  • In auto mode the root always resolves a mask-image, even when there is nothing to scroll. That makes it a stacking context and a containing block for position: fixed descendants. Set visibility explicitly if you need to opt out.
  • The scroll-driven fade uses the animation property on the root. Applying an animate-* utility to the same element replaces it and leaves no fade. Animate a wrapper instead.

API Reference

Props

PropTypeDefaultDescription
asAsTag | Component"div"The element or component to render the root as.
sizenumber40The shadow size in pixels.
offsetnumber0The scroll offset (px) before the shadow appears.
orientation"horizontal" | "vertical""vertical"The scroll orientation.
variant"fade""fade"The visual variant.
hideScrollBarbooleanfalseWhether to hide the scrollbar.
visibilityScrollShadowVisibility"auto"Which shadows to show. auto follows the scroll position; anything else forces the shadows (manual mode).
enabledbooleantrueWhether scroll detection is enabled (HeroUI's isEnabled).
uiComponentSlots<{ slots: { base: string; }; variants: { orientation: { vertical: { base: string; }; horizontal: { base: string; }; }; hideScrollBar: { false: { base: string; }; true: { base: string; }; }; variant: { fade: {}; }; }; defaultVariants: { orientation: string; hideScrollBar: boolean; variant: string; }; }>-Per-slot class overrides.

Slots

SlotPropsDescription
defaultanyThe scrollable content.

Emits

EventPayloadDescription
visibilityChange[visibility: ScrollShadowVisibility]-

On this page

No Headings