다크모드
모바일 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.vue22개 + 관리비LineSheetAsideOrg.vue1개(총 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/edsexact 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.
Sidebar outer inset
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-autoutility 그룹은 간격으로 구분하며 기본 separator를 두지 않는다. sidebar-menu-separator는 제목과 간격만으로 의미를 표현할 수 없는 별도 시각 구획에만 명시적으로 사용한다. 현재 제품 navigation 소비처에는 사용하지 않는다.- active·hover 표면의 모바일 outer inset 8px, 계층 indent, 메뉴 item inline padding과 라우팅은 불변이다.
- 정본은
@leysys/eds@2.2.0의sidebar.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와 빌링LineHeaderOrg는src/components/navigation/GlobalAppHeaderOrg.vue만 소비한다. 각 wrapper는 도메인별SheetAsideOrg를 나란히 렌더하며, 관리비 line만menu-command-for="sheet-line-navigation"을 전달한다. 새 제품도 raw.navbar를 복제하지 않는다. - 공통 홈 진입점:
GlobalAppHeaderOrg가LeyveHomeAnchorMol을 한 번 렌더한다. 데스크톱은Leyve Cloud, 모바일은 홈 아이콘으로 보이며 목적지는/workspace/home이다. - 전역 전환 버튼 금지:
Workspace와Organization을 상단 헤더에 다시 추가하지 않는다. 앱 전환은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.vue는company-adminprincipal일 때만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.vue가AssistantSheetArt인스턴스를 한 번만 소유한다. 공통 헤더는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-12wrapper나 페이지 로컬 spacing override를 추가하지 않는다. - 우측 내비 슬롯: 모든 앱 내비 root는
sidebar-menu-end-edge를 사용한다. EDS가 chevron·action 슬롯을 콘텐츠 너비로 계산해 항목의 inline-end 패딩 안쪽에 정렬한다. 메뉴 제목의 동작 없는keyboard_double_arrow_left는 전부 제거하고, 모바일 닫기는SheetAsideOrg헤더의 native close command 한 곳이 소유한다. - Disclosure chevron: 계층 메뉴는
SidebarDisclosureChevronMol한 개를 공유한다. 이 컴포넌트는 SSOTIcon name="chevron-down"에 공식.sidebar-menu-chevronclass만 전달한다. 닫힘 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또는48rembreakpoint를 쓰지 않는다. - 페이지 헤더 역할: administration·service-charge의 표준 업무 페이지는
page-header-lg를 유지한다. 새 로컬 라우트가 재사용 본문을 감쌀 때도 소속 앱의 헤더 크기를 따른다. - 일반 상세/폼 시트: navigation modifier를 사용하지 않는다. 해당 Sheet size의 기본 body padding을 그대로 사용한다.
- DS 수정 금지: flush 동작을 바꾸려면 leysys-design 정본을 고치고 패치/마이너 릴리스 후 제품의 exact package 버전을 올린다. 로컬 override 금지.
- 미정리 후속(별개): Family 2 드로어
sheet-footer의Button/Cancel/Okay플레이스홀더는 nav 드로어에 부적합 — flush와 별개로 정리 필요. Family 2AppAsideOrg메뉴 항목의 파랑 링크색도 별개 검토 대상.
검증
- 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가 공통GlobalAppHeaderOrgcomposition만 소비하는지, Workspace·Organization 부재, AI trigger, Office 범위, 전 제품 line-free header·heading anatomy, EDSbutton-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·64rembreakpoint, 신규 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 검증을 함께 통과시킨다.