sellmate-design-system-react 9.0.0-beta.71 → 9.0.0-beta.73

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.
package/AGENTS.md CHANGED
@@ -46,7 +46,7 @@
46
46
  | **레이아웃** | `SLayout` `SGnb` `SGnbSystem` `SSystemActionButton`(GNB system 패널에 한 줄씩 쌓는 액션 행 — 버튼 고르기는 §3-5) `SAccountListBox`(계정 행을 눌러 뜨는 계정 패널) `SLauncherListBox`(런처 버튼을 눌러 뜨는 서비스 목록) `SPage` `SPageHeader`(페이지 제목 영역 — `SLayout` 안에서 `SPage` 앞에 둔다) `SSectionHeaderCard` `SCard` `SLoginCard`(통합 계정 로그인 화면의 카드) `SDivider` `SSplitter` `SScrollArea` `SExpansionItem` |
47
47
  | **내비게이션** | `STabs` `SPagination` `SStepper` |
48
48
  | **차트** | `SBarChart`(막대 그래프 — 항목끼리 크기를 견준다. `stacked` 로 항목 안의 구성까지) `SLineChart`(꺾은선 그래프 — 순서가 있는 항목의 추이를 본다. `area` 로 크기까지, `stacked` 로 구성까지) `SPieChart`(원그래프 — 한 시점의 전체를 몇 개의 몫으로 나눈다) `SDonutChart`(도넛 그래프 — 가운데가 빈 원그래프. 구멍에 글자를 두지 않는다) |
49
- | **표시·상태** | `STag` `SBadge` `SIcon` `SLogo`(브랜드 로고를 아이콘처럼 — size 는 높이다) `SImage` `SCallout` `SContextAlert`(한 줄짜리 맥락 알림 — 오른쪽에 후속 동작 버튼) `SGuide` |
49
+ | **표시·상태** | `STag` `SBadge` `SIcon` `SLogo`(셀메이트·서비스 로고를 아이콘처럼 — name 으로 서비스, mode 로 배경, direction 으로 가로·세로, size 는 높이다 — `"auto"` 면 부모 폭을 채운다) `SImage` `SCallout` `SContextAlert`(한 줄짜리 맥락 알림 — 오른쪽에 후속 동작 버튼) `SGuide` |
50
50
  | **진행·로딩** | `SLinearProgress` `SCircleProgress` `SLoadingContainer` `SLoadingModal` |
51
51
  | **오버레이** | `STooltip` `SPopover` `SPopup` `SDrawer` `SPortal` |
52
52
  | **모달** | `SModal.confirm()` `SModal.create()` + `SActionModal` `SConfirmModal` `SModalOutlet`(앱 루트 1회) |
@@ -89,7 +89,7 @@ AI 에이전트는 코드를 생성하기 전에 이 목록을 반드시 지킨
89
89
  | 직접 만든 탭/페이지네이션/스텝퍼 | `STabs`, `SPagination`, `SStepper` |
90
90
  | `<ul>`/`<li>` 로 만든 목록 UI | `SList` + `SListItem` (드래그 정렬은 `SDraggableItem`) |
91
91
  | 직접 만든 섹션 카드(제목 바 + 본문 박스) | `SSectionHeaderCard` 의 `title` / `padding` props |
92
- | `<svg>` 직접 삽입, 이모지 아이콘 | `SIcon` (셀메이트 로고는 `SLogo`) |
92
+ | `<svg>` 직접 삽입, 이모지 아이콘 | `SIcon` (셀메이트·서비스 로고는 `SLogo`) |
93
93
  | `<hr>` | `SDivider` |
94
94
  | `<details>` / `<summary>` | `SExpansionItem` |
95
95
  | `<progress>` | `SLinearProgress`, `SCircleProgress` |
@@ -577,7 +577,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
577
577
  | 상태·분류를 라벨로 찍는다 | `STag` | §3-1 |
578
578
  | 색 점만으로 상태를 찍는다 | `SBadge` | §3-1 |
579
579
  | 아이콘을 넣는다 | `SIcon` | |
580
- | 셀메이트 로고를 넣는다 | `SLogo` (`SIcon` 과 달리 `size` 가 **높이**이고, 색을 주지 않으면 브랜드색이다) | §3-7-14 |
580
+ | 셀메이트·서비스 로고를 넣는다 | `SLogo` (`name` 에 서비스, 어두운 면이면 `mode="dark"`, 표기를 아래에 두려면 `direction="vertical"`. `size` 는 **높이**이고(`"auto"` 면 부모 폭을 채운다), 색을 주지 않으면 브랜드 색이다) | §3-7-14 |
581
581
  | 사진·썸네일을 보여준다 (로딩·실패 상태 포함) | `SImage` | §3-7-12 |
582
582
  | 작은 썸네일을 호버해서 크게 확인하게 한다 | `SImage previewOnHover` | 툴팁·팝오버로 직접 만들지 않는다 — 미리보기는 마우스를 통과시키고 원본의 로딩·실패도 스스로 표현한다. §3-7-12 |
583
583
  | 문장 안에서 다른 화면으로 보낸다 | `STextLink` | §3-5-6 |
@@ -1561,7 +1561,7 @@ tableRef.current.scrollToRow(row); // 복원
1561
1561
 
1562
1562
  **직접 띄우지 않는다.** 런처 버튼에 붙여 여는 것은 `SGnb` 의 `launcher` 가 맡는다 — 목록만 넘기면 버튼 아래로 · 버튼 왼쪽 끝에 맞춰 뜨고, 서비스를 고르거나 바깥을 누르면 닫힌다. 고른 서비스는 **새 탭에서 열린다** — 이동도 앱이 만들지 않는다.
1563
1563
 
1564
- **앱이 넘기는 것은 서비스 키와 갈 주소 둘뿐이다.** 로고·서비스 표기·이름·상태 태그는 디자인 시스템의 카탈로그가 서비스마다 정해 두므로 앱이 만들지 않는다.
1564
+ **앱이 넘기는 것은 서비스 키와 갈 주소, 그리고 셀메이트 콘솔 주소뿐이다.** 로고·서비스 표기·이름·상태 태그와 콘솔 줄의 문구·아이콘은 디자인 시스템이 정해 두므로 앱이 만들지 않는다.
1565
1565
 
1566
1566
  ```tsx
1567
1567
  <SGnb
@@ -1574,12 +1574,13 @@ tableRef.current.scrollToRow(row); // 복원
1574
1574
  { service: 'account', href: env.ACCOUNT_URL },
1575
1575
  { service: 'crm', href: env.CRM_URL },
1576
1576
  ],
1577
+ consoleHref: env.CONSOLE_URL, // 필수 — 목록 아래 "셀메이트 콘솔로 이동" 링크
1577
1578
  }}
1578
1579
  />
1579
1580
  ```
1580
1581
 
1581
1582
  - **`launcher` 를 주지 않으면 런처 버튼 자체가 렌더되지 않는다.** 옮겨 갈 서비스가 없는 앱은 이 슬롯을 비워 둔다 — 눌러도 아무것도 없는 버튼을 상단바에 남기지 않는다.
