Get startedFoundationsComponentsPatternsRules

Navigation System

내비게이션 시스템은 상단 내비게이션, 사이드 내비게이션, 메인, Aside, Panel 영역으로 앱 화면의 뼈대를 만들어요.

설치

pnpm dlx shadcn@latest add https://rebar.conmarket-landing.workers.dev/r/steel/navigation-system.json

한 파일에서 레이아웃(Root, Banner, TopNav, SideNav, Main, Aside, Panel)과 상단 내비 항목(AppSwitcher, AppLogo, Search, CreateButton, Notifications, Help, Settings, Profile, EndItem)을 모두 내보내요. 사이드 내비 안에 넣는 메뉴 항목은 Side Nav Items 에 있어요.

Examples

앱 셸

Root 바로 아래에 TopNav → SideNav → Main 순서로 둬요. 위 미리보기는 상단 내비(앱 전환·로고·검색·만들기·알림·도움말·설정·프로필), 프로젝트를 펼쳐 보는 사이드 내비, 백로그 표가 있는 메인으로 된 협업 도구 화면이에요.

  • 상단 내비는 높이 48px, 좌우 12px 여백, 아래 1px 테두리예요. 세 칸(Start · Middle · End) grid 라 검색이 항상 가운데에 와요.
  • 사이드 내비는 기본 320px 이고 240px ~ Root 너비의 50% 사이에서 조절돼요. 오른쪽 가장자리에 마우스를 올리면 300ms 뒤 손잡이 선이 나타나요. 드래그하거나 포커스 후 화살표 키(20px 단위)로 조절하고, 더블클릭하면 기본 너비로 돌아가요.
  • Root 는 부모 높이를 채우는 grid 예요. 앱 전체 화면에 쓸 때는 isFixed 를 주면 화면 높이(100dvh)를 채워요. 각 영역은 스스로 스크롤돼요.

Top nav

TopNavStart 에는 사이드 내비 토글·앱 전환·앱 로고, TopNavMiddle 에는 검색과 만들기, TopNavEnd 에는 알림·도움말·설정·프로필을 둬요. Search 는 입력창처럼 보이는 버튼이에요. 누르면 검색 팝업이나 검색 페이지를 열도록 onClick 을 연결해요. Notifications 의 badge 에 숫자를 주면 99 를 넘을 때 "99+" 로 줄여요. 미리 준비된 항목이 없는 동작은 EndItem 으로 만들어요.

사이드 내비 접기와 peek

