Skip to main content

General

Scroll To Top code

Copy the implementation or inspect every file that belongs to this component unit.

resources/views/components/ui/scroll-to-top.blade.php

@props([
    'label' => 'Back to top',
    'threshold' => 400,
    'smooth' => true,
    'alwaysVisible' => false,
])

@php
    /*
    | Fixed top-right scroll-to-top button. Appears after scrolling past the
    | threshold and smoothly returns the viewport to the top on click.
    |
    | Usage:
    |   <x-ui.scroll-to-top />
    |   <x-ui.scroll-to-top :threshold="200" class="top-8 right-8" />
    */
@endphp

<div
    x-data="{
        visible: @js((bool) $alwaysVisible),
        threshold: @js((int) $threshold),
        smooth: @js((bool) $smooth),
        checkScroll() {
            if (@js((bool) $alwaysVisible)) {
                return;
            }

            this.visible = window.scrollY > this.threshold;
        },
        scrollToTop() {
            window.scrollTo({ top: 0, behavior: this.smooth ? 'smooth' : 'instant' });
        },
    }"
    x-init="checkScroll()"
    @scroll.window.passive="checkScroll()"
    x-show="visible"
    x-cloak
    x-transition:enter="transition ease-out duration-150"
    x-transition:enter-start="-translate-y-2 opacity-0"
    x-transition:enter-end="translate-y-0 opacity-100"
    x-transition:leave="transition ease-in duration-100"
    x-transition:leave-start="translate-y-0 opacity-100"
    x-transition:leave-end="-translate-y-2 opacity-0"
    {{ $attributes->class(['fixed top-6 right-6 z-50']) }}
>
    <button
        type="button"
        @click="scrollToTop()"
        aria-label="{{ $label }}"
        class="inline-flex h-12 w-12 items-center justify-center rounded-full border border-gray-200 bg-white text-gray-700 shadow-lg transition hover:scale-105 focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:ring-offset-gray-950"
    >
        <x-ui.icon name="arrow-up" weight="duotone" size="lg" />
    </button>
</div>