Files
HMDesign/docs/guidelines/hm-custom-implementation.md
T

24 KiB
Raw Blame History

HM Custom Implementation Inventory

조사 기준일: 2026-10-06. 실제 코드(packages/ui/src) 기준의 현황 기록이며 확정 규격이 아니다. 구현은 바꾸지 않았다. 신규 구현은 AI/Component 구현 원칙과 Navigation Single Mode Policy의 2026-10-07 확정 정책을 따른다. 아래 조사 이력은 운영 예제나 정책 예외를 허용하는 근거가 아니다. Select의 UNDER_REVIEW는 2026-10-06 조사 당시 설계 평가이며 현재 작업 진행 상태를 뜻하지 않는다. 현재 API·동작은 docs/components/select.md와 실제 구현·대표 Story를 따른다.

현재 탐색 기준 (2026-10-08 개발 저장소): UI 구현 TSX 44개, 공개 Component 모듈 44개(222 named export), Component Story 파일/그룹 44개, Component 문서 45개(field.md는 독립 구현이 아닌 소비 가이드)다. Pattern은 소스 디렉터리/공개 모듈 8개(62 named export), Story 파일/그룹 6개, Pattern 문서 7개다. 확정 배포 기준 HMDesignTest.zip에는 Component 구성은 동일하고 Pattern 모듈 7개(50 named export)가 포함되며 Dashboard Status 모듈은 없다. 파일·심볼·그룹은 서로 다른 집계 단위다. 현재 경로 연결은 Component / Pattern Reference Index를 따른다. 아래 표와 분석은 2026-10-06 당시의 분류 기록이다.

0. 한 줄 요약

shadcn/Radix를 그대로 쓰지 않고 실제로 API·State·Behavior·Structure가 추가된 Component는 44개 중 15개다. 나머지 29개는 shadcn 구조를 유지하고 CSS/Token만 얹었다. Pattern 7종은 모두 기존 Component의 조합이다.

질문 답
꼭 필요한가? Component 기준 15개 중 REQUIRED 13, CAN_SIMPLIFY 1(Textarea), UNDER_REVIEW 1(Select). 항목 단위로는 CAN_SIMPLIFY 3건, LEGACY 1건(Button alias) (§4, §11, §12)
Public API에 영향을 주는가? 12건이 consumer에게 노출된다 (§8). 내부 전용은 6건 (§7)
shadcn 업데이트 시 관리해야 하는가? Tabs(HIGH) 우선, 이어서 Button·Select(MEDIUM). 나머지는 LOW

위 숫자는 아래 표의 합이다. 표를 고치면 이 요약도 함께 고친다.

1. 목적

  • shadcn 업데이트·재생성 시 "무엇을 손으로 지켜야 하는가"를 한 문서에서 확인한다.
  • HM 스타일이 들어갔다는 이유만으로 Custom으로 부르지 않는다. Behavior / Structure를 유지하고 CSS/Token만 바꾼 것은 HM_THEME다.
  • 이 문서는 가시화·분류·유지보수 기준만 다룬다. 제거·단순화 판단은 별도 작업이다.
  • Visual 값(height, radius, color 등)은 각 docs/components/<name>.md, docs/patterns/<name>.md가 담당하므로 여기에 나열하지 않는다.

2. 분류 기준

분류 정의
SHADCN_BASE shadcn/Radix 구조·API 그대로. .tsx에 HM 전용 코드가 없고 Theme CSS도 얇은 Token 매핑 수준
HM_THEME Behavior / Structure는 shadcn/Radix 그대로, Visual만 HM CSS / Token. 독립 Custom 아님
HM_CUSTOM shadcn에 없는 Public API, 상태/behavior, Radix 동작 확장, 추가 Context/state, helper logic, 구조 확장 중 하나 이상
HM_COMPOSITION 기존 HM/shadcn Component를 조합한 Pattern
STORY_ONLY 검증용 Story, StateBoard 등. Production Custom 아님

조사 한계(반드시 읽을 것):

  • 현재 저장소는 Git으로 관리한다. 2026-10-06 조사는 shadcn 원본 사본과의 Git diff를 수행하지 않았다. 따라서 당시 분류는 "shadcn 원본과의 diff"가 아니라 현재 코드와 코드 주석을 읽고 shadcn v4(Radix) 구조에 대한 지식과 대조해 판정했다. 경계 항목은 shadcn add로 원본을 받아 diff하면 확정할 수 있다.
  • SHADCN_BASE와 HM_THEME의 경계는 휴리스틱이다: .tsx가 shadcn 그대로이면서 packages/ui/src/theme/<name>.css가 약 70줄 이하이면 SHADCN_BASE, 그보다 크면 HM_THEME. 둘 다 "Custom 아님"이므로 유지보수 판단에는 영향이 없다.
  • Story는 전수 검토하지 않고 공용 helper와 파일 구성만 확인했다.

