e347a75953
Build & Deploy to K8s / build-and-deploy (push) Successful in 5m32s
- useDbTables: search/table/stats 의 DB 테이블 로드 hook (3 패널 중복 제거)
- TableConnectSection + AutoLoadButton: search/table 의 테이블 연결 섹션 + 자동 로드 버튼
- row-helpers: RowNumberBadge / RowExpandChevron / RowDeleteBtn (4 패널 dense list helper)
- IconPicker: shadcn 톤 -> cp 톤 (28px 트리거, focus glow, cp 변수)
- IconPicker popover: React Portal + position:fixed (부모 overflow:hidden 우회)
- input X버튼은 hoverBg={false} 로 silent visual change 원복
Codex (GPT-5.5) 와 매 단계 교차검증 후 진행
미완 후속 사항 (auto-flip / 외부 클릭 닫기 / z-index 표준화 등) 노트에 기록
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
138 lines
3.5 KiB
TypeScript
138 lines
3.5 KiB
TypeScript
"use client";
|
||
|
||
/**
|
||
* Row helpers — 4 패널 (search/table/stats/input) 의 dense list row 에서 반복되는
|
||
* 작은 visual elements 만 추출. row 뼈대 자체는 호출처에 그대로 둠.
|
||
*
|
||
* Codex 검토 (2026-04-29) 가이드:
|
||
* - helper-only 추출 (작은 cp 컴포넌트 후보)
|
||
* - DenseListRow / ExpandableRow 같은 wrapper 는 ★ silent breakage 위험으로 보류
|
||
* - 호출처별 row prop 폭증 + expanded state 위치 / hover 표시 / row padding 회귀 위험
|
||
*
|
||
* 적용 패턴:
|
||
* - RowNumberBadge: search/table/stats 의 #번호 (4 패널 중 3)
|
||
* - RowExpandChevron: table/stats 의 ▸/▾ 펼침 버튼 (2 패널)
|
||
* - RowDeleteBtn: 4 패널 모두 사용 — visible/size/아이콘 prop 으로 미세 차이 흡수
|
||
*
|
||
* silent visual change 알림:
|
||
* - input 의 옵션 ×버튼은 원래 hover bg 없었음 → helper 적용 시 hover 시 옅은 red bg 추가됨
|
||
* - 통일 차원에서 의도적
|
||
*/
|
||
|
||
import React from "react";
|
||
|
||
export interface RowNumberBadgeProps {
|
||
n: number;
|
||
}
|
||
|
||
export const RowNumberBadge: React.FC<RowNumberBadgeProps> = ({ n }) => (
|
||
<span
|
||
style={{
|
||
fontSize: 9,
|
||
color: "var(--cp-text-muted)",
|
||
fontFamily: "var(--v5-font-mono)",
|
||
textAlign: "right",
|
||
}}
|
||
>
|
||
{n}
|
||
</span>
|
||
);
|
||
|
||
export interface RowExpandChevronProps {
|
||
expanded: boolean;
|
||
onToggle: () => void;
|
||
size?: number;
|
||
}
|
||
|
||
export const RowExpandChevron: React.FC<RowExpandChevronProps> = ({
|
||
expanded,
|
||
onToggle,
|
||
size = 18,
|
||
}) => (
|
||
<button
|
||
type="button"
|
||
onClick={onToggle}
|
||
title={expanded ? "접기" : "펼침"}
|
||
style={{
|
||
width: size,
|
||
height: size,
|
||
padding: 0,
|
||
background: "transparent",
|
||
border: "none",
|
||
cursor: "pointer",
|
||
color: "var(--cp-text-muted)",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
fontSize: 10,
|
||
}}
|
||
>
|
||
{expanded ? "▾" : "▸"}
|
||
</button>
|
||
);
|
||
|
||
export interface RowDeleteBtnProps {
|
||
onClick: () => void;
|
||
/**
|
||
* 부모 hover state — false 면 transparent (자리 차지). 기본 true (항상 visible).
|
||
*
|
||
* ★ search/table/stats 같은 dense list row 에서는 반드시 `visible={hover}` 명시할 것.
|
||
* 생략하면 hover 와 무관하게 항상 빨간 ×버튼 노출 → UX 어긋남.
|
||
*/
|
||
visible?: boolean;
|
||
size?: number;
|
||
/** 아이콘 (기본 "×" 텍스트) */
|
||
children?: React.ReactNode;
|
||
title?: string;
|
||
/** hover 시 옅은 red bg 표시 (기본 true). false 면 hover bg 없이 색만 강조. */
|
||
hoverBg?: boolean;
|
||
}
|
||
|
||
export const RowDeleteBtn: React.FC<RowDeleteBtnProps> = ({
|
||
onClick,
|
||
visible = true,
|
||
size = 22,
|
||
children = "×",
|
||
title = "제거",
|
||
hoverBg = true,
|
||
}) => (
|
||
<button
|
||
type="button"
|
||
onClick={onClick}
|
||
title={title}
|
||
style={{
|
||
width: size,
|
||
height: size,
|
||
padding: 0,
|
||
background: "transparent",
|
||
border: "none",
|
||
cursor: "pointer",
|
||
color: visible ? "var(--v5-red, #ef4444)" : "transparent",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
borderRadius: 4,
|
||
...(hoverBg && {
|
||
transition: "color .12s ease, background .12s ease",
|
||
}),
|
||
}}
|
||
onMouseEnter={
|
||
hoverBg
|
||
? (e) => {
|
||
(e.currentTarget as HTMLButtonElement).style.background =
|
||
"rgba(239, 68, 68, 0.10)";
|
||
}
|
||
: undefined
|
||
}
|
||
onMouseLeave={
|
||
hoverBg
|
||
? (e) => {
|
||
(e.currentTarget as HTMLButtonElement).style.background = "transparent";
|
||
}
|
||
: undefined
|
||
}
|
||
>
|
||
{children}
|
||
</button>
|
||
);
|