1582
- - **서비스는 키(`service`)로 고른다 — 보이는 것은 아무것도 넘기지 않는다.** 쓸 수 있는 키는 `'sellmate' | 'wms' | 'account' | 'crm'`(`SLauncherService`)이고, 로고 오른쪽 표기(`WMS`·`Account`·`CRM`)·아래 줄 한글 이름·상태 태그(`NEW`·`출시예정`)·출시 여부를 카탈로그(`LAUNCHER_SERVICE_CATALOG`)가 그 키로 정한다. 앱이 넘기게 하면 같은 서비스가 앱마다 다른 이름·색·문구로 선다. **서비스가 늘거나 이름·상태가 바뀌면 디자인 시스템 릴리스로 따라온다** — 앱은 고칠 것이 없다.
1583
+ - **서비스는 키(`service`)로 고른다 — 보이는 것은 아무것도 넘기지 않는다.** 쓸 수 있는 키는 `SLogo` 가 로고를 가진 서비스 전부(`'sellmate' | 'wms' | 'chat' | 'plm' | 'account' | 'people' | 'crm' | 'work' | 'pos'` — `SLauncherService`)이고, 서비스 로고(워드마크와 `WMS`·`Account`·`CRM` … 표기가 한 덩어리인 브랜드 로고)·아래 줄 한글 이름·상태 태그(`NEW`·`출시예정`)·출시 여부를 카탈로그(`LAUNCHER_SERVICE_CATALOG`)가 그 키로 정한다. 앱이 넘기게 하면 같은 서비스가 앱마다 다른 이름·색·문구로 선다. **서비스가 늘거나 이름·상태가 바뀌면 디자인 시스템 릴리스로 따라온다** — 앱은 고칠 것이 없다.
1583
1584
 
1584
1585
  ```tsx
1585
1586
  ✅ { service: 'wms', href: env.WMS_URL }
@@ -1597,6 +1598,13 @@ tableRef.current.scrollToRow(row); // 복원
1597
1598
  ```
1598
1599
  - **갈 수 없는 서비스도 목록에서 빼지 않는다.** 그 서비스가 있다는 사실과 지금은 못 간다는 사실을 함께 알리는 것이 런처의 일이다. 지금 보고 있는 서비스를 빼면 사용자가 지금 어디에 있는지가 런처에서 사라진다.
1599
1600
  - **출시 전인 서비스는 앱이 할 일이 없다.** 카탈로그가 `출시예정` 태그와 함께 막아 두므로 주소를 줘도 열리지 않고, 열리는 날 디자인 시스템 릴리스 하나로 모든 앱에서 함께 열린다. **앱이 앞질러 열 수단은 없다.**
1601
+ - **셀메이트 콘솔 주소 `launcher.consoleHref` 는 필수다.** 목록 아래 구분선 밑에 `셀메이트 콘솔로 이동` 글자 링크(`STextLink`)가 **늘 서고**, 누르면 그 주소가 새 탭에서 열린다. 끄는 prop 은 없다 — 어느 서비스의 런처든 콘솔로 가는 길은 있어야 하고, 같은 곳을 같은 말로 안내해야 해서 문구·아이콘도 컴포넌트가 정한다. **`launcher.onConsoleClick` 도 이동을 하지 않는다**(`onSelect` 와 같다) — 누르면 목록은 스스로 닫힌다.
1602
+
1603
+ ```tsx
1604
+ ✅ launcher={{ items: SERVICES, consoleHref: env.CONSOLE_URL }}
1605
+ ❌ launcher={{ items: [...SERVICES, { service: 'console', href: … }] }} // 콘솔은 서비스가 아니다
1606
+ ❌ <SLauncherListBox …/><STextLink label="콘솔로 이동" … /> // 링크를 손으로 붙이지 않는다
1607
+ ```
1600
1608
  - **목록 순서를 앱이 정하지 않는다.** 넘긴 순서가 아니라 카탈로그 순서(`LAUNCHER_SERVICES`)로 선다 — 같은 런처가 앱마다 다른 순서로 뜨면 사용자가 매번 다시 찾는다. 정렬해서 넘기려 애쓰지 않는다.
1601
1609
  - **줄에 얹으면 "여기서 나간다"는 것이 드러난다** — 배경이 옅은 파랑으로 물들고 이름이 한 단계 진해지며, 오른쪽 끝에 페이지 이동 아이콘이 떠오른다. **앱이 켜고 끄는 prop 이 없다** — 다른 서비스로 넘어가는 자리라는 신호는 화면마다 달라지면 안 된다. 갈 수 없는 줄은 얹어도 반응하지 않는다.
1602
1610
  - **폭을 늘리지 않는다.** 로고 길이에 따라 패널이 출렁이지 않도록 고정 폭이다.
@@ -2036,25 +2044,33 @@ const [selectedId, setSelectedId] = useState<string>();
2036
2044
 
2037
2045
  #### 3-7-14. 로고 — SLogo
2038
2046
 
2039
- 셀메이트 워드마크는 `<svg>` 를 직접 붙이지 않고 `SLogo` 를 쓴다. **`SIcon` 과 같은 손맛(`name`·`size`·`color`)이지만 두 가지가 다르다.**
2047
+ 셀메이트·서비스 로고는 `<svg>` 를 직접 붙이지 않고 `SLogo` 를 쓴다. **`SIcon` 과 같은 손맛(`name`·`size`·`color`)이지만 두 가지가 다르다.**
2040
2048
 
2041
- - **`size` 는 높이다.** 로고는 가로로 긴 워드마크라 정사각으로 그리면 찌그러진다 — 폭은 비율에서 저절로 나오므로 주지 않는다.
2042
- - **색을 주지 않으면 브랜드색이다.** `SIcon` 과 달리 currentColor 를 상속하지 않는다 — 로고가 주변 글자색을 따라 물들면 브랜드 색이 화면마다 달라진다. **비활성처럼 물러나야 하는 자리에서만** `color` 를 준다. 주면 워드마크 전체가 그 한 색이 된다.
2043
- - **담고 있는 로고는 셀메이트 워드마크 하나다.** 서비스별 표기(WMS · Account · CRM …)는 그 오른쪽에 **앱이 자기 텍스트나 자기 로고로 붙인다** — 서비스가 늘어날 때마다 디자인 시스템을 다시 배포하지 않으려는 것이다.
2049
+ - **`name` 에 서비스를 넣으면 그 서비스 로고가 나온다**(`sellmate` · `wms` · `chat` · `plm` · `account` · `people` · `crm` · `work` · `pos` · `console` — `SLogoName`). [셀메이트 워드마크 + 서비스 표기]가 한 덩어리다. **워드마크 옆에 표기를 앱이 따로 잇지 않는다** — 표기의 서체·자간·색이 원본과 어긋난다.
2050
+ - **배경에 맞춰 `mode` 를 준다.** 밝은 면은 `light`(기본), 어두운 면(dark GNB 등)은 `dark`. 워드마크 색과 서비스 표기 색을 모드가 정하므로 색을 직접 주지 않는다.
2051
+ - **표기를 워드마크 아래에 두려면 `direction="vertical"` 을 준다**(로그인 카드처럼 폭이 좁고 로고가 가운데 서는 자리). 워드마크 아래에 표기를 앱이 따로 쌓지 않는다. 모든 서비스 로고가 세로를 가진다(`sellmate` 는 표기가 없어 어느 쪽이든 같다). 세로의 표기 색도 원본이 정하므로 색을 직접 맞추지 않는다.
2052
+ - **`size` 는 높이다.** 로고는 가로로 길어 정사각으로 그리면 찌그러진다 — 폭은 비율에서 저절로 나오므로 주지 않는다. `vertical` 에서는 두 줄 전체의 높이라, 같은 `size` 면 워드마크가 가로보다 작다.
2053
+ - **로고 자리의 폭이 정해져 있으면 `size="auto"` 로 그 폭을 채운다**(`SGnb` `header="fix"` 의 로고 칸). 높이는 비율에서 나온다. 폭을 채우려고 `className`·`style` 로 svg 를 덮지 않는다. **부모에 폭이 없는 자리에는 쓰지 않는다** — 기준을 잃어 브라우저 기본 크기(300px)로 그려진다. `header="full"` 의 로고 칸(140px 고정)에서도 쓰지 않는다 — 거기서는 높이로 주고 칸 안에 들어가는 크기를 고른다.
2054
+ - **색을 주지 않으면 브랜드 색이다.** `SIcon` 과 달리 currentColor 를 상속하지 않는다 — 로고가 주변 글자색을 따라 물들면 브랜드 색이 화면마다 달라진다. **비활성처럼 물러나야 하는 자리에서만** `color` 를 준다. 주면 워드마크와 서비스 표기가 모두 그 한 색이 된다(`mode` 보다 우선한다).
2044
2055
  - **`label` 은 로고가 그 자리의 유일한 이름일 때만 준다**(로그인 화면·상단바). 옆이나 아래에 서비스 이름이 이미 적혀 있으면(런처 목록의 한 줄) 주지 않는다 — 같은 이름이 두 번 읽힌다.
