VibeCoderzVibeCoderz
Telegram
All Prompts
Scrollable Filter Chip Bar with Controls preview
menufilterinteractivescrollablechipstailwindjavascript

Scrollable Filter Chip Bar with Controls

Интерактивная горизонтальная прокрутка чипов с фильтрацией и сортировкой. Кнопки навигации, плавная прокрутка. Для галерей, поиска.

Prompt

<div
  class="ring-inset xl:pt-3 xl:pb-3 xl:pl-3 xl:pr-3 [animation:fadeSlideIn_0.8s_ease-out_0.1s_both] animate-on-scroll bg-neutral-950/60 rounded-2xl ring-neutral-800 ring-1 pt-3 pr-3 pb-3 pl-3 max-w-6xl">
  <div class="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
    <!-- Left: Filter pill (h-10) -->
    <div class="flex items-center gap-3">
      <button class="inline-flex flex-none items-center whitespace-nowrap gap-2 h-10 px-3 text-sm font-medium font-geist text-neutral-200 bg-neutral-900 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5">
                    <line x1="21" y1="4" x2="14" y2="4" class=""></line>
                    <line x1="10" y1="4" x2="3" y2="4" class=""></line>
                    <line x1="21" y1="12" x2="12" y2="12" class=""></line>
                    <line x1="8" y1="12" x2="3" y2="12" class=""></line>
                    <line x1="21" y1="20" x2="16" y2="20" class=""></line>
                    <line x1="12" y1="20" x2="3" y2="20" class=""></line>
                    <circle cx="12" cy="4" r="2" class=""></circle>
                    <circle cx="8" cy="12" r="2" class=""></circle>
                    <circle cx="16" cy="20" r="2" class=""></circle>
                  </svg>
                  Filter
                </button>
    </div>

    <!-- Center: Chip scroller with same control height -->
    <div class="flex items-center justify-between gap-2 min-w-0">
      <!-- Prev -->
      <button id="btn-left" class="flex-none inline-flex items-center justify-center w-10 h-10 rounded-lg bg-neutral-900 text-neutral-300 ring-1 ring-inset ring-neutral-800 hover:text-white hover:ring-neutral-700 transition disabled:opacity-50 disabled:cursor-not-allowed" disabled="">
                  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-[16px] h-[16px]">
                    <path d="m15 18-6-6 6-6" class=""></path>
                  </svg>
                </button>

      <!-- Chips -->
      <div id="menu-track" class="flex overflow-x-auto scrollbar-none min-w-0 pr-2 pl-2 gap-x-2 gap-y-2"
        style="scrollbar-width:none; mask-image: linear-gradient(to right, transparent, black 15%, black 85%, transparent); -webkit-mask-image: linear-gradient(to right, transparent, black 15%, black 85%, transparent); scroll-behavior: smooth;">
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900 text-white ring-1 ring-inset ring-neutral-700 rounded-xl transition">
                    All Photos
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Nature
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Business
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Technology
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Portrait
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Architecture
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Food
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Travel
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Animals
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Abstract
                  </button>
        <button class="chip inline-flex flex-none items-center whitespace-nowrap h-10 px-3 text-sm font-medium font-geist bg-neutral-900/50 text-neutral-300 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                    Lifestyle
                  </button>
      </div>

      <!-- Next -->
      <button id="btn-right" class="flex-none inline-flex items-center justify-center w-10 h-10 rounded-lg bg-neutral-900 text-neutral-300 ring-1 ring-inset ring-neutral-800 hover:text-white hover:ring-neutral-700 transition disabled:opacity-50 disabled:cursor-not-allowed">
                  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-[16px] h-[16px]">
                    <path d="m9 18 6-6-6-6" class=""></path>
                  </svg>
                </button>
    </div>

    <!-- Right: Sort (same h-10) -->
    <div class="flex items-center gap-3">
      <button class="inline-flex flex-none items-center whitespace-nowrap gap-2 h-10 px-3 text-sm font-medium font-geist text-neutral-200 bg-neutral-900 ring-1 ring-inset ring-neutral-800 rounded-xl hover:text-white hover:ring-neutral-700 transition">
                  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5">
                    <path d="m6 8 6 6 6-6" class=""></path>
                  </svg>
                  Recommended
                </button>
    </div>
  </div>

  <script>
    (function() {
                const btnLeft = document.getElementById('btn-left');
                const btnRight = document.getElementById('btn-right');
                const menuTrack = document.getElementById('menu-track');
                const scrollAmount = 250;

                function updateButtons() {
                  const atStart = menuTrack.scrollLeft <= 0;
                  const atEnd = menuTrack.scrollLeft + menuTrack.clientWidth >= menuTrack.scrollWidth - 1;

                  btnLeft.disabled = atStart;
                  btnRight.disabled = atEnd;
                }

                btnLeft.addEventListener('click', function() {
                  menuTrack.scrollLeft -= scrollAmount;
                  setTimeout(updateButtons, 300);
                });

                btnRight.addEventListener('click', function() {
                  menuTrack.scrollLeft += scrollAmount;
                  setTimeout(updateButtons, 300);
                });

                menuTrack.addEventListener('scroll', updateButtons);

                updateButtons();
              })();
  </script>
</div>
All Prompts