Grid Box
폼 그리드의 컨테이너입니다. 열 수를 계산해 자식 셀(
nv-input-wrap)에게 내려줍니다.
상세 폼(nv-form-group)과 검색 폼(nv-search-form)이 이 컴포넌트를 공유합니다. 그래서 두 화면의 반응형 규칙·간격·셀 병합 동작이 항상 일치합니다.
직접 쓸 일은 많지 않습니다 — 보통은 nv-form-group 이나 nv-search-form 이 감싸 줍니다. 그 둘이 아닌 곳에 그리드가 필요할 때만 직접 사용합니다.
props
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
mode | 'columns' / 'fit' / 'inline' | 'columns' | 아래 세 가지 모드 참고 |
column-size | number | 2 | columns 모드의 열 수. 화면 폭에 따라 자동으로 줄어든다 |
min-cell-width | string | '180px' | fit/inline 모드의 셀 최소 너비 |
max-cell-width | string | '320px' | inline 모드의 셀 최대 너비 |
세 가지 모드
| mode | 트랙 | 남는 폭 | 쓰는 곳 |
|---|---|---|---|
columns (기본) | repeat(column-size, 1fr) | 채운다 | 상세 폼, 고급 검색 |
fit | repeat(auto-fit, minmax(min, 1fr)) | 채운다 | 폭을 꽉 써야 하는 곳 |
inline | 셀 개수만큼, 각 minmax(min, max) | 안 먹는다 | 검색 바 — 필드 뒤에 버튼이 바로 붙어야 한다 |
html
<!-- 열 수 고정 — 상세 폼 / 고급 검색 -->
<nv-grid-box :column-size="3">
<nv-input-wrap label="이름"><el-input v-model="model.name"/></nv-input-wrap>
<nv-input-wrap label="설명" :merge-cell="2"><el-input v-model="model.desc"/></nv-input-wrap>
</nv-grid-box>
<!-- 셀 개수만큼만 차지 — 검색 바처럼 뒤에 버튼이 붙는 곳 -->
<nv-grid-box mode="inline" min-cell-width="180px" max-cell-width="320px">
<nv-input-wrap label="키워드"><el-input v-model="keyword"/></nv-input-wrap>
</nv-grid-box>
<button>검색</button> <!-- 필드 바로 뒤에 붙는다 -->WARNING
mode="inline" 은 grid-auto-flow: column 이라 줄바꿈하지 않는다. 필드가 많으면 셀이 min-cell-width 까지 줄어든 뒤 넘친다. 필드가 여러 줄로 흘러야 하면 columns 나 fit 을 쓴다.
반응형 규칙
columns 모드에서 화면 폭에 따라 열 수가 줄어듭니다.
| 화면 폭 | 열 수 |
|---|---|
| ~480px | 1 |
| ~768px | column-size - 2 (5 이상이면 2) |
| ~1024px | column-size - 1 (5 이상이면 3) |
| 그 외 | column-size |
column-size 가 1 또는 2 면 480px 아래에서만 1 열이 됩니다.
TIP
창 크기 감지는 앱 전체가 리스너 하나를 공유합니다. 그리드를 여러 개 두어도 비용이 늘지 않습니다.
셀 병합
자식이 merge-cell 로 칸을 병합합니다. 컨테이너의 실제 열 수를 넘으면 자동으로 잘리므로, 반응형으로 열 수가 줄어도 레이아웃이 깨지지 않습니다. fit/inline 모드에서도 실제 트랙 수를 측정해 같은 규칙이 적용됩니다.
그리드 컨테이너 밖에서 nv-input-wrap 을 쓰면 merge-cell 은 1로 처리됩니다.
직접 쓰기 (컴포저블)
전용 컴포넌트를 만들 때는 컴포저블을 직접 씁니다.
typescript
import { provideGridColumnSize, useGridCell, responsiveColumnSize, useWindowWidth }
from 'src/components/plugins/grid/use-grid-box';
// 컨테이너
const width = useWindowWidth();
const cols = computed(() => responsiveColumnSize(props.columnSize, width.value));
provideGridColumnSize(cols);
// 셀
const { style: cellStyle, span } = useGridCell(() => props.mergeCell);