HowToSteps
독자가 하나씩 따라가는 안내서입니다. 한쪽에 번호가 매겨진 단계 목록이 있고 그 옆에 지금 단계의 설명이, 그 아래에 다음으로 넘어가는 버튼이 놓입니다. 마지막 단계까지 가면 끝났다는 것을 함께 알립니다.
import { HowToSteps } from 'neba';
<HowToSteps
title="cron으로 작업 예약하기"
steps={[
{ title: 'crontab 열기', content: 'crontab -e가 $EDITOR로 내 crontab을 엽니다.' },
{ title: '스케줄 작성', content: '다섯 개의 필드, 그다음 명령어.' }
]}
/>;Props
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| steps * | HowToStep[] | — | 해야 하는 순서대로의 단계. children이 아니라 배열로 받습니다. 옆의 목록과 본문이 같은 데이터를 함께 쓰고, 본문 높이가 모든 단계에 맞춰 정해지기 때문입니다 |
| title | ReactNode | — | 안내서 자신의 제목. 두 열 위에 놓입니다 |
| headingLevel | 2 | 3 | 4 | 5 | 3 | title이 쓰이는 heading 레벨. 단계의 제목은 그보다 한 단계 아래입니다. 레벨은 컴포넌트가 아니라 페이지에 대한 주장이므로, h1 아래의 안내서는 h2이고 섹션 안의 같은 안내서는 h4입니다 |
| step | number | — | 지금 보이는 단계. 직접 몰고 가려면 onStepChange와 함께 넘깁니다 |
| defaultStep | number | 0 | uncontrolled일 때 시작하는 자리 |
| onStepChange | (step: number) => void | — | 단계가 바뀔 때마다 인덱스와 함께 호출됩니다. 버튼으로 바뀌었든 목록에서 바뀌었든 |
| completed | boolean | — | 끝났는지. 이것도 직접 몰고 갈 수 있습니다 |
| defaultCompleted | boolean | false | uncontrolled일 때 끝난 상태로 시작할지 |
| onCompletedChange | (completed: boolean) => void | — | 끝났을 때, 그리고 처음으로 돌아갔을 때 호출됩니다 |
| orientation공통 | 'horizontal' | 'vertical' | 'vertical' | 목록이 흐르는 방향. vertical은 번호가 옆으로 내려가고 본문이 그 옆에 놓이며 sm 아래에서는 쌓입니다. horizontal은 위쪽에 가로로 늘어놓는데, 제목이 짧을 때에만 정직합니다 |
| maxHeight | number | string | — | 스크롤이 시작되기 전까지 커질 수 있는 높이. 시트가 커지는 대신 목록과 본문이 각자 스크롤되고, 현재 행은 보이는 자리로 따라옵니다. 숫자는 픽셀 |
| railWidth | number | string | '15rem' | 목록이 열일 때의 너비. 숫자는 픽셀 |
| navigation | boolean | true | 본문 아래의 버튼 줄. 꺼두면 목록이 유일한 이동 수단이 됩니다. 자체 내비게이션을 가진 페이지 안에 넣을 때 |
| divider | boolean | true | 목록과 본문 사이의 얇은 선. 두 열일 때는 안쪽 모서리를 따라, 쌓인 뒤에는 목록 아래를 따라 그려집니다 |
| transition공통 | NebaTransition | 'none' | 'fade' | 독자가 옮겨간 단계가 등장하는 방식. 어디서나 쓰는 그 어휘 그대로이며, none이면 꺼집니다. 눌리는 것이 아니라 패널에서 실행되고, reduced-motion 설정에서는 전부 꺼집니다 |
| completion | boolean | true | 완료 상태가 있는지. 켜져 있으면 마지막 단계의 버튼이 “완료”가 되고 누르면 끝났다고 말하는 패널로 바뀝니다. 꺼두면 마지막 단계는 그냥 마지막 단계입니다 |
| completedContent | ReactNode | locale('All steps complete') | 완료 패널이 하는 말 |
| variant공통 | 'solid' | 'outline' | 'text' | 'outline' | 시트의 weight, 컨테이너가 말하는 방식으로. 시트는 물들지 않습니다. 색을 지니는 것은 번호와 연결선과 버튼입니다 |
| size공통 | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | 번호 원의 지름, 타입 스케일, 버튼의 크기 |
| color공통 | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'primary' | 번호와 연결선과 버튼이 입는 계열 |
| density공통 | 'default' | 'compact' | 'default' | 여백만 바꿉니다 |
| elevation공통 | 0 | 1 | 2 | 3 | 0 | 그림자 깊이. 0은 그림자 없음 |
| locale | string | 'en' | 네 개의 버튼과 마지막 문장이 쓰이는 언어. 지원하지 않는 태그는 영어로 돌아갑니다 |
| previousLabel · nextLabel · doneLabel · restartLabel | string | locale | 그 네 단어를 직접 씁니다 |
color, title, content를 뺀 모든 네이티브 <div> 속성이 그대로 전달됩니다. 이 셋은 컴포넌트가 직접 씁니다. 공통 축은 prop 규칙에서 설명합니다.
HowToStep
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| title * | ReactNode | — | 제목. 목록에도, 그 단계 본문 위에도 같은 것이 놓입니다 |
| icon | ReactNode | — | 그 단계 본문의 제목 앞에 그려지는 glyph. 목록에는 그리지 않습니다. 거기에는 이미 번호가 붙은 원이 있고, 옆의 glyph는 같은 말을 두 번 합니다 |
| content | ReactNode | — | 독자가 해야 하는 일. 문장이든 CodeBlock이든 폼이든 |
| image | string | — | content 위의 그림. 말하기보다 보여주기가 쉬운 단계용 |
| imageAlt | string | title | 그 그림이 볼 수 없는 독자에게 하는 말 |
단계를 children이 아니라 배열로 받습니다. 이 컴포넌트가 다른 방식으로는 만들어질 수 없는 유일한 지점입니다. 옆의 목록과 본문은 같은 데이터를 두 번 그린 것이고, 본문 영역의 높이는 지금 보이는 단계가 아니라 모든 단계에 맞춰 정해집니다.
Examples
orientation
vertical이 기본입니다. 번호가 한쪽으로 내려가고 본문이 그 옆에 놓이며, 단계가 몇 개든 각 단계에 할 말이 얼마나 많든 받아냅니다. sm 아래에서는 위아래로 쌓입니다. horizontal은 번호를 위쪽에 가로로 늘어놓는데, 모든 제목이 짧을 때에만 정직한 배치입니다.
maxHeight
안에서 스크롤이 시작되기 전까지 안내서가 커질 수 있는 높이입니다. 숫자는 픽셀입니다. 시트가 커지는 대신 목록과 본문이 각자 안에서 스크롤되고, 단계가 바뀌면 현재 행이 보이는 자리로 따라옵니다.
step · completed
두 상태 모두 controlled로 쓸 수 있습니다. 위치를 직접 들고 있으려면(URL에, 폼 상태에) step과 onStepChange를, 마지막 상태에는 completed와 onCompletedChange를 씁니다.
icon
각 단계는 glyph를 하나 받을 수 있고, 그 단계 본문의 제목 앞에 그려집니다. 목록에는 그리지 않습니다. 목록의 행에는 이미 번호가 붙은 원이 있어서, 그 옆의 glyph는 같은 말을 두 번 하게 되기 때문입니다. 아이콘은 이것이 터미널 작업인지 파일 작업인지 경고인지처럼 어떤 종류의 단계인지를 나타낼 때 잘 맞습니다.
{ title: 'crontab 열기', icon: <TerminalIcon />, content: … }divider
목록과 본문 사이의 얇은 선입니다. 둘이 두 열일 때는 안쪽 모서리를 따라, 위아래로 쌓인 뒤에는 목록 아래를 따라 그려집니다. 기본은 켜짐입니다. 둘은 서로 다른 종류의 것이고, 여백만으로는 좁은 화면이 곧 없애버릴 gap에 그 구분을 맡기게 됩니다.
transition
독자가 어떤 단계로 옮겨갔을 때 그 단계가 등장하는 방식이며, 어디서나 transition이 쓰는 것과 같은 어휘를 씁니다. effect 이름 하나를 주거나, duration과 easing, 방향까지 정하는 객체를 넘길 수 있습니다. 'none'이면 꺼지고, reduced-motion 설정에서도 꺼집니다.
효과는 패널에서 실행되며 눌리는 것 위에서는 절대 실행되지 않습니다. 버튼과 목록 행은 가만히 있고, 움직이는 것은 그것들이 바꾼 내용입니다.
navigation · completion
navigation={false}는 버튼 줄을 없애고 목록만 남깁니다. 페이지가 자체 내비게이션을 가진 곳에 안내서를 끼워 넣을 때 쓰는 형태입니다. completion={false}는 완료 상태 자체를 없앱니다. 마지막 단계는 그냥 마지막 단계가 됩니다.
variant · size · color
세 가지 weight는 어디서나 하는 말을 그대로 합니다. 시트는 color로 물들지 않습니다. 색을 지니는 것은 번호와 연결선과 버튼입니다. 이미 시트인 Card 안에서는 text가 맞습니다.
headingLevel
title은 기본적으로 <h3>으로, 각 단계의 제목은 그보다 한 단계 아래인 <h4>로 그려집니다. headingLevel은 그 시작점을 옮깁니다. 레벨은 컴포넌트가 아니라 페이지에 대한 주장이기 때문입니다. <h1> 바로 아래에 놓인 안내서는 <h2>여야 하고, 섹션 안에 들어간 같은 안내서는 <h4>여야 합니다.
<HowToSteps steps={steps} title="시작하기" headingLevel={2} />무엇이든 담기는 단계
content는 노드를 받으므로 한 단계 안에 CodeBlock이, image로 스크린샷이, 폼이, 다른 컴포넌트가 들어갈 수 있습니다. 본문 영역이 가장 긴 단계의 높이를 유지하기 때문에 코드 블록이 들어 있는 단계에 도착해도 카드 크기가 바뀌지 않으며, 단계가 바뀔 때 아무것도 다시 mount되지 않으므로 안내서 중간의 폼은 입력해 둔 내용을 그대로 들고 있습니다.
Accessibility
- 목록은 tablist가 아니라 버튼의 목록입니다. 현재 행은
aria-current="step"을 지니며, 이것이 각 패널에 순서가 있고 독자가 그 순서대로 도달할 것을 전제한다고 말합니다. - 각 행은 "Step 3: Use it"처럼 읽힙니다. 원은 장식이고, 제목 옆에 그려진 숫자는 screen reader가 읽어 주는 숫자가 아닙니다.
title이 노드이면 그 문장을 만들 문자열이 없으므로 행은 자기 내용 그대로 읽힙니다. - 보이지 않는 단계들은 본문 높이를 유지하기 위해 문서에 남아 있으며
inert입니다. tab 순서에서 빠지고, accessibility tree에서 빠지고, 페이지 내 찾기에서도 빠집니다. - 한 페이지에 안내서가 둘 이상이면
title을 주십시오.