# Section Title 콘텐츠 한 덩어리에 이름을 붙이고, 그 덩어리에만 해당하는 설명이나 버튼을 오른쪽에 두는 제목 줄입니다. > 원본: `03_ASSET_GUIDE/catalog/section-title.js` · CSS: `03_ASSET_GUIDE/styles/elements/section-title.css` > kind `component` · category `display` · status `stable` · specSource `measured` > 데모는 `button.css`(Actions 의 util 버튼)와 `grid.css`(제목 아래 표)를 함께 씁니다 — 이 엘리먼트는 무언가의 위에 있을 때만 의미가 있기 때문입니다. --- ## 1. 구성 한 줄 안에 **Heading** 이 왼쪽, 그 덩어리에만 해당하는 **Description** 이나 **Actions** 가 오른쪽에 놓입니다. 제목 자신은 아이콘과 카운트를 함께 담을 수 있습니다. ``` ┌──────────────────────────────────────────────────────────────┐ │ [≡] 항목 목록 (1/20) 조회 기준일 정보 [EXCEL] │ └──────────────────────────────────────────────────────────────┘ ③ ④ ⑤ ⑦ ⑥ └───────── ② Heading ─────────┘ ① Container (grid 3열: minmax(0, 1fr) · auto · auto) ``` | # | 요소 | 필수 | 클래스 | 설명 | |---|---|---|---|---| | ① | Container | 필수 | `atom-section-title` | 행과 슬롯의 자리를 소유합니다. 제목의 글자 크기도 여기서 나옵니다. | | ② | Heading | 필수 | `atom-section-title__heading` | `h2` · `h3` 를 그대로 넣습니다. 이 엘리먼트는 **제목의 단계를 정하지 않습니다.** 단계는 문서 구조에 따라 정합니다. | | ③ | Icon | 선택 | `atom-section-title__icon` | 제목 앞의 아이콘입니다. **선택 사항이고 기본은 없음**입니다. 장식이므로 `aria-hidden` 입니다. AS-IS 처럼 `padding-left` 로 자리를 비워두지 않으므로, 빼면 제목이 왼쪽 끝에서 시작합니다. | | ④ | Title | 필수 | `atom-section-title__title` | 덩어리의 이름입니다. 필수입니다. | | ⑤ | Count | 선택 | `atom-section-title__count` | `(1/20)` 처럼 지금 보고 있는 양을 붙입니다. 선택 사항입니다. | | ⑥ | Actions | 선택 | `atom-section-title__actions` | 그 덩어리에만 작용하는 버튼들입니다. 선택 사항입니다. | | ⑦ | Description | 선택 | `atom-section-title__description` | 덩어리가 무엇인지 보충하는 한 줄입니다. 선택 사항입니다. | > [!NOTE] > **레이아웃 엘리먼트입니다** > 이 엘리먼트는 **행을 만들고 슬롯의 자리를 정합니다.** 글자 크기도 함께 정하지만, > heading 태그는 문서 구조가 결정합니다. `--size_small` 과 `h3` 는 서로 연동되지 > 않습니다. --- ## 2. 종류 / 크기 ### Slots 필수는 Title 하나입니다. 나머지는 없으면 자리를 차지하지 않습니다. 오른쪽 열은 **내용이 없으면 폭이 0으로 접힙니다.** 제목만 있는 경우와 버튼이 여러 개 붙은 경우 모두 같은 클래스를 씁니다. Description 과 Actions 를 함께 두면 **설명이 버튼 왼쪽**에 붙습니다. 셋을 한 셀에 겹쳐 놓지 않고 열을 따로 두었기 때문입니다. ### Layout Description 을 제목과 같은 줄에 둘지, 아래로 내릴지 정합니다. | layout | Description 자리 | 쓰는 곳 | | --- | --- | --- | | `inline` | 제목과 같은 줄의 오른쪽 끝 | 기존 화면과 모양을 맞춰야 할 때 (기본) | | `stack` | 제목 바로 아래, 왼쪽 정렬 | 설명이 길거나 폭이 넓은 화면 | Actions 는 두 layout 에서 **모두 첫 줄 오른쪽**에 남습니다. 버튼은 제목과 같은 층의 액션이기 때문입니다. > [!WARNING] > **폭이 넓으면 `inline` 의 설명은 제목에서 멀어집니다** > 1400px 표 위에서는 제목이 왼쪽 끝, 설명이 오른쪽 끝에 놓여 서로 멀어집니다. > 폭이 1000px 을 넘고 설명이 제목을 이해하는 데 꼭 필요하다면 > `stack` 을 쓰세요. `inline` 은 기존 화면과의 호환을 위한 기본값입니다. ### Variant 아래 콘텐츠와의 경계를 그릴지 정합니다. | variant | 모양 | 쓰는 곳 | | --- | --- | --- | | `plain` | 선 없음 | 제목 아래가 표나 카드처럼 이미 경계를 가진 것 (기본) | | `underline` | 아래 1px `--atom-border-default` | 제목 아래가 평범한 텍스트·폼일 때 | 선은 글자 밑이 아니라 **행 전체**에 그어집니다. 제목과 버튼이 한 줄로 묶여 아래 콘텐츠와 구분됩니다. ### Size 두 단계입니다. | size | 제목 | 아이콘 | Count · Description | 쓰는 곳 | | --- | --- | --- | --- | --- | | `medium` | 18px / 500 (`--atom-t7-size`) | 18px | 13px (`--atom-t3-size`) | 페이지가 다루는 덩어리 (기본) | | `small` | 15px / 500 (`--atom-t5-size`) | 16px | 12px (`--atom-t2-size`) | 그 안의 하위 덩어리 | `small` 아래 단계는 두지 않습니다. 본문이 15px 이므로 그보다 작은 제목은 본문과 구분되지 않습니다. 행간은 두 사이즈 모두 1.5 입니다. `--atom-t5-line` 은 1.7 이지만 본문용 값이고, [Typography](../foundation/typography.md) 는 제목 구간을 1.45–1.5 로 둡니다. 자간은 15px 에서 `normal` 이고, 18px 부터 줄입니다. ### 긴 제목 제목만 `…` 로 잘립니다. Count 와 Actions 는 밀려나지 않습니다. 버튼이 제목 길이 때문에 화면 밖으로 밀리면 작업을 할 수 없기 때문입니다. 잘린 제목도 전체 문장은 DOM 에 남아 스크린리더가 읽습니다. ### 클래스 계약 `styles/elements/section-title.css` 헤더와 원본 `registry.json` `css.blocks` 기준입니다. 클래스가 없는 값(—)은 기본 스타일 그대로입니다. | Prop | 값 | 클래스 | |---|---|---| | `size` | `small` · `medium` | `--size_small` · — | | `variant` | `plain` · `underline` | — · `--variant_underline` | | `layout` | `inline` · `stack` | — · `--layout_stack` | 파트: `__heading` · `__icon` · `__title` · `__count` · `__description` · `__actions` 상태 선택자: 없음 (원본 `css.states` 가 비어 있습니다) --- ## 3. 상태 상태가 없는 표시 엘리먼트입니다. 원본 CSS 에 `:hover` · `[data-*]` · `aria-*` 상태 선택자가 없습니다. Actions 슬롯의 버튼은 [Button](./button.md) 의 상태를 그대로 가집니다. --- ## 4. Props | Prop | Type | Default | 필수 | 설명 | |---|---|---|---|---| | `title` | `string` | | ● | 덩어리의 이름입니다. | | `as` | `"h2" \| "h3" \| "h4"` | `"h2"` | | `__heading` 이 렌더할 태그입니다. 문서 구조가 정합니다. | | `icon` | `ReactNode` | | | 제목 앞의 아이콘입니다. 장식으로 노출됩니다. | | `count` | `string` | | | `"(1/20)"` 처럼 이미 조립된 문자열입니다. | | `description` | `ReactNode` | | | 보충 한 줄입니다. | | `actions` | `ReactNode` | | | 그 덩어리에 작용하는 버튼들입니다. | | `layout` | `"inline" \| "stack"` | `"inline"` | | Description 을 같은 줄에 둘지 아래로 내릴지입니다. | | `variant` | `"plain" \| "underline"` | `"plain"` | | 행 아래 경계선입니다. | | `size` | `"small" \| "medium"` | `"medium"` | | 제목과 보조 글자의 크기입니다. | (구현 추가: `countLabel?: string` — Count 에 붙일 `aria-label`. 원본 Markup 의 `aria-label="20건 중 1건"` 을 지정하는 통로입니다.) ### Parts (compound) | Part | 요소 | 설명 | |---|---|---| | `SectionTitle` | `
` | 위 Props 를 받습니다. `__heading`(`as` 태그) 안에 Icon · Title · Count, 형제로 `

