feat(B05/B06/ui): 패널 손잡이·리사이저·편집 버튼 시인성 정리(16·18~20)

- 16: 편집 버튼 전체(▲▼·↺·⬆⬇) 21×17 통일, 겹침 간격 23px, X축 라벨 상향 19px
- 18: 유토곡선 손잡이가 오버레이 위 경계를 따라 이동(펼침 시 테이블 영역 침범 허용)
- 19: 손잡이 테두리 강조색 --panel-handle-border(라이트 파랑 #2563eb / 다크 노랑
  #e0b64a) + 이름표 옵션 — B05 '종단'·'유토곡선'·세로 '배수유역', B06 '종단/유토곡선'
- 20: 공용 리사이저 상시 표시선(1px, 같은 강조색) — hover/드래그 시 3px

Playwright: 버튼 3종 21×17, 라벨·테두리색·세로 writing-mode, 리사이저 1px/0.75,
손잡이 bottom=오버레이 top 일치, 콘솔 오류 0. typecheck 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-04 19:06:02 +09:00
co-authored by Claude Opus 5
parent cdd40a00f3
commit d4fc73c012
10 changed files with 144 additions and 27 deletions
+46 -1
View File
@@ -84,7 +84,9 @@
.ui-workflow-overlay__handle {
position: absolute;
border: 1px solid var(--color-border);
/* 배경과 같은 무채색 테두리는 손잡이가 묻혀 안 보였다(2026-08-04 사용자 지시).
테마별 강조색 테두리 — 라이트: 파랑, 다크: 노랑(--panel-handle-border, 테마 정의). */
border: 1px solid var(--panel-handle-border, var(--color-border));
background: var(--color-surface-raised);
color: var(--color-text);
box-shadow: var(--shadow-lg);
@@ -103,6 +105,49 @@
transition: transform var(--transition-fast);
}
/* 이름표 달린 손잡이 — 화살표+텍스트를 나란히 담도록 고정 폭을 푼다. */
.ui-workflow-overlay__handle.is-labeled {
display: flex;
gap: var(--spacing-4);
align-items: center;
justify-content: center;
}
.ui-workflow-overlay__handle-label {
color: var(--color-text-secondary);
font-size: var(--text-caption);
line-height: 1;
white-space: nowrap;
user-select: none;
}
/* bottom 손잡이: 화살표 오른쪽에 가로 이름표 — 폭은 내용에 맞춘다(최소 64px 유지). */
.ui-workflow-overlay__handle--bottom.is-labeled {
width: auto;
min-width: var(--spacing-64);
padding: 0 var(--spacing-8);
}
.ui-workflow-overlay__handle--bottom.is-labeled .ui-workflow-overlay__handle-icon {
margin: 0;
}
/* side 손잡이: 화살표 위쪽에 90° 세로 이름표 — 높이는 내용에 맞춘다(최소 64px 유지). */
.ui-workflow-overlay__handle--side.is-labeled {
flex-direction: column;
height: auto;
min-height: var(--spacing-64);
padding: var(--spacing-8) 0;
}
.ui-workflow-overlay__handle--side.is-labeled .ui-workflow-overlay__handle-icon {
margin: 0;
}
.ui-workflow-overlay__handle--side.is-labeled .ui-workflow-overlay__handle-label {
writing-mode: vertical-rl;
}
/* title 패널 우측 가장자리 세로 중앙 핸들 — 닫히면 이 버튼만 화면 왼쪽에 남음 */
.ui-workflow-overlay__handle--side {
top: 50%;
+17 -1
View File
@@ -38,13 +38,29 @@ export function createWorkflowPanelHandle(
* 넘겨야 한다. 좌우와 같은 이유로, 도킹 방향이 반대인데 같은 회전을 쓰면 표시가 거꾸로 된다.
*/
collapseToward: "left" | "right" | "up" | "down" = "left",
/**
* 손잡이 옆에 붙일 짧은 이름표(선택, 2026-08-04 사용자 지시 — 무엇의 손잡이인지 보이게).
* bottom 손잡이는 화살표 **오른쪽**에 가로로, side 손잡이는 화살표 **위쪽**에 90° 세로로
* 놓인다. 사이드바(제목 패널)처럼 이름이 필요 없는 곳은 생략하면 현행과 같다.
*/
label?: string,
): WorkflowPanelHandle {
const root = document.createElement("button");
root.type = "button";
root.className = `ui-workflow-overlay__handle ui-workflow-overlay__handle--${placement}`;
const icon = document.createElement("span");
icon.className = "ui-workflow-overlay__handle-icon";
root.append(icon);
if (label) {
root.classList.add("is-labeled");
const text = document.createElement("span");
text.className = "ui-workflow-overlay__handle-label";
text.textContent = label;
// side는 이름표가 화살표 위, bottom은 화살표 오른쪽 — DOM 순서로 자리를 정한다.
if (placement === "side") root.append(text, icon);
else root.append(icon, text);
} else {
root.append(icon);
}
function setOpen(isOpen: boolean): void {
// 삼각형은 회전 0°에서 오른쪽(▶)을 가리킨다. 펼친 상태면 접히는 쪽을,
+45 -6
View File
@@ -1,18 +1,57 @@
/* 공통 스플리터(드래그 리사이저) — 패널 경계에 얹는 얇은 손잡이.
레이아웃을 밀지 않도록 경계 위에 절대배치하고, 평소에는 보이지 않다가
마우스를 얹거나 끌 때만 색이 들어온다. */
레이아웃을 밀지 않도록 경계 위에 절대배치한다.
조절 가능한 패널이 여러 곳(B05 3곳·B06 1곳)인데 hover 전에는 보이지 않아 구분이
안 됐다(2026-08-04 사용자 지시) — 손잡이 테두리와 같은 강조색(--panel-handle-border)
의 **얇은 줄을 상시 표시**하고, 얹거나 끌 때 굵어진다. 히트 영역(6px)은 그대로다. */
.ui-resizer {
position: absolute;
z-index: 1;
background: transparent;
transition: background var(--transition-fast);
touch-action: none;
}
.ui-resizer:hover,
.ui-resizer.is-dragging {
background: var(--color-primary);
/* 상시 보이는 얇은 표시줄 — 히트 영역 가운데 1px. */
.ui-resizer::before {
content: "";
position: absolute;
background: var(--panel-handle-border, var(--color-primary));
opacity: 0.75;
transition:
opacity var(--transition-fast),
background var(--transition-fast);
}
.ui-resizer--vertical::before {
top: 50%;
right: 0;
left: 0;
height: 1px;
transform: translateY(-50%);
}
.ui-resizer--horizontal::before {
top: 0;
bottom: 0;
left: 50%;
width: 1px;
transform: translateX(-50%);
}
.ui-resizer:hover::before,
.ui-resizer.is-dragging::before {
opacity: 1;
}
.ui-resizer--vertical:hover::before,
.ui-resizer--vertical.is-dragging::before {
height: 3px;
}
.ui-resizer--horizontal:hover::before,
.ui-resizer--horizontal.is-dragging::before {
width: 3px;
}
/* 위아래로 끌어 높이를 조절 — 패널 위쪽 경계에 가로로 눕는다. */
+4
View File
@@ -35,6 +35,8 @@
--color-success: #1f8a4c; /* 성공/승인 */
--color-warning: #b8860b; /* 경고 (design.md 별색 #f5b800 계열) */
--color-danger: #c0392b; /* 에러/삭제 */
/* 패널 접기/펼치기 손잡이 테두리 — 배경에 묻히지 않는 강조색(라이트: 파랑, 다크: 노랑) */
--panel-handle-border: #2563eb;
--color-info: var(--color-royal-amethyst);
/* 그라디언트 (Gradient System) — 항상 흰 표면 뒤에만 배치, 텍스트 직상단 금지 */
@@ -300,6 +302,7 @@
--color-success: #3fbb6f;
--color-warning: #e0b64a;
--color-danger: #e8695a;
--panel-handle-border: #e0b64a;
--shadow-sm: rgba(0, 0, 0, 0.4) 0px 2px 4px 0px, rgba(0, 0, 0, 0.2) 0px 0px 0px 1px;
--shadow-lg: rgba(0, 0, 0, 0.5) 0px 32px 24px -12px, rgba(0, 0, 0, 0.3) 0px 3px 3px 0px;
@@ -335,6 +338,7 @@
--color-primary-text: #16121f;
--color-accent: var(--color-lavender-wash);
--color-focus-ring: var(--color-lavender-wash);
--panel-handle-border: #e0b64a;
}
}