2045
2056
 
2046
2057
  ```tsx
2047
- ✅ <SLogo size={20} /> {/* 상단바 로고 — 브랜드색 */}
2058
+ ✅ <SLogo size={20} /> {/* 상단바 로고 — 브랜드 색 */}
2059
+ ✅ <SLogo name="wms" size={20} /> {/* 서비스 로고 */}
2060
+ ✅ <SLogo name="wms" mode="dark" size={20} /> {/* 어두운 면 위 */}
2061
+ ✅ <SLogo name="wms" direction="vertical" size={48} /> {/* 워드마크 아래에 표기 — 로그인 카드 */}
2048
2062
  ✅ <SLogo size={32} label="Sellmate" /> {/* 로고가 그 자리의 유일한 이름일 때 */}
2049
- ✅ <span className="inline-flex items-center gap-sd-2"> {/* 서비스별 표기는 앱이 잇는다 */}
2050
- <SLogo size={12} />
2051
- <span className="typo-body-xs-default text-(--sys-color-fg-success)">WMS</span>
2052
- </span>
2053
- ✅ <SLogo size={12} color="grey_45" /> {/* 아직 못 쓰는 서비스 */}
2063
+ ✅ <SGnb header="fix" logo={<SLogo name="account" mode="dark" size="auto" />} … /> {/* fix 로고 칸을 채운다 */}
2064
+ ✅ <SLogo name="crm" size={12} color="grey_45" /> {/* 아직 못 쓰는 서비스 — 로고 전체가 한 색 */}
2054
2065
 
2055
- ❌ <svg viewBox="0 0 276 40">…</svg> {/* 워드마크를 손으로 붙이지 않는다 */}
2066
+ ❌ <span><SLogo /><span>WMS</span></span> {/* 표기를 잇지 않는다 — name="wms" */}
2067
+ ❌ <div><SLogo /><div>WMS</div></div> {/* 아래로 쌓지도 않는다 — direction="vertical" */}
2068
+ ❌ <SLogo name="wms" color="white" /> {/* 어두운 면이면 mode="dark" — 표기 색까지 흰색이 된다 */}
2069
+ ❌ <svg viewBox="0 0 347 50">…</svg> {/* 로고를 손으로 붙이지 않는다 */}
2056
2070
  ❌ <SLogo size={24} style={{ width: 120 }} /> {/* 폭은 비율이 정한다 — 찌그러진다 */}
2057
- ❌ <SLogo color="grey_45" /> {/* 물러날 이유가 없으면 브랜드색 그대로 둔다 */}
2071
+ ❌ <SLogo className="w-full [&>svg]:w-full!" /> {/* 폭을 채우려면 size="auto" */}
2072
+ ❌ <SGnb header="full" logo={<SLogo size="auto" />} … /> {/* full 로고 칸(140px)에서는 높이로 준다 */}
2073
+ ❌ <SLogo color="grey_45" /> {/* 물러날 이유가 없으면 브랜드 색 그대로 둔다 */}
2058
2074
  ```
2059
2075
 
2060
2076
  #### 3-7-13. 숫자 — SNumberInput 의 min·max 는 검증 경계다
@@ -2239,15 +2255,16 @@ import { SModalOutlet } from 'sellmate-design-system-react';
2239
2255
 
2240
2256
  | `header` | 상단바 배치 | 로고 폭 | `topContent` |
2241
2257
  | --- | --- | --- | --- |
2242
- | `"fix"` (기본) | `[런처 · 로고 … 폴드]` — 상단바가 GNB 컬럼 안에 있고 폴드가 컬럼 오른쪽 끝 | 내용 폭 | **렌더되지 않는다** (놓을 자리가 없다) |
2258
+ | `"fix"` (기본) | `[런처 · 로고 … 폴드]` — 상단바가 GNB 컬럼 안에 있고 폴드가 컬럼 오른쪽 끝 | 런처와 폴드 사이 남은 폭 (메뉴 폭을 따른다) | **렌더되지 않는다** (놓을 자리가 없다) |
2243
2259
  | `"full"` | `[런처 · 폴드 · 로고 · topContent … system]` — 상단바가 화면 전폭이고 `system` 은 오른쪽 끝 | **140px 고정** (런처 없으면 172px) | 로고 오른쪽 남는 폭 전체 |
2244
2260
 
2245
2261
  - `topContent` 는 상단바 로고 오른쪽 슬롯이다. 전역 검색처럼 **모든 페이지에 공통인 것만** 넣는다. 페이지별 액션은 여기가 아니라 §4-2 의 `STableBar` 로 간다.
2246
2262
  - **계정·알림·설정·도메인·서비스 전환은 `topContent` 에 손으로 만들지 않는다.** `header="full"` 이면 `system` 슬롯의 조각들이 상단바 오른쪽 끝으로 올라오므로, 그것들은 전부 `SGnbSystem` 이 그린다 (바로 아래 절).
2247
2263
  - 슬롯이 남는 폭을 통째로 받으므로 **정렬은 안에서 직접 잡는다** (좌측 정렬 + 우측은 `ml-auto`).
2248
- - `header="full"` 에서 로고 자리는 140px 로 고정된다 — 로고 내용이 바뀌어도 `topContent` 시작점이 흔들리지 않게 하기 위함이다. 로고가 그보다 넓으면 잘리므로 이 폭에 맞춰 준비한다.
2264
+ - `header="fix"` 에서 로고 자리는 런처와 폴드 버튼 사이의 남은 폭이다. **`SLogo size="auto"` 를 넣으면 그 폭을 채운다** — 메뉴 폭을 바꾸거나 로고 종류가 바뀌어도 폭에 맞춰진다. 높이(`size`)로 준 로고가 그보다 넓으면 잘린다.
2265
+ - `header="full"` 에서 로고 자리는 140px 로 고정된다 — 로고 내용이 바뀌어도 `topContent` 시작점이 흔들리지 않게 하기 위함이다. 로고가 그보다 넓으면 잘리므로 이 폭에 맞춰 준비한다. **여기서는 `SLogo size="auto"` 를 쓰지 않는다** — 높이(`size`)로 주고 140px 안에 들어가는 크기를 고른다.
2249
2266
  - `launcher` 를 주지 않으면 런처가 렌더되지 않고, 그 자리(버튼 + 간격)를 로고 슬롯이 이어받아 172px 가 된다. `topContent` 시작점은 런처 유무와 관계없이 같은 자리다.