` · `

` 를 렌더합니다. 파트는 없습니다. | --- ## 5. Component tokens | 대상 | 속성 | Token | Value | |---|---|---|---| | Container | column-gap | `{space.x5}` | 20px | | Container | row-gap | `{space.x2}` | 8px | | Heading | font | — | 18px / 1.5 / **500** · `-0.01em` (small 은 15px · 자간 normal) — 토큰 없음 | | Heading | color | `{color.fg.neutral}` | | | Heading | gap | `{space.x2}` | 8px | | Icon | size | — | 18px (small 은 16px) | | Icon | color | `{color.fg.neutral-muted}` | | | Count | font | — | 13px / **400** `tabular-nums` (small 은 12px) | | Count | color | `{color.fg.neutral-muted}` | | | Description | font | — | 13px / 1.5 (small 은 12px) | | Description | color | `{color.fg.neutral-muted}` | | | Actions | gap | `{space.x2}` | 8px | | underline | border | `{color.border.default}` | 1px · 아래 여백 `{space.x3}` (12px) | > [!NOTE] > **`--atom-t*` 토큰은 아직 CSS 에서 쓰지 않습니다** > 아래 표와 본문의 `--atom-t7-size` 같은 이름은 [Typography](../foundation/typography.md) 의 > 크기 스케일입니다. `section-title.css` 는 저장소의 다른 엘리먼트 CSS 처럼 18px · 15px · 13px · > 12px 을 직접 적었고, 값이 스케일과 같으므로 그대로 토큰으로 바꿀 수 있습니다. ```json { "section-title": { "column-gap": { "$type": "dimension", "$value": "{space.x5}" }, "row-gap": { "$type": "dimension", "$value": "{space.x2}" }, "heading": { "color": { "$type": "color", "$value": "{color.fg.neutral}" }, "gap": { "$type": "dimension", "$value": "{space.x2}" }, "font-size": { "$type": "dimension", "medium": { "$value": "18px" }, "small": { "$value": "15px" } }, "font-weight": { "$type": "fontWeight", "$value": 500 }, "line-height": { "$type": "number", "$value": 1.5 } }, "icon": { "color": { "$type": "color", "$value": "{color.fg.neutral-muted}" }, "size": { "$type": "dimension", "medium": { "$value": "18px" }, "small": { "$value": "16px" } } }, "count": { "color": { "$type": "color", "$value": "{color.fg.neutral-muted}" }, "font-size": { "$type": "dimension", "medium": { "$value": "13px" }, "small": { "$value": "12px" } } }, "description": { "color": { "$type": "color", "$value": "{color.fg.neutral-muted}" }, "font-size": { "$type": "dimension", "medium": { "$value": "13px" }, "small": { "$value": "12px" } } }, "actions-gap": { "$type": "dimension", "$value": "{space.x2}" }, "underline": { "border": { "$type": "color", "$value": "{color.border.default}" }, "padding-bottom": { "$type": "dimension", "$value": "{space.x3}" } } } } ``` ### Foundations 준수 새로 정한 값이 없습니다. 모든 크기·굵기·색상이 Foundations 의 기존 항목에서 나왔습니다. | 항목 | 이 엘리먼트 | 근거 | | --- | --- | --- | | 제목 크기 | 18px · 15px | [Typography](../foundation/typography.md) 스케일 `--atom-t7-size` · `--atom-t5-size` | | 제목 굵기 | **500** | 같은 문서의 굵기 표 — "모든 제목(`h1`–`h4` 기본값)" | | 보조 글자 | 13px · 12px | `--atom-t3-size`(보조 본문) · `--atom-t2-size`(캡션·메타) | | 보조 굵기 | 400 | 굵기 표 — "본문 기본" | | 제목 색 | `--atom-fg-neutral` | [Color](../foundation/color.md) 17.19:1 | | 보조 색 | `--atom-fg-neutral-muted` | 같은 문서 6.99:1 — 본문 기준 4.5:1 통과 | | 경계선 | `--atom-border-default` | 같은 문서 1.36:1 | | 아이콘 크기 | 18px · 16px | [Button](./button.md) · [Autocomplete](./autocomplete.md) 의 `__icon` 과 같은 쌍 | | 간격 | `--atom-x2` · `--atom-x3` · `--atom-x5` | [Spacing](../foundation/spacing.md) | > [!WARNING] > **제목에 600 을 쓰지 않습니다** > [Typography](../foundation/typography.md) 는 제목 굵기를 700 대신 500 으로 정합니다. 한글은 > 굵은 웨이트에서 속공간이 메워지므로 위계를 **크기로** 만듭니다. > 600 은 버튼·배지 라벨, 폼 라벨, 표 헤더의 굵기입니다. 제목에 600 을 쓰면 옆에 놓인 > 버튼 라벨과 굵기가 같아집니다. > [!NOTE] > **경계선 대비는 기준 미달이지만 적용 대상이 아닙니다** > `--atom-border-default` 는 흰 배경에서 1.36:1 이고 [Color](../foundation/color.md) 가 WCAG > 1.4.11 의 3:1 미달로 표시해 둔 값입니다. 그 기준은 **UI 요소의 존재와 상태를 알리는** > 경계에 적용됩니다. `--variant_underline` 의 선은 콘텐츠를 나누는 장식이며 상태를 > 전달하지 않습니다. 섹션 이름은 제목 글자가 전달합니다. ### AS-IS 대응 TANGO 화면의 `.header_box` 를 이 엘리먼트로 옮길 때의 대응입니다. 아래 값은 `OldBtsList.html` 과 `ISigMaEquipmentBaseList.html` 을 실제로 렌더해 계산 스타일을 측정한 것입니다. | AS-IS | 이 엘리먼트 | 달라지는 점 | | --- | --- | --- | | `.header_box` | `.atom-section-title` | `float` + `overflow: hidden` → grid 3열 | | `h1.Header-1.header-1` (18px/400 + 안쪽 `` 700) | `__heading` (18px/500) | weight 경로가 하나로 합쳐집니다 | | `h2` (18px/700, `padding-left: 15px`) | `__heading` (18px/500) | 아이콘 유무로 시작 위치가 갈리지 않습니다 | | `.ico_board_black` (배경이미지 20×23, `position: absolute`) | `__icon` (SVG 20×20, flex 항목) | 배경이미지 → 스프라이트 SVG | | `.count` (12px/700) | `__count` (13px/600 `tabular-nums`) | 숫자 폭이 고정됩니다 | | `.Float-right` + 텍스트 | `__description` | `body div.main` 의 float 규칙에 의존하지 않습니다 | | `.Float-right` + 버튼 | `__actions` | 버튼은 [Button](./button.md) 의 `xsmall` 을 씁니다 | | `.header_box2` (`border-bottom: 2px #c6c6c7`, 높이 32px 고정) | `--variant_underline` | 1px 토큰 · 높이는 내용이 정합니다 | > [!WARNING] > **AS-IS 의 오른쪽 정렬은 조상 클래스에 의존합니다** > `float: right` 는 `body div.main .Float-right` 규칙에서 나옵니다. `.main` 밖에 > 같은 마크업을 두면 정렬이 풀리는 것을 확인했습니다. 이 엘리먼트는 자기 안에서 > 자리를 정하므로 어디에 놓아도 같습니다. --- ## 6. 접근성 - **제목 단계** — `__heading` 에 들어가는 태그가 곧 문서 구조입니다. 페이지 제목이 `h1` 이면 섹션은 `h2`, 그 하위는 `h3` 입니다. 크기를 맞추려고 단계를 건너뛰면 스크린리더의 제목 목록이 끊깁니다. - **아이콘** — `aria-hidden="true"`. 이름은 제목 글자가 전달합니다. - **Count** — 제목 안에 있으므로 제목을 읽을 때 함께 읽힙니다. `(1/20)` 이 무슨 뜻인지 글자만으로 불분명하면 `aria-label` 로 "20건 중 1건" 을 함께 답니다. - **Description** — 제목의 형제 요소입니다. 제목과 연결이 필요하면 `aria-describedby` 로 묶습니다. `inline` layout 에서 시각적으로는 멀지만 DOM 순서는 제목 바로 다음입니다. (구현은 Description 이 있으면 Heading 에 `aria-describedby` 를 자동으로 겁니다.) - **Actions** — 아이콘만 있는 버튼에는 `aria-label` 이 필요합니다. [Button](./button.md) 의 규칙을 그대로 따릅니다. - **대비** — 제목 `--atom-fg-neutral` 4.5:1 이상. Count 와 Description 은 `--atom-fg-neutral-muted` 이므로 **보조 정보로만** 쓰고, 그것만 읽어야 알 수 있는 내용을 담지 않습니다. --- ## 7. 사용 가이드 ### 덩어리마다 하나씩, 페이지 제목과는 다릅니다 페이지 제목은 페이지에 하나뿐이고 브라우저 탭·breadcrumb 와 짝을 이룹니다. 이 엘리먼트는 **한 페이지에 여러 개** 있는 것이 정상입니다. 측정한 AS-IS 화면은 표 하나마다 하나씩, 한 페이지에 다섯 개를 씁니다. 표마다 이름이 필요하므로 올바른 구조입니다. - ✅ **Do** 표·폼·카드 묶음마다 하나씩 두고, 아래 콘텐츠와 붙여 놓습니다. - ❌ **Don't** 페이지 제목 대신 쓰지 않습니다. 페이지 제목은 문서 헤더가 소유합니다. ### 개수는 Count 에, 설명에 적지 않습니다 `(1/20)` 은 제목의 일부로, 제목 바로 뒤에 읽힙니다. 같은 정보를 Description 에 적으면 행의 반대편에 놓여 제목과 떨어집니다. - ✅ **Do** 제목 뒤 Count 슬롯에 붙입니다. - ❌ **Don't** 개수를 Description 으로 밀어내지 않습니다. Count 는 `tabular-nums` 입니다. 페이지를 넘길 때마다 숫자 폭이 달라지면 제목 전체가 좌우로 흔들립니다. ### 그 덩어리에만 작용하는 버튼만 둡니다 Actions 슬롯의 버튼은 **바로 아래 콘텐츠에 대한 작업**입니다. 화면 전체를 저장하거나 다음 단계로 넘어가는 버튼은 페이지 하단의 버튼 영역이 맡습니다. 측정한 AS-IS 화면은 이 슬롯에 버튼을 여덟 개 넣었습니다. 여덟 개가 한 줄에 늘어서면 주된 작업이 무엇인지 구분되지 않고, 폭이 좁아지면 두 줄로 넘어갑니다. - ✅ **Do** 자주 쓰는 것 2~3개만 남깁니다. - ❌ **Don't** 내려받기 종류를 전부 버튼으로 늘어놓지 않습니다. - ⚠️ **Caution** 3개를 넘으면 [Select](./select.md) 나 메뉴로 묶고 버튼 하나만 남기세요. 버튼은 제목보다 눈에 띄지 않도록 `xsmall` 을 씁니다. ### 아이콘은 종류를 구분할 때만 붙입니다 아이콘은 **선택 슬롯이고 기본은 없음**입니다. 모든 섹션에 같은 아이콘을 붙이면 구분 정보가 없습니다. 측정한 AS-IS 화면은 `ico_board_black` 하나를 다섯 번 반복합니다. 구분에 쓰이지 않는 아이콘은 제목의 시작 위치만 밀어내므로 기본값은 없음입니다. - ✅ **Do** 섹션의 성격이 실제로 다를 때 서로 다른 아이콘을 씁니다. - ❌ **Don't** 장식으로 모든 섹션에 같은 아이콘을 반복하지 않습니다. ### 관련 컴포넌트 - [Button](./button.md) — Actions 슬롯에 들어가는 버튼입니다. `xsmall` 을 씁니다. - [Grid](./grid.md) — 이 제목 아래에 가장 자주 놓이는 것입니다. - [Tabs](./tabs.md) — 같은 층위를 나눠 담아야 하면 제목을 여러 개 두는 대신 탭을 씁니다. - [Field](./field.md) — 입력 하나의 라벨은 Field 가 답니다. --- ## 8. 예시 ```tsx } title="항목 목록" count="(1/20)" countLabel="20건 중 1건" description="조회 기준일에 해당하는 정보입니다" actions={} /> ``` ```html

항목 목록 (1/20)

조회 기준일에 해당하는 정보입니다

```