sellmate-design-system-react 9.0.0-beta.31 → 9.0.0-beta.32

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.
@@ -12,6 +12,9 @@ import { type SGnbType, type SGnbHeader, type SGnbColor, type SGnbMenuItem } fro
12
12
  * `folded` 는 GNB 의 접힘 상태가 아니라 **그 자리가 접힌 레일인지**다. panel 은 두 곳에 놓이고
13
13
  * (메뉴 컬럼 바닥 · 접힘 레일 바닥) 각 자리가 자기 형태를 못 박으므로, 접는 동안 아직 미끄러져
14
14
  * 나가는 중인 메뉴 컬럼의 패널이 min 형태로 튀지 않는다.
15
+ *
16
+ * 그래서 fix 로 접혀 있는 동안 슬롯 내용은 **두 자리에 함께 마운트된다** — 미끄러져 나간 메뉴
17
+ * 컬럼(잔상)과 레일 바닥(실물). `active` 가 그 둘을 가른다.
15
18
  */
16
19
  export interface SGnbSystemContextValue {
17
20
  /** GNB 색 */
@@ -20,6 +23,15 @@ export interface SGnbSystemContextValue {
20
23
  folded: boolean;
21
24
  /** 이 자리가 세로 판인지 전폭 상단바인지 */
22
25
  placement: SGnbSystemPlacement;
26
+ /**
27
+ * 이 자리가 지금 화면에 살아 있는 자리인가. 접힌 GNB 의 메뉴 컬럼처럼 밖으로 미끄러져 나가
28
+ * 잔상으로만 남는 자리는 `false` 다.
29
+ *
30
+ * 잔상에서도 계정 리스트박스 같은 **떠 있는 층은 함께 숨지 않는다** — SPortal 로 문서 최상단에
31
+ * 그려져 컬럼의 `visibility: hidden` 이 닿지 않기 때문이다. 그래서 잔상이 된 자리는 열어 둔
32
+ * 것을 스스로 닫아야 하고, 그 신호가 이 값이다.
33
+ */
34
+ active: boolean;
23
35
  }
24
36
  export declare const SGnbSystemContext: import("react").Context<SGnbSystemContextValue | null>;
25
37
  export interface SGnbProps extends Omit<HTMLAttributes<HTMLDivElement>, 'color'> {
@@ -9,9 +9,8 @@
9
9
  | Prop | Type | Default | Description |
10
10
  |------|------|---------|-------------|
11
11
  | `color?` | `SGnbSystemColor` | — | 색상(패널 표면). light = 흰 면, dark = 오션블루 면. 미지정 시 자기를 담은 SGnb 의 color 를 따른다(단독으로 쓰면 `'light'`). |
12
- | `folded?` | `boolean` | — | 접힌(min) 형태 — 48px 레일 폭에 맞춰 알림·계정 아이콘만 남는다. 미지정 시 자기를 담은 SGnb 의 접힘 상태를 따른다. `placement="top"` 에서는 뜻이 없다. |
13
- | `placement?` | `SGnbSystemPlacement` | — | 놓이는 자리: `panel` = GNB 바닥의 세로 판, `top` = 전폭 상단바 위의 가로 한 줄. 미지정 시 자기를 담은 SGnb 가 `header` 로 정해 내려준다(fix → panel, full → top). |
14
- | `actions?` | `SGnbSystemAction[]` | — | 행 목록. 각 원소는 `SSystemActionButton` 의 props 다(`color` 제외). 판에서는 맨 위에 쌓이고, 상단바에서는 맨 왼쪽에 선다. 옆(아래)에 다른 조각이 있으면 그 사이에 구분선이 그어진다. 접히면 자리가 없어 렌더되지 않는다. |
12
+ | `folded?` | `boolean` | — | 접힌(min) 형태 — 48px 레일 폭에 맞춰 알림·계정 아이콘만 남는다. 미지정 시 자기를 담은 SGnb 의 접힘 상태를 따른다. 상단바 자리에서는 뜻이 없다. |
13
+ | `actions?` | `SGnbSystemAction[]` | — | 행 목록. 각 원소는 `SSystemActionButton` 의 props 다(`color` 제외 · 계정 행은 `account` 로 따로 준다). 판에서는 맨 위에 쌓이고, 상단바에서는 맨 왼쪽에 선다. 옆(아래)에 다른 조각이 있으면 그 사이에 구분선이 그어진다. 접히면 자리가 없어 렌더되지 않는다. |
15
14
  | `domain?` | `string` | — | 도메인 태그 텍스트. 접히면 자리가 없어 렌더되지 않는다 |
16
15
  | `alert?` | `SGnbSystemAlert` | — | 알림 버튼. 없으면 렌더하지 않는다. 판에서는 설정과 나란히 서면 남는 폭을 먹고 혼자면 폭을 다 먹는다. 상단바에서는 자리가 넉넉하지 않아 라벨 없이 아이콘+개수만 선다. |
17
16
  | `setting?` | `SGnbSystemSetting` | — | 설정 버튼. 없으면 렌더하지 않는다. 판에서는 알림과 나란히 서면 제 폭만 갖고 혼자면 폭을 다 먹고, 상단바에서는 라벨 없이 아이콘만 선다. 접히면 자리가 없어 렌더되지 않는다 — 접힌 상태에서도 닿아야 하면 SGnb 의 `foldedFooter` 에 둔다. |
@@ -25,20 +24,21 @@
25
24
  export type SGnbSystemColor = (typeof GNB_SYSTEM_COLORS)[number];
26
25
  ```
27
26
 
28
- ### SGnbSystemPlacement
29
-
30
- ```ts
31
- export type SGnbSystemPlacement = (typeof GNB_SYSTEM_PLACEMENTS)[number];
32
- ```
33
-
34
27
  ### SGnbSystemAction
35
28
 
36
29
  ```ts
37
30
  /**
38
31
  * 패널 상단에 쌓이는 행 하나. `SSystemActionButton` 의 props 를 그대로 받는다 —
39
32
  * 단 `color` 는 패널이 정하므로 받지 않고, 목록 key 로 쓸 `value` 만 더한다.
33
+ *
34
+ * `type: 'account'` 는 받지 않는다. 계정 행은 이 패널에 **하나뿐**이고 서는 자리도 맨 아래로
35
+ * 정해져 있어(§3-5-8) `account` prop 이 따로 있다 — 여기로도 받으면 계정 행이 둘인 패널이
36
+ * 만들어지고, 그중 하나는 자리가 틀린다.
40
37
  */
41
- export type SGnbSystemAction = DistributiveOmit<SSystemActionButtonProps, 'color'> & {
38
+ export type SGnbSystemAction = DistributiveOmit<
39
+ Exclude<SSystemActionButtonProps, { type: 'account' }>,
40
+ 'color'
41
+ > & {
42
42
  /** 목록 key. 없으면 순서를 key 로 쓴다 */
43
43
  value?: string;
44
44
  };
@@ -80,8 +80,22 @@ export interface SGnbSystemSetting {
80
80
  export interface SGnbSystemAccount {
81
81
  /** 계정 이름 */
82
82
  label?: string;
83
- /** 클릭 */
83
+ /** 클릭. 패널은 어차피 열리므로, 여는 것 말고 따로 할 일이 있을 때만 준다 */
84
84
  onClick?: () => void;
85
+ /**
86
+ * 계정 리스트박스가 열리고 닫힐 때. 여닫는 것은 계정 행이 스스로 하므로 **그 사실을 알아야 할
87
+ * 때만** 준다 — 열려 있는 동안 다른 층을 접어 두거나, 연 것을 기록하는 화면이 그렇다.
88
+ *
89
+ * 앱이 누르지 않은 닫힘도 온다: `header="fix"` 에서 GNB 를 접거나 펴면 계정 행이 다른 자리로
90
+ * 옮겨 서므로 패널이 닫히고 `false` 가 온다.
91
+ */
92
+ onOpenChange?: (open: boolean) => void;
93
+ /**
94
+ * 누르면 뜨는 계정 리스트박스(`SAccountListBox`) 내용. **필수다** — 계정 행은 늘 이 패널의
95
+ * 트리거이고, 눌러도 아무것도 뜨지 않는 계정 행은 없다.
96
+ * 뜨는 방향은 패널이 놓인 자리가 정하므로 앱이 넘기지 않는다.
97
+ */
98
+ listBox: SAccountListBoxContent;
85
99
  }
86
100
  ```
87
101
 
@@ -109,21 +123,11 @@ export interface SGnbSystemAccount {
109
123
  export const GNB_SYSTEM_COLORS = ['light', 'dark'] as const;
110
124
  ```
111
125
 
112
- ### GNB_SYSTEM_PLACEMENTS
113
-
114
- ```ts
115
- /**
116
- * 조각들이 놓이는 자리. GNB 의 `header` 가 정하므로 앱이 고르지 않는다.
117
- * - `panel` — GNB 바닥에 깔리는 세로 판 (header="fix"). 접히면 48px 레일용 min 형태가 된다.
118
- * - `top` — 레이아웃 전폭 상단바 위 (header="full"). 판을 깔지 않고 가로 한 줄로 선다.
119
- */
120
- export const GNB_SYSTEM_PLACEMENTS = ['panel', 'top'] as const;
121
- ```
122
-
123
126
  ## Dependencies
124
127
 
125
128
  ### Depends on
126
129
 
130
+ - [SAccountListBox](../SAccountListBox)
127
131
  - [SGnb](../SGnb)
128
132
  - [SIcon](../SIcon)
129
133
  - [SSystemActionButton](../SSystemActionButton)
@@ -132,6 +136,7 @@ export const GNB_SYSTEM_PLACEMENTS = ['panel', 'top'] as const;
132
136
 
133
137
  ```mermaid
134
138
  graph TD;
139
+ SGnbSystem --> SAccountListBox
135
140
  SGnbSystem --> SGnb
136
141
  SGnbSystem --> SIcon
137
142
  SGnbSystem --> SSystemActionButton
@@ -1,13 +1,20 @@
1
1
  import { type HTMLAttributes } from 'react';
2
+ import { type SAccountListBoxContent } from '../SAccountListBox';
2
3
  import { type SSystemActionButtonProps } from '../SSystemActionButton';
3
- import { type SGnbSystemColor, type SGnbSystemPlacement } from './gnbSystem.config';
4
+ import { type SGnbSystemColor } from './gnbSystem.config';
4
5
  /** 유니온을 유지한 채 키를 걷어낸다 — 그냥 Omit 하면 판별 유니온이 한 덩어리로 뭉개진다. */
5
6
  type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
6
7
  /**
7
8
  * 패널 상단에 쌓이는 행 하나. `SSystemActionButton` 의 props 를 그대로 받는다 —
8
9
  * 단 `color` 는 패널이 정하므로 받지 않고, 목록 key 로 쓸 `value` 만 더한다.
10
+ *
11
+ * `type: 'account'` 는 받지 않는다. 계정 행은 이 패널에 **하나뿐**이고 서는 자리도 맨 아래로
12
+ * 정해져 있어(§3-5-8) `account` prop 이 따로 있다 — 여기로도 받으면 계정 행이 둘인 패널이
13
+ * 만들어지고, 그중 하나는 자리가 틀린다.
9
14
  */
10
- export type SGnbSystemAction = DistributiveOmit<SSystemActionButtonProps, 'color'> & {
15
+ export type SGnbSystemAction = DistributiveOmit<Exclude<SSystemActionButtonProps, {
16
+ type: 'account';
17
+ }>, 'color'> & {
11
18
  /** 목록 key. 없으면 순서를 key 로 쓴다 */
12
19
  value?: string;
13
20
  };
@@ -34,8 +41,22 @@ export interface SGnbSystemSetting {
34
41
  export interface SGnbSystemAccount {
35
42
  /** 계정 이름 */
36
43
  label?: string;
37
- /** 클릭 */
44
+ /** 클릭. 패널은 어차피 열리므로, 여는 것 말고 따로 할 일이 있을 때만 준다 */
38
45
  onClick?: () => void;
46
+ /**
47
+ * 계정 리스트박스가 열리고 닫힐 때. 여닫는 것은 계정 행이 스스로 하므로 **그 사실을 알아야 할
48
+ * 때만** 준다 — 열려 있는 동안 다른 층을 접어 두거나, 연 것을 기록하는 화면이 그렇다.
49
+ *
50
+ * 앱이 누르지 않은 닫힘도 온다: `header="fix"` 에서 GNB 를 접거나 펴면 계정 행이 다른 자리로
51
+ * 옮겨 서므로 패널이 닫히고 `false` 가 온다.
52
+ */
53
+ onOpenChange?: (open: boolean) => void;
54
+ /**
55
+ * 누르면 뜨는 계정 리스트박스(`SAccountListBox`) 내용. **필수다** — 계정 행은 늘 이 패널의
56
+ * 트리거이고, 눌러도 아무것도 뜨지 않는 계정 행은 없다.
57
+ * 뜨는 방향은 패널이 놓인 자리가 정하므로 앱이 넘기지 않는다.
58
+ */
59
+ listBox: SAccountListBoxContent;
39
60
  }
40
61
  export interface SGnbSystemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'color'> {
41
62
  /**
@@ -45,16 +66,12 @@ export interface SGnbSystemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'c
45
66
  color?: SGnbSystemColor;
46
67
  /**
47
68
  * 접힌(min) 형태 — 48px 레일 폭에 맞춰 알림·계정 아이콘만 남는다.
48
- * 미지정 시 자기를 담은 SGnb 의 접힘 상태를 따른다. `placement="top"` 에서는 뜻이 없다.
69
+ * 미지정 시 자기를 담은 SGnb 의 접힘 상태를 따른다. 상단바 자리에서는 뜻이 없다.
49
70
  */
50
71
  folded?: boolean;
51
72
  /**
52
- * 놓이는 자리: `panel` = GNB 바닥의 세로 판, `top` = 전폭 상단바 위의 가로 한 줄.
53
- * 미지정 시 자기를 담은 SGnb 가 `header` 로 정해 내려준다(fix → panel, full → top).
54
- */
55
- placement?: SGnbSystemPlacement;
56
- /**
57
- * 행 목록. 각 원소는 `SSystemActionButton` 의 props 다(`color` 제외). 판에서는 맨 위에 쌓이고,
73
+ * 행 목록. 각 원소는 `SSystemActionButton` 의 props 다(`color` 제외 · 계정 행은 `account` 로
74
+ * 따로 준다). 판에서는 맨 위에 쌓이고,
58
75
  * 상단바에서는 맨 왼쪽에 선다. 옆(아래)에 다른 조각이 있으면 그 사이에 구분선이 그어진다.
59
76
  * 접히면 자리가 없어 렌더되지 않는다.
60
77
  */
@@ -78,7 +95,7 @@ export interface SGnbSystemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'c
78
95
  /**
79
96
  * SGnbSystem — GNB 의 system 조각들(액션 · 도메인 · 알림 · 설정 · 계정).
80
97
  *
81
- * 어디에 놓이느냐(`placement`)로 두 형태가 있고, SGnb 안에서는 그 값을 `header` 가 정해 내려준다.
98
+ * 어디에 놓이느냐로 두 형태가 있고, 그 자리는 담은 SGnb 의 `header` 가 정해 내려준다(앱이 고르지 않는다).
82
99
  * - `panel` (header="fix") — GNB 바닥에 깔리는 세로 판. 위에서부터 [행 목록(`actions`)] · 구분선 ·
83
100
  * [도메인 태그] · [알림 | 설정] · [계정] 을 쌓는다.
84
101
  * - `top` (header="full") — 레이아웃 전폭 상단바의 오른쪽 끝에 서는 가로 한 줄.
@@ -101,14 +118,16 @@ export interface SGnbSystemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'c
101
118
  * 접힌 패널은 렌더되지 않으므로, 접힌 상태에서도 닿아야 하는 것은 SGnb 의 `foldedTop`·`foldedFooter` 에 둔다.
102
119
  * 상단바는 접어도 남으므로 `top` 에는 접힘 형태가 없다.
103
120
  *
104
- * `alert.count` 가 1 이상이면 벨이 울리는 아이콘(`alert`)과 강조색으로 바뀐다 — light 는 파랑,
121
+ * `alert.count` 가 1 이상이면 벨이 울리는 아이콘(`bellRinging`)과 강조색으로 바뀐다 — light 는 파랑,
105
122
  * 어두운 면은 노랑(토큰이 정한다). 0 이거나 없으면 조용한 벨(`bell`)에 기본 색이다.
106
123
  *
107
124
  * 색은 놓인 면을 따른다: 판 위는 `light`/`dark`(오션블루 판), 판 없이 상단바 면에 바로 얹는 `top` 의
108
125
  * dark 는 한 단계 어두운 `darker`(네이비) 색표다 — GNB_SYSTEM_TOP_COLOR_CONFIG 가 그 대응을 쥔다.
109
126
  *
110
- * SGnb 의 `system` 슬롯에 넣으면 `color`·`folded`·`placement` 를 GNB 에서 받아오므로 앱이 다시 넘길
111
- * 필요가 없다. 단독으로 쓰면 직접 준다. 판은 폭이 늘 부모를 가득 채우고, 상단바 줄은 내용 폭만 갖는다.
127
+ * **놓이는 자리(`placement`)는 prop 이 아니다** — 자기를 담은 SGnb 가 `header` 로 정해 내려준다.
128
+ * 앱이 고르면 세로 판 자리에 가로 한 줄이 서는 조합이 만들어지고, 그것을 고를 이유가 있는 화면은 없다.
129
+ * `color`·`folded` 도 슬롯 안에서는 GNB 가 내려주므로 다시 넘기지 않는다.
130
+ * 판은 폭이 늘 부모를 가득 채우고, 상단바 줄은 내용 폭만 갖는다.
112
131
  */
113
132
  export declare const SGnbSystem: import("react").ForwardRefExoticComponent<SGnbSystemProps & import("react").RefAttributes<HTMLDivElement>>;
114
133
  export {};
@@ -20,6 +20,7 @@
20
20
 
21
21
  ### Used by
22
22
 
23
+ - [SAccountListBox](../SAccountListBox)
23
24
  - [SButton](../SButton)
24
25
  - [SCallout](../SCallout)
25
26
  - [SCheckbox](../SCheckbox)
@@ -62,6 +63,7 @@
62
63
 
63
64
  ```mermaid
64
65
  graph TD;
66
+ SAccountListBox --> SIcon
65
67
  SButton --> SIcon
66
68
  SCallout --> SIcon
67
69
  SCheckbox --> SIcon
@@ -3,6 +3,7 @@ export type IconRenderProps = {
3
3
  size?: number | string;
4
4
  } & SVGProps<SVGSVGElement>;
5
5
  export declare const ICONS: {
6
+ readonly account: (p: IconRenderProps) => import("react").JSX.Element;
6
7
  readonly add: (p: IconRenderProps) => import("react").JSX.Element;
7
8
  readonly alert: (p: IconRenderProps) => import("react").JSX.Element;
8
9
  readonly alignKorean: (p: IconRenderProps) => import("react").JSX.Element;
@@ -15,6 +16,7 @@ export declare const ICONS: {
15
16
  readonly attachFile: (p: IconRenderProps) => import("react").JSX.Element;
16
17
  readonly barcode: (p: IconRenderProps) => import("react").JSX.Element;
17
18
  readonly bell: (p: IconRenderProps) => import("react").JSX.Element;
19
+ readonly bellRinging: (p: IconRenderProps) => import("react").JSX.Element;
18
20
  readonly bill: (p: IconRenderProps) => import("react").JSX.Element;
19
21
  readonly board: (p: IconRenderProps) => import("react").JSX.Element;
20
22
  readonly box: (p: IconRenderProps) => import("react").JSX.Element;
@@ -52,6 +52,7 @@ export type SPortalAlign = 'start' | 'center' | 'end';
52
52
 
53
53
  ### Used by
54
54
 
55
+ - [SAccountListBox](../SAccountListBox)
55
56
  - [SChipInput](../SChipInput)
56
57
  - [SSelect](../SSelect)
57
58
 
@@ -59,6 +60,7 @@ export type SPortalAlign = 'start' | 'center' | 'end';
59
60
 
60
61
  ```mermaid
61
62
  graph TD;
63
+ SAccountListBox --> SPortal
62
64
  SChipInput --> SPortal
63
65
  SSelect --> SPortal
64
66
  style SPortal fill:#f9f,stroke:#333,stroke-width:4px
@@ -10,7 +10,7 @@
10
10
  |------|------|---------|-------------|
11
11
  | `type` | `'account'` | — | 계정 행 |
12
12
  | `label?` | `string` | — | 라벨 텍스트 |
13
- | `option?` | `never` | — | 아이콘이 `user` 로 고정이라 받을 것이 없다 |
13
+ | `option` | `SSystemActionButtonAccountOption` | — | 누르면 뜨는 계정 리스트박스. **필수다** — 계정 행은 늘 이 패널의 트리거이고, 눌러도 아무것도 뜨지 않는 계정 행은 없다. 아이콘은 `user` 로 고정이라 여기서 받지 않는다. |
14
14
 
15
15
  ### SSystemActionButtonBase
16
16
 
@@ -39,20 +39,53 @@
39
39
  |------|------|---------|-------------|
40
40
  | `type` | `'status'` | — | 라벨 자리에 상태 태그가 들어가는 행 |
41
41
  | `label?` | `never` | — | 태그가 라벨 자리를 차지하므로 받지 않는다 |
42
- | `option?` | `SSystemActionButtonStatusOption` | — | 상태 태그 |
42
+ | `option` | `SSystemActionButtonStatusOption` | — | 상태 태그 + 고를 목록. **필수다** — 상태 행은 늘 그 상태를 바꾸는 메뉴의 트리거다. |
43
43
 
44
- ### SSystemActionButtonText
44
+ ### SSystemActionButtonSubSelect
45
45
 
46
46
  #### Props
47
47
 
48
48
  | Prop | Type | Default | Description |
49
49
  |------|------|---------|-------------|
50
- | `type` | `'switch' \| 'subSelect'` | — | 우측에 문구가 붙는 행. switch = 보조 조작 문구, subSelect = 지금 선택된 값 |
50
+ | `type` | `'subSelect'` | — | 우측에 지금 선택된 값이 붙는 행 |
51
+ | `label?` | `string` | — | 라벨 텍스트 |
52
+ | `option` | `SSystemActionButtonSubSelectOption` | — | 선행 아이콘 + 우측 값 + 고를 목록 |
53
+
54
+ ### SSystemActionButtonSwitch
55
+
56
+ #### Props
57
+
58
+ | Prop | Type | Default | Description |
59
+ |------|------|---------|-------------|
60
+ | `type` | `'switch'` | — | 우측에 보조 조작 문구가 붙는 행 |
51
61
  | `label?` | `string` | — | 라벨 텍스트 |
52
62
  | `option` | `SSystemActionButtonTextOption` | — | 선행 아이콘 + 우측 액션 텍스트 |
53
63
 
54
64
  ## Types
55
65
 
66
+ ### SSystemActionButtonAccountOption
67
+
68
+ ```ts
69
+ /**
70
+ * `account` 타입의 option — 행을 눌렀을 때 뜨는 계정 리스트박스.
71
+ * 내용(이메일·이름·권한·행들)은 `SAccountListBox` 와 같다.
72
+ *
73
+ * **뜨는 자리는 받지 않는다.** 계정 행이 놓인 자리가 정한다 — 판이면 행 위로 · 왼쪽 끝에 맞춰,
74
+ * 전폭 상단바면 행 아래로 · 오른쪽 끝에 맞춰 펼친다(시안). 화면마다 고를 값이 아니라,
75
+ * prop 으로 열면 같은 계정 행이 앱마다 다른 방향으로 뜬다.
76
+ */
77
+ export interface SSystemActionButtonAccountOption extends SAccountListBoxContent {
78
+ /**
79
+ * 리스트박스 열림 상태를 밖에서 쥔다(controlled). 주지 않으면 버튼이 스스로 여닫는다.
80
+ * 행을 담은 쪽이 닫아야 하는 자리가 있어 열어 둔 통로다 — 리스트박스는 SPortal 로 떠 있어
81
+ * 트리거가 화면에서 빠져도(GNB 를 접으면 메뉴 컬럼이 미끄러져 나간다) 따라 사라지지 않는다.
82
+ */
83
+ open?: boolean;
84
+ /** 리스트박스 열림/닫힘 변경 */
85
+ onOpenChange?: (open: boolean) => void;
86
+ }
87
+ ```
88
+
56
89
  ### SSystemActionButtonColor
57
90
 
58
91
  ```ts
@@ -72,12 +105,42 @@ export interface SSystemActionButtonIconOption {
72
105
  ### SSystemActionButtonStatusOption
73
106
 
74
107
  ```ts
75
- /** `status` 타입의 option — 라벨 자리에 들어가는 상태 태그 */
108
+ /**
109
+ * `status` 타입의 option — 라벨 자리에 들어가는 상태 태그 + 고를 목록.
110
+ *
111
+ * `options` 는 **필수다** — 상태 행은 늘 그 상태를 바꾸는 메뉴의 트리거이고, 지금 상태(`value`)에
112
+ * 해당하는 칸의 색·이름이 곧 태그가 된다. 보여주기만 하는 상태 줄이 필요하면 이 버튼이 아니라
113
+ * `STag` 를 쓴다.
114
+ */
76
115
  export interface SSystemActionButtonStatusOption {
77
- /** 상태 태그 색 */
78
- color?: STagColor;
79
- /** 상태 태그 텍스트 */
80
- label?: string;
116
+ /** 지금 상태. `options` 에서 같은 `value` 를 찾아 그 색·이름으로 태그를 그린다 */
117
+ value?: string;
118
+ /** 고를 수 있는 상태. **필수다** — 이 목록이 행 오른쪽으로 펼쳐진다 */
119
+ options: SSystemActionButtonStatusMenuOption[];
120
+ /** 메뉴에서 상태를 고름. 고르면 메뉴가 닫힌다 */
121
+ onChange?: (value: string) => void;
122
+ }
123
+ ```
124
+
125
+ ### SSystemActionButtonSubSelectOption
126
+
127
+ ```ts
128
+ /**
129
+ * `subSelect` 타입의 option — 지금 값 + 고를 목록.
130
+ *
131
+ * `options` 는 **필수다** — `subSelect` 는 "지금 값이 적혀 있고 눌러서 바꾸는 행"이라, 눌러도
132
+ * 아무것도 뜨지 않으면 그것은 `select`(눌러 들어가는 행)이지 `subSelect` 가 아니다.
133
+ */
134
+ export interface SSystemActionButtonSubSelectOption extends SSystemActionButtonIconOption {
135
+ /**
136
+ * 지금 값. `options` 에서 같은 `value` 를 찾아 우측에 그 `label` 로 적는다
137
+ * (못 찾으면 `value` 가 그대로 남는다).
138
+ */
139
+ value?: string;
140
+ /** 고를 수 있는 값. **필수다** — 이 목록이 행 오른쪽으로 펼쳐진다 */
141
+ options: SSystemActionButtonMenuOption[];
142
+ /** 메뉴에서 값을 고름. 고르면 메뉴가 닫힌다 */
143
+ onChange?: (value: string) => void;
81
144
  }
82
145
  ```
83
146
 
@@ -112,6 +175,28 @@ export interface SSystemActionButtonTextOption extends SSystemActionButtonIconOp
112
175
  export const SYSTEM_ACTION_BUTTON_COLORS = ['light', 'dark', 'darker'] as const;
113
176
  ```
114
177
 
178
+ ### SSystemActionButtonStatusMenuOption
179
+
180
+ ```ts
181
+ /** 상태 메뉴의 한 칸 — 점과 글자가 그 상태의 색으로 함께 물든다 */
182
+ export interface SSystemActionButtonStatusMenuOption extends SSystemActionButtonMenuOption {
183
+ /** 상태 색. 기본 `'blue'` */
184
+ color?: STagColor;
185
+ }
186
+ ```
187
+
188
+ ### SSystemActionButtonMenuOption
189
+
190
+ ```ts
191
+ /** 값 고르기 메뉴의 한 칸 */
192
+ export interface SSystemActionButtonMenuOption {
193
+ /** 값. `option.value` 와 맞춰 지금 값을 가린다 */
194
+ value: string;
195
+ /** 화면에 적히는 이름 */
196
+ label: string;
197
+ }
198
+ ```
199
+
115
200
  ## Dependencies
116
201
 
117
202
  ### Used by
@@ -120,6 +205,7 @@ export const SYSTEM_ACTION_BUTTON_COLORS = ['light', 'dark', 'darker'] as const;
120
205
 
121
206
  ### Depends on
122
207
 
208
+ - [SAccountListBox](../SAccountListBox)
123
209
  - [SIcon](../SIcon)
124
210
  - [STag](../STag)
125
211
 
@@ -127,6 +213,7 @@ export const SYSTEM_ACTION_BUTTON_COLORS = ['light', 'dark', 'darker'] as const;
127
213
 
128
214
  ```mermaid
129
215
  graph TD;
216
+ SSystemActionButton --> SAccountListBox
130
217
  SSystemActionButton --> SIcon
131
218
  SSystemActionButton --> STag
132
219
  SGnbSystem --> SSystemActionButton
@@ -1,4 +1,5 @@
1
1
  import { type ButtonHTMLAttributes } from 'react';
2
+ import { type SAccountListBoxContent } from '../SAccountListBox';
2
3
  import { type SIconName } from '../SIcon';
3
4
  import { type STagColor } from '../STag';
4
5
  import { type SSystemActionButtonColor } from './systemActionButton.config';
@@ -12,12 +13,49 @@ export interface SSystemActionButtonTextOption extends SSystemActionButtonIconOp
12
13
  /** 우측 액션 텍스트 */
13
14
  text?: string;
14
15
  }
15
- /** `status` 타입의 option — 라벨 자리에 들어가는 상태 태그 */
16
- export interface SSystemActionButtonStatusOption {
17
- /** 상태 태그 색 */
16
+ /** 값 고르기 메뉴의 한 칸 */
17
+ export interface SSystemActionButtonMenuOption {
18
+ /** 값. `option.value` 와 맞춰 지금 값을 가린다 */
19
+ value: string;
20
+ /** 화면에 적히는 이름 */
21
+ label: string;
22
+ }
23
+ /**
24
+ * `subSelect` 타입의 option — 지금 값 + 고를 목록.
25
+ *
26
+ * `options` 는 **필수다** — `subSelect` 는 "지금 값이 적혀 있고 눌러서 바꾸는 행"이라, 눌러도
27
+ * 아무것도 뜨지 않으면 그것은 `select`(눌러 들어가는 행)이지 `subSelect` 가 아니다.
28
+ */
29
+ export interface SSystemActionButtonSubSelectOption extends SSystemActionButtonIconOption {
30
+ /**
31
+ * 지금 값. `options` 에서 같은 `value` 를 찾아 우측에 그 `label` 로 적는다
32
+ * (못 찾으면 `value` 가 그대로 남는다).
33
+ */
34
+ value?: string;
35
+ /** 고를 수 있는 값. **필수다** — 이 목록이 행 오른쪽으로 펼쳐진다 */
36
+ options: SSystemActionButtonMenuOption[];
37
+ /** 메뉴에서 값을 고름. 고르면 메뉴가 닫힌다 */
38
+ onChange?: (value: string) => void;
39
+ }
40
+ /** 상태 메뉴의 한 칸 — 점과 글자가 그 상태의 색으로 함께 물든다 */
41
+ export interface SSystemActionButtonStatusMenuOption extends SSystemActionButtonMenuOption {
42
+ /** 상태 색. 기본 `'blue'` */
18
43
  color?: STagColor;
19
- /** 상태 태그 텍스트 */
20
- label?: string;
44
+ }
45
+ /**
46
+ * `status` 타입의 option — 라벨 자리에 들어가는 상태 태그 + 고를 목록.
47
+ *
48
+ * `options` 는 **필수다** — 상태 행은 늘 그 상태를 바꾸는 메뉴의 트리거이고, 지금 상태(`value`)에
49
+ * 해당하는 칸의 색·이름이 곧 태그가 된다. 보여주기만 하는 상태 줄이 필요하면 이 버튼이 아니라
50
+ * `STag` 를 쓴다.
51
+ */
52
+ export interface SSystemActionButtonStatusOption {
53
+ /** 지금 상태. `options` 에서 같은 `value` 를 찾아 그 색·이름으로 태그를 그린다 */
54
+ value?: string;
55
+ /** 고를 수 있는 상태. **필수다** — 이 목록이 행 오른쪽으로 펼쳐진다 */
56
+ options: SSystemActionButtonStatusMenuOption[];
57
+ /** 메뉴에서 상태를 고름. 고르면 메뉴가 닫힌다 */
58
+ onChange?: (value: string) => void;
21
59
  }
22
60
  /** 모든 타입이 공통으로 받는 props */
23
61
  export interface SSystemActionButtonBaseProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'color' | 'type' | 'children'> {
@@ -26,14 +64,35 @@ export interface SSystemActionButtonBaseProps extends Omit<ButtonHTMLAttributes<
26
64
  /** 비활성 여부. 기본 `false` */
27
65
  disabled?: boolean;
28
66
  }
67
+ /**
68
+ * `account` 타입의 option — 행을 눌렀을 때 뜨는 계정 리스트박스.
69
+ * 내용(이메일·이름·권한·행들)은 `SAccountListBox` 와 같다.
70
+ *
71
+ * **뜨는 자리는 받지 않는다.** 계정 행이 놓인 자리가 정한다 — 판이면 행 위로 · 왼쪽 끝에 맞춰,
72
+ * 전폭 상단바면 행 아래로 · 오른쪽 끝에 맞춰 펼친다(시안). 화면마다 고를 값이 아니라,
73
+ * prop 으로 열면 같은 계정 행이 앱마다 다른 방향으로 뜬다.
74
+ */
75
+ export interface SSystemActionButtonAccountOption extends SAccountListBoxContent {
76
+ /**
77
+ * 리스트박스 열림 상태를 밖에서 쥔다(controlled). 주지 않으면 버튼이 스스로 여닫는다.
78
+ * 행을 담은 쪽이 닫아야 하는 자리가 있어 열어 둔 통로다 — 리스트박스는 SPortal 로 떠 있어
79
+ * 트리거가 화면에서 빠져도(GNB 를 접으면 메뉴 컬럼이 미끄러져 나간다) 따라 사라지지 않는다.
80
+ */
81
+ open?: boolean;
82
+ /** 리스트박스 열림/닫힘 변경 */
83
+ onOpenChange?: (open: boolean) => void;
84
+ }
29
85
  /** 계정 행 — 아이콘이 `user` 로 고정이고 우측 액션이 없다 */
30
86
  export interface SSystemActionButtonAccountProps extends SSystemActionButtonBaseProps {
31
87
  /** 계정 행 */
32
88
  type: 'account';
33
89
  /** 라벨 텍스트 */
34
90
  label?: string;
35
- /** 아이콘이 `user` 로 고정이라 받을 것이 없다 */
36
- option?: never;
91
+ /**
92
+ * 누르면 뜨는 계정 리스트박스. **필수다** — 계정 행은 늘 이 패널의 트리거이고, 눌러도 아무것도
93
+ * 뜨지 않는 계정 행은 없다. 아이콘은 `user` 로 고정이라 여기서 받지 않는다.
94
+ */
95
+ option: SSystemActionButtonAccountOption;
37
96
  }
38
97
  /** 화살표만 붙는 행 — 눌러 들어간다는 뜻 */
39
98
  export interface SSystemActionButtonSelectProps extends SSystemActionButtonBaseProps {
@@ -44,26 +103,39 @@ export interface SSystemActionButtonSelectProps extends SSystemActionButtonBaseP
44
103
  /** 선행 아이콘 */
45
104
  option: SSystemActionButtonIconOption;
46
105
  }
47
- /** 우측에 문구가 붙는 행 — `switch` 는 보조 조작 문구, `subSelect` 는 지금 선택된 값 */
48
- export interface SSystemActionButtonTextProps extends SSystemActionButtonBaseProps {
49
- /** 우측에 문구가 붙는 행. switch = 보조 조작 문구, subSelect = 지금 선택된 값 */
50
- type: 'switch' | 'subSelect';
106
+ /** 우측에 보조 조작 문구가 붙는 행 — 지금 붙어 있는 대상을 갈아 끼운다 */
107
+ export interface SSystemActionButtonSwitchProps extends SSystemActionButtonBaseProps {
108
+ /** 우측에 보조 조작 문구가 붙는 행 */
109
+ type: 'switch';
51
110
  /** 라벨 텍스트 */
52
111
  label?: string;
53
112
  /** 선행 아이콘 + 우측 액션 텍스트 */
54
113
  option: SSystemActionButtonTextOption;
55
114
  }
56
- /** 라벨 자리에 상태 태그가 들어가는 행 */
115
+ /** 우측에 지금 선택된 값이 붙는 행 — `options` 를 주면 행 오른쪽으로 메뉴가 펼쳐진다 */
116
+ export interface SSystemActionButtonSubSelectProps extends SSystemActionButtonBaseProps {
117
+ /** 우측에 지금 선택된 값이 붙는 행 */
118
+ type: 'subSelect';
119
+ /** 라벨 텍스트 */
120
+ label?: string;
121
+ /** 선행 아이콘 + 우측 값 + 고를 목록 */
122
+ option: SSystemActionButtonSubSelectOption;
123
+ }
124
+ /** 우측에 문구가 붙는 두 타입을 함께 가리킨다 — `switch` · `subSelect` */
125
+ export type SSystemActionButtonTextProps = SSystemActionButtonSwitchProps | SSystemActionButtonSubSelectProps;
126
+ /** 라벨 자리에 상태 태그가 들어가는 행 — `options` 를 주면 행 오른쪽으로 메뉴가 펼쳐진다 */
57
127
  export interface SSystemActionButtonStatusProps extends SSystemActionButtonBaseProps {
58
128
  /** 라벨 자리에 상태 태그가 들어가는 행 */
59
129
  type: 'status';
60
130
  /** 태그가 라벨 자리를 차지하므로 받지 않는다 */
61
131
  label?: never;
62
- /** 상태 태그 */
63
- option?: SSystemActionButtonStatusOption;
132
+ /**
133
+ * 상태 태그 + 고를 목록. **필수다** — 상태 행은 늘 그 상태를 바꾸는 메뉴의 트리거다.
134
+ */
135
+ option: SSystemActionButtonStatusOption;
64
136
  }
65
137
  /** `type` 으로 갈리는 판별 유니온. 타입에 맞지 않는 option 은 컴파일 단계에서 막힌다. */
66
- export type SSystemActionButtonProps = SSystemActionButtonAccountProps | SSystemActionButtonSelectProps | SSystemActionButtonTextProps | SSystemActionButtonStatusProps;
138
+ export type SSystemActionButtonProps = SSystemActionButtonAccountProps | SSystemActionButtonSelectProps | SSystemActionButtonSwitchProps | SSystemActionButtonSubSelectProps | SSystemActionButtonStatusProps;
67
139
  /**
68
140
  * SSystemActionButton — GNB system 패널의 한 줄짜리 액션 버튼.
69
141
  *
@@ -72,6 +144,16 @@ export type SSystemActionButtonProps = SSystemActionButtonAccountProps | SSystem
72
144
  * `option` 으로 받는다. 선행 아이콘은 항상 있다 — `account` 는 `user` 고정, `status` 는 태그가
73
145
  * 자리를 차지해 아이콘이 없고, 나머지는 `option.icon` 이 필수다.
74
146
  *
147
+ * `account` 는 **언제나 계정 리스트박스(`SAccountListBox`)의 트리거**다 — 눌러도 아무것도 뜨지
148
+ * 않는 계정 행은 없으므로 `option` 이 필수이고, 누르면 이메일·이름·권한과 계정 설정·언어 변경·
149
+ * 로그아웃을 보여주고 행을 고르면 닫힌다. 뜨는 자리는 받지 않고 놓인 자리가 정한다
150
+ * (판이면 행 위로 · 왼쪽 끝, 전폭 상단바면 행 아래로 · 오른쪽 끝).
151
+ *
152
+ * `subSelect` · `status` 는 **언제나 값 고르기 메뉴의 트리거**다 — 지금 값이 적혀 있는 행이라
153
+ * 누르면 그 값을 바꾸는 메뉴가 뜬다. 그래서 `option.options` 가 필수이고, 메뉴는 행 오른쪽으로
154
+ * (행 위쪽 끝에 맞춰) 펼쳐지며 고르면 `option.onChange(value)` 가 돌고 닫힌다.
155
+ * 눌러서 값 고르는 화면으로 보낼 것이면 `select`, 보여주기만 할 것이면 `STag` 다.
156
+ *
75
157
  * hover 하면 표면색이 한 단계 바뀌고, 어두운 색에서는 아이콘 프레임이 흰색으로 떠오른다.
76
158
  * 상태는 default·hover 둘뿐이다 — 토큰에 selected 가 없다.
77
159
  * 토큰은 `--cmp-gnb-system-item-*` · `--cmp-gnb-system-actionButton-*`.
@@ -1,2 +1,2 @@
1
- export { SSystemActionButton, type SSystemActionButtonProps, type SSystemActionButtonBaseProps, type SSystemActionButtonAccountProps, type SSystemActionButtonSelectProps, type SSystemActionButtonTextProps, type SSystemActionButtonStatusProps, type SSystemActionButtonIconOption, type SSystemActionButtonTextOption, type SSystemActionButtonStatusOption, } from './SSystemActionButton';
1
+ export { SSystemActionButton, type SSystemActionButtonProps, type SSystemActionButtonBaseProps, type SSystemActionButtonAccountProps, type SSystemActionButtonAccountOption, type SSystemActionButtonSelectProps, type SSystemActionButtonTextProps, type SSystemActionButtonSwitchProps, type SSystemActionButtonSubSelectProps, type SSystemActionButtonStatusProps, type SSystemActionButtonIconOption, type SSystemActionButtonTextOption, type SSystemActionButtonSubSelectOption, type SSystemActionButtonMenuOption, type SSystemActionButtonStatusOption, type SSystemActionButtonStatusMenuOption, } from './SSystemActionButton';
2
2
  export { SYSTEM_ACTION_BUTTON_COLORS, SYSTEM_ACTION_BUTTON_TYPES, SYSTEM_ACTION_BUTTON_COLOR_CONFIG, SYSTEM_ACTION_BUTTON_TYPE_CONFIG, SYSTEM_ACTION_BUTTON_LAYOUT, type SSystemActionButtonColor, type SSystemActionButtonType, } from './systemActionButton.config';