TopNavStart 의 sideNavToggleButton 에 SideNavToggleButton 을 넣으면 사이드 내비를 접고 펼 수 있어요. 접으면 완전히 사라지고, 접힌 상태에서 토글 버튼에 마우스를 0.5초 올려 두면 메인 위에 잠깐 떠서(peek) 보여줘요. 마우스가 벗어나면 0.4초 뒤 닫혀요. Root 의 defaultSideNavCollapsed 로 접힌 채 시작하고, isSideNavShortcutEnabled 를 주면 Ctrl + [ 단축키가 켜지고 툴팁에도 단축키가 보여요.

Aside 와 Panel

Aside(기본 330px)는 이슈 세부 정보나 목차처럼 이 페이지에 딸린 보조 정보예요. Panel(기본 365px)은 도움말·알림·AI 도우미처럼 앱 전역의 보조 작업 공간이에요. 둘 다 안에 PanelSplitter 를 넣으면 왼쪽 가장자리로 너비를 조절할 수 있어요. Panel 을 여는 상단 버튼에는 isSelected 와 aria-expanded 를 함께 줘요.

좁은 화면

반응형 기준은 브라우저 창이 아니라 Root 의 너비예요. Root 가 640px 보다 좁으면 사이드 내비는 접힌 채로 시작하고, 열면 메인 위에 겹쳐 떠요(바깥을 누르거나 Esc 로 닫혀요). TopNavEnd 항목은 "더 보기" 버튼 안으로 들어가고, 480px 보다 좁으면 검색이 아이콘 버튼으로 줄어요.

원본(Atlassian)은 화면 너비 64rem(1024px)을 기준으로 사이드 내비를 붙이지만, Steel 은 문서 미리보기·임베드 안에서도 쓸 수 있도록 Root 너비 40rem(640px)을 기준으로 해요.

Usage guidelines

영역 구성

#영역역할
1Banner선택. 앱 전체에 영향을 주는 Banner 를 맨 위에 보여줘요.
2Top nav앱 전역 도구. Start(왼쪽), Middle(가운데), End(오른쪽) 세 칸이에요.
3Side nav제품 안 이동. Header(고정) · Body(스크롤) · Footer(고정)로 나뉘고, 크기를 조절하고 접을 수 있어요.
4Main페이지 본문. 남는 공간을 모두 채워요. 유일한 필수 영역이에요.
5Aside선택. 페이지에 딸린 보조 정보
6Panel선택. 앱 전역 보조 작업 공간. 크기를 조절하고 닫을 수 있어요.

Panel 과 Modal dialog 의 차이

  • Panel 은 메인 옆에 나란히 내용을 보여주고, Modal dialog 는 페이지 위 레이어에 떠요.
  • 사용자가 하던 일을 계속하면서 참고할 정보나 부가 작업이면 Panel 을 써요. 여러 작업을 동시에 하게 도와줘요.
  • 결정을 내리거나 작업을 끝내야 원래 일로 돌아갈 수 있다면 Modal dialog 를 써요.

상단 내비 항목

  • 상단 내비에는 준비된 항목(AppSwitcher, AppLogo, Search, CreateButton, Notifications, Help, Settings, Profile, EndItem)만 써요. 일반 버튼이나 로그아웃 같은 임의 요소를 끼워 넣으면 앱마다 상단이 달라져 익숙함이 깨져요.
  • "만들기" 는 상단에서 유일한 primary 버튼이에요. 어디서든 이슈나 페이지를 바로 만들 수 있게 해요.
  • 제품 안의 주요 공간(보드, 백로그, 필터 등)으로 가는 링크는 상단이 아니라 사이드 내비에 둬요.
Do· 준비된 항목 쓰기
알림·도움말·설정·프로필처럼 정해진 자리에 정해진 항목을 둬요.
Don't· 임의 요소 추가
상단에 일반 버튼, 탭, 로그아웃 버튼을 직접 추가하지 않아요.

메인 영역 디자인

  • 그리드는 메인 영역 안에서만 써요. 사이드 내비와 Panel 까지 그리드에 넣어 정렬하지 않아요.
  • 메인 맨 위에는 Page header 를 두고 Breadcrumbs → 제목 → 액션 순서로 쌓아요.

Accessibility

  • 영역은 항상 Banner → TopNav → SideNav → Main → Aside → Panel 순서로 Root 바로 아래에 둬요. 이 순서가 Tab 이동 순서, 스크린 리더 읽기 순서가 돼요.
  • 각 영역은 랜드마크가 자동으로 붙어요: TopNav 는 <header>, SideNav·TopNavEnd 는 <nav>, Main 은 <main>, Aside·Panel 은 <aside>. 안에 같은 랜드마크를 또 만들지 않아요.
  • SideNav, TopNavEnd, Aside, Panel 에는 서로 다른 의미 있는 label 을 줘요. 랜드마크 이름이 돼요. "사이드바 내비게이션" 처럼 역할 이름을 반복하지 않아요.
  • Root 맨 앞에 "본문으로 건너뛰기" 링크가 있어요. Tab 을 처음 누르면 나타나고, 누르면 메인으로 포커스가 옮겨가요. 문구는 skipLinksLabel 로 바꿔요.
  • 상단 내비 항목은 label 이 필수예요. 접근성 이름이자 툴팁 내용이 돼요. 팝업·메뉴·Panel 을 여는 항목에는 aria-controls, aria-expanded, aria-haspopup 을 넘기고, 열려 있으면 isSelected 를 줘요.
  • SideNavToggleButton 은 aria-expanded 와 aria-controls(사이드 내비 id)가 자동으로 붙어요. 단축키를 켜면 툴팁에 Ctrl [ 가 보여요.
  • 너비 조절 손잡이는 화면에 보이지 않는 range 입력이라 Tab 으로 포커스한 뒤 ← → 로 20px 씩 조절해요.

Props

Root

Prop

Type

TopNav · TopNavStart · TopNavMiddle · TopNavEnd

Prop

Type

상단 내비 항목

Prop

Type

SideNavToggleButton

Prop

Type

SideNav

Prop

Type

SideNavHeader(padding 12/12/4), SideNavBody(= SideNavContent, 스크롤, padding 12), SideNavFooter(padding 12, 위 1px 테두리)는 div props 를 받아요. 상태는 useToggleSideNav(), useExpandSideNav(), useSideNavVisibility() 로 읽고 바꿔요.

PanelSplitter · SideNavPanelSplitter

Prop

Type

Main · Aside · Panel · Banner

Prop

Type

MainStickyHeader 는 메인 안에서 위에 붙어 있는 헤더예요.

On this page