3. 전체 요약

Category Count 비고
Component 총계 44 packages/ui/src/components/ui/
SHADCN_BASE 16 §5
HM_THEME 13 §5
HM_CUSTOM 15 §4 (Public 12건 + Internal 6건이 이 15개에 걸쳐 있음)
HM_COMPOSITION 7 Pattern (§6, Component 44개와 별도)
STORY_ONLY 4 묶음 §9

4. Components — HM_CUSTOM

한 Component 안에 Visual(HM_THEME)과 구조 Custom이 함께 있을 수 있다. 아래는 구조·API·상태 부분만 적었다. 평가: REQUIRED 현재 필요 / CAN_SIMPLIFY shadcn 방식으로 단순화 가능 / LEGACY 필요성 불명확 / UNDER_REVIEW 작업 중·미결정.

Component Base Custom 종류 Scope 평가 Risk
Button shadcn + Radix Slot + CVA API, Structure Public REQUIRED (+ alias는 LEGACY) MEDIUM
Input shadcn API Public REQUIRED LOW
Textarea shadcn API Public CAN_SIMPLIFY LOW
Card shadcn API Public REQUIRED LOW
Select Radix Select API, State, Structure Public + Internal UNDER_REVIEW MEDIUM
Tabs Radix Tabs API, State, Behavior, Structure Public + Internal REQUIRED HIGH
Dialog Radix Dialog API(Structure), Behavior Public + Internal REQUIRED LOW
Sheet Radix Dialog API(Structure), Behavior Public + Internal REQUIRED LOW
Drawer vaul API(Structure), Behavior Public + Internal REQUIRED LOW
Alert Dialog Radix Alert Dialog API Public REQUIRED LOW
Combobox Popover + Command (cmdk) API, State, Composition Public REQUIRED LOW
Date Picker Popover + Calendar (react-day-picker) API, State, Behavior Public + Internal REQUIRED LOW
Popover Radix Popover Behavior Internal REQUIRED LOW
Collapsible Radix Collapsible Behavior Internal REQUIRED LOW
Slider Radix Slider Behavior Internal REQUIRED LOW

4.1 항목별 기록

Button — button.tsx, theme/button.css

  • 추가: variant를 역할(primary|secondary|modify|destructive|cancel)로 교체, appearance(brand|solid|outline) 추가, data-variant/data-appearance/data-size. default·outline은 shadcn 호환 alias로 primary/primary+outline에 매핑, ghost·link는 shadcn 기본 유지.
  • 이유: ui_viz 역할/처리(treatment) 2축 규격. <Button />만으로 HM 디자인 적용.
  • Public API 영향: 있음(variant 값 집합, appearance). 기존 shadcn variant="default|outline" 코드는 alias로 동작.
  • 구조 주의: data-slot="button"을 {...props} 뒤에 둔다. 앞에 두면 <XTrigger asChild><Button/></XTrigger>가 trigger의 data-slot으로 덮어써 HM 스타일이 사라진다(§7 I3).
  • 대체 가능한 shadcn 방식: shadcn variant 값에 HM 역할을 추가하는 방식은 가능하나 appearance 2축은 표현 불가.
  • 리스크 사유: buttonVariants CVA 정의를 통째로 다시 썼다. shadcn이 buttonVariants를 바꾸면 수동 병합이 필요하다. 코드에 dark: 잔재 2곳(§11).
  • 유지 필요성: REQUIRED. 단, default/outline alias는 LEGACY(호환 목적이며 소비처가 정리되면 제거 후보).

Input — input.tsx

  • 추가: size="small|medium|large"(기본 large). 네이티브 size(문자 폭) 속성은 Omit으로 가려져 사용 불가.
  • Public API 영향: 있음, 네이티브 속성 가림. 대체: className 높이 지정(2축 상태 규칙은 불가). 유지 REQUIRED. Risk LOW.

Textarea — textarea.tsx

  • 추가: resize="vertical|none|both"(기본 vertical)를 data-resize로 노출. readonly→none은 CSS에서 처리.
  • 대체: className="resize-none" 등. 기본 정책을 컴포넌트가 갖게 하려는 목적이라 단순화 가능. CAN_SIMPLIFY, Risk LOW.

