sellmate-design-system-react 9.0.0-beta.61 → 9.0.0-beta.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@
2
2
  * 원형 차트(파이·도넛)의 공용 구현 — 조각 계산과 그림.
3
3
  *
4
4
  * `SPieChart`·`SDonutChart` 는 이 위의 얇은 껍데기다. 두 차트는 가운데를 비우는지
5
- * (`innerRatio`)와 그 빈자리에 무엇을 적는지(`center`)만 다르다.
5
+ * (`innerRatio`)만 다르다. 도넛의 빈 가운데에는 글자를 두지 않는다.
6
6
  *
7
7
  * **시안이 없다.** 공용 차트 토큰(팔레트·범례·툴팁·바탕)은 그대로 쓰고, 원형 고유의
8
8
  * 치수만 아래 상수로 정했다. 디자인 토큰이 생기면 이 상수부터 토큰 참조로 바꾼다.
@@ -13,8 +13,11 @@
13
13
  */
14
14
  import { type CSSProperties, type ReactNode } from 'react';
15
15
  import type { SChartColor, SChartLegendPosition, SChartPalette } from './types';
16
- /** 도넛 안쪽 반지름 / 바깥 반지름. 너비에 따라 고리 두께가 함께 늘고 준다. */
17
- export declare const DONUT_INNER_RATIO = 0.6;
16
+ /**
17
+ * 도넛 안쪽 반지름 / 바깥 반지름. 너비에 따라 구멍과 고리 두께가 함께 늘고 준다.
18
+ * 폭이 반응형이라 구멍을 px 로 고정하지 않고 시안의 비율(바깥 지름 248 · 구멍 지름 99)로 둔다.
19
+ */
20
+ export declare const DONUT_INNER_RATIO = 0.4;
18
21
  /**
19
22
  * 비율 라벨을 적는 최소 몫. 이보다 좁은 조각은 글자가 조각 밖으로 넘쳐 이웃 조각의
20
23
  * 라벨과 겹치므로 적지 않는다 — 값은 툴팁으로 읽는다.
@@ -22,6 +25,16 @@ export declare const DONUT_INNER_RATIO = 0.6;
22
25
  export declare const LABEL_MIN_RATIO = 0.05;
23
26
  /** 파이의 비율 라벨이 놓이는 반지름(바깥 반지름에 대한 비). 가운데는 조각이 좁아 바깥쪽에 둔다. */
24
27
  export declare const PIE_LABEL_RADIUS_RATIO = 0.65;
28
+ /**
29
+ * 짚은 조각이 자라는 길이(px). 각도는 그대로 두고 **안팎 양쪽으로** 자라, 이웃 조각을 덮지
30
+ * 않고 고리만 두꺼워진다. 배율이 아니라 px 이라 차트가 커져도 자라는 양은 늘 같게 보인다.
31
+ *
32
+ * 시안(바깥 반지름 124)에서 짚은 조각은 128 · 46.08 이다 — 바깥으로 4px, 안쪽으로 3.52px.
33
+ * 안쪽도 같은 4px 로 두어 규칙을 하나로 했다(시안과 0.48px 차이).
34
+ */
35
+ export declare const HOVER_GROW = 4;
36
+ /** 짚은 조각의 모서리 둥글기(px). 자란 조각만 네 모서리를 둥글린다. */
37
+ export declare const HOVER_CORNER = 2;
25
38
  /** 조각 하나. */
