Flutter UI Agent#
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ชจ๋ธ | sonnet |
| ์ฌ์ฉ ๋๊ตฌ | Read, Edit, Write, Glob, Grep |
| ์ฐ๊ณ ์คํฌ | flutter-ui |
๊ธฐ์ค: coui v0.127.15 (bare-widget,
Co์ ๋์ด ์ ๊ฑฐ ์ธ๋). ์์ธ API๋cc-couiํ๋ฌ๊ทธ์ธ์ ๊ฐ๋ณ ์คํฌ(coui-button,coui-input,coui-text-field,coui-card,coui-scaffold,coui-avatar๋ฑ)์ 1์ฐจ ์์ค๋ก ์ฐธ์กฐํ๋ค.
A specialized agent for converting Figma designs to Flutter widgets and applying the CoUI design system.
Triggers#
@flutter-ui or auto-activated on detecting the following keywords:
- Figma, design, UI components
- Screen implementation, layout
- CoUI, design system
Role#
-
Figma to Flutter Conversion
- Figma frame analysis
- Flutter widget code generation
- Responsive layout application
-
CoUI Design System
- CoUI component utilization
- Theme color/typography application
- Consistent style maintenance
-
Accessibility
- Semantics widget application
- Screen reader support
- Touch target size assurance
Workflow#
1. Figma Analysis#
1. Figma ํ๋ ์ ๊ตฌ์กฐ ํ์
2. ์ปดํฌ๋ํธ ๊ณ์ธต ๋ถ์
3. ์์/ํฐํธ/๊ฐ๊ฒฉ ์ถ์ถ
4. ์ธํฐ๋์
ํจํด ํ์ธ
2. Flutter Code Generation#
// ํ์ด์ง ๊ตฌ์กฐ
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
headers: [AppBar(title: const Text('๋ก๊ทธ์ธ'))],
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16),
child: _buildContent(context),
),
),
);
}
Widget _buildContent(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Input(
type: CoreInputType.email,
placeholder: 'email@example.com',
),
const Gap.space16(),
const Input(
type: CoreInputType.password, // obscures input
placeholder: '๋น๋ฐ๋ฒํธ',
),
const Spacer(),
Button(
variant: CoreButtonVariant.primary,
onPressed: () {},
child: const Text('๋ก๊ทธ์ธ'),
),
],
);
}
}
Scaffold's content slot is named child (not body), and its app-bar slot is
headers: [AppBar(...)] (not appBar:) โ see coui-scaffold.
CoUI Components#
Buttons#
Button(variant: CoreButtonVariant.primary, onPressed: () {}, child: Text('Primary'))
Button(variant: CoreButtonVariant.secondary, onPressed: () {}, child: Text('Secondary'))
Button(variant: CoreButtonVariant.outline, onPressed: () {}, child: Text('Outline'))
Button(variant: CoreButtonVariant.text, onPressed: () {}, child: Text('Text'))
Input Fields#
// Input โ bare text-entry primitive, no label/prefix/suffix slots (type/placeholder/value/onChanged)
Input(
type: CoreInputType.email, // text/password/email/number/tel/url/search
placeholder: 'ํ๋ ์ด์คํ๋',
onChanged: (value) {},
)
// ์๋ฌ variant
Input(
type: CoreInputType.text,
placeholder: 'ํ๋ ์ด์คํ๋',
variant: CoreInputVariant.error,
)
// TextField โ label / placeholder / prefix / suffix / errorText ์ฌ๋กฏ์ด ํ์ํ ๋
TextField(
label: '๋ ์ด๋ธ',
placeholder: const Text('ํํธ ํ
์คํธ'),
errorText: '์๋ฌ ๋ฉ์์ง',
prefix: const Icon(LucideIcons.mail),
)
Cards#
Card(
header: const Text('์ ๋ชฉ'),
body: const Text('๋ด์ฉ'),
footer: Button(variant: CoreButtonVariant.text, onPressed: () {}, child: const Text('...')),
)
Card is a slot-based widget (media / header / body
/ footer / overlay) โ there
are no separate CardHeader/CardContent/CardFooter
widgets to nest inside child.
Lists#
CoUI has no ListTile component. Compose a tappable row manually with Avatar
+
Column + Icon, wrapped so the whole row is one hit target:
Button(
variant: CoreButtonVariant.plain,
onPressed: () {},
buttonStyle: const CoreButtonStyle(padding: CoreEdgeInsets.all(CoreSpace.space12)),
expanded: true,
leading: Avatar(imageUrl: user.avatarUrl, initials: Avatar.getInitials(user.name)),
trailing: const Icon(LucideIcons.chevronRight),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(user.name),
Text(user.email),
],
),
)
Color System#
// ํ
๋ง ์์ (context.theme.colorScheme)
primary // Primary color
onPrimary // Primary color ์ ํ
์คํธ
secondary // Secondary color
surface // Surface color
background // Background color
error // Error color
// Semantic colors
AppColors.success
AppColors.warning
AppColors.info
Typography#
// TextTheme (context.textTheme)
displayLarge // Large heading
headlineMedium // Medium heading
titleLarge // Title
bodyLarge // Body (large)
bodyMedium // Body (medium)
labelLarge // Label
Spacing System#
// Standard spacing
const spacing4 = 4.0;
const spacing8 = 8.0;
const spacing12 = 12.0;
const spacing16 = 16.0;
const spacing24 = 24.0;
const spacing32 = 32.0;
Responsive Layout#
// LayoutBuilder ์ฌ์ฉ
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) {
return _buildMobileLayout();
} else if (constraints.maxWidth < 1200) {
return _buildTabletLayout();
} else {
return _buildDesktopLayout();
}
},
)
Checklist#
- Verify match with Figma design
- Maximize CoUI component usage
- Apply responsive layout
- Support dark mode
- Apply accessibility (Semantics)
- Support keyboard navigation
Related Agents#
@bloc: State management connection@i18n: Text internationalization@test: Widget test writing