Mask | CoUI
LogoCoUI

Mask

자식을 지정된 모양으로 클리핑하는 마스크 컴포넌트

Mask#

Mask는 자식을 circle, squircle, heart, hexagon, star, triangle 등 15종 모양으로 클리핑합니다. Flutter는 ClipPath와 커스텀 CustomClipper로 경로를 계산하고, Web은 daisyUI mask-* CSS 클래스를 사용합니다.

Live Preview#

사용 시기#

  • 아바타처럼 이미지를 특정 모양으로 잘라야 할 때
  • 장식용 도형 배경
  • 아이콘/배지에 독특한 모양을 적용할 때

기본 사용법#

SizedBox(
  width: CoreSpace.space64,
  height: CoreSpace.space64,
  child: Mask(
    shape: .hexagon,
    child: Container(color: Theme.of(context).colorScheme.primary),
  ),
)
Mask(
  shape: .hexagon,
  child: div(
    [],
    classes: 'w-${CoreSpace.scale.space64} h-${CoreSpace.scale.space64} '
        'bg-\${cs.primary}',
  ),
)

Props#

속성타입기본값설명
child Widget / Component 클리핑 대상 콘텐츠 (required)
shape CoreMaskShape squircle 마스크 모양
half CoreMaskHalf none 절반 잘라내기 (none / first / second)

스타일 시스템 (Style System)#

CoreMaskStyle 필드#

필드타입설명
shape CoreMaskShape? Mask shape. null defers to [defaultShape].
half CoreMaskHalf? Half-crop. null defers to [defaultHalf].

지원되는 shape#

circle, squircle, square, heart, hexagon, hexagon2, decagon, pentagon, diamond, star, star2, triangle, triangle2, triangle3, triangle4.

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

✅ Do#

순수 장식용 클리핑에 사용

Mask(
  shape: .circle,
  child: Image.network(avatarUrl),
)

Maskchild 의 semantics 를 그대로 통과시킵니다 (자체 role/aria 없음) — 아바타 같은 이미지 크롭에 적합하며, 스크린 리더는 마스킹 여부와 무관하게 child 를 동일하게 안내합니다.


❌ Don't#

마스크 모양을 클릭 가능 영역의 경계로 신뢰하지 않기

// ❌ Web에서는 별 모양 바깥 영역도 그대로 클릭됩니다
Mask(
  shape: .star,
  child: Button(onPressed: handleTap, child: const Text('Play')),
)

Flutter ClipPath 는 모양 바깥 포인터를 거부하지만, Web 은 mask-image 로 paint 만 클리핑하므로(half 가 아닌 한) 사각형 전체가 클릭 가능합니다. 마스크된 인터랙티브 요소는 플랫폼별로 히트 영역이 달라집니다.

접근성 (Accessibility)#

역할 / Semantics#

양 플랫폼 모두 자체 role 이나 semantics 를 전혀 내보내지 않습니다. Flutter 는 ClipPath + 커스텀 CustomClipper 만 반환하고 Semantics 호출이 없으며, Web 은 co-mask 클래스와 inline mask CSS 만 실은 평범한 <div>configureAttributes 를 override 하지 않아 role / aria-* 가 하나도 붙지 않습니다.

child 자신의 semantics 가 안내의 전부입니다. 마스크된 영역에 이름이나 설명이 필요하면 Mask 가 아니라 child 쪽에 붙여야 합니다.

키보드#

처리하는 키가 없습니다. Web 생성자는 onKeyDown / onKeyUp 조차 노출하지 않고 id / classes / css / attributes / eventHandlers 만 받습니다.

포커스#

포커스 대상이 아닙니다. Flutter 에 FocusNode / Focus 가 없고 Web 에 tabindex 가 없어 어느 플랫폼에서도 traversal 정지점이 되지 않습니다.

스크린 리더#

child 가 그대로 통과합니다. 클리핑은 Web 에서 paint 단계, Flutter 에서 render 단계에 일어날 뿐 접근성 트리를 건드리지 않으므로, 마스킹된 아바타·이미지는 마스킹하지 않았을 때와 똑같이 안내됩니다.

알려진 제약#

  • hit-test 가 플랫폼마다 다릅니다 — 마스크된 자식이 인터랙티브할 때 실제 문제가 됩니다. Flutter 의 ClipPath 는 모양 바깥 포인터를 거부하지만, Web 은 mask-image 로 잘라내므로 paint 전용이라 사각형 전체가 그대로 클릭 가능합니다 (half 일 때만 clip-path 가 함께 붙습니다). 같은 마스크된 버튼이라도 포인터/터치 타겟이 플랫폼별로 달라지므로, 마스크 모양을 히트 영역의 경계로 신뢰하지 마세요.
  • 장식으로 표시할 수단이 없습니다aria-hidden 도, decorative 플래그도, alt 텍스트 슬롯도 없습니다. 순수 장식 도형이라면 소비자가 child 쪽에서 접근성 트리 밖으로 빼야 하고, 정보를 담은 마스크 이미지라면 child 에 직접 이름을 붙여야 합니다.

이 컴포넌트가 직접 다루지 않는 대비·모션 등 전역 축은 전역 접근성 축 에서 한 곳으로 관리됩니다.

관련 컴포넌트#

  • Avatar — 사람 얼굴·아이콘에 특화된 마스크 프리셋.
  • Card — 자유로운 컨테이너 레이아웃.