fix(ui_template): 나무 화살표 · 줄 수 글자 대비 · 항목 고르기 툴팁 · 자리표 이름 (PLAN 21-10 흠 5~7)

- 나무 화살표 · 줄 수와 항목 고르기의 흐린 글을 var(--color-text-secondary) 로 — 밝은 테마 대비 3.08 → 6.3 이상
- M01 왼쪽 목록 줄 수도 같은 공용 클래스(ui-tree__count)로 — 밝은 테마 2.64 → 5.41
- 항목 고르기: 잎 툴팁 = 층 이름 + 키 · 「새 분류N」 자리표는 이름 · 나무 이름에서 뺌 · 관리 화면 단추는 개인 항목만(확인)
- ghost 단추는 두 테마 모두 6.85 이상이라 색 변경 없음 — 다크 1.06 은 ORCA 탭이 색 전환을 멈춰 생긴 측정값
- 자료 시험에 자리표 · 툴팁 추가

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K7JS47SacjPxZ718QsZKyr
This commit is contained in:
2026-09-29 13:36:36 +09:00
co-authored by Claude Sonnet 5.5
parent 5cb65dff16
commit 5b04f453a6
6 changed files with 59 additions and 17 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ export function buildSide(
? []
: [
el("span", {
className: "m01-side__muted",
className: "ui-tree__count",
text: node.count.toLocaleString("ko-KR"),
}),
]),
+30 -1
View File
@@ -11,6 +11,8 @@ import {
itemName,
pathIds,
rowId,
rowTip,
shown,
toSummary,
type PickerRow,
type TreeLabels,
@@ -72,6 +74,33 @@ assert.equal(itemName(rows[6]), "옹벽 H=2m");
assert.equal(itemName({ key: "SS000009", 열: "zz" }), "zz");
assert.equal(itemName({ key: "SS000009", 열: "" }), "SS000009");
// 「새 분류N」 자리표는 이름 · 나무 이름에서 뺌
assert.equal(shown("새 분류1"), "");
assert.equal(shown("새 분류 12"), "");
assert.equal(shown("새 분류"), "");
assert.equal(shown("새 분류표"), "새 분류표"); // 자리표가 아닌 진짜 이름은 그대로
assert.equal(shown(undefined), "");
const fresh = row("SS000300", "n1", "새 분류1", ["새 분류2", "", ""], "personal", {
분류3: "새 분류3",
});
assert.equal(itemName(fresh), "n1"); // 이름이 모두 자리표면 열 id
assert.equal(
itemName(row("SS000301", "n2", "옹벽", ["새 분류1", "H=2m", ""], "personal")),
"옹벽 H=2m",
);
const placeholderTree = buildTree([fresh], labels);
assert.equal(placeholderTree[2].children?.[0].label, "분류 없음"); // 종류
assert.equal(placeholderTree[2].children?.[0].children?.[0].label, "분류 없음"); // 분류1
assert.deepEqual(pathIds(fresh, labels), [
"personal",
"personal|분류 없음",
"personal|분류 없음|분류 없음",
]);
// 툴팁 = 층 이름 + 키
assert.equal(rowTip(rows[7], labels), "개인 · SS000201");
assert.equal(rowTip(rows[5], labels), "회사 · SS000101");
// 나무 — 그룹은 늘 마스터 · 회사 · 개인 차례 · 그룹 → 종류 → 분류1 → 잎
const tree = buildTree(rows, labels);
assert.deepEqual(
@@ -96,7 +125,7 @@ assert.equal(cat?.label, "메쌓기");
assert.equal(cat?.count, 2);
const leaf = cat?.children?.[0];
assert.equal(leaf?.label, "돌기슭막이 메쌓기 1.2m 기초유");
assert.equal(leaf?.tip, "SS000001"); // 키는 툴팁
assert.equal(leaf?.tip, "마스터 · SS000001"); // 툴팁 = 층 이름 + 키
assert.equal(leaf?.count, null);
assert.ok(leaf?.row);
+4 -4
View File
@@ -57,7 +57,7 @@
.ui-item-picker__where,
.ui-item-picker__hint {
margin: 0;
color: var(--color-text-muted);
color: var(--color-text-secondary);
font-size: var(--text-caption);
}
@@ -87,16 +87,16 @@
.ui-item-picker__folder-label {
flex: 0 0 5.5em;
color: var(--color-text-muted);
color: var(--color-text-secondary);
}
.ui-item-picker__key {
color: var(--color-text-muted);
color: var(--color-text-secondary);
font-size: 11px;
}
.ui-item-picker__none {
color: var(--color-text-muted);
color: var(--color-text-secondary);
}
.ui-item-picker__actions {
+4 -2
View File
@@ -20,6 +20,8 @@ import {
ownerOf,
pathIds,
rowId,
rowTip,
shown,
toSummary,
type FolderKind,
type PickNode,
@@ -127,7 +129,7 @@ export function openItemPicker(opts: ItemPickerOptions): Promise<ItemPickerResul
if (!chosen) {
detail.replaceChildren(hint(t("M02_PickerHint")));
} else {
const where = [labels().layers[layerOf(chosen)], chosen.종류, chosen.분류1]
const where = [labels().layers[layerOf(chosen)], shown(chosen.종류), shown(chosen.분류1)]
.filter(Boolean)
.join(" › ");
const small = (text: string): HTMLElement =>
@@ -136,7 +138,7 @@ export function openItemPicker(opts: ItemPickerOptions): Promise<ItemPickerResul
el("h4", {
className: "ui-item-picker__name",
text: itemName(chosen),
attrs: { title: chosen.key },
attrs: { title: rowTip(chosen, labels()) },
}),
small(where),
...(chosen.단위 ? [small(`${t("M02_PickerUnit")} ${chosen.단위}`)] : []),
+18 -7
View File
@@ -54,9 +54,20 @@ export interface PickNode {
row?: PickerRow;
}
/** 보이는 항목 이름 — 종류 · 분류1~3 을 이음(비면 열 id · 키) */
/** 「새 분류1」 같은 새로 만들 때의 자리표는 이름이 아님 — 보이는 글에서 뺌 */
const PLACEHOLDER = /^새 분류\s*\d*$/;
export const shown = (part?: string): string =>
part && !PLACEHOLDER.test(part.trim()) ? part : "";
/** 보이는 항목 이름 — 종류 · 분류1~3 을 이음(자리표는 뺌 · 비면 열 id · 키) */
export const itemName = (row: PickerRow): string =>
[row.종류, row.분류1, row.분류2, row.분류3].filter(Boolean).join(" ") || row.열 || row.key;
[row.종류, row.분류1, row.분류2, row.분류3].map(shown).filter(Boolean).join(" ") ||
row.열 ||
row.key;
/** 마우스를 올렸을 때 — 층 이름 + 키 */
export const rowTip = (row: PickerRow, labels: TreeLabels): string =>
`${labels.layers[layerOf(row)]} · ${row.key}`;
export const layerOf = (row: PickerRow): PickerLayer => row.layer ?? "system";
export const ownerOf = (row: PickerRow): string | null =>
@@ -108,8 +119,8 @@ export function buildTree(rows: PickerRow[], labels: TreeLabels): PickNode[] {
const mine = rows.filter((row) => layerOf(row) === layer);
const kinds = new Map<string, Map<string, PickerRow[]>>();
for (const row of mine) {
const kind = row.종류 || labels.unclassified;
const cat = row.분류1 || labels.unclassified;
const kind = shown(row.종류) || labels.unclassified;
const cat = shown(row.분류1) || labels.unclassified;
const cats = kinds.get(kind) ?? new Map<string, PickerRow[]>();
cats.set(cat, [...(cats.get(cat) ?? []), row]);
kinds.set(kind, cats);
@@ -122,7 +133,7 @@ export function buildTree(rows: PickerRow[], labels: TreeLabels): PickNode[] {
children: leaves.map((row) => ({
id: rowId(row),
label: itemName(row),
tip: row.key,
tip: rowTip(row, labels),
count: null,
row,
})),
@@ -141,8 +152,8 @@ export function buildTree(rows: PickerRow[], labels: TreeLabels): PickNode[] {
/** 잎까지 가는 길의 나무 줄 id — 처음부터 펼칠 자리 */
export function pathIds(row: PickerRow, labels: TreeLabels): string[] {
const layer = layerOf(row);
const kind = row.종류 || labels.unclassified;
const cat = row.분류1 || labels.unclassified;
const kind = shown(row.종류) || labels.unclassified;
const cat = shown(row.분류1) || labels.unclassified;
return [layer, `${layer}|${kind}`, `${layer}|${kind}|${cat}`];
}
+2 -2
View File
@@ -14,10 +14,10 @@
.ui-tree__caret {
display: inline-block;
width: var(--spacing-12);
color: var(--color-text-muted);
color: var(--color-text-secondary);
}
.ui-tree__count {
color: var(--color-text-muted);
color: var(--color-text-secondary);
font-size: var(--text-caption);
}