sellmate-design-system-react 3.2.0 → 3.3.1
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 +109 -36
- package/README.md +26 -2
- package/dist/components/SActionModal/README.md +1 -0
- package/dist/components/SActionModal/SActionModal.cjs +5 -1
- package/dist/components/SActionModal/SActionModal.cjs.map +1 -1
- package/dist/components/SActionModal/SActionModal.d.ts +6 -1
- package/dist/components/SActionModal/SActionModal.js +5 -1
- package/dist/components/SActionModal/SActionModal.js.map +1 -1
- package/dist/components/SBadge/README.md +2 -2
- package/dist/components/SIcon/README.md +0 -2
- package/dist/components/STooltip/README.md +2 -2
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +112 -39
- package/dist/llms.txt +109 -36
- package/dist/styles.css +3 -0
- package/eslint/lib/table-column.mjs +42 -6
- package/eslint/rules/require-locale-number.mjs +9 -7
- package/eslint/rules/table-numeric-align.mjs +17 -6
- package/package.json +1 -1
package/dist/llms-full.txt
CHANGED
|
@@ -126,7 +126,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
126
126
|
|
|
127
127
|
콤마 없는 `39000` 은 자릿수를 세어야 읽히지만 `39,000` 은 한눈에 읽힌다. 숫자를 그대로 출력하는 코드는 미완성으로 본다.
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
**번호·코드는 제외한다.** 전화번호·사업자번호·송장번호·상품코드처럼 대상을 가리키는 값은 크기를 비교하는 숫자가 아니라 **서식이 정해진 문자열**이다. 여기에 콤마를 넣으면 송장번호 `123456789` 가 `123,456,789` 로 보여 값 자체가 달라진다.
|
|
130
130
|
|
|
131
131
|
---
|
|
132
132
|
|
|
@@ -154,6 +154,8 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
154
154
|
|
|
155
155
|
페이지 제목만 18px 로 크게 두고 그 아래는 14 / 12 로 촘촘하게 간다. 중간 크기(16px)는 기본 골격에서 쓰지 않는다.
|
|
156
156
|
|
|
157
|
+
**보조 설명의 색** — 기본은 `text-fg-tertiary`(`grey_65`) 다. 보조 설명 안에서 위계가 한 단계 더 필요할 때만 `text-fg-secondary`(`grey_80`) → `text-fg-tertiary`(`grey_65`) 순으로 내려 쓴다 (§2-3).
|
|
158
|
+
|
|
157
159
|
### 2-2. 간격 (spacing)
|
|
158
160
|
|
|
159
161
|
- 유틸리티 숫자 = px. 스케일: `2 4 6 8 10 12 16 19 20 22 24 28 32 36 40 48 60`
|
|
@@ -165,8 +167,8 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
165
167
|
| **페이지 콘텐츠 패딩** | **`p-20`** |
|
|
166
168
|
| **섹션 ↔ 섹션** | **`gap-12`** |
|
|
167
169
|
| **페이지 내 블록 ↔ 블록** (헤더·필터·툴바·테이블 사이) | **`gap-12`** |
|
|
168
|
-
| 요소 ↔ 요소
|
|
169
|
-
| 제목 ↔ 설명 텍스트 | `gap-4
|
|
170
|
+
| 요소 ↔ 요소 | **기본 `gap-8`** (`--sys-space-stack-gap-element-normal`) · 타이트 `gap-4`(`-tight`) · 여유 `gap-12`(`-relaxed`) / `gap-16`(`-wide`) |
|
|
171
|
+
| 제목 ↔ 설명 텍스트 | **수직 배치 `gap-4`**(`--sys-space-stack-gap-text-normal`, 타이트 `gap-2`) · **가로 배치 `gap-8`**(`-relaxed`) |
|
|
170
172
|
|
|
171
173
|
정보 밀도가 높은 서비스라 블록 간격을 넓게 벌리지 않는다. `gap-16` / `gap-24` 를 페이지 골격의 기본값으로 쓰지 않는다.
|
|
172
174
|
|
|
@@ -206,23 +208,28 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
206
208
|
|
|
207
209
|
**시맨틱 유틸리티를 우선 사용한다** — 의미가 이름에 담긴 토큰이 이미 유틸리티로 존재한다.
|
|
208
210
|
|
|
209
|
-
#### 텍스트
|
|
211
|
+
#### 텍스트 회색 위계는 세 단계다
|
|
210
212
|
|
|
211
|
-
|
|
|
212
|
-
| --- | --- | --- |
|
|
213
|
-
|
|
|
214
|
-
| **보조
|
|
213
|
+
| 단계 | 유틸리티 | 값 | 용도 |
|
|
214
|
+
| --- | --- | --- | --- |
|
|
215
|
+
| **기본** | 지정하지 않는다 — 전역 기본색이 이미 적용된다 (`text-fg-primary`) | `grey_95` `#222222` | 본문·제목 |
|
|
216
|
+
| **보조 1** | **`text-fg-secondary`** | `grey_80` `#555555` | 보조 정보 |
|
|
217
|
+
| **보조 2 / 비활성** | **`text-fg-tertiary`** | `grey_65` `#888888` | 부가 설명, 비활성 |
|
|
215
218
|
|
|
219
|
+
- **위계는 순차 적용한다.** 기본 → 보조1 → 보조2 순으로 내려가며 중간 단계를 건너뛰지 않는다. 본문 바로 아래에 곧장 `text-fg-tertiary` 를 쓰지 않는다.
|
|
216
220
|
- `theme.css` 가 `body` 에 `grey_95` 를 깔아두므로 **본문에 텍스트 색 클래스를 붙이지 않는다.** `text-fg-primary` 를 매번 쓰는 것은 불필요하다.
|
|
217
|
-
-
|
|
218
|
-
-
|
|
221
|
+
- 위계가 한 단계면 충분한 보조 설명은 `text-fg-tertiary` 하나로 끝낸다 (§2-1). 두 단계가 필요할 때만 `text-fg-secondary` 를 끼워 넣는다.
|
|
222
|
+
- 비활성 표시는 단계와 무관하게 `text-fg-tertiary` 다.
|
|
219
223
|
|
|
220
224
|
```tsx
|
|
221
225
|
✅ <p>주문이 접수되었습니다.</p> // 색 지정 없음 = grey_95
|
|
222
|
-
✅ <p className="text-fg-tertiary">최근 30일 기준</p> // 보조 설명
|
|
226
|
+
✅ <p className="text-fg-tertiary">최근 30일 기준</p> // 보조 설명 한 단계
|
|
227
|
+
✅ <> // 보조 설명 두 단계
|
|
228
|
+
<p className="text-fg-secondary">배송비 정책</p>
|
|
229
|
+
<p className="text-fg-tertiary">3만원 이상 무료</p>
|
|
230
|
+
</>
|
|
223
231
|
✅ <span className="text-fg-tertiary">-</span> // 빈 값 (§3-4)
|
|
224
232
|
❌ <p className="text-fg-primary">주문이 접수되었습니다.</p> // 불필요
|
|
225
|
-
❌ <p className="text-fg-secondary">최근 30일 기준</p> // 중간 톤 사용
|
|
226
233
|
```
|
|
227
234
|
|
|
228
235
|
#### 그 밖의 색
|
|
@@ -291,7 +298,7 @@ function OrderModal({ orderId, open, onOpenChange, onClose, modalRef }: OrderMod
|
|
|
291
298
|
width={720}
|
|
292
299
|
// 주 액션은 button(단수), 보조 버튼은 footerLeft — 하단 버튼 양끝 분리 규칙과 같다
|
|
293
300
|
button={{ label: '접수', onClick: () => modalRef.ok() }}
|
|
294
|
-
footerLeft={<SButton color="
|
|
301
|
+
footerLeft={<SButton color="neutral" outline label="취소" onClick={() => modalRef.cancel()} />}
|
|
295
302
|
>
|
|
296
303
|
<SKeyValueTable fields={orderFields} values={order} />
|
|
297
304
|
</SActionModal>
|
|
@@ -306,19 +313,26 @@ SModal.create({ component: OrderModal, componentProps: { orderId } })
|
|
|
306
313
|
|
|
307
314
|
### 3-4. 테이블 컬럼 정렬
|
|
308
315
|
|
|
309
|
-
|
|
316
|
+
**값의 크기를 비교하는 숫자 컬럼은 예외 없이 오른쪽 정렬한다** (`align: 'right'`).
|
|
310
317
|
자릿수가 세로로 맞아야 값의 크기를 눈으로 비교할 수 있기 때문이다.
|
|
311
318
|
|
|
312
|
-
|
|
319
|
+
**판별 기준은 "숫자인가"가 아니라 "크기를 비교하는가"다.** 자릿수 차이가 거의 없고 값끼리 대소를 견줄 일이 없으면 숫자로만 이루어져 있어도 우측 정렬하지 않는다.
|
|
320
|
+
|
|
321
|
+
| 값 성격 | 정렬 | 예 |
|
|
313
322
|
| --- | --- | --- |
|
|
314
|
-
| **금액·수량·개수·비율 등
|
|
315
|
-
|
|
|
323
|
+
| **금액·수량·개수·비율 등 양을 나타내는 값** | **`'right'`** | `39,000원` · `12개` · `3건` · `15%` |
|
|
324
|
+
| 코드·식별자 (주문번호, 상품코드, 순번) | **`'center'`** | `RV20250728-000010` · `1024` |
|
|
325
|
+
| 전화번호·사업자번호 | **`'center'`** | `010-1234-5678` |
|
|
326
|
+
| 일자·일시 | **`'center'`** | `2024-10-23` |
|
|
316
327
|
| 텍스트 | 생략(기본 `left`) | 상품명, 카테고리 |
|
|
317
328
|
| 상태 태그·아이콘·체크박스 등 고정폭 요소 | `'center'` | `STag`, `SIcon` |
|
|
318
329
|
|
|
330
|
+
**중앙 정렬은 `align: 'center'` 를 명시한다.** 기본값이 좌측이라 생략하면 중앙이 되지 않는다.
|
|
331
|
+
|
|
319
332
|
```tsx
|
|
320
333
|
const columns: STableColumn[] = [
|
|
321
|
-
{ name: '
|
|
334
|
+
{ name: 'orderNo', label: '주문번호', field: 'orderNo', width: '140px', align: 'center' },
|
|
335
|
+
{ name: 'orderedAt', label: '주문일자', field: 'orderedAt', width: '100px', align: 'center' },
|
|
322
336
|
{ name: 'name', label: '상품명', field: 'name' }, // 텍스트 → 생략
|
|
323
337
|
{ name: 'qty', label: '수량', field: 'qty', width: '80px', align: 'right',
|
|
324
338
|
format: (v: number) => `${Number(v).toLocaleString()}개` },
|
|
@@ -329,8 +343,16 @@ const columns: STableColumn[] = [
|
|
|
329
343
|
];
|
|
330
344
|
```
|
|
331
345
|
|
|
332
|
-
- `format` 으로 단위를 붙이더라도
|
|
333
|
-
- 숫자는 §1-4 대로 **`toLocaleString()` 이 필수**다. 세 자리 콤마 없이 출력하지 않는다.
|
|
346
|
+
- `format` 으로 단위를 붙이더라도 **양을 나타내면 오른쪽 정렬**이다. 단위 때문에 문자열이 되는 것은 정렬 판단과 무관하다.
|
|
347
|
+
- 양을 나타내는 숫자는 §1-4 대로 **`toLocaleString()` 이 필수**다. 세 자리 콤마 없이 출력하지 않는다.
|
|
348
|
+
- **번호·코드에는 세 자리 콤마를 넣지 않는다.** 송장번호 `123456789` 를 `123,456,789` 로 표시하면 값 자체가 달라 보인다.
|
|
349
|
+
- **헤더는 가운데, 셀만 우측**으로 두려면 `align` 이 아니라 `tdClass` 를 쓴다. `align` 은 `<th>` 와 `<td>` 에 함께 적용된다.
|
|
350
|
+
|
|
351
|
+
```tsx
|
|
352
|
+
{ name: 'views', label: '조회수', field: 'views', align: 'center', tdClass: 'text-right!',
|
|
353
|
+
format: (v: number) => Number(v).toLocaleString() },
|
|
354
|
+
```
|
|
355
|
+
|
|
334
356
|
- `SKeyValueTable` 의 값 셀도 같은 기준을 따른다.
|
|
335
357
|
|
|
336
358
|
#### 값이 없는 셀은 회색 하이픈
|
|
@@ -358,13 +380,58 @@ const columns: STableColumn[] = [
|
|
|
358
380
|
|
|
359
381
|
| 상황 | 사용 |
|
|
360
382
|
| --- | --- |
|
|
361
|
-
| 일반 액션 | `SButton` (`color`: `primary` / `secondary` / `neutral` / `danger`, `size`: xs~
|
|
362
|
-
| **삭제 등 파괴적 액션** | **`SButton color="danger"`** 또는 **`color="danger" outline`** |
|
|
383
|
+
| 일반 액션 | `SButton` (`color`: `primary` / `secondary` / `neutral` / `danger`, `outline`, `size`: xs~md) |
|
|
384
|
+
| **삭제 등 파괴적 액션** | **`SButton color="danger"`** 또는 **`color="danger" outline`** (아래 3-5-3) |
|
|
363
385
|
| 텍스트만 있는 저강조 액션 | `SGhostButton` |
|
|
364
386
|
| 본문 속 이동 링크 | `STextLink` |
|
|
365
387
|
| 메인 액션 + 부가 메뉴 | `SDropdownButton` |
|
|
366
388
|
|
|
367
|
-
|
|
389
|
+
#### 3-5-1. 채움 버튼은 페이지당 개수 제한이 있다
|
|
390
|
+
|
|
391
|
+
`outline` 이 위계를 한 단계 낮춘다. **채움(outline 없음)이 그 페이지의 최상위 액션**이다.
|
|
392
|
+
|
|
393
|
+
| 조합 | 위계 | 페이지당 |
|
|
394
|
+
| --- | --- | --- |
|
|
395
|
+
| `color="primary"` (진남색 채움) | 최상위 실행 | **1개** |
|
|
396
|
+
| `color="danger"` (빨강 채움) | 최상위 파괴 | **1개** |
|
|
397
|
+
| `color="secondary"` (밝은 파랑 채움) | 중간 | N개 — **같은 속성 연속 배치 금지** |
|
|
398
|
+
| `primary outline` · `neutral outline` · `neutral`(흰 채움) · `danger outline` | 낮음 | N개 |
|
|
399
|
+
|
|
400
|
+
`SDropdownButton` 도 같은 규칙을 따르며, **페이지당 `primary` 채움 1개 계산에 포함**된다.
|
|
401
|
+
|
|
402
|
+
#### 3-5-2. `size` 는 놓이는 위치가 정한다
|
|
403
|
+
|
|
404
|
+
| 위치 | size |
|
|
405
|
+
| --- | --- |
|
|
406
|
+
| 테이블 **행 내부** 인라인 액션 | `xs` |
|
|
407
|
+
| 화면·목록 액션 (툴바, `STableBar`) | `sm` |
|
|
408
|
+
| **모달·위저드 푸터** | `md` |
|
|
409
|
+
|
|
410
|
+
`lg` 는 현재 사용처가 없다. 페이지 골격에서 쓰지 않는다.
|
|
411
|
+
|
|
412
|
+
#### 3-5-3. 파괴적 액션의 채움 / outline
|
|
413
|
+
|
|
414
|
+
물리적 위치가 아니라 **적용 범위 + 위험도**로 가른다.
|
|
415
|
+
|
|
416
|
+
| 상황 | 스타일 |
|
|
417
|
+
| --- | --- |
|
|
418
|
+
| 대상이 **전체**이거나 기능적 위험도가 높음 (계정 삭제, 전체 초기화) | `color="danger"` **채움** + 다른 버튼과 공간 분리 |
|
|
419
|
+
| **항목별**로 실행되거나 위험도가 상대적으로 낮음 (행 삭제, 연동 해제) | `color="danger" outline` |
|
|
420
|
+
|
|
421
|
+
#### 3-5-4. `SDropdownButton` — `split` 기준
|
|
422
|
+
|
|
423
|
+
| 설정 | 동작 | 쓰는 때 |
|
|
424
|
+
| --- | --- | --- |
|
|
425
|
+
| `split={false}` (기본) | 버튼 전체가 메뉴 토글. 클릭만으로는 실행되지 않는다 | 실행 전에 **범위·옵션을 골라야** 할 때 — `적치 지시서 출력 ▾` → 전체 항목 / 선택 항목만 |
|
|
426
|
+
| `split` | 좌측 = 기본 동작 **즉시 실행**, 우측 `⋯` = 변형 동작 | 기본 동작이 명확하고 **변형·부가 동작**을 곁들일 때 — `저장 \| 저장 후 신규 등록` |
|
|
427
|
+
|
|
428
|
+
메뉴 항목은 **기본 동작의 변형·부가 동작으로 한정**한다. 무관한 액션 여러 개를 한 드롭다운에 묶지 않는다.
|
|
429
|
+
|
|
430
|
+
#### 3-5-5. 그 밖
|
|
431
|
+
|
|
432
|
+
- 라벨은 **동사(+목적어)** — `저장` · `적치 지시` · `송장 재출력`
|
|
433
|
+
- 완료된 작업 버튼은 제거하지 않고 **`disabled` 로 남긴다.** 자리가 사라지면 행 높이가 흔들린다.
|
|
434
|
+
- **모달 보조 액션은 `color="neutral" outline`** 이 표준이다.
|
|
368
435
|
|
|
369
436
|
**하단 버튼 배치 (모든 화면 공통)** — 그룹을 모아 정렬하지 않고 **양끝으로 벌린다**(`justify-between`).
|
|
370
437
|
|
|
@@ -374,10 +441,10 @@ const columns: STableColumn[] = [
|
|
|
374
441
|
|
|
375
442
|
```tsx
|
|
376
443
|
<div className="flex items-center justify-between">
|
|
377
|
-
<SButton color="
|
|
444
|
+
<SButton color="neutral" outline label="취소" /> {/* 되돌리기 = 낮은 위계 */}
|
|
378
445
|
<div className="flex items-center gap-8">
|
|
379
446
|
<SCheckbox label="계속 등록하기" value={keep} onValueChange={setKeep} /> {/* 부가 요소 */}
|
|
380
|
-
<SButton label="저장" />
|
|
447
|
+
<SButton label="저장" /> {/* 페이지 유일한 primary 채움 */}
|
|
381
448
|
</div>
|
|
382
449
|
</div>
|
|
383
450
|
```
|
|
@@ -483,10 +550,14 @@ export default function ProductListPage() {
|
|
|
483
550
|
total={total}
|
|
484
551
|
selected={selected.length}
|
|
485
552
|
actions={
|
|
486
|
-
|
|
553
|
+
/* 선택 항목 단위 파괴 액션 → danger outline (§3-5-3) */
|
|
554
|
+
<SButton size="sm" color="danger" outline label="선택 삭제"
|
|
487
555
|
disabled={!selected.length} onClick={removeSelected} />
|
|
488
556
|
}
|
|
489
|
-
rightActions={
|
|
557
|
+
rightActions={
|
|
558
|
+
/* 이 페이지의 유일한 primary 채움 (§3-5-1) */
|
|
559
|
+
<SButton size="sm" label="상품 등록" onClick={goCreate} />
|
|
560
|
+
}
|
|
490
561
|
/>
|
|
491
562
|
|
|
492
563
|
<STable
|
|
@@ -556,7 +627,7 @@ export default function ProductCreatePage() {
|
|
|
556
627
|
|
|
557
628
|
{/* 하단 버튼은 양끝으로 벌린다. 부가 요소(체크박스 등)는 저장 바로 왼쪽 */}
|
|
558
629
|
<div className="flex items-center justify-between">
|
|
559
|
-
<SButton type="button" color="
|
|
630
|
+
<SButton type="button" color="neutral" outline label="취소" onClick={goBack} />
|
|
560
631
|
<div className="flex items-center gap-8">
|
|
561
632
|
<SCheckbox label="계속 등록하기" value={keepOpen} onValueChange={v => setKeepOpen(v as boolean)} />
|
|
562
633
|
<SButton type="submit" label="저장" />
|
|
@@ -629,7 +700,7 @@ export default function ProductDetailPage() {
|
|
|
629
700
|
|
|
630
701
|
{/* 액션은 하단 — 목록(되돌리기)은 왼쪽 끝, 실행 액션은 오른쪽 끝 */}
|
|
631
702
|
<div className="flex items-center justify-between">
|
|
632
|
-
<SButton color="
|
|
703
|
+
<SButton color="neutral" outline label="목록" onClick={goList} />
|
|
633
704
|
<div className="flex items-center gap-8">
|
|
634
705
|
<SButton color="danger" outline label="삭제" onClick={confirmDelete} />
|
|
635
706
|
<SButton label="수정" onClick={goEdit} />
|
|
@@ -664,7 +735,8 @@ export default function ProductDetailPage() {
|
|
|
664
735
|
- [ ] `text-[14px]`, `bg-[#...]` 같은 리터럴 임의 값이 없는가 (`var(--sys-*)` 참조는 허용)
|
|
665
736
|
- [ ] 텍스트에 `typo-*` 프리셋을 썼는가
|
|
666
737
|
- [ ] 간격이 전부 토큰 스케일 값인가 (`gap-13` ❌ → `gap-12` ✅)
|
|
667
|
-
- [ ] 본문이 12px(`typo-body-sm-default`)
|
|
738
|
+
- [ ] 본문이 12px(`typo-body-sm-default`)인가 (14px 본문 ❌)
|
|
739
|
+
- [ ] 텍스트 회색 위계를 순차 적용했는가 (기본 → `text-fg-secondary` → `text-fg-tertiary`, 단계 건너뛰기 ❌)
|
|
668
740
|
- [ ] 페이지 패딩이 `p-20`, 블록·섹션 간격이 `gap-12` 인가 (`gap-16`/`gap-24` ❌)
|
|
669
741
|
- [ ] 같은 컴포넌트를 나열할 때 §2-2 그룹 간격을 썼는가 (체크박스 가로 `gap-24` 등)
|
|
670
742
|
- [ ] 페이지가 §4의 표준 골격에서 시작했는가
|
|
@@ -672,11 +744,13 @@ export default function ProductDetailPage() {
|
|
|
672
744
|
- [ ] 섹션 구분에 `SSectionHeaderCard` 를 썼는가 (직접 만든 카드가 아니라)
|
|
673
745
|
- [ ] 목록의 주요 액션이 `STableBar` 의 `rightActions` 에 있는가 (페이지 제목 줄이 아니라)
|
|
674
746
|
- [ ] 상태 표시에 `STag size="sm"` 을 썼는가
|
|
675
|
-
- [ ]
|
|
676
|
-
- [ ]
|
|
677
|
-
- [ ] 금액·수량 등 양을 나타내는 숫자에 `toLocaleString()` 을 썼는가 (번호·코드는 제외)
|
|
747
|
+
- [ ] 테이블에서 양을 나타내는 컬럼(금액·수량·개수 등)이 전부 `align: 'right'` 인가
|
|
748
|
+
- [ ] 번호·코드·전화번호·일자 컬럼에 `align: 'center'` 를 **명시**했는가 (생략하면 좌측이 된다)
|
|
749
|
+
- [ ] 금액·수량 등 양을 나타내는 숫자에 빠짐없이 `toLocaleString()` 을 썼는가 (번호·코드는 제외)
|
|
678
750
|
- [ ] 하단 버튼이 양끝 분리(`justify-between`)이고, 되돌리기가 왼쪽 끝 · 실행이 오른쪽 끝인가
|
|
679
|
-
- [ ]
|
|
751
|
+
- [ ] 페이지에 `color="primary"` 채움 버튼이 **1개뿐**인가 (`danger` 채움도 1개, `SDropdownButton` 포함)
|
|
752
|
+
- [ ] 버튼 `size` 가 위치 규칙과 맞는가 (행 내부 `xs` / 화면 액션 `sm` / 모달 푸터 `md`)
|
|
753
|
+
- [ ] 파괴 액션의 채움/outline 이 **적용 범위 + 위험도** 기준과 맞는가
|
|
680
754
|
- [ ] 작업용 모달을 `SActionModal` + `SModal.create` 로 만들었는가 (직접 오버레이 ❌)
|
|
681
755
|
- [ ] 상태 표시·알림·확인 다이얼로그가 §3의 선택 규칙을 따르는가
|
|
682
756
|
|
|
@@ -693,9 +767,8 @@ export default function ProductDetailPage() {
|
|
|
693
767
|
| `sellmate/no-arbitrary-class` | §1-2 토큰 있는 속성의 임의 값 (`text-[14px]`, `bg-[#eee]`) |
|
|
694
768
|
| `sellmate/no-off-scale-spacing` | §2-2 스케일 밖 간격 (`gap-13`) |
|
|
695
769
|
| `sellmate/table-numeric-align` | §3-4 숫자 컬럼의 `align: 'right'` 누락 (`--fix` 지원) |
|
|
696
|
-
| `sellmate/require-locale-number` | §1-4
|
|
770
|
+
| `sellmate/require-locale-number` | §1-4 금액·수량 등 수량 컬럼의 `toLocaleString()` 누락 |
|
|
697
771
|
| `sellmate/component-group-gap` | §2-2 컴포넌트 그룹 간격 (체크박스 가로 24 / 세로 8 등) |
|
|
698
|
-
| `sellmate/require-locale-number` | §1-4 금액·수량 등의 `toLocaleString()` 누락 |
|
|
699
772
|
| `sellmate/prefer-typo-preset` | §1-3 낱개 폰트 조합 (`text-14 font-bold`) |
|
|
700
773
|
|
|
701
774
|
`gap-13` 처럼 스케일 밖 값은 Tailwind v4 에서 **에러 없이 조용히 무시된다**. "간격이 왜 안 먹지" 로만 보이므로 반드시 스케일 값을 쓴다.
|
|
@@ -884,6 +957,7 @@ Tailwind 유틸리티는 아래 스케일에 있는 값만 사용한다. 리터
|
|
|
884
957
|
| `open?` | `boolean` | — | |
|
|
885
958
|
| `persistent?` | `boolean` | — | true면 백드롭·ESC로 안 닫히고 흔들림 (sd-modal-container persistent) |
|
|
886
959
|
| `modalTitle?` | `string` | `''` | |
|
|
960
|
+
| `description?` | `ReactNode` | — | 제목 오른쪽에 붙는 보조 설명 (sd-action-modal 의 header-sub-title 슬롯). 문자열이면 서브텍스트 스타일로 렌더하고, 노드를 넘기면 그대로 배치한다. |
|
|
887
961
|
| `button?` | `SActionModalButton` | — | 하단 액션 버튼 (주 액션 1개). 의도적으로 단수다 — 보조 버튼(취소·삭제 등)은 `footerLeft` 슬롯에 직접 배치한다. |
|
|
888
962
|
| `footerLeft?` | `ReactNode` | — | footer 좌측 영역 (sd-action-modal 의 bottom-sub-content 슬롯). 보조 버튼이나 안내 문구를 넣는다. 버튼을 하나 더 쓰고 싶을 때 여기에 SButton 을 넣는다. |
|
|
889
963
|
| `width?` | `number \| string` | — | |
|
|
@@ -924,7 +998,7 @@ Tailwind 유틸리티는 아래 스케일에 있는 값만 사용한다. 리터
|
|
|
924
998
|
|
|
925
999
|
### Used by
|
|
926
1000
|
|
|
927
|
-
- [
|
|
1001
|
+
- [SSectionHeaderCard](../SSectionHeaderCard)
|
|
928
1002
|
|
|
929
1003
|
### Graph
|
|
930
1004
|
|
|
@@ -1955,7 +2029,6 @@ Tailwind 유틸리티는 아래 스케일에 있는 값만 사용한다. 리터
|
|
|
1955
2029
|
- [SGnb](../SGnb)
|
|
1956
2030
|
- [SGuide](../SGuide)
|
|
1957
2031
|
- [SKeyValueTable](../SKeyValueTable)
|
|
1958
|
-
- [SList](../SList)
|
|
1959
2032
|
- [SLoadingModal](../SLoadingModal)
|
|
1960
2033
|
- [SNumberInput](../SNumberInput)
|
|
1961
2034
|
- [SPagination](../SPagination)
|
|
@@ -3520,7 +3593,7 @@ function OrderModal({ open, onOpenChange, onClose, modalRef, orderId }: OrderMod
|
|
|
3520
3593
|
|
|
3521
3594
|
- [SField](../SField)
|
|
3522
3595
|
- [SKeyValueTable](../SKeyValueTable)
|
|
3523
|
-
- [
|
|
3596
|
+
- [SSectionHeaderCard](../SSectionHeaderCard)
|
|
3524
3597
|
|
|
3525
3598
|
### Depends on
|
|
3526
3599
|
|
package/dist/llms.txt
CHANGED
|
@@ -127,7 +127,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
127
127
|
|
|
128
128
|
콤마 없는 `39000` 은 자릿수를 세어야 읽히지만 `39,000` 은 한눈에 읽힌다. 숫자를 그대로 출력하는 코드는 미완성으로 본다.
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
**번호·코드는 제외한다.** 전화번호·사업자번호·송장번호·상품코드처럼 대상을 가리키는 값은 크기를 비교하는 숫자가 아니라 **서식이 정해진 문자열**이다. 여기에 콤마를 넣으면 송장번호 `123456789` 가 `123,456,789` 로 보여 값 자체가 달라진다.
|
|
131
131
|
|
|
132
132
|
---
|
|
133
133
|
|
|
@@ -155,6 +155,8 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
155
155
|
|
|
156
156
|
페이지 제목만 18px 로 크게 두고 그 아래는 14 / 12 로 촘촘하게 간다. 중간 크기(16px)는 기본 골격에서 쓰지 않는다.
|
|
157
157
|
|
|
158
|
+
**보조 설명의 색** — 기본은 `text-fg-tertiary`(`grey_65`) 다. 보조 설명 안에서 위계가 한 단계 더 필요할 때만 `text-fg-secondary`(`grey_80`) → `text-fg-tertiary`(`grey_65`) 순으로 내려 쓴다 (§2-3).
|
|
159
|
+
|
|
158
160
|
### 2-2. 간격 (spacing)
|
|
159
161
|
|
|
160
162
|
- 유틸리티 숫자 = px. 스케일: `2 4 6 8 10 12 16 19 20 22 24 28 32 36 40 48 60`
|
|
@@ -166,8 +168,8 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
166
168
|
| **페이지 콘텐츠 패딩** | **`p-20`** |
|
|
167
169
|
| **섹션 ↔ 섹션** | **`gap-12`** |
|
|
168
170
|
| **페이지 내 블록 ↔ 블록** (헤더·필터·툴바·테이블 사이) | **`gap-12`** |
|
|
169
|
-
| 요소 ↔ 요소
|
|
170
|
-
| 제목 ↔ 설명 텍스트 | `gap-4
|
|
171
|
+
| 요소 ↔ 요소 | **기본 `gap-8`** (`--sys-space-stack-gap-element-normal`) · 타이트 `gap-4`(`-tight`) · 여유 `gap-12`(`-relaxed`) / `gap-16`(`-wide`) |
|
|
172
|
+
| 제목 ↔ 설명 텍스트 | **수직 배치 `gap-4`**(`--sys-space-stack-gap-text-normal`, 타이트 `gap-2`) · **가로 배치 `gap-8`**(`-relaxed`) |
|
|
171
173
|
|
|
172
174
|
정보 밀도가 높은 서비스라 블록 간격을 넓게 벌리지 않는다. `gap-16` / `gap-24` 를 페이지 골격의 기본값으로 쓰지 않는다.
|
|
173
175
|
|
|
@@ -207,23 +209,28 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
207
209
|
|
|
208
210
|
**시맨틱 유틸리티를 우선 사용한다** — 의미가 이름에 담긴 토큰이 이미 유틸리티로 존재한다.
|
|
209
211
|
|
|
210
|
-
#### 텍스트
|
|
212
|
+
#### 텍스트 회색 위계는 세 단계다
|
|
211
213
|
|
|
212
|
-
|
|
|
213
|
-
| --- | --- | --- |
|
|
214
|
-
|
|
|
215
|
-
| **보조
|
|
214
|
+
| 단계 | 유틸리티 | 값 | 용도 |
|
|
215
|
+
| --- | --- | --- | --- |
|
|
216
|
+
| **기본** | 지정하지 않는다 — 전역 기본색이 이미 적용된다 (`text-fg-primary`) | `grey_95` `#222222` | 본문·제목 |
|
|
217
|
+
| **보조 1** | **`text-fg-secondary`** | `grey_80` `#555555` | 보조 정보 |
|
|
218
|
+
| **보조 2 / 비활성** | **`text-fg-tertiary`** | `grey_65` `#888888` | 부가 설명, 비활성 |
|
|
216
219
|
|
|
220
|
+
- **위계는 순차 적용한다.** 기본 → 보조1 → 보조2 순으로 내려가며 중간 단계를 건너뛰지 않는다. 본문 바로 아래에 곧장 `text-fg-tertiary` 를 쓰지 않는다.
|
|
217
221
|
- `theme.css` 가 `body` 에 `grey_95` 를 깔아두므로 **본문에 텍스트 색 클래스를 붙이지 않는다.** `text-fg-primary` 를 매번 쓰는 것은 불필요하다.
|
|
218
|
-
-
|
|
219
|
-
-
|
|
222
|
+
- 위계가 한 단계면 충분한 보조 설명은 `text-fg-tertiary` 하나로 끝낸다 (§2-1). 두 단계가 필요할 때만 `text-fg-secondary` 를 끼워 넣는다.
|
|
223
|
+
- 비활성 표시는 단계와 무관하게 `text-fg-tertiary` 다.
|
|
220
224
|
|
|
221
225
|
```tsx
|
|
222
226
|
✅ <p>주문이 접수되었습니다.</p> // 색 지정 없음 = grey_95
|
|
223
|
-
✅ <p className="text-fg-tertiary">최근 30일 기준</p> // 보조 설명
|
|
227
|
+
✅ <p className="text-fg-tertiary">최근 30일 기준</p> // 보조 설명 한 단계
|
|
228
|
+
✅ <> // 보조 설명 두 단계
|
|
229
|
+
<p className="text-fg-secondary">배송비 정책</p>
|
|
230
|
+
<p className="text-fg-tertiary">3만원 이상 무료</p>
|
|
231
|
+
</>
|
|
224
232
|
✅ <span className="text-fg-tertiary">-</span> // 빈 값 (§3-4)
|
|
225
233
|
❌ <p className="text-fg-primary">주문이 접수되었습니다.</p> // 불필요
|
|
226
|
-
❌ <p className="text-fg-secondary">최근 30일 기준</p> // 중간 톤 사용
|
|
227
234
|
```
|
|
228
235
|
|
|
229
236
|
#### 그 밖의 색
|
|
@@ -292,7 +299,7 @@ function OrderModal({ orderId, open, onOpenChange, onClose, modalRef }: OrderMod
|
|
|
292
299
|
width={720}
|
|
293
300
|
// 주 액션은 button(단수), 보조 버튼은 footerLeft — 하단 버튼 양끝 분리 규칙과 같다
|
|
294
301
|
button={{ label: '접수', onClick: () => modalRef.ok() }}
|
|
295
|
-
footerLeft={<SButton color="
|
|
302
|
+
footerLeft={<SButton color="neutral" outline label="취소" onClick={() => modalRef.cancel()} />}
|
|
296
303
|
>
|
|
297
304
|
<SKeyValueTable fields={orderFields} values={order} />
|
|
298
305
|
</SActionModal>
|
|
@@ -307,19 +314,26 @@ SModal.create({ component: OrderModal, componentProps: { orderId } })
|
|
|
307
314
|
|
|
308
315
|
### 3-4. 테이블 컬럼 정렬
|
|
309
316
|
|
|
310
|
-
|
|
317
|
+
**값의 크기를 비교하는 숫자 컬럼은 예외 없이 오른쪽 정렬한다** (`align: 'right'`).
|
|
311
318
|
자릿수가 세로로 맞아야 값의 크기를 눈으로 비교할 수 있기 때문이다.
|
|
312
319
|
|
|
313
|
-
|
|
320
|
+
**판별 기준은 "숫자인가"가 아니라 "크기를 비교하는가"다.** 자릿수 차이가 거의 없고 값끼리 대소를 견줄 일이 없으면 숫자로만 이루어져 있어도 우측 정렬하지 않는다.
|
|
321
|
+
|
|
322
|
+
| 값 성격 | 정렬 | 예 |
|
|
314
323
|
| --- | --- | --- |
|
|
315
|
-
| **금액·수량·개수·비율 등
|
|
316
|
-
|
|
|
324
|
+
| **금액·수량·개수·비율 등 양을 나타내는 값** | **`'right'`** | `39,000원` · `12개` · `3건` · `15%` |
|
|
325
|
+
| 코드·식별자 (주문번호, 상품코드, 순번) | **`'center'`** | `RV20250728-000010` · `1024` |
|
|
326
|
+
| 전화번호·사업자번호 | **`'center'`** | `010-1234-5678` |
|
|
327
|
+
| 일자·일시 | **`'center'`** | `2024-10-23` |
|
|
317
328
|
| 텍스트 | 생략(기본 `left`) | 상품명, 카테고리 |
|
|
318
329
|
| 상태 태그·아이콘·체크박스 등 고정폭 요소 | `'center'` | `STag`, `SIcon` |
|
|
319
330
|
|
|
331
|
+
**중앙 정렬은 `align: 'center'` 를 명시한다.** 기본값이 좌측이라 생략하면 중앙이 되지 않는다.
|
|
332
|
+
|
|
320
333
|
```tsx
|
|
321
334
|
const columns: STableColumn[] = [
|
|
322
|
-
{ name: '
|
|
335
|
+
{ name: 'orderNo', label: '주문번호', field: 'orderNo', width: '140px', align: 'center' },
|
|
336
|
+
{ name: 'orderedAt', label: '주문일자', field: 'orderedAt', width: '100px', align: 'center' },
|
|
323
337
|
{ name: 'name', label: '상품명', field: 'name' }, // 텍스트 → 생략
|
|
324
338
|
{ name: 'qty', label: '수량', field: 'qty', width: '80px', align: 'right',
|
|
325
339
|
format: (v: number) => `${Number(v).toLocaleString()}개` },
|
|
@@ -330,8 +344,16 @@ const columns: STableColumn[] = [
|
|
|
330
344
|
];
|
|
331
345
|
```
|
|
332
346
|
|
|
333
|
-
- `format` 으로 단위를 붙이더라도
|
|
334
|
-
- 숫자는 §1-4 대로 **`toLocaleString()` 이 필수**다. 세 자리 콤마 없이 출력하지 않는다.
|
|
347
|
+
- `format` 으로 단위를 붙이더라도 **양을 나타내면 오른쪽 정렬**이다. 단위 때문에 문자열이 되는 것은 정렬 판단과 무관하다.
|
|
348
|
+
- 양을 나타내는 숫자는 §1-4 대로 **`toLocaleString()` 이 필수**다. 세 자리 콤마 없이 출력하지 않는다.
|
|
349
|
+
- **번호·코드에는 세 자리 콤마를 넣지 않는다.** 송장번호 `123456789` 를 `123,456,789` 로 표시하면 값 자체가 달라 보인다.
|
|
350
|
+
- **헤더는 가운데, 셀만 우측**으로 두려면 `align` 이 아니라 `tdClass` 를 쓴다. `align` 은 `<th>` 와 `<td>` 에 함께 적용된다.
|
|
351
|
+
|
|
352
|
+
```tsx
|
|
353
|
+
{ name: 'views', label: '조회수', field: 'views', align: 'center', tdClass: 'text-right!',
|
|
354
|
+
format: (v: number) => Number(v).toLocaleString() },
|
|
355
|
+
```
|
|
356
|
+
|
|
335
357
|
- `SKeyValueTable` 의 값 셀도 같은 기준을 따른다.
|
|
336
358
|
|
|
337
359
|
#### 값이 없는 셀은 회색 하이픈
|
|
@@ -359,13 +381,58 @@ const columns: STableColumn[] = [
|
|
|
359
381
|
|
|
360
382
|
| 상황 | 사용 |
|
|
361
383
|
| --- | --- |
|
|
362
|
-
| 일반 액션 | `SButton` (`color`: `primary` / `secondary` / `neutral` / `danger`, `size`: xs~
|
|
363
|
-
| **삭제 등 파괴적 액션** | **`SButton color="danger"`** 또는 **`color="danger" outline`** |
|
|
384
|
+
| 일반 액션 | `SButton` (`color`: `primary` / `secondary` / `neutral` / `danger`, `outline`, `size`: xs~md) |
|
|
385
|
+
| **삭제 등 파괴적 액션** | **`SButton color="danger"`** 또는 **`color="danger" outline`** (아래 3-5-3) |
|
|
364
386
|
| 텍스트만 있는 저강조 액션 | `SGhostButton` |
|
|
365
387
|
| 본문 속 이동 링크 | `STextLink` |
|
|
366
388
|
| 메인 액션 + 부가 메뉴 | `SDropdownButton` |
|
|
367
389
|
|
|
368
|
-
|
|
390
|
+
#### 3-5-1. 채움 버튼은 페이지당 개수 제한이 있다
|
|
391
|
+
|
|
392
|
+
`outline` 이 위계를 한 단계 낮춘다. **채움(outline 없음)이 그 페이지의 최상위 액션**이다.
|
|
393
|
+
|
|
394
|
+
| 조합 | 위계 | 페이지당 |
|
|
395
|
+
| --- | --- | --- |
|
|
396
|
+
| `color="primary"` (진남색 채움) | 최상위 실행 | **1개** |
|
|
397
|
+
| `color="danger"` (빨강 채움) | 최상위 파괴 | **1개** |
|
|
398
|
+
| `color="secondary"` (밝은 파랑 채움) | 중간 | N개 — **같은 속성 연속 배치 금지** |
|
|
399
|
+
| `primary outline` · `neutral outline` · `neutral`(흰 채움) · `danger outline` | 낮음 | N개 |
|
|
400
|
+
|
|
401
|
+
`SDropdownButton` 도 같은 규칙을 따르며, **페이지당 `primary` 채움 1개 계산에 포함**된다.
|
|
402
|
+
|
|
403
|
+
#### 3-5-2. `size` 는 놓이는 위치가 정한다
|
|
404
|
+
|
|
405
|
+
| 위치 | size |
|
|
406
|
+
| --- | --- |
|
|
407
|
+
| 테이블 **행 내부** 인라인 액션 | `xs` |
|
|
408
|
+
| 화면·목록 액션 (툴바, `STableBar`) | `sm` |
|
|
409
|
+
| **모달·위저드 푸터** | `md` |
|
|
410
|
+
|
|
411
|
+
`lg` 는 현재 사용처가 없다. 페이지 골격에서 쓰지 않는다.
|
|
412
|
+
|
|
413
|
+
#### 3-5-3. 파괴적 액션의 채움 / outline
|
|
414
|
+
|
|
415
|
+
물리적 위치가 아니라 **적용 범위 + 위험도**로 가른다.
|
|
416
|
+
|
|
417
|
+
| 상황 | 스타일 |
|
|
418
|
+
| --- | --- |
|
|
419
|
+
| 대상이 **전체**이거나 기능적 위험도가 높음 (계정 삭제, 전체 초기화) | `color="danger"` **채움** + 다른 버튼과 공간 분리 |
|
|
420
|
+
| **항목별**로 실행되거나 위험도가 상대적으로 낮음 (행 삭제, 연동 해제) | `color="danger" outline` |
|
|
421
|
+
|
|
422
|
+
#### 3-5-4. `SDropdownButton` — `split` 기준
|
|
423
|
+
|
|
424
|
+
| 설정 | 동작 | 쓰는 때 |
|
|
425
|
+
| --- | --- | --- |
|
|
426
|
+
| `split={false}` (기본) | 버튼 전체가 메뉴 토글. 클릭만으로는 실행되지 않는다 | 실행 전에 **범위·옵션을 골라야** 할 때 — `적치 지시서 출력 ▾` → 전체 항목 / 선택 항목만 |
|
|
427
|
+
| `split` | 좌측 = 기본 동작 **즉시 실행**, 우측 `⋯` = 변형 동작 | 기본 동작이 명확하고 **변형·부가 동작**을 곁들일 때 — `저장 \| 저장 후 신규 등록` |
|
|
428
|
+
|
|
429
|
+
메뉴 항목은 **기본 동작의 변형·부가 동작으로 한정**한다. 무관한 액션 여러 개를 한 드롭다운에 묶지 않는다.
|
|
430
|
+
|
|
431
|
+
#### 3-5-5. 그 밖
|
|
432
|
+
|
|
433
|
+
- 라벨은 **동사(+목적어)** — `저장` · `적치 지시` · `송장 재출력`
|
|
434
|
+
- 완료된 작업 버튼은 제거하지 않고 **`disabled` 로 남긴다.** 자리가 사라지면 행 높이가 흔들린다.
|
|
435
|
+
- **모달 보조 액션은 `color="neutral" outline`** 이 표준이다.
|
|
369
436
|
|
|
370
437
|
**하단 버튼 배치 (모든 화면 공통)** — 그룹을 모아 정렬하지 않고 **양끝으로 벌린다**(`justify-between`).
|
|
371
438
|
|
|
@@ -375,10 +442,10 @@ const columns: STableColumn[] = [
|
|
|
375
442
|
|
|
376
443
|
```tsx
|
|
377
444
|
<div className="flex items-center justify-between">
|
|
378
|
-
<SButton color="
|
|
445
|
+
<SButton color="neutral" outline label="취소" /> {/* 되돌리기 = 낮은 위계 */}
|
|
379
446
|
<div className="flex items-center gap-8">
|
|
380
447
|
<SCheckbox label="계속 등록하기" value={keep} onValueChange={setKeep} /> {/* 부가 요소 */}
|
|
381
|
-
<SButton label="저장" />
|
|
448
|
+
<SButton label="저장" /> {/* 페이지 유일한 primary 채움 */}
|
|
382
449
|
</div>
|
|
383
450
|
</div>
|
|
384
451
|
```
|
|
@@ -484,10 +551,14 @@ export default function ProductListPage() {
|
|
|
484
551
|
total={total}
|
|
485
552
|
selected={selected.length}
|
|
486
553
|
actions={
|
|
487
|
-
|
|
554
|
+
/* 선택 항목 단위 파괴 액션 → danger outline (§3-5-3) */
|
|
555
|
+
<SButton size="sm" color="danger" outline label="선택 삭제"
|
|
488
556
|
disabled={!selected.length} onClick={removeSelected} />
|
|
489
557
|
}
|
|
490
|
-
rightActions={
|
|
558
|
+
rightActions={
|
|
559
|
+
/* 이 페이지의 유일한 primary 채움 (§3-5-1) */
|
|
560
|
+
<SButton size="sm" label="상품 등록" onClick={goCreate} />
|
|
561
|
+
}
|
|
491
562
|
/>
|
|
492
563
|
|
|
493
564
|
<STable
|
|
@@ -557,7 +628,7 @@ export default function ProductCreatePage() {
|
|
|
557
628
|
|
|
558
629
|
{/* 하단 버튼은 양끝으로 벌린다. 부가 요소(체크박스 등)는 저장 바로 왼쪽 */}
|
|
559
630
|
<div className="flex items-center justify-between">
|
|
560
|
-
<SButton type="button" color="
|
|
631
|
+
<SButton type="button" color="neutral" outline label="취소" onClick={goBack} />
|
|
561
632
|
<div className="flex items-center gap-8">
|
|
562
633
|
<SCheckbox label="계속 등록하기" value={keepOpen} onValueChange={v => setKeepOpen(v as boolean)} />
|
|
563
634
|
<SButton type="submit" label="저장" />
|
|
@@ -630,7 +701,7 @@ export default function ProductDetailPage() {
|
|
|
630
701
|
|
|
631
702
|
{/* 액션은 하단 — 목록(되돌리기)은 왼쪽 끝, 실행 액션은 오른쪽 끝 */}
|
|
632
703
|
<div className="flex items-center justify-between">
|
|
633
|
-
<SButton color="
|
|
704
|
+
<SButton color="neutral" outline label="목록" onClick={goList} />
|
|
634
705
|
<div className="flex items-center gap-8">
|
|
635
706
|
<SButton color="danger" outline label="삭제" onClick={confirmDelete} />
|
|
636
707
|
<SButton label="수정" onClick={goEdit} />
|
|
@@ -665,7 +736,8 @@ export default function ProductDetailPage() {
|
|
|
665
736
|
- [ ] `text-[14px]`, `bg-[#...]` 같은 리터럴 임의 값이 없는가 (`var(--sys-*)` 참조는 허용)
|
|
666
737
|
- [ ] 텍스트에 `typo-*` 프리셋을 썼는가
|
|
667
738
|
- [ ] 간격이 전부 토큰 스케일 값인가 (`gap-13` ❌ → `gap-12` ✅)
|
|
668
|
-
- [ ] 본문이 12px(`typo-body-sm-default`)
|
|
739
|
+
- [ ] 본문이 12px(`typo-body-sm-default`)인가 (14px 본문 ❌)
|
|
740
|
+
- [ ] 텍스트 회색 위계를 순차 적용했는가 (기본 → `text-fg-secondary` → `text-fg-tertiary`, 단계 건너뛰기 ❌)
|
|
669
741
|
- [ ] 페이지 패딩이 `p-20`, 블록·섹션 간격이 `gap-12` 인가 (`gap-16`/`gap-24` ❌)
|
|
670
742
|
- [ ] 같은 컴포넌트를 나열할 때 §2-2 그룹 간격을 썼는가 (체크박스 가로 `gap-24` 등)
|
|
671
743
|
- [ ] 페이지가 §4의 표준 골격에서 시작했는가
|
|
@@ -673,11 +745,13 @@ export default function ProductDetailPage() {
|
|
|
673
745
|
- [ ] 섹션 구분에 `SSectionHeaderCard` 를 썼는가 (직접 만든 카드가 아니라)
|
|
674
746
|
- [ ] 목록의 주요 액션이 `STableBar` 의 `rightActions` 에 있는가 (페이지 제목 줄이 아니라)
|
|
675
747
|
- [ ] 상태 표시에 `STag size="sm"` 을 썼는가
|
|
676
|
-
- [ ]
|
|
677
|
-
- [ ]
|
|
678
|
-
- [ ] 금액·수량 등 양을 나타내는 숫자에 `toLocaleString()` 을 썼는가 (번호·코드는 제외)
|
|
748
|
+
- [ ] 테이블에서 양을 나타내는 컬럼(금액·수량·개수 등)이 전부 `align: 'right'` 인가
|
|
749
|
+
- [ ] 번호·코드·전화번호·일자 컬럼에 `align: 'center'` 를 **명시**했는가 (생략하면 좌측이 된다)
|
|
750
|
+
- [ ] 금액·수량 등 양을 나타내는 숫자에 빠짐없이 `toLocaleString()` 을 썼는가 (번호·코드는 제외)
|
|
679
751
|
- [ ] 하단 버튼이 양끝 분리(`justify-between`)이고, 되돌리기가 왼쪽 끝 · 실행이 오른쪽 끝인가
|
|
680
|
-
- [ ]
|
|
752
|
+
- [ ] 페이지에 `color="primary"` 채움 버튼이 **1개뿐**인가 (`danger` 채움도 1개, `SDropdownButton` 포함)
|
|
753
|
+
- [ ] 버튼 `size` 가 위치 규칙과 맞는가 (행 내부 `xs` / 화면 액션 `sm` / 모달 푸터 `md`)
|
|
754
|
+
- [ ] 파괴 액션의 채움/outline 이 **적용 범위 + 위험도** 기준과 맞는가
|
|
681
755
|
- [ ] 작업용 모달을 `SActionModal` + `SModal.create` 로 만들었는가 (직접 오버레이 ❌)
|
|
682
756
|
- [ ] 상태 표시·알림·확인 다이얼로그가 §3의 선택 규칙을 따르는가
|
|
683
757
|
|
|
@@ -694,9 +768,8 @@ export default function ProductDetailPage() {
|
|
|
694
768
|
| `sellmate/no-arbitrary-class` | §1-2 토큰 있는 속성의 임의 값 (`text-[14px]`, `bg-[#eee]`) |
|
|
695
769
|
| `sellmate/no-off-scale-spacing` | §2-2 스케일 밖 간격 (`gap-13`) |
|
|
696
770
|
| `sellmate/table-numeric-align` | §3-4 숫자 컬럼의 `align: 'right'` 누락 (`--fix` 지원) |
|
|
697
|
-
| `sellmate/require-locale-number` | §1-4
|
|
771
|
+
| `sellmate/require-locale-number` | §1-4 금액·수량 등 수량 컬럼의 `toLocaleString()` 누락 |
|
|
698
772
|
| `sellmate/component-group-gap` | §2-2 컴포넌트 그룹 간격 (체크박스 가로 24 / 세로 8 등) |
|
|
699
|
-
| `sellmate/require-locale-number` | §1-4 금액·수량 등의 `toLocaleString()` 누락 |
|
|
700
773
|
| `sellmate/prefer-typo-preset` | §1-3 낱개 폰트 조합 (`text-14 font-bold`) |
|
|
701
774
|
|
|
702
775
|
`gap-13` 처럼 스케일 밖 값은 Tailwind v4 에서 **에러 없이 조용히 무시된다**. "간격이 왜 안 먹지" 로만 보이므로 반드시 스케일 값을 쓴다.
|