2250
- - **런처 버튼은 서비스 목록의 트리거다.** `launcher.items` 에 옮겨 갈 서비스를 **키와 주소로** 넘기면 버튼 아래로 목록이 뜨고, 고른 서비스가 새 탭에서 열린다 — 팝오버도 이동도 손으로 만들지 않는다 (§3-5-9).
2267
+ - **런처 버튼은 서비스 목록의 트리거다.** `launcher.items` 에 옮겨 갈 서비스를 **키와 주소로** 넘기면 버튼 아래로 목록이 뜨고, 고른 서비스가 새 탭에서 열린다. 셀메이트 콘솔로 가는 줄은 `launcher.consoleHref` 로 붙는다 — 팝오버도 이동도 손으로 만들지 않는다 (§3-5-9).
2251
2268
 
2252
2269
  ```tsx
2253
2270
  <SLayout type="box" header="full">
@@ -2941,9 +2958,10 @@ export default function LoginPage() {
2941
2958
  // 여백은 카드가 최소 폭을 지킬 수 있는 값으로 둔다 — 카드 폭은 className 으로 박지 않는다
2942
2959
  <div className="flex h-screen items-stretch justify-center bg-bg-neutralLight p-sd-24">
2943
2960
  <SLoginCard
2944
- product="AI assistant"
2945
- title="셀메이트 AI 어시스턴트와 함께 자료 찾는 시간은 줄이고, 업무는 빠르게!"
2946
- description="(사내 답변은 사내 문서를 기반으로 답변합니다.)"
2961
+ // 제품은 서비스 키로 고른다 — 카드가 그 서비스의 세로 로고를 그린다. 제품명을 글자로 넘기지 않는다
2962
+ service="account"
2963
+ title="쇼핑몰 대표님을 위한 정부·세무 도우미입니다."
2964
+ description="(세금 신고 일정과 지원사업 소식을 한곳에서 챙겨 드립니다.)"
2947
2965
  // 로그인 버튼은 카드가 그린다 — 동작만 넘긴다
2948
2966
  onLogin={() => navigate('/auth/sso')}
2949
2967
  footerNote="계정이 없다면 담당자에게 문의를 요청해 주세요."
@@ -2971,7 +2989,7 @@ export default function LoginPage() {
2971
2989
 
2972
2990
  | Prop | 용도 |
2973
2991
  | --- | --- |
2974
- | `product` | 로고 아래 제품명 (`AI assistant` · `account` · `chat`) |
2992
+ | `service` | 제품 — `SLogo` 의 로고명(`account` · `wms` · `chat` …, `SLogoName`). 카드 맨 위에 그 서비스의 세로 로고가 선다 |
2975
2993
  | `title` | 제품을 한 줄로 소개하는 문장 |
2976
2994
  | `description` | 소개 바로 아래 붙는 보조 설명. 소개와 한 문단으로 읽힌다 — 없으면 생략한다 |
2977
2995
  | `onLogin` | 로그인 버튼을 눌렀을 때. **버튼은 카드가 그리므로 동작만 넘긴다** — 문구·색·크기는 세 제품에서 같아야 한다 |
@@ -2984,7 +3002,12 @@ export default function LoginPage() {
2984
3002
 
2985
3003
  **크기는 부모가 정한다 — `className` 으로 폭을 박지 않는다.** 카드는 폭을 368~640px 사이에서 부모에 맞추고 높이도 부모가 준 만큼 채운다. 밖에서 고정하면 상하한이 무의미해져, 좁은 화면에서 함께 좁아져야 할 카드가 그대로 남아 넘친다. 좁게 세워야 하면 카드가 아니라 바깥 한 겹을 좁힌다.
2986
3004
 
2987
- **Sellmate 워드마크와 로그인 버튼은 카드가 직접 그린다 — prop 이 없다.** 세 제품이 같은 로고·같은 버튼 문구(`통합 계정으로 로그인`)로 서므로 넘길 것도, 갈아 끼울 것도 없다. 앱이 주는 것은 문구와 `onLogin` 동작뿐이다.
3005
+ **로고와 로그인 버튼은 카드가 직접 그린다.** 로고는 `service` 키로 고르면 카드가 그 서비스의 세로 로고(`SLogo direction="vertical"`)를 크기·접근성 이름까지 정해 세운다 — **제품명을 글자로 넘기거나 로고를 따로 얹지 않는다.** 표기의 서체·자간·색은 원본 로고가 정한다. 버튼은 모든 제품이 같은 문구(`통합 계정으로 로그인`)로 서므로 넘길 것이 없다. 앱이 주는 것은 서비스 키·문구·`onLogin` 동작뿐이다.
3006
+
3007
+ ```tsx
3008
+ ✅ <SLoginCard service="account" title="…" onLogin={login} />
3009
+ ❌ <SLoginCard service="sellmate" title={<><b>Account</b> …</>} /> {/* 제품명을 글자로 잇지 않는다 — service="account" */}
3010
+ ```
2988
3011
 
2989
3012
  **로그인 카드 옆에 다른 블록을 두지 않는다.** 이 화면에서 할 일은 로그인 하나이고, 옆에 공지·배너가 붙는 순간 그 뜻이 깨진다. 안내가 필요하면 `description` 이나 `footerNote` 로 넣는다.
2990
3013
 
@@ -16,7 +16,7 @@
16
16
  | `value?` | `string` | `''` | 현재 선택된 아이템 value |
17
17
  | `folded?` | `boolean` | — | 접힘(레일) 상태. 미지정 시 SLayout 의 folded 를 따른다. |
18
18
  | `launcher?` | `SGnbLauncher` | — | 앱런처(그리드) 버튼. 미지정 시 런처 버튼을 렌더하지 않는다. 접힘 레일(fix)에는 폴드 버튼만 남으므로 표시되지 않는다. |
19
- | `logo?` | `ReactNode` | — | 상단바 로고 영역 (slot). header="full" 이면 폭이 140px 로 고정된다. |
19
+ | `logo?` | `ReactNode` | — | 상단바 로고 영역 (slot). - `header="fix"` : 런처와 폴드 버튼 사이의 남은 폭이 로고 칸이다. `SLogo size="auto"` 를 넣으면 그 폭을 채운다(메뉴 폭을 바꿔도 따라온다). 넘치는 로고는 잘린다. - `header="full"` : 폭이 140px 로 고정된다. 여기서는 `size="auto"` 를 쓰지 않는다 — 높이(`size`)로 주고 140px 안에 들어가는 크기를 고른다. |
20
20
  | `topContent?` | `ReactNode` | — | 상단바 로고 오른쪽 슬롯 (검색·액션 등). 로고와 16px 띄고 남는 폭을 모두 차지하므로 안에서 자유롭게 정렬한다. 상단바가 전폭인 header="full" 에서만 렌더된다 (fix 는 상단바가 좁은 GNB 컬럼 안이라 놓을 자리가 없다). |
21
21
  | `railTop?` | `ReactNode` | — | 레일 상단 고정 슬롯. 레일 아이템이 많아 넘치면 아이템 목록(ul)만 스크롤되고 이 슬롯은 레일 상단(상단바 바로 아래)에 붙어 고정된다. showRail 일 때만 렌더된다. |
22
22
  | `railFooter?` | `ReactNode` | — | 레일 하단 고정 슬롯. 레일 아이템이 많아 넘치면 아이템 목록(ul)만 스크롤되고 이 슬롯은 레일 하단에 붙어 고정된다. showRail 일 때만 렌더된다. |
@@ -108,6 +108,17 @@ export interface SGnbLauncher {
108
108
  * 닫힌다(`onOpenChange(false)` 도 함께 온다).
109
109
  */
110
110
  onSelect?: (service: SLauncherService) => void;
111
+ /**
112
+ * 셀메이트 콘솔 주소. 목록 아래에 **늘 서는** "셀메이트 콘솔로 이동" 글자 링크가 누르면 이 주소를
113
+ * 새 탭에서 연다(`SLauncherListBox` 의 `consoleHref`). **필수다** — 콘솔로 가는 길은 어느
114
+ * 서비스의 런처에나 있어야 한다. 목록(`items`)이 비면 목록째 뜨지 않으므로 이 링크도 뜨지 않는다.
115
+ */
116
+ consoleHref: string;
117
+ /**
118
+ * 콘솔 링크를 누름. `onSelect` 와 같이 **화면을 옮기지 않는다** — 컴포넌트가 새 탭으로 이미 연다.
119
+ * 누르면 목록은 스스로 닫힌다.
120
+ */
121
+ onConsoleClick?: () => void;
111
122
  /**
112
123
  * 목록이 열리고 닫힐 때. 여닫는 것은 런처 버튼이 스스로 하므로 **그 사실을 알아야 할 때만** 준다
113
124
  * (연 김에 목록을 다시 불러오거나, 열려 있는 동안 다른 층을 접어 두는 화면).
@@ -62,6 +62,17 @@ export interface SGnbLauncher {
62
62
  * 닫힌다(`onOpenChange(false)` 도 함께 온다).
63
63
  */
64
64
  onSelect?: (service: SLauncherService) => void;
65
+ /**
66
+ * 셀메이트 콘솔 주소. 목록 아래에 **늘 서는** "셀메이트 콘솔로 이동" 글자 링크가 누르면 이 주소를
67
+ * 새 탭에서 연다(`SLauncherListBox` 의 `consoleHref`). **필수다** — 콘솔로 가는 길은 어느
68
+ * 서비스의 런처에나 있어야 한다. 목록(`items`)이 비면 목록째 뜨지 않으므로 이 링크도 뜨지 않는다.
69
+ */
70
+ consoleHref: string;
71
+ /**
72
+ * 콘솔 링크를 누름. `onSelect` 와 같이 **화면을 옮기지 않는다** — 컴포넌트가 새 탭으로 이미 연다.
73
+ * 누르면 목록은 스스로 닫힌다.
74
+ */
75
+ onConsoleClick?: () => void;
65
76
  /**
66
77
  * 목록이 열리고 닫힐 때. 여닫는 것은 런처 버튼이 스스로 하므로 **그 사실을 알아야 할 때만** 준다
67
78
  * (연 김에 목록을 다시 불러오거나, 열려 있는 동안 다른 층을 접어 두는 화면).
@@ -104,7 +115,13 @@ export interface SGnbProps extends Omit<HTMLAttributes<HTMLDivElement>, 'color'>
104
115
  * 접힘 레일(fix)에는 폴드 버튼만 남으므로 표시되지 않는다.
105
116
  */
106
117
  launcher?: SGnbLauncher;
107
- /** 상단바 로고 영역 (slot). header="full" 이면 폭이 140px 로 고정된다. */
118
+ /**
119
+ * 상단바 로고 영역 (slot).
120
+ * - `header="fix"` : 런처와 폴드 버튼 사이의 남은 폭이 로고 칸이다. `SLogo size="auto"` 를 넣으면
121
+ * 그 폭을 채운다(메뉴 폭을 바꿔도 따라온다). 넘치는 로고는 잘린다.
122
+ * - `header="full"` : 폭이 140px 로 고정된다. 여기서는 `size="auto"` 를 쓰지 않는다 — 높이(`size`)로
123
+ * 주고 140px 안에 들어가는 크기를 고른다.
124
+ */
108
125
  logo?: ReactNode;
109
126
  /**
110
127
  * 상단바 로고 오른쪽 슬롯 (검색·액션 등). 로고와 16px 띄고 남는 폭을 모두 차지하므로
@@ -9,6 +9,7 @@
9
9
  | Prop | Type | Default | Description |
10
10
  |------|------|---------|-------------|
11
11
  | `items?` | `SLauncherListBoxItem[]` | — | 목록에 세울 서비스. 비어 있으면 아무것도 렌더하지 않는다. **순서는 넘긴 대로가 아니라 카탈로그 순서다**(`LAUNCHER_SERVICES`) — 같은 런처가 앱마다 다른 순서로 뜨면 사용자가 매번 다시 찾는다. 같은 서비스를 두 번 넘기면 처음 것만 선다. |
12
+ | `consoleHref` | `string` | — | 셀메이트 콘솔 주소. 목록 아래에 **늘 서는** "셀메이트 콘솔로 이동" 글자 링크(`STextLink`)가 누르면 이 주소를 새 탭에서 연다. **필수다** — 어느 서비스의 런처든 콘솔로 가는 길은 있어야 한다. 문구·아이콘은 컴포넌트가 정한다 — 어느 서비스의 런처든 같은 곳을 같은 말로 안내해야 한다. 주소는 서비스 줄의 `href` 처럼 앱마다 QA·실서버가 달라 앱이 넘긴다. |
12
13
  | `ariaLabel?` | `string` | — | 목록(ul)의 접근성 레이블 |
13
14
 
14
15
  #### Events
@@ -16,6 +17,7 @@
16
17
  | Event | Type | Description |
17
18
  |-------|------|-------------|
18
19
  | `onSelect` | `(service: SLauncherService) => void` | 서비스를 고름. **가는 것은 이 콜백이 하지 않는다** — 줄이 링크라 브라우저가 `href` 를 새 탭으로 연다. 고른 것을 앱이 알아야 할 때만(기록·목록 닫기) 준다. 갈 수 없는 줄(주소가 없거나 카탈로그가 아직 출시 전으로 든 서비스)은 눌리지 않으므로 여기로 오지 않는다. |
20
+ | `onConsoleClick` | `() => void` | 콘솔 링크를 누름. **가는 것은 이 콜백이 하지 않는다** — 컴포넌트가 `consoleHref` 를 새 탭으로 이미 연다. 누른 것을 앱이 알아야 할 때만(기록·목록 닫기) 준다. |
19
21
 
20
22
  ## Types
21
23
 
@@ -43,18 +45,15 @@ export interface SLauncherListBoxItem {
43
45
 
44
46
  ### SLauncherService
45
47
 
46
- ```ts
47
- export type SLauncherService = (typeof LAUNCHER_SERVICES)[number];
48
- ```
49
-
50
- ### LAUNCHER_SERVICES
51
-
52
48
  ```ts