Card — card.tsx

  • 추가: surface="surface|content"(data-surface). size="sm"은 shadcn 기존 API.
  • 유지 REQUIRED(ui_viz Content Card 면 구분). Risk LOW.

Select — select.tsx, theme/select.css (size 계약 구현됨; 구조 선택은 아래 UNDER_REVIEW)

  • 추가(조사 시점 코드):
    • SelectTrigger의 size="medium|large"(shadcn sm|default 대체), data-size.
    • SelectSizeContext + Select Root를 Provider로 감싸 useState로 size 보관, Trigger가 useLayoutEffect로 등록. Portal 안의 SelectContent가 data-size를 읽는다. 즉 Root가 shadcn처럼 순수 SelectPrimitive.Root가 아니라 Provider 래퍼다.
    • 아이콘을 Radix 기본 대신 18×18 SVG로 교체, SelectItem의 check indicator 제거(선택 표시는 배경 면), SelectContent 기본값 position="popper", sideOffset=-1(border 1px 공유 seam).
    • long text ellipsis와 seam(--hm-select-seam-color)은 CSS 처리(select.css).
  • Public API 영향: size prop(Public). Context·setSize는 노출되지 않는 Internal.
  • 대체 가능한 shadcn 방식: shadcn은 Content가 size를 몰라도 되게 Trigger 쪽만 data-size를 둔다. Content까지 size 연동이 필요한 이유가 Portal 때문이므로 대안은 (a) Content에도 size prop을 직접 전달, (b) CSS만으로 처리, (c) 현 Context 유지. 어느 쪽이 맞는지 결정되지 않았다.
  • 유지 필요성: UNDER_REVIEW. Risk MEDIUM(Root 래퍼 + 렌더 후 useLayoutEffect로 state를 갱신하는 구조라, 첫 렌더에서 Content가 기본 large로 보일 수 있는 타이밍 의존이 있음).
  • 이 항목은 Final Spec이 아니다.

Tabs — tabs.tsx, theme/tabs.css

  • 추가:
    • TabsList에 fill(동일 폭·초록 선택 border·곡선 연결)과 panelSurface="surface|content" prop.
    • TabsList가 Radix List를 <div data-slot="tabs-frame">로 한 겹 감싼다(DOM 구조 변경).
    • 넘침 감지(ResizeObserver, MutationObserver, scroll 리스너, document.fonts.ready), 이전/다음 이동 버튼(aria-label 한국어 고정), 선택 탭 가시 유지(keepSelectedVisible), prefers-reduced-motion 분기, useId로 List id 생성, 외부 ref 병합.
    • 연결 곡선은 tabs.css의 ::before/::after + radial-gradient(HM 고유 구조 CSS).
  • Public API 영향: fill, panelSurface(Public). 나머지는 Internal.
  • 대체: shadcn Tabs는 위 기능이 전혀 없다. 넘침 버튼 없이 가로 스크롤만 허용하는 단순화는 가능하나 ui_viz D-090 규격을 포기해야 한다.
  • 유지 REQUIRED. Risk HIGH: 원본 TabsList 구조를 크게 바꿨고 Observer 기반 로직과 한국어 문구가 컴포넌트 안에 있다.
  • 2026-10-06: 대표 형태를 Primary(fill + panelSurface="content")·Secondary(fill + panelSurface="surface") 두 가지로 정리했다. Story 노출만 줄였고 코드·API·CSS branch는 그대로라 Custom complexity 변화 없음. non-fill branch는 REMOVE_CANDIDATE(사용자 확정 대기).
  • 2026-10-08 추가 개선 E 승인: 당시 fill=false, panelSurface="surface" 기본값을 현재 fill=true, panelSurface="content"(Primary)로 변경했다. Props 이름·타입·기존 CSS 디자인 값·선택자·Observer 동작은 유지하므로 Custom complexity 변화 없음. Legacy non-fill은 fill={false}로 유지하고 OLD_TEST_ONLY / REMOVE_CANDIDATE 삭제 대기 이력도 보존한다. 외부 기본 렌더링·명시적 Props 조합·CSS Override 영향은 Tabs 문서 §15를 따른다. 외부 소비자 전체 호환성은 미검증이다.

