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

Status

온라인, 오프라인 등 사용자 또는 시스템 상태를 표시하는 컴포넌트

목차

사용자 또는 시스템의 현재 상태를 컬러 점으로 표시하는 컴포넌트입니다. 채팅, 사용자 목록, 서버 모니터링 등에 활용합니다.

기본 사용법 (Basic Usage)#

// 성공 상태 (온라인)
Status(
  color: CoreStatusColor.success,
  size: CoreStatusSize.lg,
  semanticLabel: 'Online',
)

// 에러 상태
Status(
  color: CoreStatusColor.error,
  size: CoreStatusSize.md,
)

// 경고 상태
Status(
  color: CoreStatusColor.warning,
)
// 성공 상태 (온라인)
Status(
  color: CoreStatusColor.success,
  size: CoreStatusSize.lg,
  semanticLabel: 'Online',
)

// 에러 상태
Status(
  color: CoreStatusColor.error,
  size: CoreStatusSize.md,
)

// 경고 상태
Status(
  color: CoreStatusColor.warning,
)

빠른 오버라이드 (Chain)#

이미 만든 Status 인스턴스에 스타일을 빠르게 덧붙이고 싶다면 withStyle 체인을 쓸 수 있습니다. 생성자의 style 슬롯 인자와 동일하게 동작하지만, 이미 구성된 위젯 위에서 바로 이어 쓸 수 있습니다. .radius4처럼 Core 토큰 상수 이름과 똑같은 이름의 getter도 있습니다 — withStyle을 한 번 더 줄인 sugar로, 이름이 곧 값이라(radius4 == CoreRadius.radius4) 어느 컴포넌트에서 써도 뜻이 갈리지 않습니다.

class StatusChainExample extends StatefulWidget {
  const StatusChainExample({super.key});

  @override
  State<StatusChainExample> createState() => _StatusChainExampleState();
}

class _StatusChainExampleState extends State<StatusChainExample> {
  @override
  Widget build(BuildContext context) {
    return const Status(
          color: CoreStatusColor.primary,
          size: CoreStatusSize.lg,
        )
        .withStyle(
          const CoreStatusStyle(
            size: CoreSize.size24,
            color: CoreColor.token(CoreColors.tertiary),
          ),
        )
        .radius16;
  }
}
class StatusChainExample extends StatefulComponent {
  const StatusChainExample({super.key});

  @override
  State<StatusChainExample> createState() => _StatusChainExampleState();
}

class _StatusChainExampleState extends State<StatusChainExample> {
  @override
  Component build(BuildContext context) {
    return Status(
          color: CoreStatusColor.primary,
          size: CoreStatusSize.lg,
        )
        .withStyle(
          const CoreStatusStyle(
            size: CoreSize.size24,
            color: CoreColor.token(CoreColors.tertiary),
          ),
        )
        .radius16;
  }
}

Live Preview#

사용 시기 (When to Use)#

이 컴포넌트를 사용하세요:

  • 사용자의 온라인/오프라인 상태를 표시할 때
  • 서버, 서비스의 운영 상태를 표시할 때
  • 아바타 옆에 작은 상태 점을 표시할 때

대신 다른 컴포넌트를 사용하세요:

  • Badge: 숫자나 알림 개수를 표시할 때
  • ValidationBadge: 유효성 검증 결과를 표시할 때

Props / Parameters#

속성타입기본값설명
color CoreStatusColor neutral 상태 색상 (neutral, primary, secondary, tertiary, info, success, warning, error). variant 를 주면 무시됩니다
variant CoreStatusVariant? null 접속 상태 (online, busy, away, offline). 색과 모양을 함께 정합니다 — online 은 초록 채운 점, busy 는 빨간 점 위 가로 막대, away 는 노란 고리, offline 은 outline 색 고리
size CoreStatusSize md 점 크기 (xs: 6px, sm: 8px, md: 10px, lg: 12px, xl: 14px)
label Widget? / Component? null 점 옆에 보이는 글자. 크기마다 본문 역할(12 · 13 · 14 · 15 · 15)과 점과의 간격(4 · 6 · 6 · 8 · 8)이 정해집니다
semanticLabel String? null 현재 상태를 설명하는 접근성 라벨. 화면에 보이는 label 과 다른 값입니다
animatedboolfalse점의 맥동 표시
statusStyle CoreStatusStyle? null 인스턴스 단위 chrome / dimensional override (size, color, borderRadius 직접 지정)