53
49
  /**
54
- * 런처에 설 수 있는 서비스 — **목록의 순서이기도 하다.**
55
- * 앱이 넘긴 순서가 아니라 이 순서로 선다: 같은 런처가 앱마다 다른 순서로 뜨면 사용자가 매번 다시 찾는다.
50
+ * 런처에 설 수 있는 서비스 키 — **`SLogo` 가 로고를 가진 서비스 전부다(통합 콘솔 제외).**
51
+ *
52
+ * 문서에서 바로 읽히도록 키를 풀어 쓴다(`Exclude<SLogoName, …>` 로 두면 README·Storybook 에 무엇이
53
+ * 있는지 보이지 않는다). 대신 아래 `LOGO_COVERAGE` 가 로고 목록과 어긋나지 않는지 타입으로 지킨다.
56
54
  */
57
- export const LAUNCHER_SERVICES = ['sellmate', 'wms', 'account', 'crm'] as const;
55
+ export type SLauncherService =
56
+ 'sellmate' | 'wms' | 'chat' | 'plm' | 'account' | 'people' | 'crm' | 'work' | 'pos';
58
57
  ```
59
58
 
60
59
  ## Dependencies
@@ -68,6 +67,7 @@ export const LAUNCHER_SERVICES = ['sellmate', 'wms', 'account', 'crm'] as const;
68
67
  - [SIcon](../SIcon)
69
68
  - [SLogo](../SLogo)
70
69
  - [STag](../STag)
70
+ - [STextLink](../STextLink)
71
71
 
72
72
  ### Graph
73
73
 
@@ -76,6 +76,7 @@ graph TD;
76
76
  SLauncherListBox --> SIcon
77
77
  SLauncherListBox --> SLogo
78
78
  SLauncherListBox --> STag
79
+ SLauncherListBox --> STextLink
79
80
  SGnb --> SLauncherListBox
80
81
  style SLauncherListBox fill:#f9f,stroke:#333,stroke-width:4px
81
82
  ```
