Tag
태그 — 무엇을 어느 분류에 넣는지 분류색으로 보여 주는 짧은 라벨
목차
Tag 는 항목을 어느 분류에 넣는지 말하는 짧은 라벨입니다. 색은 분류색(CoreCategoryColor)
아홉 가지 중 하나이고, 세기는 옅은 바탕에 선을 두른 subtle 과 채운 bold
두 가지입니다.
표시 전용이라 누를 수 없고, 상태 · 포커스도 없습니다 — 사람이 누르거나 지우는 라벨은
Chip, 상태를 말하는 라벨은 Badge
입니다.
기본 사용법 (Basic Usage)#
Tag(color: CoreCategoryColor.blue, child: Text('디자인'))
Tag(
color: CoreCategoryColor.green,
emphasis: CoreTagEmphasis.bold,
size: CoreTagSize.sm,
child: Text('새 글'),
)
Tag(color: CoreCategoryColor.blue, child: Text('디자인'))
Tag(
color: CoreCategoryColor.green,
emphasis: CoreTagEmphasis.bold,
size: CoreTagSize.sm,
child: Text('새 글'),
)
child 에 넘긴 Text 는 태그가 정한 글자 역할(md 는 labelSmall, sm
은 labelXs)과 분류색의 글자색으로
그려지고, 한 줄로 놓입니다. 색을 정하지 않은 태그는 gray 입니다 — 정하지 않은 분류를 어떤 색이 주장하지 않게 합니다.
Live Preview#
코드 보기
class TagDefaultExample extends StatelessComponent {
const TagDefaultExample({super.key});
@override
Component build(BuildContext context) {
// Every default — gray, subtle, md.
return Tag(child: Text('Tag'));
}
}
class TagDefaultExample extends StatelessWidget {
const TagDefaultExample({super.key});
@override
Widget build(BuildContext context) {
// Every default — gray, subtle, md.
return const Tag(child: Text('Tag'));
}
}
구조 (Anatomy)#
┌─────────────┐
│ label │ child
└─────────────┘
box background · border (subtle)
| 부분 | 역할 | 슬롯 |
|---|---|---|
| 상자 | 단의 높이(24 · 20)만큼의 면. subtle 은 분류색의 컨테이너 바탕에 안쪽 1px 선, bold 는 분류색 채움 |
|
| 라벨 | 상자 가운데에 한 줄로 놓이는 글자 — 단의 글자 역할과 분류색의 글자색으로 그려집니다 | child |
Figma: ❖ Tag
Figma 속성 대응#
| Figma | 코드 | 비고 |
|---|---|---|
Color (red … gray) |
color |
CoreCategoryColor 와 같은 순서 · 이름 |
Emphasis (subtle · bold) |
emphasis |
|
Size (md · sm) | size | |
Child (텍스트) | child | 코드는 텍스트가 아니라 위젯을 받습니다 |
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 글 · 일정 · 상품 같은 항목이 어느 분류에 속하는지 보여 줄 때
- 표의 칸이나 목록의 한 줄 안에서 분류를 색으로 구별할 때
대신 다른 컴포넌트를 사용하세요:
Props / Parameters#
W 는 Flutter의 Widget / Web의 Jaspr Component입니다.
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
child | W | 필수 | 라벨 — 보통 Text |
color |
CoreCategoryColor |
CoreTagContract.defaultColor(gray) |
분류색 아홉 가지 중 하나 |
emphasis |
CoreTagEmphasis |
CoreTagEmphasis.defaultEmphasis(subtle) |
세기 — subtle(옅은 바탕 + 선) · bold(채움) |
size |
CoreTagSize |
CoreTagSize.defaultSize(md) |
단 — md(24) · sm(20) |
tagStyle |
CoreTagStyle? |
null |
모든 chrome 이 지나는 단일 슬롯 (아래 표 참고) |
CoreTagStyle 필드#
| 필드 | 타입 | 설명 |
|---|---|---|
backgroundColor |
CoreColor? |
Fill colour override.
null
defers to the hue's colour for the emphasis ([CoreTagStyle.resting]).
|
foregroundColor |
CoreColor? |
Label colour override. null defers to the hue's colour for the emphasis. |
borderColor |
CoreColor? |
Border stroke colour.
null
defers to the hue, which states one only for [CoreTagEmphasis.subtle]; with no colour no border is drawn.
|
borderWidth |
double? |
Border stroke width (logical px). null defers to [defaultBorderWidth]. |
borderRadius |
CoreBorderRadius? |
Border radius. null defers to the step's corner in [defaultsBySize]. |
padding |
CoreEdgeInsets? |
Padding around the label.
null
defers to
CoreTagStyle.defaultsBySize[size]!.padding!
. Horizontal only by default — the height is [minHeight].
|
minHeight |
double? |
Height of the tag (logical px); the label is centred in it.
null
defers to
CoreTagStyle.defaultsBySize[size]!.minHeight!
.
|
labelStyle |
CoreTextStyle? |
Label text style override.
null
defers to the step's role in [defaultsBySize] with the emphasis's weight from [defaultsByEmphasis] laid over it.
|
스타일 시스템 (Style System)#
tagStyle#
- 시맨틱: 위젯 파라미터로 직접 (
color·emphasis·size) -
chrome / dimensional:
CoreTagStyle한 곳으로 (채움 · 글자색 · 선 · 모서리 · 여백 · 높이 · 라벨 글자)
| 부분 | 필드 | md | sm |
|---|---|---|---|
| 높이 | minHeight | 24 | 20 |
| 여백 | padding | 좌우 8 | 좌우 6 |
| 모서리 | borderRadius | 6 | 4 |
| 라벨 | labelStyle |
labelSmall |
labelXs |
| 선 | borderWidth |
1 (subtle 만) |
1 (subtle 만) |
색은 분류색 하나의 다섯 슬롯에서 옵니다.
| 세기 | 채움 | 글자 | 선 | 라벨 굵기 |
|---|---|---|---|---|
subtle |
category-{c}-container |
on-category-{c}-container |
category-{c}-outline |
역할 그대로(500) |
bold |
category-{c} |
on-category-{c} |
없음 | 600 |
라이트 모드에서 outline 슬롯은 컨테이너와 같은 톤이라 선이 보이지 않고, 다크 · 고대비 모드에서 드러납니다.
이건 팔레트의 진술이고 태그가 따로 다루는 경우가 아닙니다.
Resolve chain#
CoreTagStyle.defaultsBySize[size]
→ CoreTagStyle.defaultsByEmphasis[emphasis]
→ CoreTagStyle.resting(color, emphasis) // 분류색 × 세기의 색
→ CoreTagTheme.style // 프로젝트 공통
→ CoreTagTheme.colorStyles[color]
→ CoreTagTheme.emphasisStyles[emphasis]
→ widget.tagStyle // 인스턴스별
테마로 덮어쓰기#
CoreComponentTheme(
tag: CoreTagTheme(
style: CoreTagStyle(
borderRadius: CoreBorderRadius.all(CoreRadius.radius9999),
),
emphasisStyles: {
CoreTagEmphasis.bold: CoreTagStyle(
padding: CoreEdgeInsets.symmetric(horizontal: CoreSpace.space10),
),
},
),
)
빠른 오버라이드 (Chain)#
이미 만든 Tag 인스턴스에 스타일을 빠르게 덧붙이고 싶다면 withStyle 체인을 쓸 수 있습니다. 생성자의
tagStyle 인자와 동일하게 동작하지만, 이미 구성된 위젯 위에서 바로 이어 쓸 수 있습니다.
class TagChainExample extends StatelessWidget {
const TagChainExample({super.key});
@override
Widget build(BuildContext context) {
// withStyle full-control — a tweak laid over the hue's colours.
return const Tag(
color: CoreCategoryColor.purple,
child: Text('Rounded'),
).withStyle(
const CoreTagStyle(
borderRadius: CoreBorderRadius.all(CoreRadius.radius9999),
padding: CoreEdgeInsets.symmetric(horizontal: CoreSpace.space12),
),
);
}
}
class TagChainExample extends StatelessComponent {
const TagChainExample({super.key});
@override
Component build(BuildContext context) {
// withStyle full-control — a tweak laid over the hue's colours.
return Tag(
color: CoreCategoryColor.purple,
child: Text('Rounded'),
).withStyle(
const CoreTagStyle(
borderRadius: CoreBorderRadius.all(CoreRadius.radius9999),
padding: CoreEdgeInsets.symmetric(horizontal: CoreSpace.space12),
),
);
}
}
변형 (Variants)#
분류색#
아홉 가지 — red · orange · yellow · green · blue
· purple · pink · brown · gray. 색에는
상태의 뜻이 없습니다. 같은 분류에는 화면 어디서나 같은 색을 씁니다.
emphasis: bold#
분류색 채움 위에 on 색 글자, 선 없음, 라벨은 600. 한 줄의 태그 중 하나만 눈에 띄어야 할 때 씁니다.
Tag(
color: CoreCategoryColor.red,
emphasis: CoreTagEmphasis.bold,
child: Text('긴급'),
)
size: sm#
20px 단 — 표의 칸이나 목록의 한 줄처럼 촘촘한 자리에 씁니다. 기본 md 는 24px 로 상태 배지와 같은 높이입니다.
Tag(color: CoreCategoryColor.blue, size: CoreTagSize.sm, child: Text('디자인'))
동작 스펙 (Behavior)#
배치#
- 상자는 단의 높이 이상이고, 라벨은 상자의 가로 · 세로 가운데에 한 줄로 놓입니다 — 줄바꿈하지 않습니다
- 폭은 라벨이 정합니다(좌우 여백 + 라벨 폭)
- 선은 상자 안쪽에 그려져 높이를 늘리지 않습니다
인터랙션#
- 없습니다. 누름 · hover · pressed 상태가 없고 포커스를 받지 않습니다
상태 전환#
- 상태가 없습니다. 같은
color·emphasis·size면 같은 그림입니다
애니메이션#
- 없습니다
재질#
활성 테마의 서피스 스타일이 재질을 가지면, 채움을 칠하는 태그는 내용 표면(content)으로 그 재질을 입습니다.
재질이 없는 기본 상태에서는 불투명한 채움 하나입니다.
사용 가이드라인 (Usage Guidelines)#
Do#
한 분류에는 한 색
Tag(color: CoreCategoryColor.blue, child: Text('디자인'))
Tag(color: CoreCategoryColor.green, child: Text('개발'))
이유: 색이 분류의 이름표 역할을 하려면 같은 분류가 어디서나 같은 색이어야 합니다.
Don't#
상태를 태그로 말하지 않는다
// ❌ 분류색에는 성공 · 오류의 뜻이 없다
Tag(color: CoreCategoryColor.red, child: Text('실패'))
// ✅ 상태는 Badge
Badge(tone: CoreBadgeTone.destructive, child: Text('실패'))
이유: 분류색은 고대비 · 다크 모드에서도 상태 색과 짝을 맞추지 않습니다. 상태는 상태 토큰을 쓰는 Badge 가 말합니다.
접근성 (Accessibility)#
역할#
- Flutter: 따로
Semantics를 달지 않습니다 — 라벨Text가 그대로 읽힙니다 - Web: role 없는
<span>입니다
키보드#
| 키 | Flutter | Web |
|---|---|---|
Tab | 지나치지 않음 — 포커스를 받지 않습니다 | 지나치지 않음 — 포커스를 받지 않습니다 |
스크린 리더#
이름은 child 의 텍스트에서 나옵니다. 색은 읽히지 않으므로, 색만으로 분류를 구별하지 말고 라벨 낱말이 분류를 말하게 합니다.
포커스 관리#
- 진입 · 이탈 · 트랩: 없음
알려진 제약#
- 아이콘 슬롯이 없습니다 — 라벨은
child하나입니다 - 라이트 모드의
subtle선은 보이지 않습니다(팔레트의outline슬롯이 컨테이너와 같은 톤)
전역 축(동작 줄이기 · 고대비 · 색 강제 모드 · 시맨틱 역할 · 최소 터치 타겟)은 접근성 페이지가 한 곳에서 다룹니다.
크로스 플랫폼 차이점 (Platform Differences)#
child / color / emphasis / size / tagStyle
은 양 플랫폼 동일 API 입니다.
| 항목 | Flutter | Web |
|---|---|---|
| 루트 | Container(채움 + 선) → 가운데 맞춘 Row |
<span> — inline-flex, 가운데 맞춤, 줄바꿈 없음 |
| 높이 | BoxConstraints(minHeight) |
min-h-* 클래스(크기 스케일 변수), 덮어쓴 값은 inline min-height |
| 선 | Border.all — 선 색이 있을 때만 |
border-width — 선 색이 있을 때만 |
| 라벨 글자 | DefaultTextStyle.merge 로 역할 · 굵기 · 색 설치 |
text-{role} 클래스 + 굵기 inline |
| chrome emit | paint-ready BoxDecoration / TextStyle |
Tailwind class + inline CSS |
| Web 전용 HTML 표면 | — |
attributes
·
classes
·
css
·
eventHandlers
·
id
통과
|
관련 컴포넌트 (Related Components)#
조합 예제#
Row(
spacing: CoreSpace.space8,
children: [
Text('디자인 시스템 개편').titleSmall,
Tag(color: CoreCategoryColor.blue, size: CoreTagSize.sm, child: Text('디자인')),
Tag(color: CoreCategoryColor.green, size: CoreTagSize.sm, child: Text('개발')),
],
)