Sonic UIv0.6.2

DataGrid

정렬, 행 선택, 좌/우 고정, 컬럼·행 이동이 필요한 목록에 써요. 모양은 Table이 그리고, 상태는 DataGrid가 관리해요.

변형

Figma Data Grid Cell의 type이 columns[].type과 같아요. select·handle 열은 onSelectionChange·onRowOrderChange로 생겨요. 머리글을 눌러 정렬하고, 핸들을 끌어서 행을 옮겨 보세요.

순서상태만든 날사용동작
production활성12,4802026-03-02
github-actions활성3,2152026-05-18
staging만료 예정8422026-07-09
local-dev폐기됨02026-09-21
select · pinned · switch · actions · handle
상태
service-01활성02026-01-10
service-02활성7,9192026-02-11
service-03활성15,8382026-03-12
service-04활성3,7572026-04-13
service-05만료 예정11,6762026-05-14
pagination
상태
production활성12,4802026-03-02
github-actions활성3,2152026-05-18
staging만료 예정8422026-07-09
local-dev폐기됨02026-09-21
불러오는 중이에요
refreshing
상태
loading
상태

API 키가 없어요

키를 만들면 여기에서 사용량을 볼 수 있어요.

empty
상태
error

사용법

  • 보여 주기만 하는 표는 Table정렬, 선택, 고정, 이동 중 하나라도 필요할 때 DataGrid를 써요.
  • rows에는 원본 값숫자는 number, 날짜는 ISO 문자열이에요. 쉼표와 날짜 형식은 type이 맞춰요.
  • 선택은 bg/selected, hover는 bg/subtle고정 열 경계는 1px border/default이고 그림자는 쓰지 않아요.
  • 고정 열에는 width다음 고정 열 위치를 계산할 때 써요.
  • 위험한 actions는 AlertDialog로 확인onClick에서 바로 지우지 않고 확인 창을 열어요.
  • 서버에서 나누면 rowCount현재 페이지 rows와 전체 개수를 넘기고, 정렬도 서버가 해요(onSortingChange).
  • 클라이언트 컴포넌트 안에서 정의columns에 함수가 있어서 서버 컴포넌트에서 넘길 수 없어요.

Props

prop값기본값
rows · getRowId행 데이터(원본 값)와 행 id(필수)
columnstype: text · number · date · datetime · badge(tones) · switch(onChange) · actions(actions). 공통 header · width · minWidth · pinned · sortable(필수)
aria-label표 이름(필수)
sorting · onSortingChange{ id, desc } 또는 null. 한 번에 한 열null
selection · onSelectionChange선택된 행 id 배열. 넘기면 체크박스 열이 생겨요—
columnOrder · onColumnOrderChange열 id 순서. 넘기면 머리글을 끌어서 옮겨요—
onRowOrderChange(ids) => void. 넘기면 핸들 열이 생겨요—
loadingSkeleton 행 5개 + aria-busyfalse
refreshing이전 행은 두고 본문 위에 bg/scrim-subtle 막 + 스피너. 누르자마자 보여요false
emptyState · errorState본문 자리에 보여 줄 EmptyState · ErrorState—
pagination넘기면 아래에 Pagination. { page, pageSize, pageSizeOptions, showFirstLast, rowCount, … }—

코드

tsx
<DataGrid
  aria-label="API 키"
  rows={keys}
  getRowId={row => row.id}
  columns={[
    { field: 'name', header: '이름', type: 'text', pinned: 'left', width: 160, sortable: true },
    { field: 'requests', header: '요청 수', type: 'number', sortable: true },
    { field: 'status', header: '상태', type: 'badge', tones: { active: 'success', revoked: 'danger' }, labels: { active: '활성', revoked: '폐기됨' } },
    { field: 'enabled', header: '사용', type: 'switch', onChange: (row, on) => toggle(row.id, on) },
    { id: 'actions', type: 'actions', pinned: 'right', actions: [
      { label: '이름 바꾸기', icon: Pencil, onClick: rename },
      { label: '삭제', icon: Trash2, tone: 'danger', onClick: confirmDelete },
    ] },
  ]}
  selection={selected} onSelectionChange={setSelected}
  onRowOrderChange={ids => saveOrder(ids)}
  pagination={{ defaultPageSize: 20 }}
  emptyState={<EmptyState title="API 키가 없어요" action={<Button>API 키 만들기</Button>} />}
/>