이 가로 메뉴는,무엇이 보이는지 압니다

브라우저 자체 스크롤 위에 구축된 React 스크롤 메뉴 — 항목별 가시성 추적, 화살표, 드래그, 그리고 완전한 명령형 API. gzip 5.7 kB.

Sci-Fi
Comedy
Drama
Horror
Docs
Kids
Action
Indie
Anime
Classics
Thriller
Reality

getVisible() → ['scifi', 'comedy', 'drama', 'horror', 'docs', 'kids']

This is the library, live — drag it. Dimmed tiles are the ones useIsVisible reports as off-screen.

npm install react-horizontal-scrolling-menu347k 다운로드/월5.7 kB min+gzipReact 16.8 – 19MIT

캐러셀 엔진 없이 자동 재생

autoplay 프로퍼티는 없습니다. 이 레일은 공개 API 위의 레시피입니다. 행을 양 끝으로 복제하고, 이음새에서 scrollLeft를 한 번 점프시키고, scrollNext()를 호출하는 타이머를 돌립니다. 호버, 포커스, 숨은 탭에서 일시정지하고, 동작 줄이기 설정에서는 가만히 있으며 — 이음새를 넘어 거꾸로라도 드래그할 수 있습니다.

Tokyo
Oslo
Lima
Cairo
Sydney
Quito
Seoul
Porto
Denver
Hanoi

캐러셀이 아니라 메뉴

Embla, Swiper, keen-slider는 이미지 슬라이더를 만들기 위해 JavaScript로 스크롤을 다시 구현합니다 — 스냅 포인트, 스프링 물리, 렌더 루프. 이 라이브러리는 그중 어느 것도 제공하지 않습니다. 브라우저 네이티브 스크롤을 타고, 브라우저가 주지 않는 한 가지 — 어떤 항목이 화면에 있는지 정확히 아는 것을 더합니다.

전체 화면 이미지 슬라이더에는 잘못된 도구 — 거기서는 Embla나 Swiper를 쓰세요. 카테고리 행, 탭 스트립, 칩 필터, 그리고 앱이 파악해야 하는 모든 행에는 올바른 도구.

네이티브 스크롤

관성, 스크롤바, 터치, 휠, 접근성은 물리 엔진이 아니라 브라우저에서 나옵니다. JavaScript가 하이드레이트되기 전에 이 행은 스크롤됩니다 — 이 페이지의 모든 데모는 서버 렌더링됩니다.

가시성 추적

IntersectionObserver가 어떤 항목이 화면에 있는지 보고합니다. useIsVisible(itemId)는 컴포넌트 하나를 항목 하나에 구독시킵니다 — 스크롤 위치 계산도 없고, 영향받은 항목만 다시 렌더링됩니다.

필요할 때 명령형

scrollToItem, scrollNext, scrollPrev, id나 인덱스로 조회 — 메뉴 내부의 컨텍스트를 통해서, 또는 외부에서 apiRef로.

여러분의 컴포넌트, 여러분의 CSS

화살표, 헤더, 푸터, 그리고 모든 항목은 여러분이 작성하는 컴포넌트입니다. 항목 너비는 여러분의 CSS. 라이브러리는 210바이트의 레이아웃 스타일만 제공하고 비켜 서 있습니다.

빠른 시작

파일 하나, 설정 없음: itemId가 있는 항목, VisibilityContext를 읽는 두 개의 화살표, 그리고 스타일시트 임포트.

App.tsx
import React from 'react';
import {
  ScrollMenu,
  VisibilityContext,
  type publicApiType,
} from 'react-horizontal-scrolling-menu';
import 'react-horizontal-scrolling-menu/dist/styles.css';

const items = Array.from({ length: 10 }, (_, i) => `item-${i + 1}`);

export function App() {
  return (
    <ScrollMenu LeftArrow={LeftArrow} RightArrow={RightArrow}>
      {items.map((id) => (
        <Card itemId={id} key={id} title={id} />
      ))}
    </ScrollMenu>
  );
}

function LeftArrow() {
  const visibility = React.useContext<publicApiType>(VisibilityContext);
  const isFirstVisible = visibility.useIsVisible('first', true);
  return (
    <button
      disabled={isFirstVisible}
      onClick={() => visibility.scrollPrev()}
    >

    </button>
  );
}

function RightArrow() {
  const visibility = React.useContext<publicApiType>(VisibilityContext);
  const isLastVisible = visibility.useIsVisible('last', false);
  return (
    <button
      disabled={isLastVisible}
      onClick={() => visibility.scrollNext()}
    >

    </button>
  );
}