Dialog / Sheet / Drawer — dialog.tsx, sheet.tsx, drawer.tsx

  • 추가(Public): DialogBody, SheetBody, DrawerBody — 스크롤 소유 영역(Header/Footer 고정, Body만 스크롤). shadcn에는 없는 구조 API.
  • 추가(Internal): *Close가 asChild일 때 data-slot을 넘기지 않는 규칙(§7 I3).
  • Drawer 추가: autoFocus 기본값을 true로(vaul 기본은 false라 modal에서 포커스가 trigger에 남음). 소비자가 autoFocus={false}로 되돌릴 수 있다 → Public 동작 차이.
  • showCloseButton, side는 shadcn 기존 API(Custom 아님). Radius·shadow 등은 HM_THEME.
  • 대체: Body는 className이 붙은 div로 대체 가능하나 data-slot 기반 CSS 선택이 사라진다. REQUIRED, Risk LOW.

Alert Dialog — alert-dialog.tsx

  • 추가: AlertDialogAction/AlertDialogCancel이 variant|appearance|size를 받고 Button asChild로 합성. 기본값 Action=primary/solid, Cancel=cancel/solid. shadcn도 Button 스타일을 입히지만 appearance는 HM 전용.
  • REQUIRED, Risk LOW.

Combobox — combobox.tsx

  • shadcn에는 파일이 아닌 recipe(Popover+Command)만 있고 HM은 이를 options 기반 컴포넌트로 만들었다. Public: options(value/label/disabled), value/defaultValue/onValueChange, placeholder/searchPlaceholder/emptyText, size="medium|large". State: open, 비제어용 inner(제어/비제어 분기 직접 구현). 한국어 기본 문구 포함.
  • 대체: Popover+Command를 소비자가 직접 조합(shadcn 방식). REQUIRED(서비스 공통 필요), Risk LOW(원본 파일이 없어 업스트림 충돌 없음).
  • 내부: PopoverContent에 인라인 --hm-popover-padding/width 주입 → CAN_SIMPLIFY(§11).

Date Picker — date-picker.tsx

  • 같은 성격. Public: value/defaultValue/onValueChange, placeholder, size, format, calendarProps(Calendar 옵션 일부). 제어/비제어 상태 직접 구현. Behavior: onOpenAutoFocus에서 Calendar의 tab stop 날짜로 포커스 이동(Internal). 한국어 기본 포맷.
  • 대체: Popover+Calendar 직접 조합. REQUIRED, Risk LOW.

Popover / Collapsible — popover.tsx, collapsible.tsx

  • PopoverClose, CollapsibleTrigger의 asChild data-slot 규칙만 추가(§7 I3). Risk LOW.

Slider — slider.tsx

  • 추가: aria-label을 Root가 아니라 각 Thumb에 전달(Range는 "라벨 1/2"). role="slider"가 Thumb에 있기 때문. Internal. shadcn 원본에는 없음. REQUIRED(접근성), Risk LOW.

5. Components — HM_THEME / SHADCN_BASE

.tsx에 HM 구조·API·State 추가가 없는 Component. 시각 값은 각 Component 문서가 관리한다.

SHADCN_BASE (16): Accordion, Alert, Aspect Ratio, Avatar, Badge, Breadcrumb, Checkbox, Hover Card, Label, Progress, Radio Group, Scroll Area, Separator, Skeleton, Switch, Tooltip

HM_THEME (13): Calendar, Carousel, Command, Context Menu, Dropdown Menu, Menubar, Navigation Menu, Pagination, Resizable, Sonner, Table, Toggle, Toggle Group

참고(Custom으로 보지 않은 이유):

  • Alert·Badge: 사용 가능한 variant를 HM Theme에 있는 의미로 줄였다(Alert=default/destructive, Badge=4종). API 축소이며 추가가 아니다.
  • Calendar: 기본 locale을 한국어(ko)로 두었다. shadcn도 Chevron 컴포넌트를 교체한다. 기본값 하나의 차이라 THEME로 둔다.
  • Command: shadcn의 CommandDialog가 없다(의도적 제외, 코드 주석 명시). 기능 제거이며 추가 Custom 아님.
  • Toggle Group: shadcn 그대로 Context를 쓰며 spacing을 CSS 변수(--hm-toggle-group-gap)로 넘기는 한 줄이 추가됐다.
  • Carousel: shadcn 원본 로직(Context, Embla, 키보드)이 그대로다.
  • Tooltip: 원본처럼 Tooltip이 자체 TooltipProvider를 가진다(shadcn v4).

6. Patterns — HM_COMPOSITION

