Skip to content

모바일 Aside 내비 셸 — Sheet flush + SidebarGroup 8px inset

FE 메인테이너용. Sheet primitive와 SidebarMenu는 flush로 유지하고 SidebarGroup이 8px outer inset을 소유한다.

무엇

각 도메인 앱은 모바일 헤더의 메뉴 버튼으로 좌측 시트 드로어(dialog.sheet.sheet-left.sheet-lg#sheet-aside-org)를 연다. 이 드로어가 도메인 내비(탭 레일 + 메뉴, 또는 AppAsideOrg)를 담는다. 시트 본문 패딩은 sheet-body-flush로 0을 유지하고, 모든 navigation은 SidebarBody > SidebarGroup > SidebarGroupContent > SidebarMenu를 사용한다. Group이 좌우·상하 8px을 소유하고 Menu는 flush라서 active·hover 배경의 radius가 네 모서리 모두 보인다.

어디

  • 컴포넌트: 공통 제품 SheetAsideOrg.vue 22개 + 관리비 LineSheetAsideOrg.vue 1개(총 23개).
  • 진입: 각 도메인 AppHeaderOrg.vue 또는 views/<domain>/LayoutView.vue의 메뉴 버튼(command="show-modal" commandfor="sheet-aside-org"). 셸 라우트는 /<domain>/app-view(및 그 자식).
  • DS 정본: leysys-design/src/assets/styles/eds/components/{sheet,sidebar,sidebar-menu}.css. 제품은 @leysys/eds exact package를 소비한다. 제품 로컬 CSS override·카피본 복원은 금지한다.

두 계열 (구조 차이)

계열본문 구조8px inset 효과
Family 1 (TabOrg + MenuOrg)sheet-body(flex-row) 안에 w-16 inset-edge-r(탭 레일) + grow overflow-y-auto h-full(메뉴 컬럼)MenuOrg가 합성한 SidebarGroup이 메뉴 컬럼 경계에서 active·hover 표면을 8px 떨어뜨린다.
Family 2 (AppAsideOrg)sheet-body(flex-col) 안에서 AppAsideOrg가 canonical Sidebar anatomy를 직접 합성SidebarBody > SidebarGroup > SidebarGroupContent가 Sheet 좌우 경계에서 8px을 동일하게 소유한다.
  • Family 1: facility/{asset,status,task,maintenance} · accounting · crm · human-capital/_shell · approval/_shell · administration. 계약·기준정보는 앱 전환 레일을 제거하고 현재 도메인의 AppSideNavMenuOrg만 렌더한다.
  • Family 2: billing · workspace · headquarters · commerce · tax-invoice · storefront · property-mgmt-app.

sheet-body-flush 작동

css
/* sheet.css — 사이즈 섹션 직후 정의 */
.sheet.sheet-body-flush > .sheet-content > .sheet-body {
  padding: 0;
}
  • outer .sheet에 부착하는 compose 모디파이어(sheet-filled·sheet-divide-y 동렬). 각 SheetAsideOrg의 dialog는 class="sheet sheet-left sheet-lg sheet-inset-edged sheet-filled sheet-divide-y sheet-body-flush".
  • 사이즈 클래스 body 패딩과 동일 specificity, source order로 뒤에 와서 우선 → 본문만 0. header/footer 패딩·divide-y separator는 불변(제목·닫기·푸터 정렬 유지).
  • 근거·specificity 상세: leysys-design/docs/decisions/SHEET-BODY-FLUSH-NAV-2026-06-29.md.
css
.sidebar-group {
  padding: var(--space-xs); /* 8px */
}
.sidebar-group-content,
.sidebar-menu,
.sidebar-menu-flush {
  padding: 0;
}
  • 모바일과 데스크톱은 동일하게 SidebarBody > SidebarGroup > SidebarGroupContent > SidebarMenu를 합성한다.
  • SidebarBody는 scroll만 소유하고, Group은 outer inset, Menu는 collection과 item 간격만 소유한다.
  • AppAsideOrg·AppSideNavMenuOrg 내부의 로컬 p-2/px-2 py-2는 제거한다.
  • 항목 내부 inline padding 8px은 콘텐츠 간격이고, outer inset 8px은 Sheet 경계와 active 표면 사이 간격이므로 서로 다른 책임이다.
  • chevron은 sidebar-menu-end-edge의 content-sized 슬롯을 유지하며 3rem 투명 슬롯을 추가하지 않는다.

line-free heading·utility anatomy

  • 정적 메뉴 제목은 sidebar-menu-header > sidebar-menu-heading으로 합성한다. 제목은 sidebar-menu-item을 빌리지 않으므로 cursor·hover·active surface가 없다. 크기와 font weight도 heading이 소유하므로 하위 노드에 font-semibold·font-bold를 중복하지 않는다.
  • 라우트 이동이나 disclosure를 수행하는 제목 위치의 버튼은 sidebar-menu-header > sidebar-menu-item으로 유지한다.
  • 메뉴 그룹과 하단 mt-auto utility 그룹은 간격으로 구분하며 기본 separator를 두지 않는다.
  • sidebar-menu-separator는 제목과 간격만으로 의미를 표현할 수 없는 별도 시각 구획에만 명시적으로 사용한다. 현재 제품 navigation 소비처에는 사용하지 않는다.
  • active·hover 표면의 모바일 outer inset 8px, 계층 indent, 메뉴 item inline padding과 라우팅은 불변이다.
  • 정본은 @leysys/eds@2.2.0sidebar.css·sidebar-menu.css다. 제품 로컬 <style>·!important· generic edge override를 추가하지 않는다.

확장 포인트 / 주의

  • 새 도메인 셸 추가 시: dialog에 sheet-body-flush를 적용하고 navigation은 canonical Sidebar anatomy를 합성한다. Sheet body·SidebarBody·SidebarMenu에 p-2를 추가하지 않는다.
  • 앱 간 이동 금지: 로컬 aside 또는 모바일 시트에 다른 도메인으로 이동하는 앱 전환 레일을 추가하지 않는다. 앱 전환은 /workspace/home의 업무 카드가 담당한다.
  • 전역 헤더 composition: 20개 제품 AppHeaderOrg와 빌링 LineHeaderOrgsrc/components/navigation/GlobalAppHeaderOrg.vue만 소비한다. 각 wrapper는 도메인별 SheetAsideOrg를 나란히 렌더하며, 관리비 line만 menu-command-for="sheet-line-navigation"을 전달한다. 새 제품도 raw .navbar를 복제하지 않는다.
  • 공통 홈 진입점: GlobalAppHeaderOrgLeyveHomeAnchorMol을 한 번 렌더한다. 데스크톱은 Leyve Cloud, 모바일은 홈 아이콘으로 보이며 목적지는 /workspace/home이다.
  • 전역 전환 버튼 금지: WorkspaceOrganization을 상단 헤더에 다시 추가하지 않는다. 앱 전환은 LeyveHomeAnchorMol, 조직 관리는 권한형 로컬 메뉴 진입점이 담당한다.
  • 좁은 계정 헤더·푸터: 사용자 계정 일반/보안 헤더는 모바일에서 관리코드·아이디만 노출하고 이름·약칭 메타는 sm 이상에서 표시한다. 메타 그리드는 w-full sm:w-auto로 모바일 컨테이너 폭을 넘지 않는다. 계정·프로필 인라인 편집 footer는 flex-col sm:flex-row로 안내와 액션을 분리해 버튼 압축과 가로 스크롤을 방지한다.
  • 전 제품 헤더 슬롯: GlobalAppHeaderOrg의 왼쪽 순서는 메뉴 → Leyve 홈 → AI 비서이고, 오른쪽은 업무 범위 → 언어(화면 하단 fixed) → 사이트맵(PC 개발 전용) → 로그아웃이다. AI trigger는 모든 제품에서 항상 존재한다.
  • 조직관리: workspace/AppAsideOrg.vue와 관리비 billing/_core/shell/LineAsideOrg.vuecompany-admin principal일 때만 mt-auto 하단 그룹에 /administration/organization/account/general 진입점을 표시한다. 같은 컴포넌트를 쓰는 desktop aside와 모바일 시트가 동일 계약을 소비한다. staff와 principal 미확정 상태에는 숨긴다.
  • Workspace 0 기본 범위: 헤더는 AccountScopeSwitcherMol 한 개만 렌더한다. useAccountContext.replaceAccountData()가 번호순 첫 Workspace를 선택하며 신규 Organization은 officeNumber: 0을 받는다. Company 가상 범위는 목록에 표시하지 않고 이전 캐시는 Workspace 0으로 복구한다. 헤더에서 별도 Workspace 상태를 만들거나 저장하지 않는다.
  • Assistant sheet 단일 소유: 루트 src/views/app/LayoutView.vueAssistantSheetArt 인스턴스를 한 번만 소유한다. 공통 헤더는 commandfor="assistant-sheet-art" trigger만 렌더한다. 제품 wrapper나 line header 안에 sheet 인스턴스를 중복 추가하지 않는다.
  • 버튼 규격과 간격: 헤더 액션은 EDS button-lg(36px)로 통일하고 .navbar-start.navbar-end 모두 gap-1(4px)을 쓴다. .navbar의 좌우 16px padding은 EDS SSOT가 소유한다. w-12 h-12 wrapper나 페이지 로컬 spacing override를 추가하지 않는다.
  • 우측 내비 슬롯: 모든 앱 내비 root는 sidebar-menu-end-edge를 사용한다. EDS가 chevron·action 슬롯을 콘텐츠 너비로 계산해 항목의 inline-end 패딩 안쪽에 정렬한다. 메뉴 제목의 동작 없는 keyboard_double_arrow_left는 전부 제거하고, 모바일 닫기는 SheetAsideOrg 헤더의 native close command 한 곳이 소유한다.
  • Disclosure chevron: 계층 메뉴는 SidebarDisclosureChevronMol 한 개를 공유한다. 이 컴포넌트는 SSOT Icon name="chevron-down"에 공식 .sidebar-menu-chevron class만 전달한다. 닫힘 0°/열림 180° 상태와 motion은 @leysys/eds가 소유하며, 제품에는 <style scoped>·:global(details[open])·override를 만들지 않는다. EDS selector는 details.sidebar-menu-group의 직접 summary.sidebar-menu-item 안 chevron만 대상으로 하므로 summary·라벨·하위 메뉴는 절대 회전하지 않는다.
  • 개인 계정 재진입: Workspace 업무 메뉴는 /administration/user/account/general 진입점을 내 계정으로 표시한다. 계약·결제·Workspace 권한은 최고관리자용 조직관리로 분리한다.
  • Company KPI 카드 표면: headquarters/home/HomePag.vue의 KPI 4장은 card-filled card-inset-edged card-divide-y를 사용한다. card-elevated, shadow-*, rounded-*를 페이지에서 추가하지 않는다. radius는 EDS v1.0.0 --card-radius와 사용자의 data-radius 프리셋이 소유한다.
  • 모바일 선택 후 닫기: 메뉴 항목 선택 시 해당 라우트로 이동하면서 sheet-aside-org를 닫아야 한다.
  • 셸 치수 정본: 전역 앱 헤더는 모두 navbar h-14, 데스크톱 aside는 w-64, 모바일 전환 기준은 64rem이다. 한 단계 메뉴라고 임의로 w-48 또는 48rem breakpoint를 쓰지 않는다.
  • 페이지 헤더 역할: administration·service-charge의 표준 업무 페이지는 page-header-lg를 유지한다. 새 로컬 라우트가 재사용 본문을 감쌀 때도 소속 앱의 헤더 크기를 따른다.
  • 일반 상세/폼 시트: navigation modifier를 사용하지 않는다. 해당 Sheet size의 기본 body padding을 그대로 사용한다.
  • DS 수정 금지: flush 동작을 바꾸려면 leysys-design 정본을 고치고 패치/마이너 릴리스 후 제품의 exact package 버전을 올린다. 로컬 override 금지.
  • 미정리 후속(별개): Family 2 드로어 sheet-footerButton/Cancel/Okay 플레이스홀더는 nav 드로어에 부적합 — flush와 별개로 정리 필요. Family 2 AppAsideOrg 메뉴 항목의 파랑 링크색도 별개 검토 대상.

검증

  • Playwright(모바일 360·412·448): body padding 0, 메뉴 active 표면의 좌우 경계 간격 8px, 정적 heading의 투명 배경, implicit separator 0개, radius 노출, 좌우 대칭, 세로 스크롤과 터치 영역을 확인한다. 대표 화면은 412px이며 desktop에서는 기존 aside 위치와 폭이 변하지 않아야 한다.
  • src/components/navigation/__tests__/globalHeaderConsistency.spec.js: 21개 앱 헤더 wrapper가 공통 GlobalAppHeaderOrg composition만 소비하는지, Workspace·Organization 부재, AI trigger, Office 범위, 전 제품 line-free header·heading anatomy, EDS button-lg·4px gap을 검사한다.
  • src/components/billing/_core/shell/__tests__/LineResponsiveNavigation.spec.js: Company 관리자에게는 desktop/mobile 공용 메뉴의 조직관리 진입점이 line-free 하단 그룹에 나타나고 staff에는 나타나지 않는지 검사한다.
  • src/composables/__tests__/useAccountContext.spec.js: 신규 Company가 Office 0을 기본 선택하고 Company · Office 0 · 이름 label을 만드는 계약을 검사한다.
  • src/components/navigation/__tests__/sidebarDisclosureChevronConsistency.spec.js: 모든 제품 사이드바가 공용 SSOT chevron을 사용하고 raw Material ligature·제품별 회전 CSS를 만들지 않는지, exact @leysys/eds 패키지 산출물이 공식 open/closed selector를 제공하는지 검사한다.
  • scripts/audit-sidebar-chevron-build.mjs: Vite production build가 만든 전체 CSS asset을 검사한다. .sidebar-menu-chevron이 없거나 details[open] { rotate/transform: ... } 형태의 광역 selector가 있으면 build를 실패시킨다.
  • 같은 테스트가 23개 모바일 navigation Sheet의 sheet-body-flush, 모바일·데스크톱 공통 SidebarGroup + sidebar-menu-flush, 앱 내비의 sidebar-menu-end-edge와 이중 꺾쇠 제거 계약을 고정한다.
  • 같은 테스트가 20개 레이아웃의 w-64·64rem breakpoint, 신규 Office·계정과목 헤더의 page-header-lg를 고정한다.
  • 실제 브라우저는 모바일 360·412·448px에서 active 표면 outer inset 8px·정적 heading의 투명 배경·implicit separator 0개·가로 overflow 0을 수치로 검증한다.
  • precommit DS(B/C/D=0, ad-hoc 0) · 단위·boundary·build·docs mirror 검증을 함께 통과시킨다.