Pluto Design System
Components

SidebarList

사이드바의 섹션 헤더(타이틀 + count + actions) + 라벨-only 리스트 + more 토글이 한 단위로 묶인 패턴.

사용

라벨만 있는 항목들의 컬렉션을 사이드바에 둘 때. 섹션 헤더에 타이틀, count 배지, 우측 액션(추가/검색/정렬 등 IconButton 묶음)이 함께 들어가는 패턴이 한 컴포넌트로 캡슐화된다. 항목 수가 initialVisibleCount 보다 많으면 자동으로 more 토글이 붙는다.

검색·정렬 동작은 컴포넌트가 갖지 않는다. 사용처에서 actions 슬롯에 IconButton 을 넣고, 외부에서 Input / DropdownMenu 를 조합한다.

import { SidebarList } from "@fluxloop-ai/pds-ui/components/sidebar-list";
import { IconButton } from "@fluxloop-ai/pds-ui/components/icon-button";
import { Plus, MagnifyingGlass, Funnel } from "@fluxloop-ai/pds-icons/icons";

<SidebarList
  title="Library"
  count={skills.length}
  actions={
    <>
      <IconButton size="xs" aria-label="신규 스킬"><Plus /></IconButton>
      <IconButton size="xs" aria-label="검색"><MagnifyingGlass /></IconButton>
      <IconButton size="xs" aria-label="정렬"><Funnel /></IconButton>
    </>
  }
  items={skills}
  selectedId={selected}
  onSelect={setSelected}
  initialVisibleCount={10}
/>

Basic

Library15
audience-profiler
brainstorming-guide
brand-voice
campaign-planning
card-news-contents-maker
card-news-copy-evaluator
card-news-copy-writer
card-news-image-generator
card-news-maker
card-news-orchestrator

Without more toggle

initialVisibleCount 를 지정하지 않으면 모든 항목이 항상 노출된다.

Pinned4
audience-profiler
brainstorming-guide
brand-voice
campaign-planning

Item actions

renderItemTrailing 으로 각 항목 우측에 노출되는 trailing 슬롯을 채울 수 있다. 평소엔 숨김, hover · keyboard focus · selected · dropdown open 시 노출된다. 슬롯 영역의 클릭/키 이벤트는 내부에서 stopPropagation 되어 항목 선택을 트리거하지 않는다.

전형적인 조합은 <DropdownMenu> + <IconButton> 메뉴 트리거. rename · delete · duplicate 등 항목 단위 액션을 메뉴 안에 모은다.

Library6
audience-profiler
brainstorming-guide
brand-voice
campaign-planning
card-news-contents-maker
card-news-copy-evaluator
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@fluxloop-ai/pds-ui/components/dropdown-menu";
import { IconButton } from "@fluxloop-ai/pds-ui/components/icon-button";
import { DotsThree, PencilSimple, Trash } from "@fluxloop-ai/pds-icons/icons";

<SidebarList
  title="Library"
  items={skills}
  selectedId={selected}
  onSelect={setSelected}
  renderItemTrailing={(item) => (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <IconButton size="sm" variant="subtle" aria-label={`${item.label} 메뉴 열기`}>
          <DotsThree />
        </IconButton>
      </DropdownMenuTrigger>
      <DropdownMenuContent size="sm" align="end">
        <DropdownMenuItem onSelect={() => rename(item.id)}>
          <PencilSimple /><span>이름 변경</span>
        </DropdownMenuItem>
        <DropdownMenuItem onSelect={() => remove(item.id)}>
          <Trash /><span>삭제</span>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  )}
/>

Props

SidebarList

Prop타입기본설명
titlestring-섹션 타이틀 (예: "Library")
countnumber-헤더 우측 옆 pill 배지로 표시
actionsReactNode-헤더 우측 액션 슬롯 (e.g., IconButton 묶음)
itemsSidebarListItem[]-필수. { id, label }
selectedIdstring | nullnull선택된 항목 id
onSelect(id: string) => void-항목 클릭 시 호출
initialVisibleCountnumber-지정 시 초과분은 more 토글로 펼친다. 미지정 시 전체 노출
moreLabelstring"more"more 토글 라벨
renderItemTrailing(item: SidebarListItem) => ReactNode-각 항목 우측 trailing 슬롯. hover · focus-within · selected · [data-state=open] 시 노출. 클릭/키 이벤트는 stopPropagation 되어 항목 선택을 트리거하지 않는다
stickyHeaderbooleanfalse헤더를 부모 스크롤 컨테이너 상단에 sticky 로 고정 (부모가 overflow-y-auto 일 때만 의미 있음)

SidebarListItem

Field타입설명
idstring고유 id
labelstring표시 라벨

Registry 설치

npx shadcn add https://pds.pluto.com/r/sidebar-list