function Card({ itemId, title }: { itemId: string; title: string }) {
  const visibility = React.useContext<publicApiType>(VisibilityContext);
  const isVisible = visibility.useIsVisible(itemId);
  return (
    <div className="card" data-visible={isVisible}>
      <div>{title}</div>
      <div>visible: {String(isVisible)}</div>
    </div>
  );
}

The code on the left, running:

item-1
visible: true
item-2
visible: true
item-3
visible: true
item-4
visible: false
item-5
visible: false
item-6
visible: false
item-7
visible: false
item-8
visible: false
item-9
visible: false
item-10
visible: false

itemId는 모든 항목에 필수입니다 — 추적이 이렇게 동작합니다. React의 key는 폴백으로 동작합니다.

styles.css는 별도 임포트입니다. JS 번들이 CSS를 주입하는 일은 없습니다.

항목 너비는 여러분의 CSS에서 나옵니다 — 메뉴가 측정하는 것은 없습니다.

전체 시작하기 예제 읽기

또는 코딩 에이전트에게 맡기세요

구버전으로 학습한 모델은 visibleElements, Separator 항목, Arrows 프로퍼티 — 모두 수년 전에 제거됨 — 에 여전히 손을 뻗고, 존재한 적 없는 autoplay 프로퍼티를 만들어 냅니다. 이 패키지는 이를 막기 위한 8개의 SKILL.md 파일을 제공합니다. 에이전트가 TanStack Intent를 통해 온디맨드로 로드하는 작업 범위 가이드로, 이 페이지가 아니라 라이브러리와 함께 버전이 관리됩니다.

npx @tanstack/intent@latest install

패키지가 이미 설치된 프로젝트에서 한 번 실행하세요. 이후 에이전트는 node_modules/react-horizontal-scrolling-menu/skills/에서 스킬을 발견합니다.

  • menu-setup처음 동작하는 메뉴, 화살표, 필수 CSS 임포트
  • menu-visibility화면에 무엇이 있는지, 그리고 양 끝의 화살표 상태
  • menu-scrollingscrollToItem, apiRef, 한 번에 한 페이지씩 페이징
  • menu-interactions드래그, 휠, 터치 — 그리고 해당 핸들러 팩토리
  • menu-recipes자동 재생, 무한 루프, 더 불러오기: 프로퍼티가 아니라 레시피
  • menu-transitions-rtl애니메이션 타이밍, 커스텀 이징, 오른쪽에서 왼쪽
  • menu-testing-ssrNext.js와 RSC, Jest 목, Playwright
  • menu-migrationv8 이전 코드 업그레이드, 그리고 모델이 여전히 만들어 내는 API

상자 안에 있는 것

  • 항목별 가시성 훅 — useIsVisible(itemId)
  • 화살표 상태를 위한 first / last 헬퍼
  • scrollToItem · scrollNext · scrollPrev
  • 메뉴 외부에서 제어하는 apiRef
  • 드래그, 휠, 터치, 스크롤바 입력
  • 동적 추가/제거 감지
  • Header와 Footer 슬롯
  • slidingWindow + getItemsPos 페이징 헬퍼
  • 오른쪽에서 왼쪽 지원
  • 커스텀 전환 함수
  • SSR 안전 — 이 페이지가 증명
  • TypeScript 우선 — publicApiType 내보냄
  • React 16.8 – 19에서 하나의 안정적인 API

상자 안에 없는 것

  • 스냅과 스프링 물리
  • 전체 화면 이미지 슬라이더
  • 라이트박스

그것은 이미지 슬라이더의 영역입니다 — Embla와 Swiper가 잘 합니다. 무한 루프자동 재생도 프로퍼티가 아닙니다 — 레시피입니다. 각각 공개 API의 약 60줄이며, Storybook에서 라이브 편집할 수 있습니다. 이 페이지 위쪽의 레일은 바로 그 레시피가 돌고 있는 것입니다. 이것은 메뉴로 남습니다.

지난달 약 20,000개 리포지토리에서 347,516회 다운로드 — 2018년부터 유지보수.

GitHub 스타 788개React Status #257에서 소개Our World in Data에서 프로덕션 사용

모든 예제를 브라우저에서 편집 가능

Storybook은 플레이그라운드를 겸합니다. 각 스토리에는 라이브러리의 실제 타입 정의를 로드한 Monaco 에디터가 함께 제공됩니다. 코드를 바꾸고 다시 렌더링되는 것을 보세요 — 샌드박스 계정도, 로컬 설정도 없습니다.

Aleksandr Smyshliaev가 구축하고 유지

2018년 첫 공개, React 16.8부터 19까지 같은 공개 API. Aleksandr는 프런트엔드 엔지니어(React, Next.js, TypeScript)이며, 현재 계약 및 정규직 일에 열려 있습니다.