26
39
  export interface RadialSlice {
27
40
  name: string;
@@ -46,12 +59,11 @@ export interface RadialChartProps {
46
59
  showTooltip?: boolean;
47
60
  formatValue?: (value: number) => string;
48
61
  onSliceClick?: (slice: RadialSlicePoint) => void;
62
+ tooltipFooter?: (slice: RadialSlicePoint) => ReactNode;
49
63
  className?: string;
50
64
  style?: CSSProperties;
51
65
  /** 가운데를 비우는 비율. 0 이면 파이다 */
52
66
  innerRatio: number;
53
- /** 가운데 빈자리에 놓을 내용. 합계를 받아 그린다 */
54
- renderCenter?: (total: number) => ReactNode;
55
67
  /** 스크린 리더가 읽는 그래프 종류 */
56
68
  kind: string;
57
69
  }
@@ -62,8 +74,12 @@ export declare function formatRatio(ratio: number): string;
62
74
  *
63
75
  * 한 바퀴 전체(조각이 하나)는 호 하나로 그릴 수 없다 — 시작점과 끝점이 같으면 SVG 가
64
76
  * 호를 그리지 않는다. 그래서 반원 둘로 나눠 그리고, 도넛은 `evenodd` 로 가운데를 뚫는다.
77
+ *
78
+ * `corner` 를 주면 네 모서리를 그 반지름으로 둥글린다. 모서리는 반지름 방향 변과 호에
79
+ * 동시에 닿는 원이라, 변은 접점까지 짧아지고 호는 접점까지 각도가 줄어든다. 한 바퀴
80
+ * 전체는 반지름 방향 변이 없어 둥글릴 모서리도 없다.
65
81
  */
66
- export declare function slicePath(center: number, outer: number, inner: number, start: number, end: number): string;
82
+ export declare function slicePath(center: number, outer: number, inner: number, start: number, end: number, corner?: number): string;
67
83
  /**
68
84
  * 파이·도넛 공용 그림.
69
85
  *
@@ -71,8 +87,3 @@ export declare function slicePath(center: number, outer: number, inner: number,
71
87
  * 원의 지름은 잰 폭이라 부모가 줄면 원도 함께 준다. 범례는 정사각형 바깥에 붙는다.
72
88
  */
73
89
  export declare const RadialChart: import("react").ForwardRefExoticComponent<RadialChartProps & import("react").RefAttributes<HTMLDivElement>>;
74
- /** 도넛 가운데 — 윗줄 라벨과 큰 값. */
75
- export declare function RadialCenter({ label, value }: {
76
- label?: ReactNode;
77
- value: ReactNode;
78
- }): import("react").JSX.Element;
@@ -1,3 +1,15 @@
1
+ /**
2
+ * 차트 툴팁 — 기준 막대 옆에 서는 값 상자.
3
+ *
4
+ * 커서를 따라다니지 않는다. 커서를 따라가면 상자가 막대를 가리는 자리로 계속 밀려들고,
5
+ * 같은 값을 읽는 동안에도 상자가 흔들려 눈이 따라가야 한다. 대신 호출 쪽이 정한
6
+ * **기준 막대**(`anchor`)에 붙여 한자리에 세운다.
7
+ *
8
+ * 차트 컨테이너 **안에** absolute 로 뜬다. Portal 을 쓰지 않는 이유: 차트는 카드·모달
9
+ * 안에 들어가는 일이 많은데, 상자가 차트 밖으로 나갈 만큼 크지 않아 굳이 부모를
10
+ * 벗어날 이유가 없다. 대신 부모가 `relative` 여야 한다.
11
+ */
12
+ import type { ReactNode } from 'react';
1
13
  export interface ChartTooltipItem {
2
14
  /** 계열 점 색 */
3
15
  color: string;
@@ -38,6 +50,11 @@ export interface ChartTooltipProps {
38
50
  };
39
51
  /** 기준 자리에서 띄우는 가로 거리. 기본값은 양쪽 다 4px */
40
52
  gapX?: ChartTooltipGapX;
53
+ /**
54
+ * 값 목록 아래에 붙이는 내용 — 차트의 `tooltipFooter` 가 짚은 항목을 받아 그린 것이다.
55
+ * 상자가 마우스를 통과시키므로 누를 수 있는 것은 넣지 못한다.
56
+ */
57
+ footer?: ReactNode;
41
58
  className?: string;
42
59
  }
43
- export declare function ChartTooltip({ title, items, anchor, bounds, gapX, className, }: ChartTooltipProps): import("react").JSX.Element;
60
+ export declare function ChartTooltip({ title, items, anchor, bounds, gapX, footer, className, }: ChartTooltipProps): import("react").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import type { ComponentPropsWithoutRef } from 'react';
2
+ import * as RDropdown from '@radix-ui/react-dropdown-menu';
3
+ import { type SIconName } from '../components/SIcon';
4
+ /**
5
+ * 버튼에 매달린 액션 메뉴(SDropdownButton · SMeatballButton)의 공용 층.
6
+ * 두 컴포넌트가 **같은 메뉴로 그려져야** 해서 한 곳에 둔다 — Root/Trigger 는 트리거 모양이
7
+ * 달라 각 컴포넌트가 갖고, 여기는 Portal + Content + Item 만 맡는다.
8
+ */
9
+ export interface DropdownMenuItem {
10
+ value: string | number;
11
+ label: string;
12
+ icon?: SIconName;
13
+ disabled?: boolean;
14
+ }
15
+ export interface DropdownMenuContentProps extends Omit<ComponentPropsWithoutRef<typeof RDropdown.Content>, 'children'> {
16
+ items: readonly DropdownMenuItem[];
17
+ onItemClick?: (value: string | number) => void;
18
+ }
19
+ export declare function DropdownMenuContent({ items, onItemClick, align, className, ...contentProps }: DropdownMenuContentProps): import("react").JSX.Element;
@@ -47,13 +47,13 @@
47
47
 
48
48
  | 분류 | 컴포넌트 |
49
49
  | --- | --- |
50
- | **버튼·링크** | `SButton` `SGhostButton` `SDropdownButton` `STextLink` `SSwitch` `SToggle` |
50
+ | **버튼·링크** | `SButton` `SGhostButton` `SMeatballButton`(⋯ 로 '더 보기' 메뉴를 여는 아이콘 버튼) `SDropdownButton` `STextLink` `SSwitch` `SToggle` |
51
51
  | **입력 (폼)** | `SForm` `SField` `SInput` `SChatInput`(대화 입력창) `SSearchInput` `SNumberInput` `STextarea` `SEditor` `SSelect` `SCheckbox` `SRadio` `SRadioGroup` `SRadioButton` `SRadioCard` `SRadioCardGroup` `SChip` `SChipInput` `SBarcodeInput` `SFilePicker` |
52
52
  | **날짜·시간** | `SCalendar` `SCalendarBoard`(한 달치 일정 판) `SDatePicker` `SDatePickerYearListbox` `SDatePickerMonthListbox` `SDateRangePicker` `STimePicker` `STimeRangePicker` |
53
53
  | **표·목록** | `SChatMessage`(대화의 메시지 한 건) `SChatAttachedFile`(입력창 위, 아직 보내지 않은 첨부 한 칸) `SChatFile`(대화 흐름에 선, 보낸 파일 한 칸) `SChatSystemMessage`(대화 흐름 가운데 서는 시스템 안내) `STable` `STableBar` `SChipFilter` `SKeyValueTable` `SList` `SListItem` `SExpansionList` `SDraggableList` `SDraggableItem` `STree` |
54
54
  | **레이아웃** | `SLayout` `SGnb` `SGnbSystem` `SSystemActionButton`(GNB system 패널에 한 줄씩 쌓는 액션 행 — 버튼 고르기는 §3-5) `SAccountListBox`(계정 행을 눌러 뜨는 계정 패널) `SLauncherListBox`(런처 버튼을 눌러 뜨는 서비스 목록) `SPage` `SPageHeader`(페이지 제목 영역 — `SLayout` 안에서 `SPage` 앞에 둔다) `SSectionHeaderCard` `SCard` `SLoginCard`(통합 계정 로그인 화면의 카드) `SDivider` `SSplitter` `SScrollArea` `SExpansionItem` |
55
55
  | **내비게이션** | `STabs` `SPagination` `SStepper` |
56
- | **차트** | `SBarChart`(막대 그래프 — 항목끼리 크기를 견준다. `stacked` 로 항목 안의 구성까지) `SLineChart`(꺾은선 그래프 — 순서가 있는 항목의 추이를 본다. `area` 로 크기까지, `stacked` 로 구성까지) `SPieChart`(원그래프 — 한 시점의 전체를 몇 개의 몫으로 나눈다) `SDonutChart`(도넛 그래프 — 몫과 함께 가운데에 합계를 적는다) |
56
+ | **차트** | `SBarChart`(막대 그래프 — 항목끼리 크기를 견준다. `stacked` 로 항목 안의 구성까지) `SLineChart`(꺾은선 그래프 — 순서가 있는 항목의 추이를 본다. `area` 로 크기까지, `stacked` 로 구성까지) `SPieChart`(원그래프 — 한 시점의 전체를 몇 개의 몫으로 나눈다) `SDonutChart`(도넛 그래프 — 가운데가 빈 원그래프. 구멍에 글자를 두지 않는다) |
57
57
  | **표시·상태** | `STag` `SBadge` `SIcon` `SLogo`(브랜드 로고를 아이콘처럼 — size 는 높이다) `SImage` `SCallout` `SGuide` |
58
58
  | **진행·로딩** | `SLinearProgress` `SCircleProgress` `SLoadingContainer` `SLoadingModal` |
59
59
  | **오버레이** | `STooltip` `SPopover` `SPopup` `SDrawer` `SPortal` |
@@ -80,7 +80,7 @@ AI 에이전트는 코드를 생성하기 전에 이 목록을 반드시 지킨
80
80
 
81
81
  | 금지 | 대신 사용 |
82
82
  | --- | --- |
83
- | `<button>` | `SButton`, `SGhostButton`, `SDropdownButton`, `STextLink` |
83
+ | `<button>` | `SButton`, `SGhostButton`, `SMeatballButton`, `SDropdownButton`, `STextLink` |
84
84
  | `<input type="text/password/...">` | `SInput` |
85
85
  | `<input type="search">` | `SSearchInput` |
86
86
  | `<input type="number">` | `SNumberInput` |
@@ -176,7 +176,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
176
176
  | --- | --- | --- |
177
177
  | **셸** | 앱 전체 뼈대. 페이지가 바뀌어도 남는다 | `SLayout` `SGnb` `SGnbSystem`(GNB 맨 아래 판 · 전폭 상단바 오른쪽 끝) `SPage` `SPageHeader`(`SLayout` 안에서 `SPage` 앞에 둔다) |
178
178
  | **블록** | `SPage` 의 직계 자식. 페이지를 세로로 쌓는 단위 | `SSectionHeaderCard` `SCard` `SChatMessage` `SChatSystemMessage` `SChatInput` `SLoginCard`(유일하게 `SPage` 밖에 선다 — 로그인 화면 자체가 자기 자리다, §4-6) `SForm` `SSplitter` `SScrollArea` `SCalendarBoard` `STable` `STableBar` `SChipFilter` `SKeyValueTable` `SList` `SExpansionList` `SDraggableList` `STree` `SCallout` `SBarChart` `SLineChart` `SPieChart` `SDonutChart` `STabs` `SStepper` `SPagination` `SDivider` |
179
- | **요소** | 블록 **안에** 놓이는 컨트롤. 혼자 페이지에 서지 않는다 | `SButton` `SGhostButton` `SDropdownButton` `SSystemActionButton` `SField` `SInput` `SSearchInput` `SNumberInput` `STextarea` `SEditor` `SSelect` `SCheckbox` `SRadio` `SRadioGroup` `SRadioButton` `SRadioCard` `SRadioCardGroup` `SSwitch` `SToggle` `SChipInput` `SBarcodeInput` `SFilePicker` `SDatePicker` `SDatePickerYearListbox` `SDatePickerMonthListbox` `SDateRangePicker` `STimePicker` `STimeRangePicker` `SCalendar` `SListItem` `SExpansionItem` `SDraggableItem` `SChatAttachedFile` `SChatFile` `SImage` `SLinearProgress` `SCircleProgress` |
179
+ | **요소** | 블록 **안에** 놓이는 컨트롤. 혼자 페이지에 서지 않는다 | `SButton` `SGhostButton` `SMeatballButton` `SDropdownButton` `SSystemActionButton` `SField` `SInput` `SSearchInput` `SNumberInput` `STextarea` `SEditor` `SSelect` `SCheckbox` `SRadio` `SRadioGroup` `SRadioButton` `SRadioCard` `SRadioCardGroup` `SSwitch` `SToggle` `SChipInput` `SBarcodeInput` `SFilePicker` `SDatePicker` `SDatePickerYearListbox` `SDatePickerMonthListbox` `SDateRangePicker` `STimePicker` `STimeRangePicker` `SCalendar` `SListItem` `SExpansionItem` `SDraggableItem` `SChatAttachedFile` `SChatFile` `SImage` `SLinearProgress` `SCircleProgress` |
180
180
  | **인라인** | 텍스트 흐름·셀·라벨 안에 섞인다. 혼자 블록이 되지 않는다 | `STag` `SBadge` `SIcon` `SLogo` `STextLink` `SChip` |
181
181
  | **레이어** | 문서 흐름 **밖**에 떠서 그려진다. 어느 층에서 띄우든 레이아웃에 영향이 없다 | `SModal` `SActionModal` `SConfirmModal` `SPopup` `SDrawer` `SPopover` `STooltip` `SPortal` `SAccountListBox`(계정 행에 붙어 뜬다 — 직접 띄우지 않는다) `SLauncherListBox`(런처 버튼에 붙어 뜬다 — 직접 띄우지 않는다) `SToast` `SLoadingModal` `SLoadingContainer` `SGuide` |
182
182
 
@@ -333,7 +333,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
333
333
  | `SCheckbox` | **`gap-sd-24`** | `gap-sd-8` |
334
334
  | `SRadio` | **`gap-sd-24`** | `gap-sd-8` |
335
335
  | `STextLink` | **`gap-sd-16`**(sm) / **`gap-sd-24`**(md·lg) | `gap-sd-4` |
336
- | `SGhostButton` | `gap-sd-4` | `gap-sd-4` |
336
+ | `SGhostButton` · `SMeatballButton` | `gap-sd-4` | `gap-sd-4` |
337
337
  | `SButton` | `gap-sd-8` (xs·sm·md) / **`gap-sd-12`**(lg) | 〃 |
338
338
  | `STag` | `gap-sd-8` | `gap-sd-8` |
339
339
  | `SToggle` | `gap-sd-8` | `gap-sd-8` |
@@ -579,7 +579,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
579
579
  | 여러 항목의 추이를 **합계와 함께** 보여준다 (채널별 매출이 쌓여 전체가 되는 흐름) | `SLineChart stacked area` | 합계가 뜻을 갖는 값일 때만 쌓는다. 음수가 섞이거나 더해서 뜻이 없는 값(비율·평균)은 쌓지 말고 겹쳐 그린다 |
580
580
  | 항목의 크기와 **그 안의 구성**을 함께 보여준다 (주문 상태별 내역, 유입 경로별 몫) | `SBarChart stacked` | 계열끼리 견주는 것이 목적이면 `stacked` 없이 나란히 세운다. 더해서 뜻이 없는 값(비율·평균)은 쌓지 않는다 — 합계 라벨이 거짓말이 된다 |
581
581
  | 한 시점의 **전체를 몇 개의 몫으로** 나눠 보여준다 (채널별 매출 비중, 회원 등급 구성) | `SPieChart` | 조각이 대여섯 개를 넘거나 몫끼리 크기를 견주는 것이 목적이면 `SBarChart` — 사람은 각도보다 길이를 정확히 견준다. 순서가 있는 추이(월별)는 몫이 아니라 흐름이라 `SLineChart`. 0·음수는 그려지지 않으므로 증감은 원으로 나타내지 않는다. 조각은 큰 순으로 넘긴다. 폭은 부모를 따르고 그림은 그 폭의 정사각형이다 — 폭이 필요하면 `className` 으로 폭만 주고 높이는 주지 않는다 (`SDonutChart` 도 같다) |
582
- | 몫과 함께 **전체의 크기(합계)** 를 먼저 읽게 한다 (주문 상태별 구성 + 총 주문 수, 목표 달성률) | `SDonutChart` | 합계가 필요 없으면 `SPieChart`. 가운데 값은 기본이 그려진 조각의 합계이고, 합계가 아닌 대표값(달성률 등)은 `centerValue` 로 준다. 여러 기간에 걸친 구성 변화는 원을 여러 개 늘어놓지 말고 `SBarChart stacked` |
582
+ | 한 시점의 전체를 몫으로 나누되 **가운데가 빈 고리 모양**으로 보여준다 (시안이 도넛일 때) | `SDonutChart` | 쓰임·데이터 규칙은 `SPieChart` 와 같고 모양만 다르다 — 시안이 정한 쪽을 쓴다. **구멍에 합계·라벨을 겹쳐 올리지 않는다.** 합계 같은 값이 필요하면 차트 바깥(카드 제목·요약 값)에 적는다. 여러 기간에 걸친 구성 변화는 원을 여러 개 늘어놓지 말고 `SBarChart stacked` |
583
583
  | 표 위에 건수 요약과 액션을 얹는다 | `STableBar` | 표의 이름도 여기 `title` 슬롯에 넣는다 — 제목만으로 블록을 따로 세우지 않는다. §4-2 |
584
584
  | 상태·분류를 라벨로 찍는다 | `STag` | §3-1 |
585
585
  | 색 점만으로 상태를 찍는다 | `SBadge` | §3-1 |
@@ -594,6 +594,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
594
594
  | --- | --- | --- |
595
595
  | 라벨이 있는 일반 액션을 준다 | `SButton` | §3-5 |
596
596
  | 아이콘 하나로 뜻이 통하는 부가 조작을 준다 | `SGhostButton` | §3-5-5 |
597
+ | 자리가 좁아 부가 조작 여러 개를 ⋯ 뒤 메뉴로 접어 둔다 | `SMeatballButton` | §3-5-5 |
597
598
  | 한 버튼에 여러 선택지를 매단다 | `SDropdownButton` | §3-5-4 |
598
599
  | GNB system 패널에서 한 줄짜리 행 액션을 준다 | `SSystemActionButton` | §3-5-7 |
599
600
 
@@ -693,7 +694,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
693
694
  | --- | --- |
694
695
  | `default` | 흰 면 위 (`SPage background="frame"`) — 옅은 회색 면이라 페이지와 구분된다 |
695
696
  | `white` | 회색 면 위 (`background="neutral"`·`"screen"`) — 그 위에서는 `default` 가 배경에 묻힌다 |
696
- | `danger` | 경고. 좌측에 "주의사항" 타이틀이 붙으므로 단순 안내에는 쓰지 않는다 |
697
+ | `danger` | 경고. 좌측에 "주의사항" 타이틀이 붙으므로 단순 안내에는 쓰지 않는다. 주변에 이미 경고 맥락(제목 등)이 있어 타이틀이 중복되면 `showTitle={false}` 로 타이틀만 뺀다 — 경고 면은 유지된다 |
697
698
 
698
699
  ### 3-3. 플로팅/오버레이류
699
700
 
@@ -1216,6 +1217,7 @@ tableRef.current.scrollToRow(row); // 복원
1216
1217
  | 일반 액션 | `SButton` (`color`: `primary` / `secondary` / `neutral` / `danger`, `outline`, `size`: xs~md) |
1217
1218
  | **삭제 등 파괴적 액션** | **`SButton color="danger"`** 또는 **`color="danger" outline`** (아래 3-5-3) |
1218
1219
  | **아이콘 하나로 뜻이 통하는 부가 조작** | **`SGhostButton`** — 라벨이 없는 아이콘 전용 버튼 (아래 3-5-5) |
1220
+ | **부가 조작 여러 개를 ⋯ 메뉴로 접기** | **`SMeatballButton`** — ⋯ 아이콘 버튼 + `SDropdownButton` 과 같은 메뉴 (아래 3-5-5) |
1219
1221
  | 본문 속 이동 링크 | `STextLink` |
1220
1222
  | 메인 액션 + 부가 메뉴 | `SDropdownButton` |
1221
1223
  | **GNB system 패널의 한 줄 액션** | **`SSystemActionButton`** — 행 전체가 버튼인 표면형 (아래 3-5-7) |
@@ -1329,6 +1331,24 @@ tableRef.current.scrollToRow(row); // 복원
1329
1331
  ❌ <SGhostButton icon="download" ariaLabel="엑셀 다운로드" /> // 목록의 주 액션 → SButton
1330
1332
  ```
1331
1333
 
1334
+ ##### `SMeatballButton` — ⋯ 뒤에 메뉴를 접어 둘 때
1335
+
1336
+ 자리가 좁아 부가 조작을 하나하나 아이콘으로 늘어놓을 수 없을 때, **⋯ 하나로 접고 누르면 메뉴를 띄운다.** 버튼의 크기·색·hover·툴팁은 `SGhostButton` 과, 메뉴 모양은 `SDropdownButton` 과 같다.
1337
+
1338
+ - **메뉴는 컴포넌트가 띄운다.** `items` 를 넘기고 선택은 `onItemClick(value)` 로 받는다. 메뉴를 따로 만들어 붙이지 않고, 열림 상태(`aria-expanded`)도 직접 넣지 않는다.
1339
+ - **`SGhostButton icon="etc"` 로 직접 만들지 않는다.** '더 보기' 메뉴는 항상 `SMeatballButton` 이다.
1340
+ - **`intent` 는 `default` / `inverse` 뿐이다.** ⋯ 는 조작이 아니라 메뉴를 여는 것이므로 `action`·`danger` 색을 받지 않는다. 어두운 배경 위에서만 `inverse`.
1341
+ - 툴팁·`ariaLabel` 은 기본 문구가 들어 있어 **주지 않아도 된다.** 한 화면에 ⋯ 가 여러 개라 무엇의 메뉴인지 구분해야 할 때만 `tooltipText` 를 바꾼다(`ariaLabel` 이 따라간다).
1342
+ - 메인 액션에 변형 동작을 곁들이는 것이면 `SMeatballButton` 이 아니라 `SDropdownButton split`(§3-5-4)이다.
1343
+
1344
+ ```tsx
1345
+ ✅ <SMeatballButton size="xs" // 행 끝 부가 조작 묶음
1346
+ items={[{ value: 'copy', label: '복제', icon: 'copy' }, { value: 'remove', label: '삭제', icon: 'remove' }]}
1347
+ onItemClick={v => handleRowAction(row, v)} />
1348
+ ✅ <SMeatballButton intent="inverse" items={items} onItemClick={onAction} /> // 어두운 배경 위
1349
+ ❌ <SGhostButton icon="etc" ariaLabel="더 보기" onClick={openMyMenu} /> // 직접 조립 → SMeatballButton
1350
+ ```
1351
+
1332
1352
  #### 3-5-6. 그 밖
1333
1353
 
1334
1354
  - 라벨은 **동사(+목적어)** — `저장` · `적치 지시` · `송장 재출력`
@@ -3149,6 +3169,7 @@ export const BADGE_COLORS = [
3149
3169
  | `showTooltip?` | `boolean` | `true` | 막대에 마우스를 올리면 값 상자를 띄운다 |
3150
3170
  | `formatValue?` | `(value: number) => string` | `defaultFormat` | 값 표시 형식 |
3151
3171
  | `height?` | `number \| string` | — | 차트 높이. **아래 축 텍스트까지 포함한 값**이다 — 그림은 그만큼 줄어든다 |
3172
+ | `tooltipFooter?` | `(category: SBarChartTooltipCategory) => ReactNode` | — | 툴팁의 값 아래에 덧붙일 내용. 짚은 항목을 받아 그린다 — 계열 값만으로 모자란 맥락 (합계, 전월 대비 등)을 적는다. 툴팁은 누를 수 없으므로 버튼·링크는 넣지 않는다 |
3152
3173
  | `className?` | `string` | — | |
3153
3174
  | `style?` | `CSSProperties` | — | |
3154
3175
 
@@ -3229,6 +3250,20 @@ export interface SBarChartPoint {
3229
3250
  }
3230
3251
  ```
3231
3252
 
3253
+ ### SBarChartTooltipCategory
3254
+
3255
+ ```ts
3256
+ /** 툴팁 하단(`tooltipFooter`)이 받는 짚은 항목. */
3257
+ export interface SBarChartTooltipCategory {
3258
+ /** 카테고리 인덱스 */
3259
+ categoryIndex: number;
3260
+ /** 카테고리 이름 */
3261
+ name: string;
3262
+ /** 툴팁에 값이 뜬 지점들 — 값이 없는 계열은 빠진다 */
3263
+ points: SBarChartPoint[];
3264
+ }
3265
+ ```
3266
+
3232
3267
  ---
3233
3268
 
3234
3269
  # SBarcodeInput
@@ -3567,6 +3602,7 @@ export const CALENDAR_BOARD_EVENT_COLORS = [
3567
3602
  | Prop | Type | Default | Description |
3568
3603
  |------|------|---------|-------------|
3569
3604
  | `type?` | `SCalloutType` | `'default'` | 콜아웃 타입 (색상·아이콘·타이틀 결정). - `default` — 옅은 회색 면. 흰 페이지(`background="frame"`) 위의 기본 안내. - `white` — 같은 안내인데 배경만 흰 면. 회색 면(`neutral`·`screen`) 위에서 default 가 묻힐 때. - `danger` — 좌측에 주의사항 타이틀이 붙는 경고. |
3605
+ | `showTitle?` | `boolean` | `true` | `danger` 좌측의 주의사항 타이틀(아이콘+라벨) 표시 여부. 기본 `true`. `false` 면 타이틀만 빠지고 danger 의 면·테두리·본문색은 그대로다. 다른 타입에는 영향이 없다. |
3570
3606
  | `message?` | `SCalloutMessage[]` | `[]` | 표시할 메시지 목록 (배열 중첩으로 depth 표현). 각 문자열은 인라인 HTML(`<b>`, `<a>` 등)을 허용하며 sanitizeInlineHtml 로 살균 후 렌더된다. |
3571
3607
  | `children?` | `ReactNode` | — | message 대신 직접 본문을 넣을 때 |
3572
3608
  | `className?` | `string` | — | |
@@ -4792,14 +4828,12 @@ export type SDateRangePickerSize = SFieldSize;
4792
4828
  | `data` | `SDonutChartSlice[]` | — | 조각 목록. 주는 순서대로 12시에서 시계 방향으로 그린다 — 보통 큰 순으로 준다 |
4793
4829
  | `palette?` | `SDonutChartPalette` | `'multi'` | 색 팔레트. `custom` 일 때만 `colors` 를 본다 |
4794
4830
  | `colors?` | `SDonutChartColor[]` | — | `palette='custom'` 에서 쓸 색 이름을 조각 순서대로. 조각보다 짧으면 앞에서부터 순환하고, 비어 있으면 `multi` 로 그린다 |
4795
- | `centerLabel?` | `ReactNode` | — | 가운데 윗줄에 적을 이름 (예: "총 주문") |
4796
- | `centerValue?` | `ReactNode` | — | 가운데 큰 값. 주지 않으면 그려진 조각의 합계를 `formatValue` 로 적는다 |
4797
- | `hideCenter?` | `boolean` | `false` | 가운데를 비운다 — 합계 대신 범례·툴팁만으로 읽게 할 때 |
4798
4831
  | `showValueLabel?` | `boolean` | `false` | 고리 위에 몫(%)을 적는다. 좁은 조각은 글자가 넘치므로 적지 않는다 |
4799
4832
  | `showLegend?` | `boolean` | `true` | 범례를 보인다 |
4800
4833
  | `legendPosition?` | `SDonutChartLegendPosition` | `'top'` | 범례 위치 |
4801
4834
  | `showTooltip?` | `boolean` | `true` | 조각에 마우스를 올리면 값 상자를 띄운다 |
4802
- | `formatValue?` | `(value: number) => string` | `defaultFormat` | 값 표시 형식 — 툴팁과 가운데 합계에 함께 쓰인다 |
4835
+ | `formatValue?` | `(value: number) => string` | — | 값 표시 형식 |
4836
+ | `tooltipFooter?` | `(slice: SDonutChartSlicePoint) => ReactNode` | — | 툴팁의 값 아래에 덧붙일 내용. 짚은 조각을 받아 그린다 — 몫·값만으로 모자란 맥락 (전월 대비, 건수 등)을 적는다. 툴팁은 누를 수 없으므로 버튼·링크는 넣지 않는다 |
4803
4837
  | `className?` | `string` | — | 폭은 기본 100% 다. 폭을 정하려면 여기에 준다 — 그림은 그 폭의 정사각형이 된다 |
4804
4838
  | `style?` | `CSSProperties` | — | |
4805
4839
 
@@ -5790,6 +5824,7 @@ export type SGhostButtonIntent = 'default' | 'danger' | 'action' | 'subAction' |
5790
5824
  - [SGnb](../SGnb)
5791
5825
  - [SGuide](../SGuide)
5792
5826
  - [SInput](../SInput)
5827
+ - [SMeatballButton](../SMeatballButton)
5793
5828
  - [SModalContainer](../SModalContainer)
5794
5829
  - [SOverlayHeader](../SOverlayHeader)
5795
5830
  - [SPage](../SPage)
@@ -6650,6 +6685,7 @@ export type SLayoutHeader = SGnbHeader;
6650
6685
  | `showTooltip?` | `boolean` | `true` | 항목에 마우스를 올리면 값 상자를 띄운다 |
6651
6686
  | `formatValue?` | `(value: number) => string` | `defaultFormat` | 값 표시 형식 |
6652
6687
  | `height?` | `number \| string` | — | 차트 높이. **아래 축 텍스트까지 포함한 값**이다 — 그림은 그만큼 줄어든다 |
6688
+ | `tooltipFooter?` | `(category: SLineChartTooltipCategory) => ReactNode` | — | 툴팁의 값 아래에 덧붙일 내용. 짚은 항목을 받아 그린다 — 계열 값만으로 모자란 맥락 (합계, 전월 대비 등)을 적는다. 툴팁은 누를 수 없으므로 버튼·링크는 넣지 않는다 |
6653
6689
  | `className?` | `string` | — | |
6654
6690
  | `style?` | `CSSProperties` | — | |
6655
6691
 
@@ -6730,6 +6766,20 @@ export interface SLineChartPoint {
6730
6766
  }
6731
6767
  ```
6732
6768
 
6769
+ ### SLineChartTooltipCategory
6770
+
6771
+ ```ts
6772
+ /** 툴팁 하단(`tooltipFooter`)이 받는 짚은 항목. */
6773
+ export interface SLineChartTooltipCategory {
6774
+ /** 카테고리 인덱스 */
6775
+ categoryIndex: number;
6776
+ /** 카테고리 이름 */
6777
+ name: string;
6778
+ /** 툴팁에 값이 뜬 지점들 — 값이 없는 계열은 빠진다. 누적이어도 각 계열이 제 몫으로 가진 값이다 */
6779
+ points: SLineChartPoint[];
6780
+ }
6781
+ ```
6782
+
6733
6783
  ---
6734
6784
 
6735
6785
  # SLinearProgress
@@ -7045,6 +7095,70 @@ export const LOGO_NAMES = ['sellmate'] as const;
7045
7095
 
7046
7096
  ---
7047
7097
 
7098
+ # SMeatballButton
7099
+
7100
+ > 자동 생성 문서 — `npm run docs:gen`. 소스: 각 컴포넌트의 Props/Handle 인터페이스 + import 의존성.
7101
+
7102
+ ### SMeatballButton
7103
+
7104
+ #### Props
7105
+
7106
+ | Prop | Type | Default | Description |
7107
+ |------|------|---------|-------------|
7108
+ | `size?` | `SMeatballButtonSize` | `'sm'` | 버튼 크기 |
7109
+ | `intent?` | `SMeatballButtonIntent` | `'default'` | 색상 의도. 어두운 배경 위에서는 inverse |
7110
+ | `items?` | `SMeatballButtonItem[]` | `[]` | 메뉴 항목 목록 |
7111
+ | `tooltipText?` | `string` | `'기능 더 보기'` | 호버 시 표시할 툴팁 텍스트. 빈 문자열이면 툴팁을 띄우지 않는다. 메뉴가 열려 있는 동안은 숨는다. |
7112
+ | `ariaLabel?` | `string` | — | 스크린리더용 접근성 레이블. 미지정 시 tooltipText, 그것도 비면 '기능 더 보기' |
7113
+ | `disabled?` | `boolean` | `false` | 비활성 |
7114
+ | `className?` | `string` | — | 버튼을 감싸는 요소의 클래스. 위치 조정(absolute 배치 등)용 |
7115
+ | `style?` | `CSSProperties` | — | 버튼을 감싸는 요소의 스타일. 위치 조정용 |
7116
+
7117
+ #### Events
7118
+
7119
+ | Event | Type | Description |
7120
+ |-------|------|-------------|
7121
+ | `onItemClick` | `(value: string \| number) => void` | 메뉴 항목 선택 |
7122
+ | `onOpenChange` | `(open: boolean) => void` | 열림/닫힘 변경 |
7123
+
7124
+ #### Methods (ref)
7125
+
7126
+ | Method | Type | Description |
7127
+ |--------|------|-------------|
7128
+ | `open` | `() => void` | 메뉴 열기 |
7129
+ | `close` | `() => void` | 메뉴 닫기 |
7130
+
7131
+ ## Types
7132
+
7133
+ ### SMeatballButtonSize
7134
+
7135
+ ```ts
7136
+ export type SMeatballButtonSize = SGhostButtonSize;
7137
+ ```
7138
+
7139
+ ### SMeatballButtonIntent
7140
+
7141
+ ```ts
7142
+ export type SMeatballButtonIntent = 'default' | 'inverse';
7143
+ ```
7144
+
7145
+ ### SMeatballButtonItem
7146
+
7147
+ ```ts
7148
+ /** 메뉴 항목 — SDropdownButton 과 같은 모양이다 */
7149
+ export type SMeatballButtonItem = SDropdownButtonItem;
7150
+ ```
7151
+
7152
+ ## Dependencies
7153
+
7154
+ ### Depends on
7155
+
7156
+ - [SGhostButton](../SGhostButton)
7157
+
7158
+ ### Graph
7159
+
7160
+ ---
7161
+
7048
7162
  # SModal
7049
7163
 
7050
7164
  > 수작성 문서 — SModal 은 컴포넌트가 아니라 **명령형 모달 서비스**라 `docs:gen`(Props/Events 표) 대상이 아니다.
@@ -7625,6 +7739,7 @@ export const PAGE_CONTENT_WIDTHS = ['full', 'fixed', 'fixedCenter'] as const;
7625
7739
  | `legendPosition?` | `SPieChartLegendPosition` | `'top'` | 범례 위치 |
7626
7740
  | `showTooltip?` | `boolean` | `true` | 조각에 마우스를 올리면 값 상자를 띄운다 |
7627
7741
  | `formatValue?` | `(value: number) => string` | — | 값 표시 형식 |
7742
+ | `tooltipFooter?` | `(slice: SPieChartSlicePoint) => ReactNode` | — | 툴팁의 값 아래에 덧붙일 내용. 짚은 조각을 받아 그린다 — 몫·값만으로 모자란 맥락 (전월 대비, 건수 등)을 적는다. 툴팁은 누를 수 없으므로 버튼·링크는 넣지 않는다 |
7628
7743
  | `className?` | `string` | — | 폭은 기본 100% 다. 폭을 정하려면 여기에 준다 — 그림은 그 폭의 정사각형이 된다 |
7629
7744
  | `style?` | `CSSProperties` | — | |
7630
7745
 
package/dist/llms.txt CHANGED
@@ -48,13 +48,13 @@
48
48
 
49
49
  | 분류 | 컴포넌트 |
50
50
  | --- | --- |
51
- | **버튼·링크** | `SButton` `SGhostButton` `SDropdownButton` `STextLink` `SSwitch` `SToggle` |
51
+ | **버튼·링크** | `SButton` `SGhostButton` `SMeatballButton`(⋯ 로 '더 보기' 메뉴를 여는 아이콘 버튼) `SDropdownButton` `STextLink` `SSwitch` `SToggle` |
52
52
  | **입력 (폼)** | `SForm` `SField` `SInput` `SChatInput`(대화 입력창) `SSearchInput` `SNumberInput` `STextarea` `SEditor` `SSelect` `SCheckbox` `SRadio` `SRadioGroup` `SRadioButton` `SRadioCard` `SRadioCardGroup` `SChip` `SChipInput` `SBarcodeInput` `SFilePicker` |
53
53
  | **날짜·시간** | `SCalendar` `SCalendarBoard`(한 달치 일정 판) `SDatePicker` `SDatePickerYearListbox` `SDatePickerMonthListbox` `SDateRangePicker` `STimePicker` `STimeRangePicker` |
54
54
  | **표·목록** | `SChatMessage`(대화의 메시지 한 건) `SChatAttachedFile`(입력창 위, 아직 보내지 않은 첨부 한 칸) `SChatFile`(대화 흐름에 선, 보낸 파일 한 칸) `SChatSystemMessage`(대화 흐름 가운데 서는 시스템 안내) `STable` `STableBar` `SChipFilter` `SKeyValueTable` `SList` `SListItem` `SExpansionList` `SDraggableList` `SDraggableItem` `STree` |
55
55
  | **레이아웃** | `SLayout` `SGnb` `SGnbSystem` `SSystemActionButton`(GNB system 패널에 한 줄씩 쌓는 액션 행 — 버튼 고르기는 §3-5) `SAccountListBox`(계정 행을 눌러 뜨는 계정 패널) `SLauncherListBox`(런처 버튼을 눌러 뜨는 서비스 목록) `SPage` `SPageHeader`(페이지 제목 영역 — `SLayout` 안에서 `SPage` 앞에 둔다) `SSectionHeaderCard` `SCard` `SLoginCard`(통합 계정 로그인 화면의 카드) `SDivider` `SSplitter` `SScrollArea` `SExpansionItem` |
56
56
  | **내비게이션** | `STabs` `SPagination` `SStepper` |
57
- | **차트** | `SBarChart`(막대 그래프 — 항목끼리 크기를 견준다. `stacked` 로 항목 안의 구성까지) `SLineChart`(꺾은선 그래프 — 순서가 있는 항목의 추이를 본다. `area` 로 크기까지, `stacked` 로 구성까지) `SPieChart`(원그래프 — 한 시점의 전체를 몇 개의 몫으로 나눈다) `SDonutChart`(도넛 그래프 — 몫과 함께 가운데에 합계를 적는다) |
57
+ | **차트** | `SBarChart`(막대 그래프 — 항목끼리 크기를 견준다. `stacked` 로 항목 안의 구성까지) `SLineChart`(꺾은선 그래프 — 순서가 있는 항목의 추이를 본다. `area` 로 크기까지, `stacked` 로 구성까지) `SPieChart`(원그래프 — 한 시점의 전체를 몇 개의 몫으로 나눈다) `SDonutChart`(도넛 그래프 — 가운데가 빈 원그래프. 구멍에 글자를 두지 않는다) |
58
58
  | **표시·상태** | `STag` `SBadge` `SIcon` `SLogo`(브랜드 로고를 아이콘처럼 — size 는 높이다) `SImage` `SCallout` `SGuide` |
59
59
  | **진행·로딩** | `SLinearProgress` `SCircleProgress` `SLoadingContainer` `SLoadingModal` |
60
60
  | **오버레이** | `STooltip` `SPopover` `SPopup` `SDrawer` `SPortal` |
@@ -81,7 +81,7 @@ AI 에이전트는 코드를 생성하기 전에 이 목록을 반드시 지킨
81
81
 
82
82
  | 금지 | 대신 사용 |
83
83
  | --- | --- |
84
- | `<button>` | `SButton`, `SGhostButton`, `SDropdownButton`, `STextLink` |
84
+ | `<button>` | `SButton`, `SGhostButton`, `SMeatballButton`, `SDropdownButton`, `STextLink` |
85
85
  | `<input type="text/password/...">` | `SInput` |
86
86
  | `<input type="search">` | `SSearchInput` |
87
87
  | `<input type="number">` | `SNumberInput` |
@@ -177,7 +177,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
177
177
  | --- | --- | --- |
178
178
  | **셸** | 앱 전체 뼈대. 페이지가 바뀌어도 남는다 | `SLayout` `SGnb` `SGnbSystem`(GNB 맨 아래 판 · 전폭 상단바 오른쪽 끝) `SPage` `SPageHeader`(`SLayout` 안에서 `SPage` 앞에 둔다) |
179
179
  | **블록** | `SPage` 의 직계 자식. 페이지를 세로로 쌓는 단위 | `SSectionHeaderCard` `SCard` `SChatMessage` `SChatSystemMessage` `SChatInput` `SLoginCard`(유일하게 `SPage` 밖에 선다 — 로그인 화면 자체가 자기 자리다, §4-6) `SForm` `SSplitter` `SScrollArea` `SCalendarBoard` `STable` `STableBar` `SChipFilter` `SKeyValueTable` `SList` `SExpansionList` `SDraggableList` `STree` `SCallout` `SBarChart` `SLineChart` `SPieChart` `SDonutChart` `STabs` `SStepper` `SPagination` `SDivider` |
180
- | **요소** | 블록 **안에** 놓이는 컨트롤. 혼자 페이지에 서지 않는다 | `SButton` `SGhostButton` `SDropdownButton` `SSystemActionButton` `SField` `SInput` `SSearchInput` `SNumberInput` `STextarea` `SEditor` `SSelect` `SCheckbox` `SRadio` `SRadioGroup` `SRadioButton` `SRadioCard` `SRadioCardGroup` `SSwitch` `SToggle` `SChipInput` `SBarcodeInput` `SFilePicker` `SDatePicker` `SDatePickerYearListbox` `SDatePickerMonthListbox` `SDateRangePicker` `STimePicker` `STimeRangePicker` `SCalendar` `SListItem` `SExpansionItem` `SDraggableItem` `SChatAttachedFile` `SChatFile` `SImage` `SLinearProgress` `SCircleProgress` |
180
+ | **요소** | 블록 **안에** 놓이는 컨트롤. 혼자 페이지에 서지 않는다 | `SButton` `SGhostButton` `SMeatballButton` `SDropdownButton` `SSystemActionButton` `SField` `SInput` `SSearchInput` `SNumberInput` `STextarea` `SEditor` `SSelect` `SCheckbox` `SRadio` `SRadioGroup` `SRadioButton` `SRadioCard` `SRadioCardGroup` `SSwitch` `SToggle` `SChipInput` `SBarcodeInput` `SFilePicker` `SDatePicker` `SDatePickerYearListbox` `SDatePickerMonthListbox` `SDateRangePicker` `STimePicker` `STimeRangePicker` `SCalendar` `SListItem` `SExpansionItem` `SDraggableItem` `SChatAttachedFile` `SChatFile` `SImage` `SLinearProgress` `SCircleProgress` |
181
181
  | **인라인** | 텍스트 흐름·셀·라벨 안에 섞인다. 혼자 블록이 되지 않는다 | `STag` `SBadge` `SIcon` `SLogo` `STextLink` `SChip` |
182
182
  | **레이어** | 문서 흐름 **밖**에 떠서 그려진다. 어느 층에서 띄우든 레이아웃에 영향이 없다 | `SModal` `SActionModal` `SConfirmModal` `SPopup` `SDrawer` `SPopover` `STooltip` `SPortal` `SAccountListBox`(계정 행에 붙어 뜬다 — 직접 띄우지 않는다) `SLauncherListBox`(런처 버튼에 붙어 뜬다 — 직접 띄우지 않는다) `SToast` `SLoadingModal` `SLoadingContainer` `SGuide` |
183
183
 
@@ -334,7 +334,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
334
334
  | `SCheckbox` | **`gap-sd-24`** | `gap-sd-8` |
335
335
  | `SRadio` | **`gap-sd-24`** | `gap-sd-8` |
336
336
  | `STextLink` | **`gap-sd-16`**(sm) / **`gap-sd-24`**(md·lg) | `gap-sd-4` |
337
- | `SGhostButton` | `gap-sd-4` | `gap-sd-4` |
337
+ | `SGhostButton` · `SMeatballButton` | `gap-sd-4` | `gap-sd-4` |
338
338
  | `SButton` | `gap-sd-8` (xs·sm·md) / **`gap-sd-12`**(lg) | 〃 |
339
339
  | `STag` | `gap-sd-8` | `gap-sd-8` |
340
340
  | `SToggle` | `gap-sd-8` | `gap-sd-8` |
@@ -580,7 +580,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
580
580
  | 여러 항목의 추이를 **합계와 함께** 보여준다 (채널별 매출이 쌓여 전체가 되는 흐름) | `SLineChart stacked area` | 합계가 뜻을 갖는 값일 때만 쌓는다. 음수가 섞이거나 더해서 뜻이 없는 값(비율·평균)은 쌓지 말고 겹쳐 그린다 |
581
581
  | 항목의 크기와 **그 안의 구성**을 함께 보여준다 (주문 상태별 내역, 유입 경로별 몫) | `SBarChart stacked` | 계열끼리 견주는 것이 목적이면 `stacked` 없이 나란히 세운다. 더해서 뜻이 없는 값(비율·평균)은 쌓지 않는다 — 합계 라벨이 거짓말이 된다 |
582
582
  | 한 시점의 **전체를 몇 개의 몫으로** 나눠 보여준다 (채널별 매출 비중, 회원 등급 구성) | `SPieChart` | 조각이 대여섯 개를 넘거나 몫끼리 크기를 견주는 것이 목적이면 `SBarChart` — 사람은 각도보다 길이를 정확히 견준다. 순서가 있는 추이(월별)는 몫이 아니라 흐름이라 `SLineChart`. 0·음수는 그려지지 않으므로 증감은 원으로 나타내지 않는다. 조각은 큰 순으로 넘긴다. 폭은 부모를 따르고 그림은 그 폭의 정사각형이다 — 폭이 필요하면 `className` 으로 폭만 주고 높이는 주지 않는다 (`SDonutChart` 도 같다) |
583
- | 몫과 함께 **전체의 크기(합계)** 를 먼저 읽게 한다 (주문 상태별 구성 + 총 주문 수, 목표 달성률) | `SDonutChart` | 합계가 필요 없으면 `SPieChart`. 가운데 값은 기본이 그려진 조각의 합계이고, 합계가 아닌 대표값(달성률 등)은 `centerValue` 로 준다. 여러 기간에 걸친 구성 변화는 원을 여러 개 늘어놓지 말고 `SBarChart stacked` |
583
+ | 한 시점의 전체를 몫으로 나누되 **가운데가 빈 고리 모양**으로 보여준다 (시안이 도넛일 때) | `SDonutChart` | 쓰임·데이터 규칙은 `SPieChart` 와 같고 모양만 다르다 — 시안이 정한 쪽을 쓴다. **구멍에 합계·라벨을 겹쳐 올리지 않는다.** 합계 같은 값이 필요하면 차트 바깥(카드 제목·요약 값)에 적는다. 여러 기간에 걸친 구성 변화는 원을 여러 개 늘어놓지 말고 `SBarChart stacked` |
584
584
  | 표 위에 건수 요약과 액션을 얹는다 | `STableBar` | 표의 이름도 여기 `title` 슬롯에 넣는다 — 제목만으로 블록을 따로 세우지 않는다. §4-2 |
585
585
  | 상태·분류를 라벨로 찍는다 | `STag` | §3-1 |
586
586
  | 색 점만으로 상태를 찍는다 | `SBadge` | §3-1 |
@@ -595,6 +595,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
595
595
  | --- | --- | --- |
596
596
  | 라벨이 있는 일반 액션을 준다 | `SButton` | §3-5 |
597
597
  | 아이콘 하나로 뜻이 통하는 부가 조작을 준다 | `SGhostButton` | §3-5-5 |
598
+ | 자리가 좁아 부가 조작 여러 개를 ⋯ 뒤 메뉴로 접어 둔다 | `SMeatballButton` | §3-5-5 |
598
599
  | 한 버튼에 여러 선택지를 매단다 | `SDropdownButton` | §3-5-4 |
599
600
  | GNB system 패널에서 한 줄짜리 행 액션을 준다 | `SSystemActionButton` | §3-5-7 |
600
601
 
@@ -694,7 +695,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
694
695
  | --- | --- |
695
696
  | `default` | 흰 면 위 (`SPage background="frame"`) — 옅은 회색 면이라 페이지와 구분된다 |
696
697
  | `white` | 회색 면 위 (`background="neutral"`·`"screen"`) — 그 위에서는 `default` 가 배경에 묻힌다 |
697
- | `danger` | 경고. 좌측에 "주의사항" 타이틀이 붙으므로 단순 안내에는 쓰지 않는다 |
698
+ | `danger` | 경고. 좌측에 "주의사항" 타이틀이 붙으므로 단순 안내에는 쓰지 않는다. 주변에 이미 경고 맥락(제목 등)이 있어 타이틀이 중복되면 `showTitle={false}` 로 타이틀만 뺀다 — 경고 면은 유지된다 |
698
699
 
699
700
  ### 3-3. 플로팅/오버레이류
700
701
 
@@ -1217,6 +1218,7 @@ tableRef.current.scrollToRow(row); // 복원
1217
1218
  | 일반 액션 | `SButton` (`color`: `primary` / `secondary` / `neutral` / `danger`, `outline`, `size`: xs~md) |
1218
1219
  | **삭제 등 파괴적 액션** | **`SButton color="danger"`** 또는 **`color="danger" outline`** (아래 3-5-3) |
1219
1220
  | **아이콘 하나로 뜻이 통하는 부가 조작** | **`SGhostButton`** — 라벨이 없는 아이콘 전용 버튼 (아래 3-5-5) |
1221
+ | **부가 조작 여러 개를 ⋯ 메뉴로 접기** | **`SMeatballButton`** — ⋯ 아이콘 버튼 + `SDropdownButton` 과 같은 메뉴 (아래 3-5-5) |
1220
1222
  | 본문 속 이동 링크 | `STextLink` |
1221
1223
  | 메인 액션 + 부가 메뉴 | `SDropdownButton` |
1222
1224
  | **GNB system 패널의 한 줄 액션** | **`SSystemActionButton`** — 행 전체가 버튼인 표면형 (아래 3-5-7) |
@@ -1330,6 +1332,24 @@ tableRef.current.scrollToRow(row); // 복원
1330
1332
  ❌ <SGhostButton icon="download" ariaLabel="엑셀 다운로드" /> // 목록의 주 액션 → SButton
1331
1333
  ```
1332
1334
 
1335
+ ##### `SMeatballButton` — ⋯ 뒤에 메뉴를 접어 둘 때
1336
+
1337
+ 자리가 좁아 부가 조작을 하나하나 아이콘으로 늘어놓을 수 없을 때, **⋯ 하나로 접고 누르면 메뉴를 띄운다.** 버튼의 크기·색·hover·툴팁은 `SGhostButton` 과, 메뉴 모양은 `SDropdownButton` 과 같다.
1338
+
1339
+ - **메뉴는 컴포넌트가 띄운다.** `items` 를 넘기고 선택은 `onItemClick(value)` 로 받는다. 메뉴를 따로 만들어 붙이지 않고, 열림 상태(`aria-expanded`)도 직접 넣지 않는다.
1340
+ - **`SGhostButton icon="etc"` 로 직접 만들지 않는다.** '더 보기' 메뉴는 항상 `SMeatballButton` 이다.
1341
+ - **`intent` 는 `default` / `inverse` 뿐이다.** ⋯ 는 조작이 아니라 메뉴를 여는 것이므로 `action`·`danger` 색을 받지 않는다. 어두운 배경 위에서만 `inverse`.
1342
+ - 툴팁·`ariaLabel` 은 기본 문구가 들어 있어 **주지 않아도 된다.** 한 화면에 ⋯ 가 여러 개라 무엇의 메뉴인지 구분해야 할 때만 `tooltipText` 를 바꾼다(`ariaLabel` 이 따라간다).
1343
+ - 메인 액션에 변형 동작을 곁들이는 것이면 `SMeatballButton` 이 아니라 `SDropdownButton split`(§3-5-4)이다.
1344
+
1345
+ ```tsx
1346
+ ✅ <SMeatballButton size="xs" // 행 끝 부가 조작 묶음
1347
+ items={[{ value: 'copy', label: '복제', icon: 'copy' }, { value: 'remove', label: '삭제', icon: 'remove' }]}
1348
+ onItemClick={v => handleRowAction(row, v)} />
1349
+ ✅ <SMeatballButton intent="inverse" items={items} onItemClick={onAction} /> // 어두운 배경 위
1350
+ ❌ <SGhostButton icon="etc" ariaLabel="더 보기" onClick={openMyMenu} /> // 직접 조립 → SMeatballButton
1351
+ ```
1352
+
1333
1353
  #### 3-5-6. 그 밖
1334
1354
 
1335
1355
  - 라벨은 **동사(+목적어)** — `저장` · `적치 지시` · `송장 재출력`
@@ -2956,7 +2976,7 @@ Tailwind 유틸리티는 아래 스케일에 있는 값만 사용한다. 리터
2956
2976
  --sys-color-purple-strong
2957
2977
  --sys-color-purple-subtle
2958
2978
 
2959
- ## 3. 컴포넌트 인덱스 (84종)
2979
+ ## 3. 컴포넌트 인덱스 (85종)
2960
2980
 
2961
2981
  **Props 는 이 문서에 없다.** 쓸 컴포넌트를 정했으면 그 컴포넌트의 README 를 읽는다.
2962
2982
 
@@ -2965,4 +2985,4 @@ Tailwind 유틸리티는 아래 스케일에 있는 값만 사용한다. 리터
2965
2985
  예) SButton 을 쓴다면 `dist/components/SButton/README.md`.
2966
2986
  prop 을 추측해서 쓰지 말고 반드시 README 로 확인한다 (분류별 용도는 §1 의 "전체 컴포넌트 인덱스" 참조).
2967
2987
 
2968
- SAccountListBox · SActionModal · SBadge · SBarChart · SBarcodeInput · SButton · SCalendar · SCalendarBoard · SCallout · SCard · SChatAttachedFile · SChatFile · SChatInput · SChatMessage · SChatSystemMessage · SCheckbox · SChip · SChipFilter · SChipInput · SCircleProgress · SConfirmModal · SDatePicker · SDateRangePicker · SDivider · SDonutChart · SDraggableItem · SDraggableList · SDrawer · SDropdownButton · SEditor · SExpansionItem · SExpansionList · SField · SFilePicker · SForm · SGhostButton · SGnb · SGnbSystem · SGuide · SIcon · SImage · SInput · SKeyValueTable · SLauncherListBox · SLayout · SLineChart · SLinearProgress · SList · SListItem · SLoadingContainer · SLoadingModal · SLoginCard · SLogo · SModal · SNumberInput · SPage · SPagination · SPieChart · SPopover · SPopup · SPortal · SRadio · SRadioButton · SRadioCard · SScrollArea · SSearchInput · SSectionHeaderCard · SSelect · SSplitter · SStepper · SSwitch · SSystemActionButton · STable · STableBar · STabs · STag · STextLink · STextarea · STimePicker · STimeRangePicker · SToast · SToggle · STooltip · STree
2988
+ SAccountListBox · SActionModal · SBadge · SBarChart · SBarcodeInput · SButton · SCalendar · SCalendarBoard · SCallout · SCard · SChatAttachedFile · SChatFile · SChatInput · SChatMessage · SChatSystemMessage · SCheckbox · SChip · SChipFilter · SChipInput · SCircleProgress · SConfirmModal · SDatePicker · SDateRangePicker · SDivider · SDonutChart · SDraggableItem · SDraggableList · SDrawer · SDropdownButton · SEditor · SExpansionItem · SExpansionList · SField · SFilePicker · SForm · SGhostButton · SGnb · SGnbSystem · SGuide · SIcon · SImage · SInput · SKeyValueTable · SLauncherListBox · SLayout · SLineChart · SLinearProgress · SList · SListItem · SLoadingContainer · SLoadingModal · SLoginCard · SLogo · SMeatballButton · SModal · SNumberInput · SPage · SPagination · SPieChart · SPopover · SPopup · SPortal · SRadio · SRadioButton · SRadioCard · SScrollArea · SSearchInput · SSectionHeaderCard · SSelect · SSplitter · SStepper · SSwitch · SSystemActionButton · STable · STableBar · STabs · STag · STextLink · STextarea · STimePicker · STimeRangePicker · SToast · SToggle · STooltip · STree
package/dist/styles.css CHANGED
@@ -635,6 +635,9 @@
635
635
  .top-\[-1px\] {
636
636
  top: -1px;
637
637
  }
638
+ .top-\[10px\] {
639
+ top: 10px;
640
+ }
638
641
  .top-\[12px\] {
639
642
  top: 12px;
640
643
  }
@@ -674,6 +677,9 @@
674
677
  .right-\[2px\] {
675
678
  right: 2px;
676
679
  }
680
+ .right-\[8px\] {
681
+ right: 8px;
682
+ }
677
683
  .right-\[10px\] {
678
684
  right: 10px;
679
685
  }
@@ -3905,9 +3911,6 @@
3905
3911
  .text-\(--cmp-chart-axis-color\) {
3906
3912
  color: var(--cmp-chart-axis-color);
3907
3913
  }
3908
- .text-\(--cmp-chart-bar-dataLabel-color-default\) {
3909
- color: var(--cmp-chart-bar-dataLabel-color-default);
3910
- }
3911
3914
  .text-\(--cmp-chart-chartTooltip-title-color\) {
3912
3915
  color: var(--cmp-chart-chartTooltip-title-color);
3913
3916
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sellmate-design-system-react",
3
- "version": "9.0.0-beta.61",
3
+ "version": "9.0.0-beta.62",
4
4
  "description": "Sellmate Design System — React (TypeScript + Tailwind v4) port",
5
5
  "license": "UNLICENSED",
6
6
  "keywords": [