Gap#
Row/Column (또는 Web의 flex) 레이아웃에서 자식 간격을 추가하는 유틸리티 컴포넌트입니다. 부모의 주축(main axis)을 자동 감지해 해당 축으로만 공간을 차지합니다.
CoUI는 세 가지 변형을 제공합니다:
- CoGap — 고정 크기의 기본 간격
- CoMaxGap — 최대 크기까지만 차지하고 공간이 모자라면 양보하는 유연한 간격
-
CoSliverGap —
CustomScrollView안의 sliver 간격 (Flutter 전용 프로토콜; Web은 flex 스페이서로 대체)
Live Preview#
default
Web
Flutter
Loading Flutter...
class GapDefaultExample extends StatelessComponent {
const GapDefaultExample({super.key});
@override
Component build(BuildContext context) {
return div(
[
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: Component.text('A'),
),
CoGap(size: CoreSpace.space16),
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: Component.text('B'),
),
],
classes: 'flex flex-row items-center',
);
}
}
class GapDefaultExample extends StatelessWidget {
const GapDefaultExample({super.key});
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: const Text('A'),
),
const CoGap(size: CoreSpace.space16),
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: const Text('B'),
),
],
);
}
}
max
Web
Flutter
Loading Flutter...
class GapMaxExample extends StatelessComponent {
const GapMaxExample({super.key});
@override
Component build(BuildContext context) {
return div(
[
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: Component.text('A'),
),
CoMaxGap(size: CoreSpace.space64),
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: Component.text('B'),
),
],
classes: 'flex flex-row items-center',
);
}
}
class GapMaxExample extends StatelessWidget {
const GapMaxExample({super.key});
@override
Widget build(BuildContext context) {
return Row(
children: [
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: const Text('A'),
),
const CoMaxGap(size: CoreSpace.space64),
CoButton(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: const Text('B'),
),
],
);
}
}
sliver
Web
Top item
Middle item
Bottom item
Flutter
Loading Flutter...
class GapSliverExample extends StatelessComponent {
const GapSliverExample({super.key});
@override
Component build(BuildContext context) {
final ts = context.typography;
final cs = context.colorScheme;
final textClass = 'text-\${ts.bodyMedium} text-\${cs.onSurface}';
return div(
[
div([Component.text('Top item')], classes: textClass),
CoSliverGap(size: CoreSpace.space24),
div([Component.text('Middle item')], classes: textClass),
CoSliverGap(size: CoreSpace.space24),
div([Component.text('Bottom item')], classes: textClass),
],
classes: 'flex flex-col items-start',
styles: Styles(raw: {'height': '\${160 / 16}rem'}),
);
}
}
class GapSliverExample extends StatelessWidget {
const GapSliverExample({super.key});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final textStyle = theme.typography.bodyMedium.copyWith(
color: theme.colorScheme.onSurface,
);
return SizedBox(
height: 160,
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(child: Text('Top item', style: textStyle)),
const CoSliverGap(size: CoreSpace.space24),
SliverToBoxAdapter(child: Text('Middle item', style: textStyle)),
const CoSliverGap(size: CoreSpace.space24),
SliverToBoxAdapter(child: Text('Bottom item', style: textStyle)),
],
),
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- Row나 Column 내에서 자식 간 일관된 간격이 필요할 때
CoreSpace디자인 토큰 기반 간격을 사용하고 싶을 때SizedBox대안으로 의도가 분명한 간격 표현이 필요할 때
대신 다른 컴포넌트를 사용하세요:
Padding: 위젯 주변에 사방 여백을 추가할 때Spacer: Row/Column에서 남은 공간을 모두 채울 때Separator/Divider: 시각적 구분선이 필요할 때
기본 사용법 (Basic Usage)#
// 수직 간격 (부모가 Column/flex-col일 때)
Column(
children: [
Text('제목'),
CoGap(size: CoreSpace.space16),
Text('내용'),
],
)
// 수평 간격 (부모가 Row/flex-row일 때)
Row(
children: [
Icon(Icons.person),
CoGap(size: CoreSpace.space8),
Text('사용자 이름'),
],
)
// cross 축도 지정 (예: 4px 세로 spacer를 100px 가로로 강조)
CoGap(size: CoreSpace.space4, crossAxisExtent: 100)
// 색을 채워 디버그/구분선 목적
CoGap(size: CoreSpace.space16, color: Colors.red)
// cross 축을 무한대로 확장 (parent 전체 채우기)
CoGap.expand(CoreSpace.space16)
MaxGap 사용법#
// 주축을 최대 space64까지만 차지, 공간 부족 시 양보
Row(
children: [
CoButton(variant: .primary, onPressed: () {}, child: Text('A')),
CoMaxGap(size: CoreSpace.space64),
CoButton(variant: .primary, onPressed: () {}, child: Text('B')),
],
)
SliverGap 사용법#
CustomScrollView(
slivers: [
SliverToBoxAdapter(child: Text('Top')),
CoSliverGap(size: CoreSpace.space24),
SliverToBoxAdapter(child: Text('Middle')),
CoSliverGap(size: CoreSpace.space24, color: Colors.red),
SliverToBoxAdapter(child: Text('Bottom')),
],
)
Web은 sliver 프로토콜이 없으므로
CoSliverGap이CoGap과 동일한 flex 스페이서로 렌더링됩니다. API는 동일합니다.
Props / Parameters#
CoGap#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
size |
double? |
null → CoreGapTheme.defaultSize → CoreSpace.space4 |
부모 주축 방향 간격 (px) |
crossAxisExtent |
double? |
null → parent cross constraint |
교차축 크기 (px). null이면 parent를 채움 |
color |
Color? (Flutter) · String? (Web) |
null |
gap 영역을 채울 색. Web은 #hex / rgba(...) 문자열 |
CoMaxGap (Flutter 전용 flexible 래핑, Web도 동일 API로 노출)#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
size |
double? |
null → CoreMaxGapTheme.defaultSize → CoreSpace.space4 |
최대 주축 크기 |
crossAxisExtent |
double? |
null |
교차축 크기 |
color |
Color? / String? |
null |
fill 색 |
CoSliverGap#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
size |
double? |
null → CoreSliverGapTheme.defaultSize → CoreSpace.space4 |
sliver 주축 크기 |
color |
Color? / String? |
null |
fill 색 |
팩토리 생성자#
-
CoGap.expand(mainAxisExtent, {color})/CoMaxGap.expand(...)—crossAxisExtent를double.infinity로 설정한 단축형.
동작 스펙 (Behavior)#
방향 자동 감지#
별도 axis/direction 파라미터 없음. 부모의 flex/axis 방향을 자동으로 따라갑니다.
-
Flutter:
RenderGap이 부모RenderFlex.direction을 감지. 부모가 Flex가 아니면 enclosingScrollable의 axis를 fallback으로 사용. -
Web: CSS
flex-basis: ${size/16}rem+flex-shrink: 0+align-self: stretch→ 부모flex-direction에 따라row면width로,column이면height로 해석됨
렌더링#
-
Flutter:
LeafRenderObjectWidget→RenderGap(custom RenderBox). - Web:
<div>+ inline CSS (no Tailwind 클래스).
사용 가이드라인 (Usage Guidelines)#
✅ Do — 디자인 토큰 사용#
Column(
children: [
TitleWidget(),
CoGap(size: CoreSpace.space16),
BodyWidget(),
CoGap(size: CoreSpace.space24),
ActionWidget(),
],
)
❌ Don't — 매직 넘버 사용#
CoGap(size: 13) // 왜 13px?
CoGap(size: 27) // 일관성 없음
❌ Don't — Padding 용도로 사용#
컨테이너 내부 여백은 Padding 또는 CSS p-* class 사용. Gap은 자식 간 간격 전용.
접근성 (Accessibility)#
- 정적 간격 컴포넌트로 인터랙션 없음
- 스크린 리더에 시각적 요소로만 노출
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | CoGap / CoMaxGap / CoSliverGap |
동일 |
| 렌더링 | 자체 RenderGap / RenderSliverGap |
<div> + CSS flex-basis |
| 방향 감지 | 부모 Flex.direction → Scrollable axis | 부모 flex-direction (CSS) |
| 색 타입 | Color? | String? (CSS value) |
| Sliver 지원 | RenderSliver 기반 | flex 스페이서로 대체 (API 동일) |
| 테마 | CoreGapTheme / CoreMaxGapTheme / CoreSliverGapTheme |
동일 |