Frame#
CoFrame 은 CoUI 의 통합 레이아웃 프리미티브입니다. Flutter 의 Container / Row /
Column / Wrap / Padding / Center / Align
/ SizedBox / Expanded / DecoratedBox / Opacity /
Transform / ClipRRect / Visibility 와 Web 의 <div>
를 한 컴포넌트로 흡수하여, Figma Frame 의 모든 "Inspect" 슬롯이 1:1 로 코드 prop 에 대응합니다.
Live Preview#
default
Web
Flutter
Loading Flutter...
class FrameDefaultExample extends StatelessComponent {
const FrameDefaultExample({super.key});
@override
Component build(BuildContext context) {
final cs = context.colorScheme;
return CoFrame(
direction: CoreFrameDirection.row,
gap: CoreSpace.space12,
crossAxisAlignment: CoreCrossAxisAlignment.center,
padding: CoreSpace.space16,
backgroundColor: 'rgb(var(--coui-${cs.surfaceContainer}))',
borderRadius: CoreRadius.radius16,
borderColor: 'rgb(var(--coui-${cs.outlineVariant}))',
borderWidth: CoreStrokeWidth.stroke1,
children: [
CoIcon(CoLucideIcons.frame, iconStyle: CoreIconStyle(size: CoreSpace.space24)),
Text('Frame primitive'),
],
);
}
}
class FrameDefaultExample extends StatelessWidget {
const FrameDefaultExample({super.key});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return CoFrame(
direction: CoreFrameDirection.row,
gap: CoreSpace.space12,
crossAxisAlignment: CoreCrossAxisAlignment.center,
padding: const EdgeInsets.all(CoreSpace.space16),
backgroundColor: colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(CoreRadius.radius16),
borderColor: colorScheme.outlineVariant,
borderWidth: CoreStrokeWidth.stroke1,
children: const [
CoIcon(CoLucideIcons.frame, iconStyle: CoreIconStyle(size: CoreSpace.space24)),
Text('Frame primitive'),
],
);
}
}
column
Web
Flutter
Loading Flutter...
class FrameColumnExample extends StatelessComponent {
const FrameColumnExample({super.key});
@override
Component build(BuildContext context) {
final cs = context.colorScheme;
return CoFrame(
direction: CoreFrameDirection.column,
gap: CoreSpace.space8,
padding: CoreSpace.space16,
backgroundColor: 'rgb(var(--coui-${cs.surfaceContainer}))',
borderRadius: CoreRadius.radius16,
children: [
Text('First row'),
Text('Second row'),
Text('Third row'),
],
);
}
}
class FrameColumnExample extends StatelessWidget {
const FrameColumnExample({super.key});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return CoFrame(
direction: CoreFrameDirection.column,
gap: CoreSpace.space8,
padding: const EdgeInsets.all(CoreSpace.space16),
backgroundColor: colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(CoreRadius.radius16),
children: const [
Text('First row'),
Text('Second row'),
Text('Third row'),
],
);
}
}
dashed
Web
Flutter
Loading Flutter...
class FrameDashedExample extends StatelessComponent {
const FrameDashedExample({super.key});
@override
Component build(BuildContext context) {
final cs = context.colorScheme;
return CoFrame(
direction: CoreFrameDirection.row,
mainAxisAlignment: CoreMainAxisAlignment.center,
crossAxisAlignment: CoreCrossAxisAlignment.center,
padding: CoreSpace.space24,
borderRadius: CoreRadius.radius16,
borderColor: 'rgb(var(--coui-${cs.outline}))',
borderWidth: CoreStrokeWidth.stroke2,
borderStyle: CoreFrameBorderStyle.dashed,
child: Text('Dashed-border frame'),
);
}
}
class FrameDashedExample extends StatelessWidget {
const FrameDashedExample({super.key});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return CoFrame(
direction: CoreFrameDirection.row,
mainAxisAlignment: CoreMainAxisAlignment.center,
crossAxisAlignment: CoreCrossAxisAlignment.center,
padding: const EdgeInsets.all(CoreSpace.space24),
borderRadius: BorderRadius.circular(CoreRadius.radius16),
borderColor: colorScheme.outline,
borderWidth: CoreStrokeWidth.stroke2,
borderStyle: CoreFrameBorderStyle.dashed,
child: const Text('Dashed-border frame'),
);
}
}
elevated
Web
Flutter
Loading Flutter...
class FrameElevatedExample extends StatelessComponent {
const FrameElevatedExample({super.key});
@override
Component build(BuildContext context) {
final cs = context.colorScheme;
return CoFrame(
direction: CoreFrameDirection.column,
gap: CoreSpace.space4,
padding: CoreSpace.space16,
backgroundColor: 'rgb(var(--coui-${cs.surface}))',
borderRadius: CoreRadius.radius16,
elevation: CoreFrameElevation.medium,
children: [
Text('Elevated frame'),
Text('Shadow-md preset, no border.'),
],
);
}
}
class FrameElevatedExample extends StatelessWidget {
const FrameElevatedExample({super.key});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return CoFrame(
direction: CoreFrameDirection.column,
gap: CoreSpace.space4,
padding: const EdgeInsets.all(CoreSpace.space16),
backgroundColor: colorScheme.surface,
borderRadius: BorderRadius.circular(CoreRadius.radius16),
elevation: CoreFrameElevation.medium,
children: const [
Text('Elevated frame'),
Text('Shadow-md preset, no border.'),
],
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- Figma 디자인을 Flutter / Web 어느 쪽으로든 코드로 옮길 때 — 디자인의 한 Frame 이 그대로 한
CoFrame으로 매핑됩니다. - Auto Layout (direction · gap · alignment) 과 Sizing · Fill · Stroke · Effects 를 같이 다뤄야 할 때.
- 단순
<div>/Container를 raw 위젯으로 박지 않고 디자인 토큰 경유로 통일하고 싶을 때.
대신 다른 컴포넌트를 사용하세요:
CoCard: 사용자 의미 있는 카드 단위 (header / body / footer 슬롯 포함) 가 필요할 때.-
CoStacks/CoPosition: 자식들이 z 축으로 겹쳐야 하는 경우 (FlutterStack시맨틱). CoGroup: 절대 좌표로 자식을 배치해야 하는 경우.
기본 사용법 (Basic Usage)#
// 단일 자식 + chrome
CoFrame(
padding: EdgeInsets.all(CoreSpace.space16),
backgroundColor: theme.colorScheme.surface,
borderRadius: BorderRadius.circular(CoreRadius.box),
child: Text('Inside frame'),
)
// Auto Layout (Row)
CoFrame(
direction: CoreFrameDirection.row,
gap: CoreSpace.space12,
crossAxisAlignment: CoreCrossAxisAlignment.center,
children: [icon, label],
)
// Sizing + flex (이 frame 자체가 부모 flex 의 자식)
CoFrame(
flex: 1,
fit: CoreFlexFit.tight,
child: child,
)
// 효과 (elevation + dashed border)
CoFrame(
elevation: CoreFrameElevation.medium,
borderColor: theme.colorScheme.outline,
borderWidth: CoreBorderWidth.medium,
borderStyle: CoreFrameBorderStyle.dashed,
child: Text('Dashed elevated'),
)
// SEO 시맨틱 태그 (Web). Flutter 는 Semantics role 로 매핑.
CoFrame(
tag: 'main',
child: pageBody,
)
Props / Parameters#
Layer 1 — Visual / Figma#
| Prop | Type | 설명 |
|---|---|---|
direction |
CoreFrameDirection? |
row
/
column
/
rowReverse
/
columnReverse
/
wrap
.
null
이면 flex 아님 (block).
|
gap | double? | flex 자식 사이 간격 (logical px). |
mainAxisAlignment |
CoreMainAxisAlignment? |
direction 이 있을 때 주축 정렬. |
crossAxisAlignment |
CoreCrossAxisAlignment? |
교차축 정렬. |
alignment |
CoreAlignment? |
direction 이 null 일 때 9-grid 정렬. |
width / height | double? | 고정 크기. |
minWidth / minHeight / maxWidth / maxHeight |
double? |
제약. |
flex | int? | 부모 flex 내에서의 grow weight. |
fit |
CoreFlexFit? |
tight (flex-basis: 0) / loose (intrinsic). |
padding / margin | platform 타입 | inner / outer 간격. |
backgroundColor | platform 타입 | 단색 배경. |
gradient | CoreGradient? | 선형/방사형 그라디언트. |
backgroundImage |
CoreImageSource? |
배경 이미지 (URL / asset). |
borderColor
/
borderWidth
/
borderStyle
/
borderRadius
|
platform 타입 | Stroke. dashed / dotted 지원. |
boxShadow / innerShadow |
platform 타입 | 임의 그림자. boxShadow 가 elevation 보다 우선. |
layerBlur / backdropBlur |
double? |
자체 / 배경 블러 sigma. |
elevation |
CoreFrameElevation? |
none / soft / medium / strong 프리셋. |
clipBehavior |
CoreClipBehavior |
overflow 클립 정책. 기본 hardEdge. |
opacity | double? | 0..1. |
transform / transformAlignment |
platform 타입 / CoreAlignment? |
2D / 3D 변환 + 변환 원점. |
visible |
bool |
false 면 레이아웃에서 제거. 기본 true. |
Layer 2 — Behaviour#
| Prop | Type | 설명 |
|---|---|---|
onTap | void Function()? | 클릭 / 탭. |
onHover |
CoreValueChanged<bool>? |
마우스 호버 enter/leave. |
onFocus | CoreValueChanged<bool>? | 포커스 진입/이탈. |
cursor |
CoreCursor? |
pointer / text / grab / … 마우스 커서. |
Layer 3 — HTML / SEO (Web 우선, Flutter 는 Semantics 매핑)#
| Prop | Type | 설명 |
|---|---|---|
tag |
String |
Web 에서 emit 되는 HTML 태그. 기본
'div'
.
'main'
/
'nav'
/
'section'
/
'article'
/
'header'
/
'footer'
/
'aside'
로 SEO 구조 명시. Flutter 에서는 가장 가까운
Semantics
role 로 매핑.
|
Layer 4 — Accessibility / DOM metadata#
| Prop | Type | 설명 |
|---|---|---|
a11y |
CoreFrameA11y? |
role
(ARIA),
label
(
aria-label
/
Semantics.label
),
id
(Web DOM id),
attributes
(
aria-*
/
data-*
). 일반 케이스는
null
.
|
Children#
| Prop | Type | 설명 |
|---|---|---|
child | platform widget? | 단일 자식. |
children |
List<W>? |
다중 자식. child 와 동시 지정 금지. |
Figma 매핑#
| Figma 슬롯 | CoFrame prop |
|---|---|
| Auto Layout direction (Horizontal / Vertical / Wrap) | direction |
| Auto Layout spacing | gap |
| Auto Layout 정렬 (9-grid) | mainAxisAlignment + crossAxisAlignment |
| Sizing (Fixed / Hug / Fill) |
width
+
height
+
flex
(Fill 은
flex: 1, fit: tight
)
|
| Padding | padding |
| Fill — Solid | backgroundColor |
| Fill — Linear / Radial gradient | gradient |
| Fill — Image | backgroundImage |
| Stroke (color / weight / style / radius) |
borderColor
/
borderWidth
/
borderStyle
/
borderRadius
|
| Effects — Drop shadow | boxShadow 또는 elevation 프리셋 |
| Effects — Inner shadow | innerShadow |
| Effects — Layer blur | layerBlur |
| Effects — Background blur | backdropBlur |
| Layer opacity | opacity |
| Transform (rotate / skew / scale) | transform |
| Clip content | clipBehavior |
접근성 (Accessibility)#
-
일반 케이스는
a11y를null로 두면 됩니다 — Frame 자체는 시맨틱 의미가 없는 컨테이너이므로 보조 기술이 자동으로 자식만 노출합니다. -
클릭 가능한 영역은
onTap을 주면 자동으로Semantics(button: true)(Flutter) /tabindex="0"(Web) 가 부여됩니다. - ARIA role 이 필요한 경우
a11y: CoreFrameA11y(role: 'navigation', label: 'Sidebar')처럼 명시. -
Web 에서
tag: 'main'/'nav'/'section'/'article'등을 명시해야 검색 엔진과 스크린 리더가 페이지 구조를 정확히 파악합니다.