packages/ui/src/patterns/. 모두 기존 HM Component의 조합이며 별도 primitive가 아니다. 전부 shadcn에 없는 Public API다(Pattern 이름 자체).

Pattern Composition Custom Logic Public API
GNB Navigation Menu, Dropdown Menu, Avatar, Sheet, Button 있음: GNBMobileMenu(open state, Context, Sheet 합성), GNBMobileLink가 preventDefault된 클릭에도 Sheet를 닫음, GNBUser 기본 aria-label GNB(sticky), GNBBrand, GNBNav, GNBUtilities, GNBUser, GNBMobileMenu, GNBMobileLink, GNBMobileGroup
LNB Collapsible, Slot 없음(LNBGroup은 Collapsible 합성) LNB, LNBBrand, LNBNav, LNBItem, LNBGroup, LNBProfile
Dashboard Layout 현재는 Dashboard 내부 Header/Menu/Sidebar 조합만 허용 없음(레이아웃) DashboardLayout(header, sidebar), DashboardMain, DashboardContent
Page Header Breadcrumb·Button을 child로 받음 없음 PageHeader, PageHeaderContent/Title/Description/Actions
Loading Screen 없음(자체 요소) 24개 막대 렌더, CSS 애니메이션·reduced-motion, role="status" LoadingScreen(fullscreen)
Filter Bar Input, Select·Combobox·Date Picker·Button을 child로 받음 있음: FilterBarSearch(검색 아이콘 + Input + 지우기 버튼, aria-label 기본값) FilterBar, FilterBarSearch, FilterBarActions
Data Table Table, Checkbox, Dropdown Menu, Pagination, Select, Skeleton, Button + TanStack Table v9 있음: 기능(feature) 등록, useDataTable, dataTableSelectColumn, DataTableColumnHeader(정렬 순환·aria-sort), DataTableViewOptions, DataTablePagination(pageRange), loading/empty 상태 DataTable, useDataTable, dataTableSelectColumn, DataTableColumnHeader, DataTableViewOptions, DataTablePagination

CSS 자체가 구조를 구현하는 항목(HM 고유): GNB 아래쪽 concave join과 current 항목 연결 곡선(gnb.css), LNB와 콘텐츠 join(lnb.css, --hm-lnb-join), Loading Screen 막대 애니메이션(loading-screen.css). 각 Navigation Mode는 독립 레이아웃을 소유하며 Dashboard에 외부 GNB/LNB를 넣지 않는다.

과거 조사에서는 GNB+LNB 동시 조립과 Brand ownership을 기록했으나 현재 단일 Navigation 정책으로 대체되었다. 혼합 Story는 기술 검증 목적의 verification 태그와 VERIFICATION ONLY 표시가 있을 때만 유지할 수 있으며 운영 Reference로 사용하지 않는다(docs/patterns/gnb.md, lnb.md).

7. Internal Custom

consumer에게 노출되지 않는 내부 구현. 6건.

# 항목 위치 평가 Risk
I1 Select size Context + useLayoutEffect 등록 (작업 중일 수 있음) select.tsx UNDER_REVIEW MEDIUM
I2 Tabs 넘침 측정(Observer·scroll·state) 과 이동 버튼 tabs.tsx REQUIRED HIGH
I3 asChild 시 data-slot을 child에 남기는 규칙(Dialog/Sheet/Drawer/Popover/Collapsible의 Close·Trigger, Button의 data-slot 후순위 배치) 여러 파일 REQUIRED LOW
I4 Slider thumb별 aria-label 전달 slider.tsx REQUIRED LOW
I5 Date Picker onOpenAutoFocus 날짜 포커스 date-picker.tsx REQUIRED LOW
I6 Combobox·Date Picker의 PopoverContent 인라인 --hm-popover-* 변수 combobox.tsx, date-picker.tsx CAN_SIMPLIFY LOW

8. Public API Custom

shadcn 원본에 없는 consumer-facing 확장. Component 12건 + Pattern 전체(§6).

