Tiro
Tiro Design
Components

ScrollArea

스크롤 가능한 영역의 인디케이터 패턴과 스크롤바 스타일 규칙.

Platform: Web · Desktop only (React Native는 native ScrollView 사용).

스크롤 영역은 단순히 overflow를 자르는 것 이상입니다. 사용자가 더 많은 내용이 있음을 인지하게 하는 방법을 맥락에 따라 선택해야 합니다.

Mobile

ScrollArea 컴포넌트는 모바일에 사용하지 않는다. RN의 native ScrollView / FlatList / SectionList를 직접 사용한다. 본 문서의 인디케이터 패턴(fade·gradient mask 등)은 web 전용 시각 장치이며, 모바일은 native 스크롤 동작 자체가 인디케이터 역할을 한다.

  • 컴포넌트 선택:
    • 짧은 정적 리스트: ScrollView
    • 동적/긴 리스트: FlatList (virtualization)
    • 섹션 그룹화: SectionList
    • 고성능 대량 리스트: FlashList (@shopify/flash-list)
  • scrollbar 표시: 기본 native 인디케이터 사용. showsVerticalScrollIndicator={true} 기본값 유지. 커스텀 scrollbar 그리지 말 것
  • bouncing: iOS의 over-scroll bounce는 사용자가 끝에 도달했음을 알리는 신호 — 비활성화하지 말 것 (bounces={true} 기본 유지)
  • momentum scroll: native 기본값 유지. JS로 가속도 조작하지 말 것
  • fade indicator: 콘텐츠가 잘리는 가장자리에 fade mask가 필요하면 react-native-linear-gradient로 상/하단 mask layer 별도 배치
  • Pull-to-refresh: 리스트 상단 새로고침은 RefreshControl 사용. 색상은 brown-800 (tintColor)
  • BottomSheet 내부 스크롤: TrueSheet의 scrollable prop을 사용하면 시트 자체가 스크롤 가능. 추가 ScrollView 중첩 시 nestedScrollEnabled 주의 — Dialog Mobile 참조

스크롤 인디케이터 패턴

Tiro에서 사용하는 인디케이터는 두 가지입니다.

패턴언제
Scrollbar리스트, 패널처럼 사용자가 스크롤을 인지하고 직접 조작하는 영역
Scroll Fog더 있다는 힌트만 주면 되는 카드, 프리뷰, 드롭다운, 인라인 콘텐츠

1. Scrollbar

언제 사용

  • 노트 리스트, 트랜스크립트 뷰어, 설정 패널 등 사용자가 직접 스크롤을 조작하는 주요 영역
  • 스크롤 가능 여부를 명확히 알려야 할 때
  • 콘텐츠가 많아 사용자가 스크롤을 예상하는 맥락

Token Mapping

TokenValue
track 너비8px (w-2)
thumb 시각 너비6px (p-[1px] 내부)
thumb 색상 (기본)stone-200
thumb 색상 (hover)stone-300
thumb radiusrounded-full
tracktransparent
auto-hide스크롤 멈춤 1500ms 후

플랫폼별 처리

환경동작
macOS스크롤 시에만 overlay 방식으로 나타남 — layout shift 없음
Windows항상 표시. scrollbar-gutter: stable 적용해 layout shift 방지

2. Scroll Fog

콘텐츠가 경계 너머로 이어짐을 그라디언트 페이드로 암시합니다. 스크롤바 없이 조용하게 "더 있음"을 전달합니다.

언제 사용

  • 카드 내부 미리보기, 인라인 콘텐츠처럼 암시만 필요할 때
  • 드롭다운, 셀렉트 목록처럼 스크롤바가 시각적으로 방해될 때
  • 사용자가 스크롤보다 클릭으로 상세 화면으로 이동하는 프리뷰 영역

표시 정책 — 항상 표시

Scroll Fog는 스크롤 위치와 무관하게 항상 표시합니다. 스크롤 상태에 따라 on/off하면 flicker가 발생하고 불필요한 복잡도가 생깁니다.

콘텐츠가 실제로 넘치지 않는 경우에도 fog를 표시해도 괜찮습니다. 그라디언트가 워낙 조용하기 때문에 사용자가 인지하지 못합니다.

크기 스펙

위치높이비고
Bottom80px기본. 콘텐츠가 많을수록 효과적
Top20px위로 스크롤됐을 때 적용
Left / Right20px수평 스크롤 시

최소 20px, 영역 전체 높이의 15–20%를 넘지 않는 범위에서 조정합니다.

배경색 매칭

Fog 색상은 컨테이너 배경색과 반드시 일치해야 합니다. 배경이 달라지면 fog도 바꿉니다.

배경Fog
whitefrom-white
stone-50 (#FAFAF9)from-[#FAFAF9]
stone-100 (#F5F5F4)from-[#F5F5F4]

방향 결정

상황적용
초기 상태 (아래에 더 있음)bottom fog
위로 스크롤된 상태top fog
중간 스크롤top + bottom 동시

패턴 선택 기준

스크롤 영역인가?

├─ 사용자가 직접 조작 (리스트, 패널, 트랜스크립트)?
│   └─ Scrollbar

└─ 힌트만 필요 (카드 프리뷰, 드롭다운, 인라인)?
    └─ Scroll Fog (스크롤바 숨김)

Usage

{/* Scrollbar — 리스트/패널 */}
<ScrollArea className="h-80">
  <NoteList />
</ScrollArea>

{/* Scroll Fog — 드롭다운 / 카드 프리뷰 */}
<div className="relative h-[180px] overflow-hidden rounded-lg">
  <div className="h-full overflow-y-auto [&::-webkit-scrollbar]:hidden">
    <OptionList />
  </div>
  {/* 항상 표시 — 스크롤 상태로 조건부 렌더링 하지 않음 */}
  <div className="pointer-events-none absolute bottom-0 inset-x-0 h-20 bg-gradient-to-t from-white to-transparent" />
</div>

Do / Don't

  • Do: Scroll Fog는 항상 표시 — 스크롤 위치에 따라 on/off 하지 않음
  • Do: Fog 색상을 컨테이너 배경색과 정확히 맞출 것
  • Do: Windows 환경에 scrollbar-gutter: stable 적용
  • Don't: Chevron(▼) 등 명시적 스크롤 인디케이터 추가 금지 — Scroll Fog로 충분
  • Don't: 같은 영역에 Scrollbar + Scroll Fog 동시 사용 금지
  • Don't: 페이지 전체 스크롤을 ScrollArea 내부로 중첩 금지
  • Don't: 스크롤이 불필요한 작은 영역에 남용 금지

On this page