FormLabel | CoUI
LogoCoUI

FormLabel

폼 입력 필드용 라벨 (필수 표시 옵션 포함)

FormLabel#

폼 입력에 붙는 설명 라벨입니다. isRequiredtrue 면 라벨 뒤에 필수 표시(*)를 붙입니다(커스텀 표시는 requiredIndicator, 기본은 error 색 별표). Flutter / Web 1:1 동일 API 입니다.

Live Preview#

사용법#

FormLabel(label: const Text('이메일'), isRequired: true)

빠른 오버라이드 (Chain)#

이미 만든 FormLabel 인스턴스에 스타일을 빠르게 덧붙이고 싶다면 withStyle 체인을 쓸 수 있습니다. 생성자의 style 슬롯 인자와 동일하게 동작하지만, 이미 구성된 위젯 위에서 바로 이어 쓸 수 있습니다.

class FormLabelChainExample extends StatelessWidget {
  const FormLabelChainExample({super.key});

  @override
  Widget build(BuildContext context) {
    return FormLabel(
      label: const Text('이메일'),
      isRequired: true,
    ).withStyle(
      const CoreFormLabelStyle(
        labelStyle: CoreTextStyle.token(
          CoreTextStyles.titleMedium,
          color: CoreColor.token(CoreColors.primary),
        ),
        requiredColor: CoreColor.token(CoreColors.tertiary),
        requiredIndicatorGapStyle: CoreGapStyle(size: CoreSpace.space12),
      ),
    );
  }
}
class FormLabelChainExample extends StatelessComponent {
  const FormLabelChainExample({super.key});

  @override
  Component build(BuildContext context) {
    return FormLabel(
      label: Text('이메일'),
      isRequired: true,
    ).withStyle(
      const CoreFormLabelStyle(
        labelStyle: CoreTextStyle.token(
          CoreTextStyles.titleMedium,
          color: CoreColor.token(CoreColors.primary),
        ),
        requiredColor: CoreColor.token(CoreColors.tertiary),
        requiredIndicatorGapStyle: CoreGapStyle(size: CoreSpace.space12),
      ),
    );
  }
}

Props#

파라미터타입기본값설명
label Widget / Component required (Flutter) 라벨 콘텐츠
isRequired bool false 필수 표시(*) 노출 여부
requiredIndicator Widget / Component? null 커스텀 필수 표시 (기본: error 색 별표)
formLabelStyle CoreFormLabelStyle? null chrome / 타이포 단일 진입점

스타일 시스템 (Style System)#

CoreFormLabelStyle 필드#

필드타입설명
labelStyle CoreTextStyle? Nested [CoreTextStyle] slot for the label typography — role + colour. null → the design-system [defaultLabelStyle] ( labelLarge / on-surface). A caller that overrides only the colour keeps the default role, and vice versa, because the resolver merges this override on top of [defaultLabelStyle].
requiredColor CoreColor? Override colour applied to the required indicator.
requiredIndicatorGapStyle CoreGapStyle? Nested [CoreGapStyle] slot for the gap between the label and the required indicator — forwarded straight to Gap(gapStyle: …) . Gap runs its own resolve step, so this slot is merged on top of the design-system default in pre-scaling units (the receiving widget owns scaling).

사용 가이드라인 (Usage Guidelines)#

✅ Do#

입력 컴포넌트에 접근 가능한 이름을 직접 지정

FormLabel(label: const Text('이메일'), isRequired: true)
TextField(
  placeholder: const Text('you@company.com'),
  // 접근 가능한 이름은 이 TextField 쪽에서 직접 책임져야 함
)

FormLabel이 그리는 <label>for를 emit하지 않고 Flutter에는 대응하는 Semantics 연결조차 없어, 라벨이 어떤 컨트롤과도 연결되지 않습니다. 접근 가능한 이름은 입력 컴포넌트 쪽에서 직접 지정해야 합니다.


❌ Don't#

isRequired 하나로 "필수" 여부가 낭독된다고 가정하지 않기

// ❌ isRequired 는 시각적 별표만 만들 뿐 보조기술에 아무것도 알리지 않음
FormLabel(label: const Text('이메일'), isRequired: true)

isRequired는 시각적 별표만 만들 뿐 aria-required도, "필수"라는 텍스트도 보조기술에 노출하지 않습니다. 필수 여부를 낭독시키려면 입력 컴포넌트(예: FormFieldaria-required) 쪽에 별도로 표기해야 합니다.

접근성 (Accessibility)#

역할 / 시맨틱#

  • Web: 네이티브 <label> 요소로 렌더됩니다. 다만 for 속성을 emit 하지 않습니다 — 컴포넌트가 붙이는 속성은 호출자가 넘긴 것뿐입니다.
  • Flutter: Semantics / CoUISemantics 가 전혀 없습니다. DefaultTextStyle.mergeRow 로 텍스트만 그립니다.

기본 필수 표시(*)는 양 플랫폼 모두 낭독에서 제외됩니다 — Web 은 <span aria-hidden="true">, Flutter 는 ExcludeSemantics 입니다.

키보드#

처리하는 키가 없습니다. Web 의 <label> 도 클릭을 입력으로 전달하지 못합니다 — for 를 emit 하지 않고, FormField 안에서도 입력을 감싸지 않고 형제로 배치되기 때문입니다.

포커스#

포커스 관련 동작이 없습니다 — FocusNode / tabindex / 포커스 링 / 트랩 / 복원 모두 없습니다.

스크린 리더#

라벨 텍스트가 읽힙니다. Web 의 <label> 은 존재하지만 어떤 컨트롤과도 연결되어 있지 않아, 컨트롤의 접근 가능한 이름이 아니라 그냥 일반 텍스트로 낭독됩니다.

알려진 제약#

  • for / id 연결도, 입력 감싸기도 없어 <label> 의 시맨틱이 실질적으로 장식입니다. 이 라벨은 입력의 이름이 되지 못하며, Flutter 에는 라벨 연결 수단 자체가 없습니다. 입력의 접근 가능한 이름은 입력 컴포넌트 쪽에서 직접 지정하세요.
  • isRequired시각적 별표만 만듭니다. aria-required 도, "필수"라는 텍스트도 보조기술에 노출되지 않으므로 필수 여부는 입력 자체에 따로 표기해야 합니다.
  • 커스텀 requiredIndicator 는 숨김 처리를 우회합니다. 기본 별표와 달리 aria-hidden(Web) / ExcludeSemantics(Flutter) 가 붙지 않아 그대로 낭독됩니다. 장식용 마커라면 호출자가 직접 숨겨야 합니다.