LogoCocode Skills

CoUI Flutter Quick Reference

이 프로젝트에서는 **`context.textStyles`**를 사용합니다 (22개 파일에서 사용 중).

💡 전체 가이드는 CLAUDE.md를 참조하세요. 이 문서는 CoUI 컴포넌트 사용 시 빠른 참조를 위한 요약본입니다.

Typography API 가이드#

프로젝트 표준: context.textStyles#

이 프로젝트에서는 **context.textStyles**를 사용합니다 (22개 파일에서 사용 중).

// ✅ 프로젝트 표준: textStyles 사용
style: context.textStyles.lgSemibold
style: context.textStyles.smSemibold
style: context.textStyles.sm.merge(context.textStyles.medium)

// ✅ copyWith 조합
style: context.textStyles.lgSemibold.copyWith(
  color: context.appColors.neutral5,
)

API 선택#

API상태
context.textStyles프로젝트 표준 (22개 파일 사용)
context.typography❌ 사용 금지 (0건)

조합 Getters (자주 사용)#

Getter구성예시
lgSemibold16px + 600 weight제목, 강조 텍스트
smSemibold12px + 600 weight라벨, 배지
baseMedium14px + 500 weight본문 강조
sm12px보조 텍스트
xs10px캡션

Font Size 전체 목록#

GetterSize용도
xs10px캡션, 주석
sm12px보조 텍스트, 라벨
base14px기본 본문
lg16px강조 본문, 소제목
xl20px제목
x2l24px큰 제목
x3l30px페이지 제목
x4l36px대형 제목
x5l48pxHero 텍스트

TextField features 파라미터#

⚠️ deprecated: leading, trailing 파라미터는 deprecated되었습니다.

// ✅ 새로운 API: features 파라미터
TextField(
  controller: controller,
  placeholder: const Text('입력해주세요'),
  filled: true,  // 배경색 적용 (base200)
  features: [
    InputFeature.leading(const Icon(Icons.search, size: 20)),
    InputFeature.trailing(const Icon(Icons.clear, size: 18)),
  ],
  onChanged: (value) => ...,
)

// ❌ deprecated: leading/trailing 파라미터
TextField(
  leading: Icon(Icons.search),   // deprecated
  trailing: Icon(Icons.clear),   // deprecated
)

TextField 주요 속성#

속성타입설명
filledbooltrue면 배경색(base200) 적용
border Border 테두리 설정 (Border.all(color: context.colorScheme.base300))
borderRadiusBorderRadius테두리 반경
features List leading, trailing, clear 등

ButtonSize & ButtonDensity#

ButtonSize 옵션#

⚠️ 주의: ButtonSize.medium존재하지 않습니다!

상수스케일용도
ButtonSize.xSmall0.5x매우 작은 버튼
ButtonSize.small0.75x작은 버튼
ButtonSize.normal1.0x기본값
ButtonSize.large2.0x큰 버튼
ButtonSize.xLarge3.0x매우 큰 버튼
// ✅ CORRECT: 존재하는 크기 사용
ButtonStyle.primary(size: .normal)
ButtonStyle.primary(size: .small)

// ❌ WRONG: medium 없음 (컴파일 에러)
ButtonStyle.primary(size: .medium)  // 에러!

ButtonDensity 옵션#

상수용도
ButtonDensity.normal기본 밀도
ButtonDensity.comfortable여유로운 패딩
ButtonDensity.dense컴팩트한 버튼 (테이블 내 버튼)
ButtonDensity.compact최소 패딩
ButtonDensity.icon아이콘 전용
ButtonDensity.iconComfortable아이콘 + 여유 패딩
ButtonDensity.iconDense아이콘 + 컴팩트
// 테이블 내 컴팩트한 버튼
Button.outline(
  style: const ButtonStyle.outline(density: .dense),
  onPressed: handleTap,
  child: const Text('복사'),
)

Badge 컴포넌트#

상태 표시용 배지 컴포넌트입니다. ButtonStyle과 함께 사용합니다.

Badge 종류#

컴포넌트용도기본 색상
PrimaryBadge긍정적 상태 (판매중, 활성 등)primary
DestructiveBadge부정적 상태 (중지, 삭제 등)destructive (red)

사용 예시#

// ✅ 기본 사용
const PrimaryBadge(child: Text('판매중'))
const DestructiveBadge(child: Text('판매 중지'))

// ✅ density 조절로 컴팩트하게
const PrimaryBadge(
  style: ButtonStyle.primary(density: .dense),
  child: Text('판매중'),
)

