FormLabel | CoUI
본문으로 건너뛰기
LogoCoUI

FormLabel

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

목차

폼 입력에 붙는 설명 라벨입니다. isRequired 가 true 면 라벨 뒤에 필수 표시(*)를 붙입니다(커스텀 표시는 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 / Parameters#

W 는 Flutter의 Widget, Web의 Jaspr Component 입니다. 공통 호출에서는 label을 명시합니다. Web에서 label을 생략할 수 있는 것은 기존 soft-requiredness 호환 예외입니다.

파라미터타입기본값설명
labelW?명시라벨 콘텐츠
isRequired bool false 필수 표시(*) 노출 여부
requiredIndicator W? null 커스텀 필수 표시 (기본: error 색 별표)
size CoreComponentSize md 라벨 크기 단계 — xs · sm · md 는 label-medium (13 / 500), lg · xl · xl2 는 label-large (14 / 500)
enabled bool true 라벨 활성/비활성 타이포그래피 — 활성은 onSurfaceVariant (라벨은 컨트롤의 이름이고 값이 더 크게 읽힙니다), 비활성은 disabledColor (기본 disabledContent )입니다. TextField · TextArea 는 자기 labelDisabledColor ( onSurfaceSubtle )를 넘겨 한 단계 위에 둡니다
formLabelStyle CoreFormLabelStyle? null chrome / 타이포 단일 진입점

스타일 시스템 (Style System)#

CoreFormLabelStyle 필드#

필드타입설명
labelStyle CoreTextStyle? Nested [CoreTextStyle] slot for the label typography — role + colour. null → the size-keyed default in [defaultsBySize]. A caller that overrides only the colour keeps the default role, and vice versa, because the resolver merges this override on top of that size default.
requiredColor CoreColor? Override colour applied to the required indicator while enabled.
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).
disabledColor CoreColor? Override colour applied to the label and the required indicator while CoreFormLabelContract.enabled is false . null → the design-system [defaultDisabledColor].

동작 스펙 (Behavior)#

  • label과 선택적 필수 표시를 가로로 놓습니다. isRequired: true 이면 requiredIndicator를 쓰고, 없으면 기본 별표를 표시합니다. 기본 별표는 장식으로 리더에서 제외합니다.
  • required는 검증 규칙이 아니라 표시입니다. enabled: false 도 라벨 스타일만 바꾸며 연결된 입력을 비활성화하지 않습니다. 자체 콜백·포커스·입력값이 없습니다.
  • 검증·description·error까지 필요한 필드 래퍼이면 FormField, 단순 정적 라벨이면 Label 입니다.

사용 가이드라인 (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도, "필수"라는 텍스트도 보조기술에 노출하지 않습니다. 필수 여부를 낭독시키려면 입력 컴포넌트(예: FormField의 aria-required) 쪽에 별도로 표기해야 합니다.

접근성 (Accessibility)#

역할#

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

기본 필수 표시(*)는 양 플랫폼 모두 낭독에서 제외됩니다 — 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) 가 붙지 않아 그대로 낭독됩니다. 장식용 마커라면 호출자가 직접 숨겨야 합니다.

크로스 플랫폼 차이점 (Platform Differences)#

항목FlutterWeb
렌더링Row·DefaultTextStyle<label> 래퍼
입력 연결호출부의 필드 의미로 구성필요 시 caller attributes의 for로 연결
기본 별표 숨김ExcludeSemanticsaria-hidden span
생성자 관대함nullable label 인자를 필수로 받음label 생략 가능