본문으로 건너뛰기
레이아웃 / layout

Layout

Stack · Cluster · Grid · Container — inline flex/grid 재발명을 대체하는 레이아웃 프리미티브 4종.
레이아웃layoutStatic specimenlayout레이아웃stackcluster
01 · Specimen

먼저 보고, 그다음 계약을 읽습니다

Stack · Cluster · Grid · Container — inline flex/grid 재발명을 대체하는 레이아웃 프리미티브 4종.

Workbench 불러오는 중…
Component intent의도와 경계 읽기

spacing scale 토큰(--space-N)에 1:1 매핑되는 얇은 레이아웃 원소 묶음이다. Stack = 세로 flex+gap, Cluster = 가로 flex+wrap+gap(툴바·헤더 액션 줄), Grid = 고정/auto-fill 반응형 grid(대시보드 카드), Container = max-width 중앙 정렬+좌우 gutter. 각 서비스(matrix 헤더의 inline `display:flex;gap`, cortex `.cortex-metric-grid` 등)가 반복 재발명하던 패턴을 SSOT 로 흡수한다. 전부 forwardRef + className 병합이며 순수 CSS 클래스로도 동일하게 소비 가능(상태 없음).

02 · Use

예제

SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.

01Stack — 세로 흐름tsxfragment
Stack — 세로 흐름
import { Stack } from "@axe/ui";<Stack gap={5} as="main">  <h1>포트폴리오</h1>  <p>이번 분기 요약…</p></Stack>
02Cluster — 헤더 액션 줄tsxfragment
Cluster — 헤더 액션 줄
import { Cluster, Button } from "@axe/ui";<Cluster gap={2} justify="between">  <h2>딜 파이프라인</h2>  <Cluster gap={2}>    <Button variant="ghost">필터</Button>    <Button variant="primary">새 딜</Button>  </Cluster></Cluster>
03Grid — auto-fill 카드 그리드tsxfragment
Grid — auto-fill 카드 그리드
import { Grid, MetricCard } from "@axe/ui";<Grid auto min="16rem" gap={4}>  <MetricCard label="TVPI" value="1.8x" />  <MetricCard label="DPI" value="0.4x" />  <MetricCard label="IRR" value="22%" /></Grid>
04Container — 본문 폭 제한tsxfragment
Container — 본문 폭 제한
import { Container, Stack } from "@axe/ui";<Container size="md" as="main">  <Stack gap={6}>…</Stack></Container>
05CSS-only (비-React)htmlfragment
CSS-only (비-React)
<div class="axe-container axe-container--md">  <div class="axe-stack axe-stack--gap-5">    <div class="axe-cluster axe-cluster--gap-2 axe-cluster--justify-between">      <h2>제목</h2>      <button class="axe-btn axe-btn--primary">액션</button>    </div>    <div class="axe-grid axe-grid--auto axe-grid--gap-4">      <div class="axe-card">…</div>      <div class="axe-card">…</div>    </div>  </div></div>
03 · React

Props

TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.

이름타입필수기본값설명
Stack.gap0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 104항목 간 세로 간격(--space-N, 0=간격 없음).
Stack.align"start" | "center" | "end" | "stretch"교차축(가로) 정렬. 미지정 시 flex 기본값 stretch(modifier 클래스 없음).
Stack.asReact.ElementType"div"렌더 태그. main/section/header 등 시맨틱 요소로 교체.
Cluster.gap0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 103항목 간 간격(--space-N).
Cluster.align"start" | "center" | "end" | "baseline" | "stretch""center"교차축(세로) 정렬. 기본 center 는 루트 클래스가 제공(명시 시에만 modifier 부여).
Cluster.justify"start" | "center" | "end" | "between"주축(가로) 분배. 미지정 시 flex-start.
Cluster.nowrapboolean줄바꿈 비활성화(한 줄 강제). 기본은 wrap.
Cluster.asReact.ElementType"div"렌더 태그.
Grid.cols1 | 2 | 3 | 4 | 5 | 63고정 컬럼 수. auto=false 일 때만 적용.
Grid.gap0 | 1 | 2 | 3 | 4 | 5 | 64항목 간 간격(--space-N).
Grid.responsivebooleantrue좁은 화면에서 컬럼 단계 축소(≤1023.98px: cols≥3→2, ≤639.98px: cols≥2→1). auto 모드엔 무효.
Grid.autobooleanauto-fill 모드 — cols 대신 항목 최소 폭(min)으로 컬럼 수 자동 결정.
Grid.minstring"15rem"auto 모드 항목 최소 폭(--axe-grid-min). auto=false 면 무시.
Container.size"sm" | "md" | "lg" | "xl" | "full""lg"최대 폭 토큰. sm 40 / md 56 / lg 72 / xl 80rem / full 100%.
Container.asReact.ElementType"div"렌더 태그. main/section 등으로 교체.
...restReact.HTMLAttributes<HTMLElement>네 컴포넌트 공통 — className 은 병합, 나머지(id·style·data-* 등)는 루트 요소로 전파(Grid 는 HTMLDivElement).
04 · Any stack

