fix: align org chart hierarchy and typography weights

This commit is contained in:
shkim4 committed 2026-10-14 13:33:59 +09:00
1 parent 72d427fcd2
commit d42466f5eb
33 files changed
+358 -85

No files matched your search

+7 -7
View File
@@ -9,7 +9,7 @@
| 항목 | 내용 |
|---|---|
| 구현 상태 | HM 스타일 적용 완료 (`<Card />`만으로 적용, `hm-card` class 없음) |
| 기준일 | 2026-10-02 (문서·주석 정합성 정정 2026-10-08, 디자인 값 변경 없음) |
| 기준일 | 2026-10-02 (2026-10-08 문서 정정, 2026-10-14 Font Weight 3단계 통합) |
| 기반 | shadcn/ui Card (div 기반, Radix 없음) |
| 대표 Story | `Components/Data & Display/Card` → `All` (이름 "Card") |
| 보류 | Eyebrow, Divider, Footer·Media, 반응형, 폭 (§11) |
@@ -20,7 +20,7 @@
- **ui_viz 채택(SOURCE_ADOPTED, Canonical Pattern Q6 `YES`, 2026-09-28)**: border 1px, body-padding 24px 사방, header↔body 간격 24px(D-093 D-042/D-059), title↔action 간격 20px, 교차축 중앙 정렬, 상태 없음. 이 값들은 문서상 `Confirmed` 표기가 아니라 owner가 채택한 Canonical 값이다. HM Card는 이 채택 값을 적용한다.
- **ui_viz LOCAL_EXCEPTION(컴포넌트 범위 값)**: border 색 `#DEDBD2`(전역 token 아님, Tabs·Search Field와 값만 같고 alias 금지), Beige border `#ECD4A2`(Primitive `hm-brown-light-4`와 같은 값). **현재 HM 구현은 이 두 값을 컴포넌트 전용 값으로 두지 않고 공유 Semantic Token에 연결한다.** 차이는 §6.1에 기록한다.
- **ui_viz CANONICAL_OVERRIDE**: Title Source 19px/700 → `heading-md` 20/28/600.
- **HM 사용자 결정**: 없음.
- **HM 사용자 결정 (2026-10-14)**: Font Weight 400 / 500 / 700 통합. 카드 제목은 700이며 크기·행간·간격은 유지한다. 이전 ui_viz 600 근거와 과거 실측은 당시 기록이다.
- **shadcn 유지**: 아래 §7.
- **ui_viz 미정의**: Description, Footer, `size="sm"`, Media, Hover/Selected/Clickable, shadow.
@@ -35,7 +35,7 @@
| Padding | 24px 사방 (Card 위/아래, Header·Content 좌우) | 채택 |
| Header ↔ Content 간격 | 24px | 채택 (D-093) |
| 자식 clipping | 하지 않음 (`overflow: visible`) | 채택 (Type B) |
| Title | 20px / 28px / 600, `--hm-sem-fg-primary` | CANONICAL_OVERRIDE |
| Title | 20px / 28px / 700, `--hm-sem-fg-primary` | HM 사용자 결정 (2026-10-14) |
| Header 안 Title ↔ Action 간격 | 20px (`column-gap`) | 채택 |
| Action 정렬 | Title 반대쪽 끝, 교차축 중앙 | 채택 |
| Description | shadcn 기본 (`text-sm text-muted-foreground`), HM Card CSS 미적용. 사용 범위는 §5.1 | ui_viz 미정의 |
@@ -118,14 +118,14 @@ semantic HTML(`div`), React composition(Header/Title/Description/Action/Content/
- `rounded-xl`, `bg-card`, `ring-1 ring-foreground/10`, `overflow-hidden`, 기본 `--card-spacing: 16px`을 TSX에서 제거하고 theme CSS(border, radius 4px, surface, 24px)가 담당.
- ring 대신 실제 1px border 사용, shadow 없음.
- Title을 20/28/600으로 변경(`size="sm"` 제외).
- 기본 Title은 20/28/700으로 통합(2026-10-14). `size="sm"`도 굵기 700을 사용하며 기존 14px 크기와 행간은 유지한다. 이전 20/28/600 도입·실측은 §13의 당시 검증 기록으로 보존한다.
- Header 열 간격 20px, Action 교차축 중앙 정렬.
- Footer 아래 모서리를 컨테이너 radius(border 안쪽 3px)에 맞춤. Footer 표면은 shadcn 그대로다.
- `surface` prop 추가.
### 8.1 Demo `.hm-panel`과 운영 Card 구분
- **운영 Card**: `@hm-design/ui`의 `<Card />`와 `packages/ui/src/theme/card.css`. 이 문서 §3의 값(padding 24px, Title 20/28/600 등)과 대표 Story `All`이 기준이다. 소비 프로젝트는 `hm-panel*` class 없이 이 API만 쓴다.
- **운영 Card**: `@hm-design/ui`의 `<Card />`와 `packages/ui/src/theme/card.css`. 이 문서 §3의 값(padding 24px, Title 20/28/700 등)과 대표 Story `All`이 기준이다. 소비 프로젝트는 `hm-panel*` class 없이 이 API만 쓴다.
- **과거 Demo Panel**: 공식 이전 전 UI Demo의 `src/App.tsx`에 있던 4개 Card에 붙은 `hm-panel`, `hm-panel-header`, `hm-panel-icon`, `hm-panel-content` class와 `src/hm-theme.css` 규칙. 패키지(`packages/ui`)에 포함되지 않으며 Card 규격 Reference가 아니다.
- `.hm-panel`은 Card 외형(border, radius, background, shadow)을 지정하지 않는다. 다만 Demo class 묶음은 운영 Card 값을 다음처럼 덮어쓴다.
@@ -133,7 +133,7 @@ semantic HTML(`div`), React composition(Header/Title/Description/Action/Content/
|---|---|---|
| `.hm-panel` | `gap: 0`, `--card-spacing: 16px` | gap·padding 24px |
| `.hm-panel-header` | 아이콘 34px 열 grid, `column-gap: 11px`, `border-bottom: 1px solid #ede9df`, `padding: 22px 23px 17px` | Header 좌우 24px, column-gap 20px, divider 없음 |
| `.hm-panel-header [data-slot="card-title"]` | 15px / 1.35 / 700, letter-spacing -.02em | 20 / 28 / 600 |
| `.hm-panel-header [data-slot="card-title"]` | 15px / 1.35 / 700, letter-spacing -.02em | 20 / 28 / 700 |
| `.hm-panel-header [data-slot="card-description"]` | 11px, `--hm-muted`, margin-top 2px | shadcn 기본 `text-sm text-muted-foreground` |
| `.hm-panel-icon` | 34px 아이콘 박스 | 해당 요소 없음 |
| `.hm-panel-content` | `padding: 23px` | 좌우 24px |
@@ -150,7 +150,7 @@ semantic HTML(`div`), React composition(Header/Title/Description/Action/Content/
## 10. 사용자 확정 결정
추가 사용자 결정 없음.
2026-10-14: 카드 제목 기본 굵기를 600에서 700으로 통합한다. `--hm-card-title-font-weight` 이름은 유지하며 `--hm-font-weight-bold`를 참조한다. `size="sm"` 제목도 700을 사용하며 크기와 행간은 기존 값을 유지한다.
## 11. 미확정 / 보류
+1 -1
View File
@@ -19,7 +19,7 @@
## 2. 적용 근거
- **ui_viz Confirmed (Dialog-local)**: radius 8px(USER_DECISION 2026-09-17), shadow `0 0 12px rgba(0,0,0,.2)`(D-093 D-088), 내용 기준 크기와 최대 너비·높이 공식(D-088), Header `24/24/16`·Title↔Description 8·Body 24·Actions `0/24/24`·Action gap 8(D-093), Header 아래 inset divider 위치·두께와 Footer divider 없음, Body만 scroll, 긴 텍스트 줄바꿈, 표는 Body 안 가로 scroll, 표면 `color.bg.surface`·전경 `color.fg.primary`, Title/Description/Body 타이포.
- **CANONICAL_OVERRIDE**: Title `heading-md` 20/28 중 weight **700**은 Dialog Title에만 적용(D-006, 600 대체). Foundation `heading-md`는 600 그대로.
- **CANONICAL_OVERRIDE**: Title `heading-md` 20/28 중 weight **700**은 Dialog Title에만 적용(D-006, 600 대체). 이는 당시 ui_viz 근거다. 2026-10-14 HM 정책은 400 / 500 / 700이며 카드 제목도 700을 사용한다. Dialog Title의 700은 유지한다.
- **현재 HM Actions**: Footer padding은 `16px 24px 24px`이며 divider는 없다. 위 ui_viz 도입 근거의 `0/24/24`와 구분한다.
- **Temporary / TBD(적용했으나 확정값 아님)**: 외곽선·Header divider 색 `#DEDBD2`는 `Temporary`, Token relation TBD(DIALOG-10 FOLLOW_UP). 이전 확정 색(`#9A9284`/`#E0DACE`)은 대체됐고 D-093 실행 화면과 같은 값이라 현재 구현을 따랐다. 색 역할이 정해지기 전까지 Dialog 범위 값이다.
- **PARTIAL / REFERENCE_ONLY(적용)**: Description 전경 `color.fg.secondary`(DIALOG-06 PARTIAL, 현재 style 보존). edge 16px(REVIEW).
+2
View File
@@ -1,5 +1,7 @@
# AI 화면 선택·완료 계약
> Typography: HMDesign의 Font Weight는 400(Regular), 500(Medium), 700(Bold)의 3단계만 사용한다. Font Weight 600은 사용하지 않으며, 카드 제목은 700을 기본으로 한다. 신규 화면과 컴포넌트 생성에도 적용한다.
읽는 순서는 `AGENTS.md` → 아래 해당 기능 행 → [공개 인덱스](component-pattern-reference.md)의 선택 문서와 대표 All Story다. 과거 보고서·verification Story의 기능을 새 요구사항으로 복사하지 않는다.
## 구현 전 기록
@@ -308,3 +308,16 @@ HMDesignSystem의 핵심 원칙은 다음과 같다.
현재 Storybook의 `Theme/Designer Playground/Editor`에서 JSON URL/파일을 Preview하고 상위 컬러 17개 역할을 편집·Reset·Export/Import할 수 있다. Component Token은 직접 수정하지 않는다. 운영 컬러 원본은 `themes/default.json`/서비스 JSON이며 package fallback CSS/데이터는 생성한다. Production은 `@hm-design/ui/theme`의 URL Loader/Apply를 사용한다. Theme artifact는 UI package와 별도 배포한다. 상세 절차/제한은 [디자인팀 Theme 가이드](designer-theme-guide.md), [Theme delivery](theme-delivery.md), Runtime 적용·제한은 [Runtime Theme](runtime-theme.md)를 참고한다. 기존 디자인 정책/과거 기록은 유지한다.
<a id="font-weight-policy"></a>
## Font Weight 정책 — 2026-10-14
HMDesign의 Font Weight는 400(Regular), 500(Medium), 700(Bold)의 3단계만 사용한다. Font Weight 600은 사용하지 않으며, 카드 제목은 700을 기본으로 한다.
- 400: 본문·입력·기본 텍스트. 기존 `--hm-input-font-weight: 400`을 유지한다.
- 500: 버튼·필드 라벨·직위 배지·일반 강조. `--hm-font-weight-medium: 500`.
- 700: 제목·카드 제목·직원 이름·그룹 제목·강한 강조. `--hm-font-weight-bold: 700`.
- `--hm-card-title-font-weight`는 이름을 유지하고 `var(--hm-font-weight-bold)`를 참조한다. 기본 Card와 `size="sm"` Card 제목에 700을 적용한다.
- 신규 컴포넌트·Storybook·AI 생성 코드에 같은 정책을 적용한다. Tailwind `font-normal` / `font-medium` / `font-bold`만 사용하며 `font-semibold`나 750·800 등 추가 단계는 사용하지 않는다.
- 폰트 패밀리·크기·행간·자간은 변경하지 않는다. `@font-face`의 100–900은 가변 폰트의 지원 범위이며 UI 사용 단계가 아니다. 폰트 파일과 라이선스는 보존한다.
- Typography는 Runtime Theme JSON 공개 allowlist 입력이 아니다. 공개 API·외부 CSS 커스터마이징 계약은 유지하며 과거 보고서의 600 실측값은 당시 검증 기록으로 보존한다.
@@ -56,6 +56,17 @@ Codex·Claude가 조직도 생성 요청을 받았을 때 **생성 방식이 명
Depth에 회사나 직원 카드를 포함하는지, 조직별 인원이 직접 소속인지 하위 조직 포함인지 구분한다. 의미가 불분명해 구조나 총원이 달라지는 경우 해당 항목만 질문한다. 내부 렌더러의 0부터 시작하는 인덱스를 사용자 Depth와 혼동하지 않는다.
### 2.1 확장형 조직 위계 규칙
확장형 OrgChart의 조직 계층 생성 시 팀(Team)을 셀(Cell)의 하위에 배치해서는 안 된다. Storybook 샘플 및 AI가 생성하는 조직 데이터는 정의된 조직 위계를 따라야 한다.
- 셀 → 팀 직접 관계와 셀의 모든 하위 계층에 나타나는 팀을 금지한다. 팀의 전체 부모 경로를 확인하며 중간 조직이 있어도 같은 규칙을 적용한다.
- 팀 → 셀은 허용한다. 셀을 무조건 말단으로 처리하지 않으며 다른 하위 조직의 허용 여부는 기존 정책을 따른다.
- 현재 type은 `root | division | office | div | cell | team`이다. enum 선언 순서는 허용 위계의 순서가 아니다. 그 외 유형의 기존 부모·자식 관계를 유지하고 새 유형·제약·필수 중간 계층을 임의 추가하지 않는다.
- TB / LR / Hybrid는 동일한 `parentId` 데이터의 표시 방식이다. 레이아웃에 따라 위계를 변경하지 않으며 팀·셀을 모든 예제에 필수로 생성하지 않는다.
- 제공 JSON·CSV·Excel의 관계가 이 규칙과 충돌하면 원본 경로·ID와 충돌을 보고하고 필요한 수정 조건을 확인한다. 원본 부모·유형을 조용히 치환하거나 데이터를 삭제하지 않는다.
- 이 규칙은 Storybook 샘플·AI 데이터 생성 및 사전 정합성 확인에 적용한다. 현재 제품 Validator·Drag & Drop 이동 정책의 자동 거절을 보장하지 않으며 런타임 검증 기능·공개 API 변경에는 별도 승인이 필요하다.
## 3. 자연어에서 가상 데이터 생성
- 명시된 회사·조직명·관계·유형·조직 수·직원 수·직위·대표이사 유무를 정확히 반영한다. 합계가 충돌하거나 관계를 결정할 수 없으면 생성 전에 필요한 조건만 질문한다.
+3
View File
@@ -65,6 +65,8 @@ Storybook 4개 화면과 Chart Only를 포함한다. 기존 NOT VERIFIED인 브
### Chart Only — React / Vanilla
**2026-10-14 Font Weight 통합 사용자 요청:** HMDesign 기본 굵기는 400(Regular) / 500(Medium) / 700(Bold)의 3단계다. Fixed 직원 이름·그룹 제목은 600→700, 직원 직위 배지는 600→500, 중앙 허브 제목은 750→700으로 통합한다. Expanded의 기존 400 / 500 / 700은 유지한다. 폰트 패밀리·크기·행간·자간, 카드 크기·색상·간격·연결선·배치와 조직 데이터·기능은 유지한다. 이 요청은 기존 접근성 미해결 사항이나 전체 회귀 검증 상태를 변경하지 않는다.
Auto/Expanded Chart Only의 승인 기준은 다음과 같다.
- 흰색 캔버스, 외부 제목·설명·요약·툴바 없음.
@@ -123,6 +125,7 @@ Cell Border Only 디자인 실험은 사용자 결정으로 정식 적용에서
1. 승인된 기존 디자인을 기본 기준으로 사용하고 카드·색상·Typography·간격을 임의 변경하지 않는다.
2. 사용자 요청에 따른 조직 계층·직원 데이터 생성은 계속 허용하며 정확한 요청 구조·인원·원본 데이터를 보존한다.
- 확장형 OrgChart의 Storybook 샘플·AI 생성 데이터는 셀(Cell)의 직접 자식 및 모든 하위 계층에 팀(Team)을 배치하지 않는다. 팀 → 셀은 허용하며 다른 유형의 기존 관계와 셀의 다른 하위 조직 허용 여부는 유지한다. [AI 생성 정책 §2.1](ai-page-generation-rules.md#21-확장형-조직-위계-규칙)을 따른다. 이는 승인된 디자인 변경이나 제품 런타임 검증·공개 API 변경 승인이 아니다.
3. 외부 CSS 테마를 통한 의도적인 커스터마이징은 허용한다. 기본값 자체 변경과 구분한다.
4. 승인된 기본값 자체를 변경할 때는 사전 사용자 확인을 받는다. 이미 해당 변경을 명시적으로 승인받은 요청은 같은 확인을 반복하지 않는다.
5. 접근성 미해결 사항을 숨기거나 PASS로 변경하지 않는다.
+2
View File
@@ -45,6 +45,8 @@ file:// Fetch는 지원하지 않는다. 이번 작업에 외부 API·서버·DB
기존 JSON 예시는 Small 20명/3회사, Medium 100명/5회사, Large 300명/7회사다.
P7의 7회사 합산·회사별 선택은 Large를 기반으로 아래 공개 helper를 사용한다.
Storybook·AI 생성 데이터의 조직 위계는 [AI 생성 정책 §2.1](ai-page-generation-rules.md#21-확장형-조직-위계-규칙)을 따른다. 셀의 직접 자식 및 모든 하위 계층에 팀을 배치하지 않으며 팀 → 셀은 허용한다. 셀을 일괄 말단으로 제한하지 않는다. fixture 생성기는 Large의 기존 ID·직원·분배를 유지하면서 `실 → 팀 → 셀`과 실 아래 형제 협력팀을 만든다. Small/Medium은 기존 구조를 유지한다. TB / LR / Hybrid는 같은 위계를 표시하고 helper는 template의 위계를 보존한다. 제품 Validator·Drag & Drop의 새 계층 거절 기능은 이번 데이터 정책에 포함되지 않는다.
## React
```tsx
+4 -2
View File
@@ -568,7 +568,7 @@ nullable 필드는 생략하거나 빈 문자열로 대신하지 않는다. 필
### 깊은 JSON: 회사 → 부문 → 본부 → 부서 → 팀 → 직원
현재 Auto의 트리는 enum 순서에 종속되지 않고 실제 parentId 관계를 따른다. 다음은 5개 조직 계층 + 직원 카드 예제다. 본부=`office`, 부서=`div` 대응은 이 예제의 변환 선택이며 일반 기업 의미를 강제하지 않는다.
현재 Auto의 트리는 enum 순서에 종속되지 않고 실제 parentId 관계를 따른다. **확장형 조직 데이터 생성 시 셀(Cell)의 직접 자식 또는 모든 하위 계층에 팀(Team)을 배치하지 않는다. 팀 → 셀은 허용한다.** 셀을 무조건 말단으로 처리하지 않으며 다른 유형의 기존 관계는 유지한다. 이 데이터 생성 규칙은 현재 Validator·Drag & Drop의 런타임 계층 거절 기능을 의미하지 않는다. 제공 데이터와 충돌하면 원본을 보존하고 수정 조건을 확인한다. [AI 생성 정책 §2.1](ai-page-generation-rules.md#21-확장형-조직-위계-규칙)을 따른다. 다음은 5개 조직 계층 + 직원 카드 예제다. 본부=`office`, 부서=`div` 대응은 이 예제의 변환 선택이며 일반 기업 의미를 강제하지 않는다.
```json
{
@@ -657,7 +657,7 @@ Fixed는 별도의 기존 부서 ID별 스타일·SVG를 사용한다. 회사
### 카드와 글자
- Fixed의 기존 대표자 SVG는 146×74, 1Depth 조직장 SVG는 146×68, 더 깊은 조직장/일반 직원의 small SVG는 108×52다. 등록 부서 자산이 없는 조직은 기존 fallback 카드다. 모든 Fixed 데이터에 SVG 매핑이 있는 것은 아니다.
- Fixed SVG 직위/이름 기본 크기는 small 15/18px, 대표자 20/24px, 부서장 SVG 직위 18px·이름 24px다. 이름 weight 600, 직위 400이며 전역 서체는 Noto Sans KR 등 기존 fallback을 따른다. 재설계 규격으로 사용하지 않는다.
- Fixed SVG 직위/이름 기본 크기는 small 15/18px, 대표자 20/24px, 부서장 SVG 직위 18px·이름 24px다. 이름 weight 700(2026-10-14 Font Weight 통합), 직위 400이며 전역 서체는 Noto Sans KR 등 기존 fallback을 따른다. 재설계 규격으로 사용하지 않는다.
- Auto는 SVG 배경 대신 기존 중립 카드와 회사 강조 Border를 쓴다. 일반 직원 폭 114px·최소 높이 54px, 조직장/상단 카드 폭 154px·최소 높이 72px, 사진 36×36, padding 8px, Border 1px, inset 강조 3px, 이름/직위 13/10px다. 긴 텍스트는 실측 높이가 늘 수 있다.
- Auto의 Root 대표자와 하위 조직장 카드는 같은 leader geometry를 사용한다. 1Depth/2Depth별 새 디자인 prop은 없다. 3글자 한글 이름은 표시 계층에서 띄어 쓰고 직위 공백을 표시상 제거하지만 원본과 callback 데이터는 유지한다.
- Auto 일반 카드에서 jobTitle·근무 상태를 별도 행으로 출력하지 않는 경로가 있다. 팝업은 원본 jobTitle/workStatus를 보여준다. Fixed의 파견/휴직 보조 카드·요약과 Auto의 직원 카드를 혼동하지 않는다.
@@ -785,6 +785,8 @@ export function UpdatingChart({ dataset }: { dataset: OrgChartDataset }) {
공개 `createOrgChartExampleDataset`는 기존 template에서 `employeeCount: 20 | 100 | 300`, scope `total | per-company`로 가상 예시를 만드는 helper다. 임의 500명 생성·실제 Excel 변환 API가 아니다. 회사별 모드는 선택 회사마다 N명이며 total 모드는 원래 회사별 분배 후 선택 회사만 필터링한다. 실제 사용자 데이터를 이 helper로 재생성하지 않는다.
Expanded Storybook은 `examples/org-chart/create-expanded-fixtures.mjs`가 생성한 Large template을 위 helper로 재사용한다. Large의 분기는 `회사(root) → 본부(division) → 실(office) → 팀(team) → 셀(cell)`이며 협력팀은 같은 실 아래 형제 팀이다. Small/Medium은 기존 규모·유형을 유지하고 팀을 강제로 추가하지 않는다. helper는 입력 template의 위계를 보존하므로 호출자는 template 자체의 셀 하위 팀 여부도 확인해야 한다. TB / LR / Hybrid가 위계를 각각 생성하지 않는다.
### Chart Only 정책과 현재 기능의 관계
[AI 페이지 생성 정책](ai-page-generation-rules.md)을 먼저 읽고 AGENTS.md·CLAUDE.md의 연결을 따른다. **생성 방식이 미지정이면 코드 작성 전에 Chart Only / Full Page를 질문하고 답변 후 구현한다.** Chart Only를 선택하면 조직도 캔버스만 표시하고 외부 제목·통계·설명·조작 패널을 만들지 않는다. Full Page를 선택하면 기존 HM UI와 OrgChart Core·React Wrapper로 요청된 UI와 전체 레이아웃을 구성한다. 이미 명시된 방식은 다시 묻지 않으며 Fixed·Auto는 생성 방식 선택을 대신하지 않는다.