@@ -33,6 +33,19 @@ export interface SLauncherListBoxProps extends Omit<HTMLAttributes<HTMLDivElemen
33
33
  * 여기로 오지 않는다.
34
34
  */
35
35
  onSelect?: (service: SLauncherService) => void;
36
+ /**
37
+ * 셀메이트 콘솔 주소. 목록 아래에 **늘 서는** "셀메이트 콘솔로 이동" 글자 링크(`STextLink`)가
38
+ * 누르면 이 주소를 새 탭에서 연다. **필수다** — 어느 서비스의 런처든 콘솔로 가는 길은 있어야 한다.
39
+ *
40
+ * 문구·아이콘은 컴포넌트가 정한다 — 어느 서비스의 런처든 같은 곳을 같은 말로 안내해야 한다.
41
+ * 주소는 서비스 줄의 `href` 처럼 앱마다 QA·실서버가 달라 앱이 넘긴다.
42
+ */
43
+ consoleHref: string;
44
+ /**
45
+ * 콘솔 링크를 누름. **가는 것은 이 콜백이 하지 않는다** — 컴포넌트가 `consoleHref` 를 새 탭으로
46
+ * 이미 연다. 누른 것을 앱이 알아야 할 때만(기록·목록 닫기) 준다.
47
+ */
48
+ onConsoleClick?: () => void;
36
49
  /** 목록(ul)의 접근성 레이블 */
37
50
  ariaLabel?: string;
38
51
  }
@@ -41,7 +54,7 @@ export interface SLauncherListBoxProps extends Omit<HTMLAttributes<HTMLDivElemen
41
54
  *
42
55
  * 한 줄이 서비스 하나다: 위에 브랜드 로고(+ 상태 태그), 아래에 한글 이름.
43
56
  *
44
- * **앱이 넘기는 것은 서비스 키와 주소 둘뿐이다.** 로고·서비스 표기·이름·상태 태그는 카탈로그
57
+ * **앱이 넘기는 것은 서비스 키와 주소 둘뿐이다.** 로고는 서비스 키가, 이름·상태 태그는 카탈로그
45
58
  * (`LAUNCHER_SERVICE_CATALOG`)가 서비스마다 한 모습으로 정해 두므로 앱이 넘기지 않는다 —
46
59
  * 넘기게 하면 같은 서비스가 앱마다 다른 이름·색·문구로 선다.
47
60
  *
@@ -1,2 +1,2 @@
1
1
  export { SLauncherListBox, type SLauncherListBoxProps, type SLauncherListBoxItem, } from './SLauncherListBox';
2
- export { LAUNCHER_LIST_BOX_LAYOUT, LAUNCHER_LIST_BOX_LOGO_HEIGHT, LAUNCHER_LIST_BOX_LOGO_SERVICE_GAP, LAUNCHER_LIST_BOX_TRAILING_ICON, LAUNCHER_LIST_BOX_WIDTH, LAUNCHER_SERVICES, LAUNCHER_SERVICE_CATALOG, type SLauncherService, type SLauncherServiceEntry, } from './launcherListBox.config';
2
+ export { LAUNCHER_LIST_BOX_CONSOLE_HEIGHT, LAUNCHER_LIST_BOX_CONSOLE_ICON, LAUNCHER_LIST_BOX_CONSOLE_LABEL, LAUNCHER_LIST_BOX_LAYOUT, LAUNCHER_LIST_BOX_LOGO_HEIGHT, LAUNCHER_LIST_BOX_TRAILING_ICON, LAUNCHER_LIST_BOX_WIDTH, LAUNCHER_SERVICES, LAUNCHER_SERVICE_CATALOG, type SLauncherService, type SLauncherServiceEntry, } from './launcherListBox.config';
@@ -1,4 +1,5 @@
1
1
  import type { SIconName } from '../SIcon';
2
+ import type { SLogoName } from '../SLogo/logo.config';
2
3
  import type { STagColor } from '../STag';
3
4
  /**
4
5
  * 패널 고정 폭(px, 시안 — 전용 토큰 없음).
@@ -12,10 +13,19 @@ export declare const LAUNCHER_LIST_BOX_WIDTH = 320;
12
13
  */
13
14
  export declare const LAUNCHER_LIST_BOX_LOGO_HEIGHT = 12;
14
15
  /**
15
- * 워드마크 ↔ 서비스 표기 간격(px, 시안 — 전용 토큰 없음).
16
- * 토큰의 `logo.gap` 은 [워드마크+표기] 묶음과 태그 사이의 간격이라 여기 쓸 값이 아니다.
16
+ * 하단 "셀메이트 콘솔로 이동" 줄의 높이(px, 시안 — 전용 토큰 없음).
17
+ * 글자 한 줄(20)을 가운데 둔 띠라 여백이 아니라 높이로 정한다.
17
18
  */
18
- export declare const LAUNCHER_LIST_BOX_LOGO_SERVICE_GAP = 8;
19
+ export declare const LAUNCHER_LIST_BOX_CONSOLE_HEIGHT = 40;
20
+ /**
21
+ * 하단 콘솔 줄의 문구. **앱이 바꾸지 않는다** — 모든 서비스의 런처가 같은 곳(통합 콘솔)으로
22
+ * 같은 말로 안내해야 하기 때문이다.
23
+ */
24
+ export declare const LAUNCHER_LIST_BOX_CONSOLE_LABEL = "\uC140\uBA54\uC774\uD2B8 \uCF58\uC194\uB85C \uC774\uB3D9";
25
+ /**
26
+ * 콘솔 링크 앞 아이콘(시안의 글리프와 같다). 뒤의 chevron 은 `STextLink` 의 `rightArrow` 가 그린다.
27
+ */
28
+ export declare const LAUNCHER_LIST_BOX_CONSOLE_ICON: SIconName;
19
29
  /**
20
30
  * hover 때 줄 오른쪽 끝에 나타나는 아이콘 — "여기서 다른 서비스로 옮겨 간다"는 표시.
21
31
  * 크기·색은 토큰이 정하지만 **어떤 글리프인지는 토큰에 없어** 뜻이 가장 가까운 것을 골랐다.
@@ -23,18 +33,34 @@ export declare const LAUNCHER_LIST_BOX_LOGO_SERVICE_GAP = 8;
23
33
  */
24
34
  export declare const LAUNCHER_LIST_BOX_TRAILING_ICON: SIconName;
25
35
  /**
26
- * 런처에 설 수 있는 서비스 — **목록의 순서이기도 하다.**
36
+ * 런처에 설 수 있는 서비스 키 — **`SLogo` 가 로고를 가진 서비스 전부다(통합 콘솔 제외).**
37
+ *
38
+ * 문서에서 바로 읽히도록 키를 풀어 쓴다(`Exclude<SLogoName, …>` 로 두면 README·Storybook 에 무엇이
39
+ * 있는지 보이지 않는다). 대신 아래 `LOGO_COVERAGE` 가 로고 목록과 어긋나지 않는지 타입으로 지킨다.
40
+ */
41
+ export type SLauncherService = 'sellmate' | 'wms' | 'chat' | 'plm' | 'account' | 'people' | 'crm' | 'work' | 'pos';
42
+ /**
43
+ * 런처에 설 수 있는 서비스 — **목록의 순서이기도 하다**(로고 순서와 같다).
27
44
  * 앱이 넘긴 순서가 아니라 이 순서로 선다: 같은 런처가 앱마다 다른 순서로 뜨면 사용자가 매번 다시 찾는다.
28
45
  */