const DestructiveBadge(
  style: ButtonStyle.destructive(density: .dense),
  child: Text('판매 중지'),
)

// ✅ 조건부 배지
child: book.isActive
    ? const PrimaryBadge(
        style: ButtonStyle.primary(density: .dense),
        child: Text('판매중'),
      )
    : const DestructiveBadge(
        style: ButtonStyle.destructive(density: .dense),
        child: Text('판매 중지'),
      ),

Gap & Insets 상수#

Gap 사용법#

const Gap.s1()        // 4px
const Gap.s2()        // 8px
const Gap.s4()        // 16px
Gap(Insets.small)     // 8px
Gap(Insets.medium)    // 16px
Gap(Insets.large)     // 24px

Insets 상수 표#

상수용도
Insets.xSmall4px아이콘 간격
Insets.small8px요소 간격
Insets.medium16px섹션 패딩
Insets.large24px카드 패딩
Insets.xLarge32px페이지 마진

로딩/스켈레톤 패턴#

// 스켈레톤 로딩 (전체 위젯)
widget.skeletonizer(enabled: state.isLoading)

// 조건부 로딩 (스피너)
widget.loadingOr(
  isLoading: state.isLoading,
  loadingWidget: const CircularProgressIndicator(),
)

// 빈 상태 처리
listWidget.emptyOrWhen(
  condition: () => list.isEmpty,
  emptyWidget: const EmptyStateWidget(),
)

완전한 페이지 예시#

class MyPage extends HookWidget {
  const MyPage({super.key});

  @override
  Widget build(BuildContext context) {
    final appColors = context.appColors;

    return BlocProvider(
      create: (_) => getIt<MyBloc>(),
      child: BlocBuilder<MyBloc, MyState>(
        builder: (context, state) {
          return Scaffold(
            headers: [
              AppBar(
                title: Text(
                  '페이지 제목',
                  style: context.textStyles.lgSemibold.copyWith(
                    color: appColors.neutral5,
                  ),
                ),
              ),
            ],
            child: Padding(
              padding: const .symmetric(horizontal: Insets.medium),
              child: Column(
                crossAxisAlignment: .start,
                children: [
                  const Gap(Insets.medium),
                  TextField(
                    placeholder: const Text('이름을 입력하세요'),
                    features: const [
                      InputFeature.leading(Icon(Icons.person, size: 20)),
                    ],
                    onChanged: (value) => context.read<MyBloc>().add(
                      MyEvent.nameChanged(value),
                    ),
                  ),
                  const Gap(Insets.medium),
                  Button.primary(
                    expanded: true,
                    enabled: state.isValid,
                    onPressed: () => context.read<MyBloc>().add(
                      const MyEvent.submitted(),
                    ),
                    child: const Text('저장'),
                  ),
                ],
              ),
            ).skeletonizer(enabled: state.isLoading),
          );
        },
      ),
    );
  }
}

색상 체계 (Console UI)#

AppColors neutral 시리즈#

색상HEX용도
neutral100#FFFFFF흰색 배경
neutral95#F9FAFB헤더/섹션 배경 (본문과 구분)
neutral85#F4F5F6밝은 회색
neutral80#ECEEEF기본 테두리
neutral70#B4B8C4진한 테두리 (선명한 구분선)
neutral60#8F929A비활성 텍스트
neutral30-본문 텍스트
// 헤더 배경 (본문과 구분)
color: context.appColors.neutral95,

// 진한 테두리 (선명하게)
border: Border(
  right: .new(color: context.appColors.neutral70),
),

// 기본 테두리
border: Border.all(color: context.appColors.neutral80),

ColorScheme base 시리즈#

CoUI의 DaisyUI 기반 색상 체계입니다.

색상용도
base100가장 밝은 배경
base200중간 배경 (filled TextField)
base300가장 진한 배경/테두리
// TextField 배경
TextField(
  filled: true,  // base200 배경
  border: Border.all(color: context.colorScheme.base300),
)

// 필터 다이얼로그 테두리
OutlinedContainer(
  backgroundColor: theme.colorScheme.base100,
  borderColor: theme.colorScheme.base300,  // 진한 테두리
)

참조 문서#

다음 내용은 **CLAUDE.md**를 참조하세요:

  • 색상 규칙 (AppColors, context.appColors)
  • Dot Shorthand 규칙 (Dart 3.10+)
  • Button/IconButton 사용법
  • BLoC Event/State 패턴 (sealed class)
  • BLoC async 핸들러 (isClosed 체크)
  • Context Extensions 전체 목록