diff --git a/B07_DesignDetail/openwebcad/src/App.css b/B07_DesignDetail/openwebcad/src/App.css index 9c4c7197a..994e1d59c 100644 --- a/B07_DesignDetail/openwebcad/src/App.css +++ b/B07_DesignDetail/openwebcad/src/App.css @@ -27,7 +27,8 @@ --cad-text-dim: var(--color-text-secondary); --cad-text-muted: var(--color-text-muted); --cad-accent: var(--color-accent); - --cad-hover: var(--color-mist-violet); + /* 마우스 바탕 = 부품 상자와 같은 값 · 켜짐 바탕은 --color-accent-soft */ + --cad-hover: var(--color-hover); --cad-canvas: var(--draw-canvas); } @@ -111,21 +112,12 @@ body > canvas[data-id="canvas"] { flex: 1; min-width: 0; } +/* 접기 단추 = 아이콘 단추 부품(단 20) · 여기는 자리만 */ .cad-ribbon-tabs__collapse { - width: 24px; - height: 20px; align-self: center; - padding: 0; - border: 1px solid transparent; - border-radius: 4px; - background: transparent; - color: var(--cad-text-dim); - font-size: 11px; } -.cad-ribbon-tabs__collapse:hover { - background: var(--cad-hover); -} -.cad-ribbon-tabs button { +/* 리본 탭 = CAD 고유 꼴 그대로(토큰만) */ +.cad-ribbon-tabs > button:not(.ui-icon-btn) { padding: 0 14px; border: 1px solid transparent; border-bottom: 0; @@ -134,10 +126,10 @@ body > canvas[data-id="canvas"] { color: var(--cad-text-dim); font-size: 12px; } -.cad-ribbon-tabs button:hover { +.cad-ribbon-tabs > button:not(.ui-icon-btn):hover { background: var(--cad-hover); } -.cad-ribbon-tabs button[data-active="true"] { +.cad-ribbon-tabs > button[data-active="true"] { background: var(--cad-chrome); border-color: var(--cad-line); color: var(--color-text); @@ -185,53 +177,25 @@ body > canvas[data-id="canvas"] { .cad-ribbon-group__label[data-expandable="true"]:hover { color: var(--cad-accent); } +/* 꼴 = 메뉴 부품(`ui-ctx-menu`) · 여기는 자리만 */ .cad-ribbon-overflow { /* 리본 패널 줄이 가로 스크롤 상자라 그 안에서는 잘린다 — 화면 좌표로 띄운다 */ position: fixed; z-index: 20; - display: flex; - flex-direction: column; min-width: 170px; max-height: 72vh; - padding: 4px; - overflow-y: auto; - background: var(--cad-chrome-raised); - border: 1px solid var(--cad-line); - border-radius: 4px; - box-shadow: var(--shadow-lg); } -.cad-ribbon-overflow button { +.cad-ribbon-overflow > .ui-ctx-menu__item { display: flex; gap: 8px; align-items: center; - padding: 5px 8px; - border: 0; - border-radius: 3px; - background: transparent; - font-size: 11px; - text-align: left; -} -.cad-ribbon-overflow button:hover { - background: var(--cad-hover); } +/* ↶ ↷ = 아이콘 단추 부품(단 20) · 여기는 자리만 */ .cad-quick-access { display: flex; gap: 2px; align-self: center; } -.cad-ribbon-tabs .cad-quick-access button { - width: 24px; - height: 20px; - padding: 0; - border: 1px solid transparent; - border-radius: 4px; - line-height: 1; - font-size: 13px; -} -.cad-quick-access button:hover { - border-color: var(--cad-line); - background: var(--cad-hover); -} .cad-ribbon-props { display: flex; flex-direction: column; @@ -252,15 +216,16 @@ body > canvas[data-id="canvas"] { width: 52px; text-align: left; } +/* 리본 안 칸 = CAD 고유 꼴(토큰만) · 높이 = 크기 단 18 · 둥글기 4 */ .cad-prop select, .cad-prop input[type="number"] { - height: 19px; + height: 18px; min-width: 78px; padding: 0 3px; color: var(--cad-text); background: var(--cad-chrome-sunken); border: 1px solid var(--cad-line); - border-radius: 3px; + border-radius: 4px; font-size: 11px; } .cad-prop input[type="number"] { @@ -268,13 +233,13 @@ body > canvas[data-id="canvas"] { width: 52px; } .cad-prop input[type="color"] { - height: 19px; + height: 18px; width: 44px; padding: 1px; background: var(--cad-chrome-sunken); /* 흰색을 골라도 스와치 자리가 보이게 테두리를 진하게 준다 (2026-09-01) */ border: 1px solid var(--cad-text-muted); - border-radius: 3px; + border-radius: 4px; cursor: pointer; } /* 고른 것들 색이 다름(488) — 빈 견본(투명 · 점선 테두리) */ @@ -328,7 +293,7 @@ input[type="color"][data-mixed="true"]::-webkit-color-swatch { background: trans } .cad-tool[data-active="true"] { border-color: var(--cad-accent); - background: var(--cad-hover); + background: var(--color-accent-soft); box-shadow: inset 0 -2px var(--cad-accent); } .cad-tool:disabled { @@ -373,23 +338,14 @@ input[type="color"][data-mixed="true"]::-webkit-color-swatch { background: trans background: var(--cad-chrome-raised); color: var(--cad-text-dim); } +/* 꼴 = 탭 부품(`ui-tabs`) · 여기는 칸 둘이 폭을 나누는 배치만 */ .cad-inspector-tabs { display: grid; grid-template-columns: 1fr 1fr; - height: 38px; - border-bottom: 1px solid var(--cad-line); + gap: 0; } -.cad-inspector-tabs button { - border: 0; - border-bottom: 2px solid transparent; - background: var(--cad-chrome-sunken); - color: var(--cad-text-dim); - font-size: 12px; -} -.cad-inspector-tabs button[data-active="true"] { - border-bottom-color: var(--cad-accent); - background: var(--cad-chrome-raised); - color: var(--color-text); +.cad-inspector-tabs > .ui-tabs__tab { + justify-content: center; } .cad-properties { padding: 14px 12px; diff --git a/B07_DesignDetail/openwebcad/src/App.types.ts b/B07_DesignDetail/openwebcad/src/App.types.ts index db75fc6de..6a1d0346e 100644 --- a/B07_DesignDetail/openwebcad/src/App.types.ts +++ b/B07_DesignDetail/openwebcad/src/App.types.ts @@ -74,7 +74,6 @@ export interface Layer { export enum LOCAL_STORAGE_KEY { DRAWING = 'OPEN_WEB_CAD__DRAWING', - DROPDOWN = 'OPEN_WEB_CAD__DROPDOWN', } export interface StartAndEndpointEntity { diff --git a/B07_DesignDetail/openwebcad/src/App_Layers.css b/B07_DesignDetail/openwebcad/src/App_Layers.css index c46a6d7d1..040234e55 100644 --- a/B07_DesignDetail/openwebcad/src/App_Layers.css +++ b/B07_DesignDetail/openwebcad/src/App_Layers.css @@ -14,22 +14,22 @@ padding-right: 2px; min-width: 0; } -/* 도면층 버튼 — 색은 토큰으로만, 상태는 Button이 붙이는 data-* 속성으로 가른다. */ +/* 도면층 버튼 — 목록 줄 부품(`ui-sidebar-row`) 꼴 · 상태는 Button이 붙이는 data-* 속성으로 가른다. */ .cad-layer-manager button[data-type="regular"] { - background: var(--cad-chrome-sunken); - color: var(--cad-accent); + background: transparent; + color: var(--color-text-body); } .cad-layer-manager button[data-type="transparent"] { background: transparent; - color: var(--cad-accent); + color: var(--color-text-secondary); } .cad-layer-manager button:hover { - background: var(--cad-hover); + background: var(--color-hover); color: var(--color-text); } .cad-layer-manager button[data-active="true"] { - background: var(--color-primary); - color: var(--color-primary-text); + background: var(--color-accent-soft); + color: var(--color-accent); } .cad-view-controls { @@ -41,7 +41,7 @@ align-items: center; overflow: hidden; border: 1px solid var(--cad-line); - border-radius: 4px; + border-radius: var(--radius-buttons); background: var(--cad-chrome-raised); box-shadow: var(--shadow-lg); } @@ -87,21 +87,7 @@ body.cad-file-dragging::after { pointer-events: none; } -.cad-view-controls button { - width: 34px; - height: 32px; - border: 0; - border-right: 1px solid var(--cad-line); - background: transparent; - font-size: 17px; -} -.cad-view-controls button:hover { - background: var(--cad-hover); -} -.cad-view-controls__fit { - color: var(--cad-accent); - font-size: 15px; -} +/* 단추 = 아이콘 단추 부품(단 32) · 여기는 배율 글만 */ .cad-view-controls span { min-width: 48px; color: var(--cad-text-dim); @@ -133,30 +119,16 @@ body.cad-file-dragging::after { color: var(--cad-text-muted); font: 11px Consolas, monospace; } +/* 꼴 = 메뉴 부품(`ui-ctx-menu`) · 여기는 자리와 명령 글꼴만 */ .cad-command-suggestions { position: absolute; z-index: 6; bottom: 100%; left: 10px; - display: flex; - flex-direction: column; min-width: 220px; - padding: 4px; - background: var(--cad-chrome-raised); - border: 1px solid var(--cad-line); - border-radius: 4px; - box-shadow: var(--shadow-lg); } -.cad-command-suggestions button { - padding: 4px 8px; - border: 0; - border-radius: 3px; - background: transparent; - font: 11px Consolas, monospace; - text-align: left; -} -.cad-command-suggestions button:hover { - background: var(--cad-hover); +.cad-command-suggestions > .ui-ctx-menu__item { + font: 12px Consolas, monospace; } .cad-prop--wide select { min-width: 132px; @@ -180,12 +152,13 @@ body.cad-file-dragging::after { font-size: 11px; font-weight: 600; } +/* 명령 칸 = CAD 고유 꼴(토큰만) · 높이 = 크기 단 28 */ .cad-command-area input { flex: 1; - height: 26px; + height: 28px; padding: 0 8px; border: 1px solid var(--cad-line); - border-radius: 2px; + border-radius: var(--radius-buttons); outline: none; background: var(--cad-chrome-sunken); color: var(--cad-text); @@ -210,23 +183,7 @@ body.cad-file-dragging::after { background: var(--cad-chrome); border-top: 1px solid var(--cad-line); } -.cad-statusbar button { - height: 21px; - padding: 0 8px; - border: 1px solid transparent; - border-radius: 2px; - background: transparent; - color: var(--cad-text-dim); - font-size: 10px; -} -.cad-statusbar button:hover { - background: var(--cad-hover); -} -.cad-statusbar button[data-active="true"] { - border-color: var(--cad-accent); - background: var(--color-primary); - color: var(--color-primary-text); -} +/* 켜기 = 켜기 칩 부품(`ui-toggle--chip` · 단 22) */ .cad-statusbar__hint { margin-left: auto; color: var(--cad-text-muted); @@ -261,13 +218,14 @@ body.cad-file-dragging::after { font-size: 11px; color: var(--cad-text-dim); } +/* 칸 = 크기 단 24(둥글기 6) · 토큰만 */ .cad-properties-editor select, .cad-properties-editor input { height: 24px; min-width: 0; padding: 0 4px; border: 1px solid var(--cad-line); - border-radius: 3px; + border-radius: 6px; background: var(--cad-chrome-sunken); color: var(--cad-text); font-size: 11px; @@ -292,59 +250,19 @@ body.cad-file-dragging::after { color: var(--cad-text); text-overflow: ellipsis; } -.cad-properties__empty { - margin: 0; - color: var(--cad-text-muted); - font-size: 11px; -} -/* 빠른 특성 — 화면 위에 뜨는 작은 상자 */ -.cad-quick-properties { - position: fixed; - z-index: 5; - top: calc(var(--cad-title-height) + var(--cad-ribbon-height) + 12px); - right: 14px; - width: 240px; - padding: 8px 10px 10px; - background: var(--cad-chrome-raised); - border: 1px solid var(--cad-line); - border-radius: 5px; - box-shadow: var(--shadow-lg); -} -.cad-quick-properties__header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 6px; - color: var(--cad-text-dim); - font-size: 11px; -} -.cad-quick-properties__header button { - border: 0; - background: transparent; - color: var(--cad-text-muted); - font-size: 12px; -} -/* 블록 라이브러리 팔레트 (INSERT/BLOCK) */ +/* 빠른 특성 · 블록 라이브러리 — 꼴 = 떠 있는 판 부품(`ui-float-panel`) · 여기는 자리 · 폭만 */ +.cad-quick-properties, .cad-block-library { position: fixed; z-index: 5; top: calc(var(--cad-title-height) + var(--cad-ribbon-height) + 12px); right: 14px; width: 240px; - padding: 8px 10px 10px; - background: var(--cad-chrome-raised); - border: 1px solid var(--cad-line); - border-radius: 5px; - box-shadow: var(--shadow-lg); -} -.cad-block-library__empty { - margin: 0; - color: var(--cad-text-muted); - font-size: 11px; - line-height: 1.5; } + +/* 블록 라이브러리 팔레트 (INSERT/BLOCK) */ .cad-block-library__list { max-height: 220px; margin: 0; @@ -357,40 +275,26 @@ body.cad-file-dragging::after { align-items: center; gap: 4px; } -.cad-block-library__list li button { - border: 0; - background: transparent; - color: var(--cad-text); - font-size: 12px; -} +/* 블록 줄 = 목록 줄 부품(`ui-sidebar-row`) · 지우기 = 아이콘 단추 부품(단 20) · 여기는 줄 폭만 */ .cad-block-library__name { flex: 1; + min-width: 0; overflow: hidden; - padding: 3px 4px; - text-align: left; text-overflow: ellipsis; white-space: nowrap; } -.cad-block-library__name:hover { - background: var(--cad-chrome-sunken); -} +/* 단추 = 단추 부품(보조 · 단 24) · 여기는 둘이 폭을 나눔만 */ .cad-block-library__actions { display: flex; gap: 6px; margin-top: 8px; } -.cad-block-library__actions button { +.cad-block-library__actions > .ui-btn { flex: 1; - padding: 4px 0; - border: 1px solid var(--cad-line); - border-radius: 3px; - background: transparent; - color: var(--cad-text-dim); - font-size: 11px; } /* 도각 자리표 패널 — 도각 편집으로 도면을 실었을 때만 뜬다 (2026-09-06 사용자 지시로 - 부모 사이드바에서 캐드 안으로 옮김). 도면 오른쪽 위, 리본 아래에 붙는다. */ + 부모 사이드바에서 캐드 안으로 옮김). 꼴 = 떠 있는 판 부품(`ui-float-panel`) · 여기는 자리 · 폭 · 줄 배치만. */ .cad-frame-tokens { position: fixed; /* 오른쪽 위는 진행단계 패널이 쓴다 — 아래쪽(상태막대·명령행 위)에 붙인다. */ @@ -398,36 +302,13 @@ body.cad-file-dragging::after { bottom: calc(var(--cad-status-height) + var(--cad-command-height) + 8px); z-index: 3; max-height: 46vh; - overflow-y: auto; + width: 236px; +} + +.cad-frame-tokens__body { display: flex; flex-direction: column; gap: 6px; - width: 236px; - padding: 8px; - border: 1px solid var(--cad-line); - border-radius: 6px; - background: var(--cad-chrome-raised); - box-shadow: var(--shadow-lg); - color: var(--cad-text); -} - -.cad-frame-tokens__header { - display: flex; - justify-content: space-between; - align-items: flex-start; - gap: 6px; - color: var(--cad-text-dim); - font-size: 11px; - line-height: 1.4; -} - -.cad-frame-tokens__fold { - flex: none; - border: 1px solid var(--cad-line); - border-radius: 4px; - background: transparent; - color: var(--cad-text); - cursor: pointer; } .cad-frame-tokens__group { @@ -439,39 +320,9 @@ body.cad-file-dragging::after { .cad-frame-tokens__title { width: 100%; - color: var(--cad-text-dim); - font-size: 11px; } -.cad-frame-tokens__button { - padding: 3px 7px; - border: 1px solid var(--cad-line); - border-radius: 4px; - background: var(--cad-chrome); - color: var(--cad-text); - font-size: 11px; - cursor: pointer; -} - -.cad-frame-tokens__button:hover { - background: var(--cad-accent-soft, var(--cad-chrome-raised)); -} - -/* 자리표 칸 크기 입력 (2026-09-06) */ -.cad-frame-tokens__size { - display: flex; - align-items: center; - gap: 4px; - color: var(--cad-text-dim); - font-size: 11px; -} - -.cad-frame-tokens__size input { +/* 자리표 칸 크기 입력 (2026-09-06) — 칸 = 입력 부품(단 24) */ +.cad-frame-tokens__size > .ui-input { width: 64px; - padding: 2px 4px; - border: 1px solid var(--cad-line); - border-radius: 4px; - background: var(--cad-chrome); - color: var(--cad-text); - font-size: 11px; } diff --git a/B07_DesignDetail/openwebcad/src/commands/commands.insert.ts b/B07_DesignDetail/openwebcad/src/commands/commands.insert.ts index 6cb2b8d73..d5d377d45 100644 --- a/B07_DesignDetail/openwebcad/src/commands/commands.insert.ts +++ b/B07_DesignDetail/openwebcad/src/commands/commands.insert.ts @@ -5,6 +5,7 @@ import { setBlockLibraryVisible } from '../components/ui-state'; import { importImageFromFile } from '../helpers/import-export-handlers/import-image-from-file'; import { pickFile } from '../helpers/pick-file'; import { importDrawingFile } from '../integration/dxf-clip-paste'; +import { askText } from '../integration/ui-kit'; import { getActiveToolActor, getSelectedEntities } from '../state'; import { Tool } from '../tools'; import { imageImportToolStateMachine } from '../tools/image-import-tool'; @@ -39,13 +40,15 @@ export const INSERT_COMMANDS: CadCommand[] = [ needsSelection: true, run: () => { const entities = getSelectedEntities(); - const name = window.prompt('블록 이름', '')?.trim(); - if (!name) return '블록 작성 취소'; - void saveBlockFromEntities(name, entities).then(() => { + // 글 묻기 = 확인창 부품(window.prompt 대신 · 553-6) + void askText({ message: '블록 이름', okLabel: '저장' }).then(async (text) => { + const name = text?.trim(); + if (!name) return; + await saveBlockFromEntities(name, entities); toast.success(`블록 '${name}' 저장 (객체 ${entities.length}개)`); setBlockLibraryVisible(true); }); - return `블록 '${name}' 저장`; + return '블록 이름 입력'; }, }, { diff --git a/B07_DesignDetail/openwebcad/src/components/BlockLibraryPanel.tsx b/B07_DesignDetail/openwebcad/src/components/BlockLibraryPanel.tsx index 3fc99300a..f53c3ffa7 100644 --- a/B07_DesignDetail/openwebcad/src/components/BlockLibraryPanel.tsx +++ b/B07_DesignDetail/openwebcad/src/components/BlockLibraryPanel.tsx @@ -1,4 +1,4 @@ -/** 블록 라이브러리 팔레트 — 저장한 블록을 고르면 삽입 도구가 켜진다 (INSERT/BLOCK) */ +/** 블록 라이브러리 팔레트 — 저장한 블록을 고르면 삽입 도구가 켜진다 (INSERT/BLOCK) · 떠 있는 판 부품 */ import type { FC } from 'react'; import { deleteBlock, @@ -7,6 +7,7 @@ import { importBlocksFromFile, } from '../blocks/block-library'; import { pickFile } from '../helpers/pick-file'; +import { askConfirm } from '../integration/ui-kit'; import { startBlockInsert } from '../tools/insert-block-tool'; import { isBlockLibraryVisible, setBlockLibraryVisible } from './ui-state'; @@ -16,57 +17,83 @@ export const BlockLibraryPanel: FC = () => { const blocks = getBlocks(); return ( -