29
- export declare const LAUNCHER_SERVICES: readonly ["sellmate", "wms", "account", "crm"];
30
- export type SLauncherService = (typeof LAUNCHER_SERVICES)[number];
31
- /** 카탈로그 한 줄 — 그 서비스가 런처에서 갖는 고정된 모습 */
46
+ export declare const LAUNCHER_SERVICES: readonly ["sellmate", "wms", "chat", "plm", "account", "people", "crm", "work", "pos"];
47
+ /**
48
+ * 서비스가 아닌 로고 — 런처의 서비스 줄로 세우지 않는다.
49
+ * `console` 은 통합 콘솔이라 목록 아래 "셀메이트 콘솔로 이동" 링크가 늘 맡는다. 줄로도 세우면 같은 곳이 두 번 선다.
50
+ */
51
+ type NonServiceLogo = 'console';
52
+ /**
53
+ * 로고 ↔ 서비스 키 대조. **로고를 더했는데 위 키에 적지 않았거나, 로고가 없는 키를 적으면 이 줄이
54
+ * 타입 에러가 된다** — "로고가 있는 서비스는 모두 런처에 설 수 있다"를 손으로 기억하지 않게 한다.
55
+ * (키를 더하면 `LAUNCHER_SERVICES` 와 아래 카탈로그도 함께 채워야 한다 — 카탈로그는 Record 라 타입이 막는다.)
56
+ */
57
+ type Uncovered = Exclude<SLogoName, SLauncherService | NonServiceLogo> | Exclude<SLauncherService, SLogoName> | Exclude<SLauncherService, (typeof LAUNCHER_SERVICES)[number]>;
58
+ export declare const LOGO_COVERAGE: [Uncovered] extends [never] ? true : Uncovered;
59
+ /**
60
+ * 카탈로그 한 줄 — 그 서비스가 런처에서 갖는 고정된 모습.
61
+ * 로고는 여기 적지 않는다 — 서비스 키를 그대로 `SLogo` 의 `name` 으로 넘겨 그 서비스 로고를 그린다.
62
+ */
32
63
  export interface SLauncherServiceEntry {
33
- /**
34
- * 워드마크 오른쪽에 잇는 서비스 표기(`WMS` · `Account` · `CRM`). 셀메이트 본체처럼 표기가
35
- * 없는 서비스는 비운다 — 워드마크만 선다.
36
- */
37
- mark?: string;
38
64
  /** 로고 아래 줄에 적히는 서비스 이름 */
39
65
  name: string;
40
66
  /**
@@ -95,10 +121,8 @@ export declare const LAUNCHER_LIST_BOX_LAYOUT: {
95
121
  readonly nameColorHover: string;
96
122
  /** 로고 줄의 위아래 여백 */
97
123
  readonly logoPaddingY: string;
98
- /** [워드마크 + 서비스 표기] ↔ 태그 간격 */
124
+ /** 서비스 로고 ↔ 태그 간격 */
99
125
  readonly logoTagGap: string;
100
- /** 워드마크 ↔ 서비스 표기 간격 */
101
- readonly logoServiceGap: "8px";
102
126
  /** hover 아이콘 크기 */
103
127
  readonly trailingIconSize: string;
104
128
  /** hover 아이콘 색 */
@@ -109,10 +133,22 @@ export declare const LAUNCHER_LIST_BOX_LAYOUT: {
109
133
  */
110
134
  readonly nameDisabledColor: string;
111
135
  /**
112
- * 아직 못 쓰는 서비스의 로고 색 — 워드마크와, 글자로 온 서비스 표기에 함께 건다.
113
- * 둘 다 색만 갈아끼우면 되므로 그래픽 마크에 거는 필터(회색화)를 태우지 않는다 — 태우면
114
- * 밝은 accentLight 가 워드마크보다 더 옅어져 둘이 따로 논다. 로고는 글자가 아니라 그림에
136
+ * 아직 못 쓰는 서비스의 로고 색 — 워드마크와 서비스 표기를 함께 이 한 색으로 덮는다.
137
+ * 필터(회색화)를 태우지 않는다 — 태우면 밝은 서비스 색이 워드마크보다 더 옅어져 둘이
138
+ * 따로 논다. 로고는 글자가 아니라 그림에
115
139
  * 가까우므로 글자색(disabled-text)이 아니라 아이콘 비활성색을 쓴다.
116
140
  */
117
141
  readonly logoDisabledColor: string;
142
+ /** 목록 ↔ 콘솔 줄 구분선 */
143
+ readonly consoleDivider: string;
144
+ /** 콘솔 줄 배경 */
145
+ readonly consoleBg: string;
146
+ /**
147
+ * 콘솔 링크 글자색. STextLink 기본(`--cmp-textLink-content-default`)보다 한 단계 옅다(시안).
148
+ * 크기·간격·hover(밑줄)는 STextLink `sm` 이 정한다.
149
+ */
150
+ readonly consoleColor: string;
151
+ /** 콘솔 링크 앞 아이콘 색. STextLink 기본(파랑)이 아니라 회색이다(시안) */
152
+ readonly consoleIconColor: string;
118
153
  };
154
+ export {};
@@ -8,7 +8,7 @@
8
8
 
9
9
  | Prop | Type | Default | Description |
10
10
  |------|------|---------|-------------|
11
- | `product` | `ReactNode` | — | 로고 아래 제품명 (예: `AI assistant` · `account` · `chat`) |
11
+ | `service` | `SLogoName` | — | 제품 — 그 서비스의 **세로 로고**([셀메이트 워드마크 + 서비스 표기])가 카드 맨 위에 선다. 제품명을 글자로 넘기지 않는다 — 표기의 서체·자간·색은 원본 로고가 정한다. |
12
12
  | `title` | `ReactNode` | — | 제품을 한 줄로 소개하는 문장 |
13
13
  | `description?` | `ReactNode` | — | 소개 문장 바로 아래 붙는 보조 설명. 소개와 한 덩어리로 읽힌다 |
14
14
  | `footerNote?` | `ReactNode` | — | 버튼 아래 안내 문구 (예: 계정 발급 문의 안내) |
@@ -1,7 +1,11 @@
1
1
  import { type HTMLAttributes, type ReactNode } from 'react';
2
+ import { type SLogoName } from '../SLogo';
2
3
  export interface SLoginCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
3
- /** 로고 아래 제품명 (예: `AI assistant` · `account` · `chat`) */
4
- product: ReactNode;
4
+ /**
5
+ * 제품 — 그 서비스의 **세로 로고**([셀메이트 워드마크 + 서비스 표기])가 카드 맨 위에 선다.
6
+ * 제품명을 글자로 넘기지 않는다 — 표기의 서체·자간·색은 원본 로고가 정한다.
7
+ */
8
+ service: SLogoName;
5
9
  /** 제품을 한 줄로 소개하는 문장 */
6
10
  title: ReactNode;
7
11
  /** 소개 문장 바로 아래 붙는 보조 설명. 소개와 한 덩어리로 읽힌다 */
@@ -25,8 +29,8 @@ export interface SLoginCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 't
25
29
  /**
26
30
  * SLoginCard — 통합 계정 로그인 화면의 카드.
27
31
  *
28
- * 로고·제품명·소개·로그인 버튼·안내 문구를 세로 가운데로 세운다. 제품마다 다른 것은 문구뿐이라
29
- * 문구와 로그인 동작만 prop 으로 받고 로고·버튼·간격·타이포·색은 카드가 쥔다.
32
+ * 서비스 세로 로고·소개·로그인 버튼·안내 문구를 세로 가운데로 세운다. 제품마다 다른 것은 서비스와
33
+ * 문구뿐이라 서비스 키·문구·로그인 동작만 prop 으로 받고 로고·버튼·간격·타이포·색은 카드가 쥔다.
30
34
  *
31
35
  * **크기는 부모가 정한다** — 폭은 368~640px 사이에서 부모를 채우고, 높이도 부모가 준 만큼 채운다.
32
36
  *
@@ -8,9 +8,11 @@
8
8
 
9
9
  | Prop | Type | Default | Description |
10
10
  |------|------|---------|-------------|
11
- | `name?` | `SLogoName` | `'sellmate'` | 로고명 |
12
- | `size?` | `number \| string` | `LOGO_DEFAULT_SIZE` | **높이**(px 또는 CSS 길이). 폭은 주지 않는다 — 워드마크 비율에서 저절로 나온다. `SIcon` 의 `size` 와 달리 정사각이 아니다(로고는 가로로 길다). |
13
- | `color?` | `SColor` | — | 색. 팔레트 키(`grey_45`, `red_95` …) 또는 임의 CSS 색상. **로고 전체가 이 한 색이 된다.** 미지정 시 **브랜드 기본색**이다 — `SIcon` 과 달리 currentColor 를 상속하지 않는다. 로고가 주변 글자색을 따라 물들면 브랜드 색이 화면마다 달라지기 때문이다. 비활성처럼 물러나야 하는 자리에서만 색을 준다. |
11
+ | `name?` | `SLogoName` | `'sellmate'` | 로고명 — 셀메이트 본체(`sellmate`) 또는 서비스(`wms` · `account` · `crm` …). 서비스 로고는 [셀메이트 워드마크 + 서비스 표기]가 한 덩어리로 나온다 — 앱이 표기를 잇지 않는다. |
12
+ | `mode?` | `SLogoMode` | `'light'` | 로고가 서는 배경. 밝은 면에는 `light`(남색 워드마크), 어두운 면에는 `dark`(흰 워드마크). 서비스 표기 색도 원본이 모드마다 정한 값으로 바뀐다. |
13
+ | `direction?` | `SLogoDirection` | `'horizontal'` | 배치. `horizontal` 은 워드마크 오른쪽에 서비스 표기, `vertical` 은 워드마크 아래 가운데에 표기 (로그인 카드처럼 폭이 좁고 로고가 가운데 서는 자리). `sellmate` 는 표기가 없어 어느 쪽이든 같다. 표기 색이 가로와 다른 로고도 있다(POS 세로는 light 에서도 `#4886FF`) — 원본을 따른다. |
14
+ | `size?` | `number \| 'auto' \| (string & {})` | `LOGO_DEFAULT_SIZE` | **높이**(px 또는 CSS 길이). 폭은 주지 않는다 — 로고 비율에서 저절로 나온다. `SIcon` 의 `size` 와 달리 정사각이 아니다(로고는 가로로 길다). `vertical` 은 두 줄 전체의 높이다 — 같은 `size` 면 워드마크가 가로보다 작게 선다. `'auto'` 면 높이를 정하지 않는다 — **부모 폭을 꽉 채우고 높이는 비율로 따라온다.** 로고 자리의 폭이 정해진 곳(`SGnb` `header="fix"` 의 로고 칸)에서 쓴다. 부모에 폭이 없으면 기준을 잃어 브라우저 기본 크기(300px)로 그려진다. |
15
+ | `color?` | `SColor` | — | 색. 팔레트 키(`grey_45`, `red_95` …) 또는 임의 CSS 색상. **워드마크와 서비스 표기가 모두 이 한 색이 된다.** 미지정 시 **브랜드 색**(`mode` 가 정한 워드마크 색 + 서비스 색)이다 — `SIcon` 과 달리 currentColor 를 상속하지 않는다. 로고가 주변 글자색을 따라 물들면 브랜드 색이 화면마다 달라지기 때문이다. 비활성처럼 물러나야 하는 자리에서만 색을 준다. |
14
16
  | `label?` | `string` | — | 접근성 라벨. 없으면 `aria-hidden` 이다 — 로고 옆에 서비스 이름이 이미 적혀 있는 자리 (런처 목록의 한 줄 등)에서는 이름이 두 번 읽히지 않도록 그대로 둔다. 로고가 그 자리의 유일한 이름이면(로그인 화면·상단바) 브랜드명을 넘긴다. |
15
17
  | `className?` | `string` | — | |
16
18
  | `style?` | `CSSProperties` | — | |
@@ -23,6 +25,18 @@
23
25
  export type SLogoName = (typeof LOGO_NAMES)[number];
24
26
  ```
25
27
 
28
+ ### SLogoMode
29
+
30
+ ```ts
31
+ export type SLogoMode = (typeof LOGO_MODES)[number];
32
+ ```
33
+
34
+ ### SLogoDirection
35
+
36
+ ```ts
37
+ export type SLogoDirection = (typeof LOGO_DIRECTIONS)[number];
38
+ ```
39
+
26
40
  ### LOGO_NAMES
27
41
 
28
42
  ```ts
@@ -33,8 +47,42 @@ export type SLogoName = (typeof LOGO_NAMES)[number];
33
47
  * 하고, 워드마크의 비율은 자산 자체가 정한다. 그래서 이 파일의 값은 토큰 참조가 아니다.
34
48
  */
35
49
 
36
- /** 담고 있는 로고. 늘어나면 여기와 `logos.tsx` 의 맵에 함께 추가한다 */
37
- export const LOGO_NAMES = ['sellmate'] as const;
50
+ /**
51
+ * 담고 있는 로고 — 셀메이트 본체와 서비스들, 그리고 통합 콘솔. 로고 한 벌은 [셀메이트 워드마크 + 표기]다.
52
+ * 늘어나면 여기와 `logos.tsx` 의 맵에 함께 추가한다.
53
+ */
54
+ export const LOGO_NAMES = [
55
+ 'sellmate',
56
+ 'wms',
57
+ 'chat',
58
+ 'plm',
59
+ 'account',
60
+ 'people',
61
+ 'crm',
62
+ 'work',
63
+ 'pos',
64
+ 'console',
65
+ ] as const;
66
+ ```
67
+
68
+ ### LOGO_MODES
69
+
70
+ ```ts
71
+ /**
72
+ * 로고가 서는 배경. 밝은 면에는 `light`(남색 워드마크), 어두운 면에는 `dark`(흰 워드마크).
73
+ * 서비스 표기 색도 모드마다 원본이 정한 값으로 바뀐다(Account·POS 는 dark 에서 더 밝다).
74
+ */
75
+ export const LOGO_MODES = ['light', 'dark'] as const;
76
+ ```
77
+
78
+ ### LOGO_DIRECTIONS
79
+
80
+ ```ts
81
+ /**
82
+ * 로고의 배치. `horizontal` 은 워드마크 오른쪽에 서비스 표기, `vertical` 은 워드마크 아래 가운데에 표기.
83
+ * 모든 서비스 로고가 세로 원본을 갖는다. 셀메이트 본체는 표기가 없어 세로여도 모양이 같다.
84
+ */
85
+ export const LOGO_DIRECTIONS = ['horizontal', 'vertical'] as const;
38
86
  ```
39
87
 
40
88
  ## Dependencies