# Component HM API shadcn 원본 Risk
P1 Button variant(역할 5종+alias), appearance variant 값이 다름 MEDIUM
P2 Input `size="small medium large"`
P3 Textarea resize 없음 LOW
P4 Card surface 없음(size는 있음) LOW
P5 SelectTrigger `size="medium large"` (작업 중일 수 있음) `sm
P6 TabsList fill, panelSurface (+ 프레임 DOM) 없음 HIGH
P7 Dialog DialogBody 없음 LOW
P8 Sheet SheetBody 없음 LOW
P9 Drawer DrawerBody, autoFocus 기본 true 없음 / vaul 기본 false LOW
P10 AlertDialogAction / Cancel appearance (variant·size 포함) appearance 없음 LOW
P11 Combobox options 등 전체 API 파일 없음(recipe) LOW
P12 Date Picker format, calendarProps 등 전체 API 파일 없음(recipe) LOW

9. Storybook-only Custom (STORY_ONLY)

Production Custom 목록에 포함하지 않는다. 4묶음.

묶음 위치 내용
StateBoard helper src/components/story-board.tsx BoardState(note, noteAfter, wide), StateBoard. 39개 Story 파일이 사용
고정 상태·검증 Story src/components/*.stories.tsx, src/patterns/*.stories.tsx States, StandardStates, ListSizeComparison 등 비교·검증용 export. 전수 검토하지 않았음
샘플 데이터 src/patterns/sample-users.ts Data Table Story용
Demo / CENTER Story src/hm-theme.css, src/theme/preview.ts, src/center/* Demo 스타일, preview 설정, center-graphic 전용 Story(UI 규격과 분리)

10. External Library Base

Library 사용처 구분
radix-ui 대부분의 primitive Base. Custom은 §4
class-variance-authority Button, Badge, Alert, Toggle shadcn 구조. Button만 CVA 정의를 HM 값으로 교체
cmdk Command, Combobox Library Base + HM Theme (Combobox는 HM_CUSTOM 합성)
vaul Drawer Library Base + HM Custom(DrawerBody, autoFocus 기본값)
embla-carousel-react Carousel Library Base + HM Theme (shadcn 로직 그대로)
react-resizable-panels Resizable Library Base + HM Theme
react-day-picker Calendar, Date Picker Library Base + HM Theme (Date Picker는 HM_CUSTOM 합성)
sonner Sonner(Toast) Library Base + HM Theme
@tanstack/react-table v9 Data Table Library Base + HM Composition (v9 feature 등록 방식)
lucide-react 아이콘 전반 shadcn 기본

11. CAN_SIMPLIFY 후보

평가만 한다. 변경은 하지 않았다.

항목 단순화 방향 비고
Textarea resize (P3) className(resize-none 등)로 대체 가능 기본 정책을 컴포넌트에 두려는 의도라면 유지
Combobox·Date Picker 인라인 --hm-popover-* (I6) CSS 선택자·data-slot으로 이동
dark: 잔재 현재 button.tsx 2개 행에만 남아 있고 select.tsx에는 없다. 기존 upstream dark: 분기는 보존할 수 있으며 새 HM Dark 분기는 추가하지 않는다 HM_CUSTOM이 아니라 shadcn 원본 잔재. 정리 후보

12. UNDER_REVIEW / LEGACY

항목 상태 비고
Select size Context (P5 + I1) UNDER_REVIEW 조사 당시 미결 설계 평가. 대안은 §4.1 Select 참조. 현재 작업 중이라는 뜻이 아니며 현재 API는 Select 문서·코드를 따른다
Button default/outline alias (P1) LEGACY shadcn 호환용. 소비처 사용 여부 미확인

13. 유지 원칙

  1. HM_THEME·SHADCN_BASE는 CSS/Token만 바꾼다. .tsx에 구조·상태를 추가하려면 shadcn-기반-구현-원칙.md §6의 Custom 허용 조건과 기록 요건을 확인하고 이 문서에 행을 추가한다.
  2. shadcn 재생성·업데이트 시 우선 확인 순서: Tabs → Button → Select → 나머지 Body/Close 규칙(I3). 이 파일들은 덮어쓰지 않고 수동 병합한다.
  3. data-slot을 child에 남기는 규칙(I3)은 새 asChild 지원 컴포넌트에도 같은 방식으로 적용한다.
  4. 새 Pattern은 §6 표에 "Composition / Custom Logic / Public API"를 한 행으로 기록한다.
  5. 이 문서의 수치는 조사 시점(2026-10-06) 기준이다. Select 설계 평가가 변경되면 §4·§7·§8·§12를 함께 갱신한다.

2026-10-06 Theme infrastructure

Default/External 동일 Runtime 계약, 패키지 theme API, Semantic/팔레트 연결과 Accent derived 공통화는 HM_THEME / Theme infrastructure다. Component DOM/props/state/Portal/breakpoint를 바꾸지 않았으므로 위 HM_CUSTOM Inventory 수를 늘리지 않는다. 상세: Runtime Theme.