@t3q-ui/design-system 1.57.0 → 1.58.0

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.
@@ -269,10 +269,10 @@ export function ModelDetailPage({ fetchModel }: { fetchModel: () => Promise<Mode
269
269
  <Table>
270
270
  <TableHeader>
271
271
  <TableRow>
272
+ {/* 열 순서는 이름 → 상태 → 숫자 → 날짜(같은 화면의 표끼리 같게). 짧은 열은 폭을 준다 — 폭 없는 열은 남는 폭을 똑같이 나눠 상태 열이 비어 보인다(table-fixed) */}
272
273
  <TableHead>엔드포인트</TableHead>
273
- <TableHead align='right'>레플리카</TableHead>
274
- {/* 짧은 열은 폭을 준다 — 폭 없는 열은 남는 폭을 똑같이 나눠 상태 열이 비어 보인다(table-fixed) */}
275
274
  <TableHead className='w-32'>상태</TableHead>
275
+ <TableHead align='right'>레플리카</TableHead>
276
276
  <TableHead className='w-44'>갱신일</TableHead>
277
277
  </TableRow>
278
278
  </TableHeader>
@@ -280,13 +280,13 @@ export function ModelDetailPage({ fetchModel }: { fetchModel: () => Promise<Mode
280
280
  {data.deployments.slice(0, 3).map((d) => (
281
281
  <TableRow key={d.id}>
282
282
  <TableCell>{d.endpoint}</TableCell>
283
- <TableCell align='right'>{d.replicas}</TableCell>
284
283
  <TableCell>
285
284
  <Badge variant={DEPLOY_STATUS[d.status].variant}>
286
285
  {DEPLOY_STATUS[d.status].icon}
287
286
  {DEPLOY_STATUS[d.status].label}
288
287
  </Badge>
289
288
  </TableCell>
289
+ <TableCell align='right'>{d.replicas}</TableCell>
290
290
  <TableCell>{d.updatedAt}</TableCell>
291
291
  </TableRow>
292
292
  ))}
@@ -305,24 +305,24 @@ export function ModelDetailPage({ fetchModel }: { fetchModel: () => Promise<Mode
305
305
  <TableHeader>
306
306
  <TableRow>
307
307
  <TableHead>버전</TableHead>
308
- <TableHead>정확도</TableHead>
309
- <TableHead>크기</TableHead>
310
- <TableHead>상태</TableHead>
311
- <TableHead>등록일</TableHead>
308
+ <TableHead className='w-32'>상태</TableHead>
309
+ <TableHead align='right'>정확도</TableHead>
310
+ <TableHead align='right'>크기</TableHead>
311
+ <TableHead className='w-44'>등록일</TableHead>
312
312
  </TableRow>
313
313
  </TableHeader>
314
314
  <TableBody>
315
315
  {data.versions.map((v) => (
316
316
  <TableRow key={v.version}>
317
317
  <TableCell>{v.version}</TableCell>
318
- <TableCell>{(v.accuracy * 100).toFixed(1)}%</TableCell>
319
- <TableCell>{v.sizeMb.toLocaleString()} MB</TableCell>
320
318
  <TableCell>
321
319
  <Badge variant={STATUS[v.status].variant}>
322
320
  {STATUS[v.status].icon}
323
321
  {STATUS[v.status].label}
324
322
  </Badge>
325
323
  </TableCell>
324
+ <TableCell align='right'>{(v.accuracy * 100).toFixed(1)}%</TableCell>
325
+ <TableCell align='right'>{v.sizeMb.toLocaleString()} MB</TableCell>
326
326
  <TableCell>{v.createdAt}</TableCell>
327
327
  </TableRow>
328
328
  ))}
@@ -334,22 +334,22 @@ export function ModelDetailPage({ fetchModel }: { fetchModel: () => Promise<Mode
334
334
  <TableHeader>
335
335
  <TableRow>
336
336
  <TableHead>엔드포인트</TableHead>
337
- <TableHead>레플리카</TableHead>
338
- <TableHead>상태</TableHead>
339
- <TableHead>갱신일</TableHead>
337
+ <TableHead className='w-32'>상태</TableHead>
338
+ <TableHead align='right'>레플리카</TableHead>
339
+ <TableHead className='w-44'>갱신일</TableHead>
340
340
  </TableRow>
341
341
  </TableHeader>
342
342
  <TableBody>
343
343
  {data.deployments.map((d) => (
344
344
  <TableRow key={d.id}>
345
345
  <TableCell>{d.endpoint}</TableCell>
346
- <TableCell>{d.replicas}</TableCell>
347
346
  <TableCell>
348
347
  <Badge variant={DEPLOY_STATUS[d.status].variant}>
349
348
  {DEPLOY_STATUS[d.status].icon}
350
349
  {DEPLOY_STATUS[d.status].label}
351
350
  </Badge>
352
351
  </TableCell>
352
+ <TableCell align='right'>{d.replicas}</TableCell>
353
353
  <TableCell>{d.updatedAt}</TableCell>
354
354
  </TableRow>
355
355
  ))}
@@ -22,7 +22,7 @@
22
22
  * - 열 폭: 이름 열 `flex: 2, minWidth: 200, maxWidth: 480`, 글자가 들어가는 열은 **모두** `flex: 1, minWidth: 120`(여기서는 소유자 하나지만 팀·프레임워크·설명이 있으면 전부) — 남는 폭이 여러 열로 흩어져야 이름 열만 넓어지지 않는다(2026-10-20 17차·18차). 글자 열이 하나도 없으면 maxWidth 를 뺀다(표 오른쪽이 빈다). 숫자·날짜·상태·진행률 열은 `width`(제목이 들어가는 최소 폭은 표가 보정하고 넘치는 글자는 말줄임표).
23
23
  * 보조 정보(이미지·id·경로)는 열을 늘리지 않고 `secondaryField` 로 이름 아래 줄에 — 열이 6~7개를 넘으면 잘린다
24
24
  * - 빠른 필터의 건수 뱃지는 표의 상태 뱃지와 같은 색(`countVariant: STATUS[s].tone`)
25
- * - 목 데이터는 소비 앱(App.tsx)이 `fetchEnvs` 로 넘긴다 — **20행 이상**(페이지 크기 20 이면 두 페이지). 10행이면 표 아래가 비어 보인다
25
+ * - 목 데이터는 소비 앱(App.tsx)이 `fetchEnvs` 로 넘긴다 — **20행 이상**(한 페이지 10행이면 두세 페이지). 데이터가 10행뿐이면 표 아래가 비어 보이고, 한 페이지가 20행이면 첫 화면에서 페이지네이션이 잘린다
26
26
  */
27
27
  import { type ReactNode, useEffect, useMemo, useState } from 'react'
28
28
  import {
@@ -77,7 +77,8 @@ const STATUS_OPTIONS = (Object.keys(STATUS) as Status[]).map((s) => ({
77
77
  value: s,
78
78
  label: STATUS[s].label,
79
79
  }))
80
- const PAGE_SIZE = 20
80
+ // 한 페이지 10행 — 첫 화면(1440×1000)에 표와 페이지네이션이 함께 들어간다. 데이터는 20행 이상(두 페이지 분량, 2026-11-06)
81
+ const PAGE_SIZE = 10
81
82
 
82
83
  // 남는 폭은 이름 열(flex 2, 상한 480)과 글자 열 전부(flex 1)가 나눈다 — 글자 열이 하나뿐이면 2:1 로 나눠도 이름 열이 500px 라 비어 보인다(2026-10-20 17차·18차).
83
84
  // maxWidth 를 주면 넓은 화면에서 표 오른쪽이 빈다. 이미지는 열이 아니라 이름 아래 보조 줄(ListPage secondaryField='image')
@@ -385,6 +385,7 @@ const WithoutIcon = () => (
385
385
 
386
386
  언제 쓰나: 실행 중/중지/오류 같은 상태(`success`·`danger`·`warning`·`info`), 개수·등급 표시. 의미 variant 를 쓰고 색을 직접 바꾸지 않는다. `appearance='outline'` 은 흰 바탕 + 1px accent 테두리.
387
387
  언제 안 쓰나: 사용자가 붙이고 뗄 수 있는 라벨(→ Tag), 클릭해 동작하는 것(→ Button), 지나가는 알림(→ Toast).
388
+ 모양은 기본 pill — 상태·건수 뱃지와 빠른 필터 칩이 한 계열(2026-11-06). 4px 는 `rounded='square'`.
388
389
  대신/함께: **상태 표시는 Badge 에 아이콘 + 글자** — `<Badge variant='success'><LucideIcon iconComponentName='circle-check' />완료</Badge>`(아이콘은 자식으로 바로, 16px·글자색). 별도 상태 컴포넌트는 없다(2026-10-30). 크기는 기본(`size` 를 주지 않는다). 상태값 → variant·아이콘 매핑은 소비 앱의 상수 한 곳에 둔다.
389
390
 
390
391
  | prop | 타입 | 기본값 | 설명 |
@@ -470,7 +471,7 @@ const Playground = () => <MetaItem label="등록자" value="smkim1" />;
470
471
  언제 쓰나: 0~100 의 비율을 길이로 보여 줄 때. 이름은 `aria-label` 로 준다 — 표에서는 행마다 `'GPU 사용률 46%'` 처럼 **무엇의 비율인지**.
471
472
  이름을 안 주면 `'46%'`(값이 없으면 `'진행 중'`)를 기본 이름으로 붙인다 — 이름 없는 progressbar 는 axe serious(aria-progressbar-name, 2026-10-20 17차). 기본 이름은 숫자뿐이라 뜻이 약하니 호출자가 주는 것이 맞다.
472
473
  언제 안 쓰나: 단계가 있는 진행(→ Stepper), 불확정 대기(→ Spinner).
473
- 대신/함께: 막대 옆에 % 글자를 같이 둔다(`tabular-nums`). 색은 `variant` 로 상태와 맞춘다.
474
+ 대신/함께: 막대 옆에 % 글자를 같이 둔다(`tabular-nums`). 색(`variant`)은 **값의 뜻대로** — 높을수록 좋은 비율(정상 행·통과율·완료율)은 기본(primary)이나 success, 낮을수록 좋은 값의 경고 구간만 warning·danger. 페이지·항목의 실패 상태에 맞춰 칠하지 않는다(2026-11-06 홀드아웃 20: "정상 행 99%" 막대가 빨강).
474
475
 
475
476
  | prop | 타입 | 기본값 | 설명 |
476
477
  |---|---|---|---|