본문으로 건너뛰기

TreeView

서로 속해 있는 항목들을 접었다 펼 수 있는 행으로 보여줍니다. 폴더 목록, 사이드바 내비게이션, 접어 둘 수 있어야 하는 그룹 목록에 씁니다.

tsx
import { TreeItem, TreeView } from 'neba';

<TreeView label="Project files" lines="folder" defaultExpanded={['src']}>
  <TreeItem value="src" label="src">
    <TreeItem value="index" label="index.ts" />
  </TreeItem>
  <TreeItem value="readme" label="README.md" />
</TreeView>;

Props

TreeView

Prop타입기본값설명
variant공통'solid' | 'outline' | 'text''outline'표면의 무게. 채움 / 하이라인 / 없음
size공통'xs' | 'sm' | 'md' | 'lg' | 'xl''md'행 높이, 타입 스케일, 시트의 반경, 그리고 한 단계 들여쓰는 폭
color공통'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'의미론적 색 역할. 임의 색상값은 받지 않습니다
density공통'default' | 'compact''default'행의 좌우 여백만 바꿉니다. 행 높이도 들여쓰기도 그대로입니다
elevation공통0 | 1 | 2 | 30그림자 깊이. 0은 그림자 없음
lines'none' | 'simple' | 'folder''simple'계층을 어떻게 그릴지. none은 들여쓰기만, simple은 레벨마다 세로선 하나, folder는 거기에 각 행으로 꺾여 들어가는 선까지, 마지막 자식의 세로선은 그 행에서 끊깁니다
expanded(string | number)[]열려 있는 가지들. onExpandedChange와 함께 쓰면 controlled가 됩니다
defaultExpanded(string | number)[]처음에 열려 있을 가지들
onExpandedChange(expanded: (string | number)[]) => void열림 상태가 바뀔 때
selected(string | number)[]선택된 행들. multiple이 꺼져 있어도 배열입니다. Accordion의 value와 같은 모양이라, multiple을 켜도 값의 타입은 바뀌지 않습니다
defaultSelected(string | number)[]처음에 선택되어 있을 행들
onSelectedChange(selected: (string | number)[]) => void선택이 바뀔 때
multiplebooleanfalse여러 행을 동시에 선택할 수 있는지. 켜면 aria-multiselectable도 함께 붙습니다
disabledbooleanfalse사용 불가. 모든 행이 반응하지 않습니다
labelstring트리가 읽히는 이름. tree에 aria-label로 붙습니다
childrenReactNode최상위 TreeItem들

expandedonExpandedChange로 열림 상태가 controlled가 되고, defaultExpanded로는 uncontrolled가 됩니다. 선택은 selectedonSelectedChange가 같은 방식으로 다루며, 두 값 모두 행의 value 배열입니다.

나머지 <ul> 속성은 그대로 트리에 전달됩니다. 공용 축은 prop 규약에 있습니다.

TreeItem

Prop타입기본값설명
valuestring | numberexpanded와 selected에서 이 행을 가리키는 식별자. 생략하면 하나가 생성되므로, 코드로 다룰 일이 없는 트리라면 없어도 됩니다
labelReactNode행의 텍스트. children이 아닌 별도 prop인 이유는, 트리에서 children은 그 아래 행들이기 때문입니다
startIconReactNode라벨 앞의 내용, 폴더 글리프, 파일 종류, 상태 점
endIconReactNode라벨 뒤의 내용, 개수, 배지
actionReactNode행 끝에 고정되는 컨트롤. 누를 수 있는 영역 바깥에 놓입니다. 열리기도 하고 메뉴 버튼도 가진 행은 누를 것이 두 개입니다
hrefstring행을 링크로 렌더링합니다. 트리가 내비게이션일 때
onClickMouseEventHandler<HTMLElement>행을 누를 때, 열리거나 선택되기 전에 호출됩니다. preventDefault를 부르면 둘 다 일어나지 않습니다
expandableboolean아직 children이 없는 행에도 펼침 화살표를 그립니다. 처음 열 때 가져오는 가지
disabledbooleanfalse사용 불가. 열려 있는 가지는 계속 동작합니다
childrenReactNode이 행 아래의 TreeItem들

나머지 <li> 속성은 그대로 행에 전달됩니다.

예시

lines

lines는 계층을 어떻게 그릴지 정합니다. none은 들여쓰기만 하고, simple은 레벨마다 세로선 하나를 내리며, folder는 거기에 각 행으로 꺾여 들어가는 선을 더하고 가지의 마지막 자식 아래에서 세로선을 끊습니다.

variant

sheet는 색으로 채워지지 않습니다. 이미 표면이 있는 Card나 사이드바 안에서는 text를 쓰세요.

행 선택

행을 누르면 선택되고, 자식이 있으면 함께 열립니다. multiple을 켜면 여러 행을 동시에 선택할 수 있고, 끄면 새 행을 고를 때마다 앞의 선택이 교체됩니다.

펼침 화살표는 별도의 과녁입니다. 행을 선택하지 않고 가지만 엽니다.

href

href가 있는 행은 링크로 렌더링되며, 내비게이션 트리는 이것으로 만듭니다. 별도의 tab stop이 되지는 않습니다. 트리 전체가 하나이고, 행에는 방향키로 갑니다.

expandable

닫힌 가지는 DOM에 없으므로, 행을 처음 열 때 자식을 가져오는 트리에는 아직 그릴 것이 없습니다. expandable은 그래도 화살표를 그립니다. onExpandedChange에서 가져온 뒤, 도착하면 행을 렌더링하세요.

tsx
<TreeView expanded={expanded} onExpandedChange={load}>
  <TreeItem value="remote" label="Remote" expandable>
    {children.map((child) => (
      <TreeItem key={child.id} value={child.id} label={child.name} />
    ))}
  </TreeItem>
</TreeView>

접근성

  • 트리는 tree, 각 행은 treeitem, 가지의 자식들은 group입니다.
  • 트리 전체가 하나의 tab stop입니다. 안에 들어오면 ArrowUp·ArrowDown이 보이는 행들을 오르내리고, ArrowRight는 닫힌 가지를 열고 열린 가지에서는 그 안으로 들어가며, ArrowLeft는 가지를 닫고 잎에서는 부모로 올라갑니다. Home·End는 양 끝으로, Enter는 focus된 행을 선택합니다. 방향키는 선택을 바꾸지 않습니다.
  • RTL에서는 ArrowLeft와 ArrowRight가 바뀌므로, 전진 방향의 화살표는 언제나 "더 안쪽"을 뜻합니다.
  • label을 넘겨 트리에 이름을 주세요. 없으면 screen reader가 이름 없는 트리로 읽습니다.
  • multiple은 트리에 aria-multiselectable을 붙입니다.

Released under the MIT License