스타일 시스템 (Style System)#

CoreStatusStyle 필드#

필드타입설명
size double? Status dot size override (logical px). When non-null, overrides the size resolved from [defaultsBySize] for the variant. Raw double — single-axis pixel value (verify.md u-1 exception).
color CoreColor? Status dot colour override. When non-null, overrides the colour resolved from [defaultsByColor] for the variant.
borderRadius CoreBorderRadius? Status dot border radius override. When non-null, overrides [defaultBorderRadius] (the full pill / circle radius).
ringWidth double? Stroke of a ring state. null → [defaultRingWidth].
barLength double? Length of the bar across a busy dot — the bar's width as the eye reads it, running across the dot (the designer's "막대 폭"); [barWidth] is its thickness. null → the size row's value in [defaultsBySize]: 4 · 4 · 6 · 8 · 8 from xs to xl.
barWidth double? Thickness of the bar across a busy dot. null → [defaultBarWidth].
barColor CoreColor? Colour of the bar across a busy dot. null → [defaultBarColor].
barBorderRadius CoreBorderRadius? Corners of the bar across a busy dot. null → [defaultBarBorderRadius] (round ends — half the bar's thickness).
labelStyle CoreTextStyle? Text style of the visible label. null → the size row's role in [defaultsBySize] (xs 12 · sm 13 · md 14 · lg, xl 15 — the body roles) in on-surface , merged with the state's own label colour in [defaultsByVariant] ( offline reads on-surface-variant ).
labelSpacing double? Space between the dot and the visible label. null → the size row's value in [defaultsBySize].

CoreStatusStyle 변형별 기본값 (CoreStatusStyle)#

필드 online busy away offline
colorsuccesserrorwarningoutline
labelStyle — — — CoreTextStyle(color: CoreColor.token(CoreColors.onSurfaceVari…

동작 스펙 (Behavior)#

  • 원형 dot으로 렌더링
  • 색상은 CoreStatusColor enum으로 선택하거나, CoreStatusVariant 로 접속 상태(색 + 모양)를 선택
  • variant 가 없으면 기존처럼 색 하나로 채운 점입니다. 있으면 online·busy 는 채운 점, away·offline 은 안쪽으로 2px 그린 고리입니다 (점 크기는 같습니다)
  • busy 는 점 위에 2px 가로 막대를 그립니다. 막대 길이는 점 크기에 따라 4 · 4 · 6 · 8 · 8 이고, 끝은 두께의 절반으로 둥급니다(barBorderRadius)
  • 크기는 CoreStatusSize enum으로 선택
  • CoreStatusTheme으로 프로젝트 레벨 size/color override 가능
  • animated는 표시 점을 맥동시키며 연결 상태를 측정하거나 주기적으로 데이터를 요청하지 않습니다. 이름과 상태 변경은 호출자가 새 파라미터로 전달합니다.

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

하나의 현재 상태를 작은 점으로 표시하면 Status를 사용합니다. 텍스트 라벨·개수가 함께 필요하면 Badge, 여러 시점의 상태 이력은 Tracker, 검증 규칙의 pending/valid/invalid 표시는 ValidationBadge를 선택합니다. 점의 색만으로 상태를 말하지 말고 주변 텍스트나 semanticLabel을 함께 제공합니다.

✅ Do#

색만으로 상태를 전달하지 말고 semanticLabel을 함께 주기

Status(
  color: CoreStatusColor.success,
  semanticLabel: 'Online',
)

semanticLabel이 없으면 Flutter는 시맨틱을 아예 만들지 않아 스크린 리더가 점을 건너뜁니다. 상태를 색상 하나로만 전달하면 스크린 리더 사용자와 색맹 사용자 모두에게 그 의미가 사라지므로, 무엇의 상태인지 말해주는 라벨을 항상 함께 주세요.


❌ Don't#

숫자·텍스트 라벨이 필요한 곳에 사용하지 않기

// ❌ 읽지 않은 알림 개수를 표시하려는 의도
Status(color: CoreStatusColor.error)

Status는 원형 점 하나만 그리는 컴포넌트라 숫자나 텍스트를 표시할 수 없습니다. 알림 개수 같은 값은 Badge를 사용하세요.

접근성 (Accessibility)#

역할#

  • Web — 항상 role="status" + aria-label 을 emit 합니다. configureAttributes 에서 붙고 호출자 attributes 가 뒤에 병합되므로, 원하면 호출자가 덮어쓸 수 있습니다.
  • Flutter — semanticLabel 을 준 경우에만 Semantics(label:) 로 감쌉니다. role 도 liveRegion 도 설정하지 않고, 라벨이 없으면 시맨틱 노드 없이 색 상자만 남습니다.

키보드#

없음. 점은 양 플랫폼 모두 포커스를 받지 않고 키 핸들러가 없습니다. Web 생성자는 attributes 는 노출하지만 이벤트 핸들러 파라미터는 노출하지 않아, 호출자가 키 조작을 붙일 수 없습니다.

스크린 리더#

  • 이름의 출처는 semanticLabel 하나입니다.
  • Web 은 semanticLabel 이 없으면 하드코딩된 영어 "status" 를 aria-label 로 내보냅니다. 로컬라이제이션을 거치지 않아 로케일과 무관하게 그대로 읽히고, 정작 어떤 상태인지는 말하지 않습니다.
  • Flutter 는 같은 경우 아무것도 읽지 않습니다. 점 옆에 이미 상태를 말하는 텍스트가 있는 배치를 전제한 선택입니다.
  • 통보는 Web 에서만 됩니다. role="status" 의 암묵적 polite 라이브 리전이라 라벨이 바뀌면 다시 읽히고, Flutter 는 liveRegion 을 설정하지 않아 조용합니다.

포커스 관리#

없음. 오버레이가 아니어서 진입 시 포커스 이동이 없고, 이탈·트랩도 해당하지 않습니다.

알려진 제약#

  • 라이브 리전이 한쪽 플랫폼에만 있습니다. 같은 코드가 Web 에서는 상태 변화를 통보하고 Flutter 에서는 통보하지 않습니다. Status 에 liveRegion 토글이 없어 Flutter 쪽에서 켤 방법이 없으므로, 변화 통보가 필요하면 상태 텍스트를 담은 라이브 리전을 호출자가 따로 두어야 합니다.
  • 이름의 기본값이 플랫폼마다 다릅니다. semanticLabel 을 생략하면 Web 은 번역되지 않은 "status" 를 읽고 Flutter 는 침묵합니다. semanticLabel 을 항상 명시하면 양쪽이 같아집니다.
  • color 만 쓰면 상태를 색으로만 구분합니다. 8 개 CoreStatusColor 는 색 토큰만 다르고 크기 · 모양 · 아이콘은 동일한 원입니다. variant 를 쓰면 online · busy(막대) · away/offline(고리) 가 모양으로도 갈립니다. 색 강제 모드에서는 이 색들이 같은 시스템 색으로 접혀 서로 구분되지 않습니다. 대안은 semanticLabel 을 반드시 주고, 점 옆에 상태를 말하는 텍스트를 함께 두는 것입니다.

전역 축(동작 줄이기 · 고대비 · 색 강제 모드 · 시맨틱 역할 · 최소 터치 타겟)은 접근성 페이지가 한 곳에서 다룹니다.

Flutter는 semanticLabel이 있을 때 live region을 추가하며 라벨을 생략하면 장식 점만 렌더합니다. 현재 Web은 라벨 유무와 관계없이 status 역할을 내보내고 라벨이 있으면 aria-label을 추가합니다. 두 플랫폼 모두 상태의 실제 의미를 알려야 하면 호출자가 라벨을 지정해야 합니다.

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

항목FlutterWeb
클래스명StatusStatus
렌더링 Container + BoxDecoration(circle) span + inline style border-radius: 50%
접근성라벨이 있을 때 Semantics live region현재 status 역할은 항상, aria-label은 라벨이 있을 때
  • Avatar: 아바타 옆에 Status dot을 배치
  • Badge: 숫자/텍스트 라벨이 필요한 경우
  • ValidationBadge: 유효성 검증 결과 표시