.axe-* 클래스 계약

React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.

클래스안정성용도
.axe-stackstableStack 루트 — flex column + gap + min-width:0.
.axe-stack--gap-{0-10}stable세로 간격 = --space-N (gap-0 은 0).
.axe-stack--align-{start|center|end|stretch}stable교차축(가로) 정렬.
.axe-clusterstableCluster 루트 — flex row wrap + align-items:center + gap.
.axe-cluster--gap-{0-10}stable간격 = --space-N.
.axe-cluster--align-{start|center|end|baseline|stretch}stable교차축(세로) 정렬.
.axe-cluster--justify-{start|center|end|between}stable주축(가로) 분배.
.axe-cluster--nowrapstableflex-wrap:nowrap(한 줄 강제).
.axe-gridstableGrid 루트 — display:grid + gap + min-width:0.
.axe-grid--gap-{0-6}stable간격 = --space-N.
.axe-grid--cols-{1-6}stable고정 N컬럼(repeat(N, minmax(0,1fr))).
.axe-grid--autostableauto-fill 모드 — repeat(auto-fill, minmax(--axe-grid-min, 1fr)).
.axe-grid--responsivestable미디어쿼리로 cols-N 을 좁은 화면에서 단계 축소.
.axe-containerstableContainer 루트 — max-width(--axe-container-max) 중앙 정렬 + 좌우 gutter(--space-4).
.axe-container--{sm|md|lg|xl|full}stable--axe-container-max 토큰 설정(40/56/72/80rem/100%).
비-React 소비 노트
네 프리미티브 모두 상태 없는 순수 CSS 클래스 — maud/jinja 등 서버 렌더에서 `.axe-stack`/`.axe-cluster`/`.axe-grid`/`.axe-container` 마크업을 그대로 써도 동일 결과. gap/cols/size 는 modifier 클래스, Container 는 --axe-container-max, Grid auto 는 --axe-grid-min 인라인 var 로 미세 조정.
05 · Inclusive

접근성

키보드, ARIA, 구현 노트를 함께 검토합니다.

ARIA

네 컴포넌트 모두 시맨틱 없는 표현용 컨테이너 — role/aria 를 자동 부여하지 않는다.

Notes

랜드마크가 필요한 자리(본문·헤더·내비)에는 `as`(Stack/Cluster/Container) 로 main/section/header/nav 를 지정해 문서 구조를 세운다. Grid/Stack/Cluster 는 DOM 순서를 재배치하지 않으므로 시각 순서 == 읽기/탭 순서. Stack·Cluster·Grid 루트에는 min-width:0 이 있어 긴 콘텐츠가 flex/grid 트랙을 밀어 넘치는 문제를 방지한다(Container 루트는 예외 — max-width 중앙 정렬만).

06 · Judgment

권장 · 지양

권장
  • 간격은 gap prop(토큰)으로만 — 개별 margin 을 섞지 말 것.
  • 랜드마크가 필요하면 as 로 main/section/header 를 지정한다.
  • 대시보드 카드처럼 개수가 유동적이면 Grid auto + min, 고정 열이면 cols 를 쓴다.
지양
  • Stack/Cluster/Grid 를 클릭 타깃으로 쓰지 말 것(표현용 컨테이너 — 포커스/role 없음).
  • Container 를 AppShell content slot(이미 max-width 처리) 안에 중첩해 폭을 이중 제한하지 말 것.
검색창을 열면 컴포넌트 인덱스를 불러옵니다.