From b037073b10c1484dccdb67a3edd17efb7e228fb3 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 26 Oct 2026 22:11:14 +0900 Subject: [PATCH] =?UTF-8?q?style(spreadsheet):=20=EC=85=80=20=EC=84=9C?= =?UTF-8?q?=EC=8B=9D=20=C2=B7=20=EB=A9=94=EB=AA=A8=20=C2=B7=20=EC=B0=BE?= =?UTF-8?q?=EA=B8=B0=20=C2=B7=20=ED=8C=A8=EB=84=90=20=EC=B0=BD=20=C2=B7=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=E2=9A=A0=20=EB=A5=BC=20=EB=B6=80=ED=92=88?= =?UTF-8?q?=20=EB=AA=A8=EB=8B=AC=20=C2=B7=20=ED=83=AD=20=C2=B7=20=EB=96=A0?= =?UTF-8?q?=20=EC=9E=88=EB=8A=94=20=ED=8C=90=20=C2=B7=20=EB=8B=A8=EC=B6=94?= =?UTF-8?q?=EB=A1=9C=20(PLAN=20553-6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 셀 서식 창 = 부품 모달(40rem) · 탭(32) · 칸 = 부품 입력 · 고르기 28 · 자체 판 · 탭 · 칸 CSS 지움 - 메모 편집 = 공용 확인창 판(.ui-confirm) · 글 칸 = 부품 입력 - 찾기 · 바꾸기 = 떠 있는 판(머리 없음) · 칸 24 · 단추 22 · 닫기 = 아이콘 단추 - 데이터 패널 창(조건부 서식 · 유효성 · 이름) = 떠 있는 판(머리 · 닫기 ✕) - 오류 ⚠ = 아이콘 단추(선 18) · 골라 붙여넣기 · 정렬 칸 · 알약 찾기 칸 = 부품 단추 · 고르기 · 입력 - 옛 보라 별칭 · 날 검정 가림막 → 공통 값(hover · accent · scrim) · 창 닫힘 감시가 모달도 기다림 - 날 단추 23 → 15(남음 = 수식 줄 칸 단추 · 격자 안 ▼ · 알약) · 자체 꼴 규칙 95 → 77 · 격자 색 전후 같음 Co-Authored-By: Claude Opus 5.5 --- A00_Common/spreadsheet/spreadsheet.css | 72 +++++-------------- A00_Common/spreadsheet/spreadsheet_actions.ts | 9 ++- .../spreadsheet/spreadsheet_analysis.css | 16 ++--- .../spreadsheet/spreadsheet_data_menu.ts | 21 +++--- .../spreadsheet/spreadsheet_errcheck.ts | 10 ++- A00_Common/spreadsheet/spreadsheet_extras.ts | 8 +-- .../spreadsheet/spreadsheet_find_panel.ts | 43 +++++------ .../spreadsheet/spreadsheet_format_dialog.css | 61 +--------------- .../spreadsheet/spreadsheet_format_dialog.ts | 64 +++++++++-------- A00_Common/spreadsheet/spreadsheet_links.css | 13 +--- A00_Common/spreadsheet/spreadsheet_links.ts | 4 +- A00_Common/spreadsheet/spreadsheet_menu.ts | 8 +-- .../spreadsheet/spreadsheet_sort_dialog.ts | 7 +- .../spreadsheet/spreadsheet_sortfilter.css | 13 ++-- A00_Common/spreadsheet/spreadsheet_stage3.css | 4 +- .../spreadsheet/spreadsheet_toolbar.css | 39 ++-------- 16 files changed, 128 insertions(+), 264 deletions(-) diff --git a/A00_Common/spreadsheet/spreadsheet.css b/A00_Common/spreadsheet/spreadsheet.css index 4577256a9..a245b9474 100644 --- a/A00_Common/spreadsheet/spreadsheet.css +++ b/A00_Common/spreadsheet/spreadsheet.css @@ -109,7 +109,7 @@ bottom: 40px; z-index: 20; padding: 6px 10px; - border-radius: 4px; + border-radius: var(--radius-buttons); background: var(--color-primary); color: var(--color-primary-text); } @@ -126,6 +126,10 @@ cursor: pointer; } +.ss-brush:hover { + background: var(--color-hover); +} + .ss-brush.is-on { background: color-mix(in srgb, var(--color-focus-ring) 20%, var(--color-surface-raised)); box-shadow: inset 0 0 0 2px var(--color-focus-ring); @@ -135,19 +139,17 @@ cursor: copy; } -.ss-find { - position: absolute; +/* 찾기 = 떠 있는 판 부품(머리 없음) · 칸 · 단추 = 부품 — 여기는 자리 · 줄 배치만(553-6) */ +.ss-find.ui-float-panel { top: 4px; right: 16px; z-index: 20; +} + +.ss-find > .ui-float-panel__body { display: flex; flex-direction: column; gap: 4px; - padding: 8px; - border: 1px solid var(--color-border); - border-radius: 6px; - background: var(--color-surface-raised); - box-shadow: var(--shadow-lg); } .ss-find[hidden], @@ -166,32 +168,17 @@ .ss-find__input { width: 180px; - padding: 2px 6px; - border: 1px solid var(--color-border); - background: var(--color-surface-raised); - color: var(--color-text-body); - font: inherit; -} - -.ss-find__btn { - padding: 2px 8px; - border: 1px solid var(--color-border); - border-radius: 4px; - background: var(--color-surface); - color: var(--color-text-body); - font: inherit; - cursor: pointer; } .ss-find__opt { display: flex; align-items: center; gap: 2px; - font-size: 12px; + font-size: var(--text-caption); } .ss-find__status { - font-size: 12px; + font-size: var(--text-caption); color: var(--color-text-secondary); } @@ -223,19 +210,11 @@ gap: 2px; padding: 4px; border: 1px solid var(--color-border); + border-radius: var(--radius-cards); background: var(--color-surface-raised); box-shadow: var(--shadow-lg); } -.ss-pick > button { - padding: 2px 8px; - border: 1px solid var(--color-border); - background: var(--color-surface); - color: var(--color-text-body); - font: inherit; - cursor: pointer; -} - /* 함수 자동 완성 · 인자 도움말 */ .ss-hint { position: absolute; @@ -265,22 +244,17 @@ } .ss-hint__item.is-on { - background: color-mix(in srgb, var(--color-accent) 18%, var(--color-surface-raised)); + background: var(--color-accent-soft); } /* 데이터 메뉴 — 패널 창 · 유효성 목록 ▼ */ -.ss-dialog { - position: absolute; +/* 패널 창 = 떠 있는 판 부품 — 여기는 자리 · 크기만(553-6) */ +.ss-dialog.ui-float-panel { top: 4px; right: 16px; z-index: 21; max-width: min(720px, calc(100% - 32px)); max-height: calc(100% - 8px); - overflow: auto; - border: 1px solid var(--color-border); - border-radius: 6px; - background: var(--color-surface-raised); - box-shadow: var(--shadow-lg); } .ss-dialog[hidden], @@ -288,20 +262,6 @@ display: none; } -.ss-dialog__head { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - padding: 6px 8px; - border-bottom: 1px solid var(--color-border); - font-weight: bold; -} - -.ss-dialog__body { - padding: 8px; -} - .ss-list-arrow { position: absolute; z-index: 8; diff --git a/A00_Common/spreadsheet/spreadsheet_actions.ts b/A00_Common/spreadsheet/spreadsheet_actions.ts index a29be7fdc..8e1b654d3 100644 --- a/A00_Common/spreadsheet/spreadsheet_actions.ts +++ b/A00_Common/spreadsheet/spreadsheet_actions.ts @@ -118,10 +118,15 @@ export function dialogKeys(overlay: HTMLElement, close: () => void, run?: () => }); } -/** body 에 뜬 창(.ui-confirm)이 다 닫히면 초점을 격자로 — 창을 연 바로 뒤에 부름 */ +/** body 에 뜬 창(.ui-confirm · 모달)이 다 닫히면 초점을 격자로 — 창을 연 바로 뒤에 부름 */ export function watchClose(back: () => void): void { const w = new MutationObserver(() => { - if (document.querySelector("body > .ui-confirm, body > .ui-confirm__panel")) return; + if ( + document.querySelector( + "body > .ui-confirm, body > .ui-confirm__panel, body > .ui-modal__backdrop", + ) + ) + return; w.disconnect(); back(); }); diff --git a/A00_Common/spreadsheet/spreadsheet_analysis.css b/A00_Common/spreadsheet/spreadsheet_analysis.css index 31a7041dd..c0b6dd1be 100644 --- a/A00_Common/spreadsheet/spreadsheet_analysis.css +++ b/A00_Common/spreadsheet/spreadsheet_analysis.css @@ -63,7 +63,7 @@ display: flex; align-items: center; justify-content: center; - background: rgb(0 0 0 / 18%); + background: var(--color-scrim); } .ss-steps__box { @@ -115,18 +115,10 @@ overflow: visible; } -.ss-errtip__btn { +/* ⚠ = 아이콘 단추 부품(선 · 18) — 여기는 자리 · 경고 색만(553-6) */ +.ss-errtip__btn.ui-icon-btn { position: absolute; - width: 18px; - height: 18px; - padding: 0; - font-size: 11px; - line-height: 16px; - cursor: pointer; color: var(--color-warning); - background: var(--color-surface); - border: 1px solid var(--color-border); - border-radius: var(--radius-sm); } .ss-errtip__balloon { @@ -183,5 +175,5 @@ } .ss-errtip__item:hover { - background: var(--color-mist-violet); + background: var(--color-hover); } diff --git a/A00_Common/spreadsheet/spreadsheet_data_menu.ts b/A00_Common/spreadsheet/spreadsheet_data_menu.ts index 3441b644e..695728089 100644 --- a/A00_Common/spreadsheet/spreadsheet_data_menu.ts +++ b/A00_Common/spreadsheet/spreadsheet_data_menu.ts @@ -12,6 +12,7 @@ import "./spreadsheet_stage3.css"; // sub4 패널 스타일(잇는 쪽이 붙임) import { createMapContextMenu, type MapContextMenuItem } from "@ui/ui_template_context_menu"; import { el, showToast } from "@ui/ui_template_elements"; +import { createFloatPanel } from "@ui/ui_template_float_panel"; import { parseRange, rangeToA1, toA1 } from "./spreadsheet_address"; import { autoSumCells, autoSumRange } from "./spreadsheet_autosum"; import { isError } from "./spreadsheet_eval"; @@ -40,7 +41,6 @@ const TEXT = { validation: "데이터 유효성…", names: "이름 관리…", grid: "눈금선 보이기 · 숨기기", - close: "닫기", list: "값 목록(Alt+↓)", sheets: "시트 숨기기 · 탭 색…", audit: "수식 분석", @@ -121,18 +121,14 @@ export function mountDataMenu(ctx: SpreadsheetContext, back: () => void): DataMe }; // ── 패널 창(조건부 서식 · 유효성 · 이름) — 한 번에 하나 ───────────────────── - const title = el("span", { className: "ss-dialog__title" }); - const body = el("div", { className: "ss-dialog__body" }); - const shut = el("button", { - className: "ss-find__btn", - text: "×", - attrs: { type: "button", title: TEXT.close }, - }); - const dialog = el("div", { - className: "ss-dialog ui-popup", - attrs: { hidden: "" }, - children: [el("div", { className: "ss-dialog__head", children: [title, shut] }), body], + // 떠 있는 판 부품(머리 · 닫기 ✕ · 몸 · 553-6) — 자리는 `.ss-dialog` + const { root: dialog, body } = createFloatPanel({ + title: " ", + onClose: () => (closePanel(), back()), }); + dialog.classList.add("ss-dialog"); + dialog.setAttribute("hidden", ""); + const title = dialog.querySelector(".ui-float-panel__title") as HTMLElement; ctx.root.append(dialog); let panel: PartHandle | null = null; const closePanel = (): void => { @@ -141,7 +137,6 @@ export function mountDataMenu(ctx: SpreadsheetContext, back: () => void): DataMe body.replaceChildren(); dialog.setAttribute("hidden", ""); }; - shut.addEventListener("click", () => (closePanel(), back())); dialog.addEventListener("keydown", (e) => { if (e.key !== "Escape") return; e.stopPropagation(); diff --git a/A00_Common/spreadsheet/spreadsheet_errcheck.ts b/A00_Common/spreadsheet/spreadsheet_errcheck.ts index b46422341..103f91131 100644 --- a/A00_Common/spreadsheet/spreadsheet_errcheck.ts +++ b/A00_Common/spreadsheet/spreadsheet_errcheck.ts @@ -11,7 +11,7 @@ * 시트 전체를 훑지 말고 그리는 칸만 물음(값 하나 · 칸 하나 읽는 값싼 부름). * ========================================================================== */ -import { el } from "@ui/ui_template_elements"; +import { createIconButton, el } from "@ui/ui_template_elements"; import { currentLanguageIndex } from "@ui/ui_template_locale"; import { toA1 } from "./spreadsheet_address"; import { isError } from "./spreadsheet_eval"; @@ -137,11 +137,9 @@ export function attachErrorTip(ctx: SpreadsheetContext, trace?: TraceHandle): Er const g = ctx.grid.root.getBoundingClientRect(); layer.style.left = `${box.x - (a.left - g.left) - 20}px`; layer.style.top = `${box.y - (a.top - g.top)}px`; - const btn = el("button", { - className: "ss-errtip__btn", - text: "⚠", - attrs: { type: "button", "aria-label": w.까닭 }, - }); + const btn = createIconButton({ glyph: "⚠", title: w.까닭, variant: "outline", size: 18 }); + btn.classList.add("ss-errtip__btn"); + btn.removeAttribute("title"); // 까닭은 옆 풍선이 보임 const balloon = el("div", { className: "ss-errtip__balloon", text: w.까닭 }); btn.addEventListener("mousedown", (ev) => ev.stopPropagation()); btn.addEventListener("click", () => (menu ? closeMenu() : openMenu(w, r, c))); diff --git a/A00_Common/spreadsheet/spreadsheet_extras.ts b/A00_Common/spreadsheet/spreadsheet_extras.ts index ccf2db0c6..437ce0520 100644 --- a/A00_Common/spreadsheet/spreadsheet_extras.ts +++ b/A00_Common/spreadsheet/spreadsheet_extras.ts @@ -6,7 +6,7 @@ * 빨간 세모는 C 격자 · 우클릭 [메모 …] 는 E 메뉴 몫(브레인 배정). * ========================================================================== */ -import { el } from "@ui/ui_template_elements"; +import { createButton, el } from "@ui/ui_template_elements"; import { watchClose } from "./spreadsheet_actions"; import { parseClipboard } from "./spreadsheet_clipboard"; import { attachComments, getComment, setComment } from "./spreadsheet_comments"; @@ -138,10 +138,8 @@ export function attachExtras( : undefined; picker.replaceChildren( ...(Object.keys(TEXT.modes) as PasteSpecialMode[]).map((mode) => { - const b = el("button", { - text: TEXT.modes[mode], - attrs: { type: "button", "data-mode": mode }, - }); + const b = createButton({ label: TEXT.modes[mode], variant: "ghost", size: 22 }); + b.dataset.mode = mode; b.addEventListener("click", () => { picker.setAttribute("hidden", ""); // 늦게 — 크기 예산 diff --git a/A00_Common/spreadsheet/spreadsheet_find_panel.ts b/A00_Common/spreadsheet/spreadsheet_find_panel.ts index 985ffd1bd..d2894ad96 100644 --- a/A00_Common/spreadsheet/spreadsheet_find_panel.ts +++ b/A00_Common/spreadsheet/spreadsheet_find_panel.ts @@ -4,7 +4,8 @@ * Enter = 다음 · Esc = 닫고 격자로. 바꾸기 = 활성 칸이 맞으면 바꾸고 다음으로(엑셀). * ========================================================================== */ -import { el } from "@ui/ui_template_elements"; +import { createButton, createIconButton, el, setUiSize } from "@ui/ui_template_elements"; +import { createFloatPanel } from "@ui/ui_template_float_panel"; import { findAll, findNext, replaceAll, replaceOne, type FindOptions } from "./spreadsheet_find"; import { selectCell } from "./spreadsheet_selection"; import type { PartHandle, SpreadsheetContext } from "./spreadsheet_view_types"; @@ -29,12 +30,14 @@ export interface FindPanelHandle extends PartHandle { } export function mountFindPanel(ctx: SpreadsheetContext, back: () => void): FindPanelHandle { - const query = el("input", { className: "ss-find__input", attrs: { placeholder: TEXT.find } }); - const repl = el("input", { className: "ss-find__input", attrs: { placeholder: TEXT.replace } }); + const field = (placeholder: string): HTMLInputElement => + setUiSize(el("input", { className: "ui-input ss-find__input", attrs: { placeholder } }), 24); + const query = field(TEXT.find); + const repl = field(TEXT.replace); const status = el("span", { className: "ss-find__status" }); const button = (text: string, onClick: () => void): HTMLButtonElement => { - const b = el("button", { className: "ss-find__btn", text, attrs: { type: "button" } }); - b.addEventListener("click", onClick); + const b = createButton({ label: text, variant: "ghost", size: 22, onClick }); + b.classList.add("ss-find__btn"); return b; }; const check = (text: string): HTMLInputElement => { @@ -42,8 +45,8 @@ export function mountFindPanel(ctx: SpreadsheetContext, back: () => void): FindP options.append(el("label", { className: "ss-find__opt", children: [box, text] })); return box; }; - const closeBtn = button("×", close); - closeBtn.title = TEXT.close; + const closeBtn = createIconButton({ glyph: "×", title: TEXT.close, size: 22, onClick: close }); + closeBtn.classList.add("ss-find__btn"); const options = el("div", { className: "ss-find__row" }); const caseBox = check(TEXT.case); const wholeBox = check(TEXT.whole); @@ -52,19 +55,19 @@ export function mountFindPanel(ctx: SpreadsheetContext, back: () => void): FindP className: "ss-find__row", children: [repl, button(TEXT.one, one), button(TEXT.all, all)], }); - const root = el("div", { - className: "ss-find", - attrs: { hidden: "" }, - children: [ - el("div", { - className: "ss-find__row", - children: [query, button(TEXT.next, next), closeBtn], - }), - replaceRow, - options, - status, - ], - }); + // 떠 있는 판 부품(머리 없음 · 553-6) — 자리는 `.ss-find` + const { root, body } = createFloatPanel({ popover: true }); + root.classList.add("ss-find"); + root.setAttribute("hidden", ""); + body.append( + el("div", { + className: "ss-find__row", + children: [query, button(TEXT.next, next), closeBtn], + }), + replaceRow, + options, + status, + ); ctx.root.append(root); const opts = (): FindOptions => ({ diff --git a/A00_Common/spreadsheet/spreadsheet_format_dialog.css b/A00_Common/spreadsheet/spreadsheet_format_dialog.css index 64cf66693..8f8730213 100644 --- a/A00_Common/spreadsheet/spreadsheet_format_dialog.css +++ b/A00_Common/spreadsheet/spreadsheet_format_dialog.css @@ -1,50 +1,9 @@ /* ============================================================================= * spreadsheet_format_dialog.css (2단계 · 주인 sub_laptop_1) - * 셀 서식 대화상자 — 뿌리 배경(`.ui-confirm`)은 공용 확인 모달과 같은 것을 그대로 씀. + * 셀 서식 대화상자 — 창 · 탭 · 칸 = 부품 모달(40rem) · 탭(32) · 입력 · 고르기(28) · 여기는 안 배치만(553-6). * 색 · 간격은 테마 토큰만(`ui_template_theme.css`). * ========================================================================== */ -.ss-fmtdlg__panel { - display: flex; - flex-direction: column; - width: min(560px, 92vw); - max-height: 84vh; - padding: var(--spacing-16); - border-radius: var(--radius-cards); - background: var(--color-surface-raised); - box-shadow: var(--shadow-lg); -} - -.ss-fmtdlg__title { - margin: 0 0 var(--spacing-8); - font-size: 1rem; - color: var(--color-text-body); -} - -.ss-fmtdlg__tabs { - display: flex; - flex-wrap: wrap; - gap: 2px; - border-bottom: 1px solid var(--color-border); -} - -.ss-fmtdlg__tabbtn { - padding: 6px 12px; - border: 1px solid var(--color-border); - border-bottom: 0; - border-radius: var(--radius-sm) var(--radius-sm) 0 0; - background: var(--color-paper); - color: var(--color-text-secondary); - font-size: 0.82rem; - cursor: pointer; -} - -.ss-fmtdlg__tabbtn.is-active { - background: var(--color-canvas); - color: var(--color-text-body); - font-weight: 600; -} - .ss-fmtdlg__body { flex: 1; min-height: 300px; @@ -68,21 +27,7 @@ width: 140px; flex-shrink: 0; color: var(--color-text-secondary); - font-size: 0.82rem; -} - -.ss-fmtdlg__row select, -.ss-fmtdlg__row input[type="text"], -.ss-fmtdlg__row input:not([type]), -.ss-fmtdlg__row input[type="number"], -.ss-fmtdlg__code { - height: 28px; - padding: 0 6px; - border: 1px solid var(--color-border); - border-radius: var(--radius-sm); - background: var(--color-canvas); - color: var(--color-text-body); - font-size: 0.82rem; + font-size: var(--text-body-sm); } .ss-fmtdlg__code { @@ -135,7 +80,7 @@ .ss-fmtdlg__note { margin: 0 0 var(--spacing-8); color: var(--color-text-muted); - font-size: 0.8rem; + font-size: var(--text-caption); } .ss-fmtdlg__actions { diff --git a/A00_Common/spreadsheet/spreadsheet_format_dialog.ts b/A00_Common/spreadsheet/spreadsheet_format_dialog.ts index ce97d678d..e4c2d2442 100644 --- a/A00_Common/spreadsheet/spreadsheet_format_dialog.ts +++ b/A00_Common/spreadsheet/spreadsheet_format_dialog.ts @@ -12,7 +12,9 @@ * 우클릭 메뉴 [셀 서식] 도 같은 함수를 부르면 됨(`spreadsheet_menu.ts`). * ========================================================================== */ -import { createButton, el } from "@ui/ui_template_elements"; +import { createButton, el, setUiSize } from "@ui/ui_template_elements"; +import { createTabs } from "@ui/ui_template_tabs"; +import { openModal } from "@ui/ui_template_modal"; import { toFrac } from "@ui/sheet/ui_template_sheet_frac"; import { colName, rangeToA1, toA1 } from "./spreadsheet_address"; import { @@ -39,6 +41,7 @@ const TEXT = { tabProtect: "보호", ok: "확인", cancel: "취소", + close: "닫기", category: "범주", decimals: "소수 자릿수", thousands: "천 단위 구분 기호 사용", @@ -105,17 +108,9 @@ export function openFormatDialog(ctx: SpreadsheetContext): void { const spansMany = range.r0 !== range.r1 || range.c0 !== range.c1; let mergeWanted = (ctx.sheet().병합 ?? []).includes(rangeToA1(range)); - const overlay = el("div", { className: "ui-confirm ss-fmtdlg" }); - const panel = el("div", { className: "ss-fmtdlg__panel" }); const tabsBar = el("div", { className: "ss-fmtdlg__tabs" }); const body = el("div", { className: "ss-fmtdlg__body" }); - overlay.append(panel); - panel.append(el("h2", { className: "ss-fmtdlg__title", text: TEXT.title }), tabsBar, body); - - const close = (): void => overlay.remove(); - overlay.addEventListener("click", (ev) => { - if (ev.target === overlay) close(); - }); + let close = (): void => {}; // ── 표시 형식 ──────────────────────────────────────────────────────── let category: Category = guessCategory(draft.형식); @@ -464,22 +459,25 @@ export function openFormatDialog(ctx: SpreadsheetContext): void { [TEXT.tabProtect, protectTab], ]; - function showTab(index: number): void { - body.replaceChildren(tabs[index][1]()); - tabsBar.querySelectorAll(".ss-fmtdlg__tabbtn").forEach((btn, i) => { - btn.classList.toggle("is-active", i === index); - }); - } - - tabs.forEach(([label], i) => { - const btn = el("button", { - className: "ss-fmtdlg__tabbtn", - text: label, - attrs: { type: "button" }, - }); - btn.addEventListener("click", () => showTab(i)); - tabsBar.append(btn); + const tabBar = createTabs({ + tabs: tabs.map(([label], i) => ({ key: String(i), label })), + value: "0", + size: 32, + onChange: (key) => showTab(Number(key)), }); + tabsBar.append(tabBar.root); + + function showTab(index: number): void { + const tab = tabs[index][1](); + // 칸 = 부품 입력 · 고르기 28(553-6) + const fields = "select, input:not([type]), input[type=text], input[type=number]"; + for (const f of tab.querySelectorAll(fields)) { + f.classList.add(f.tagName === "SELECT" ? "ui-select" : "ui-input"); + setUiSize(f, 28); + } + body.replaceChildren(tab); + tabBar.select(String(index)); + } function apply(): void { ctx.dispatch({ 종류: "서식", 시트: ctx.selection.시트, 범위: ctx.selection.범위, 바꿀: draft }); @@ -497,13 +495,21 @@ export function openFormatDialog(ctx: SpreadsheetContext): void { const actions = el("div", { className: "ss-fmtdlg__actions", children: [ - createButton({ label: TEXT.cancel, variant: "ghost", onClick: close }), + createButton({ label: TEXT.cancel, variant: "ghost", onClick: () => close() }), createButton({ label: TEXT.ok, variant: "filled", onClick: apply }), ], }); - panel.append(actions); showTab(0); - document.body.append(overlay); - dialogKeys(overlay, close, apply); + openModal({ + title: TEXT.title, + closeLabel: TEXT.close, + width: "40rem", + dialogClass: "ss-fmtdlg", + mount: (box, shut) => { + close = shut; + box.append(tabsBar, body, actions); + dialogKeys(box.parentElement ?? box, shut, apply); + }, + }); } diff --git a/A00_Common/spreadsheet/spreadsheet_links.css b/A00_Common/spreadsheet/spreadsheet_links.css index 185a59526..f1087d6a5 100644 --- a/A00_Common/spreadsheet/spreadsheet_links.css +++ b/A00_Common/spreadsheet/spreadsheet_links.css @@ -120,20 +120,11 @@ width: 320px; padding: var(--spacing-8); border: 1px solid var(--color-border); - border-radius: var(--radius-sm); + border-radius: var(--radius-cards); background: var(--color-surface-raised); box-shadow: var(--shadow-lg); } -.ss-links__search { - padding: 4px 6px; - border: 1px solid var(--color-border); - border-radius: var(--radius-sm); - background: var(--color-canvas); - color: var(--color-text-body); - font: inherit; -} - .ss-links__list { display: flex; flex-direction: column; @@ -155,7 +146,7 @@ } .ss-links__row:hover { - background: var(--color-mist-violet); + background: var(--color-hover); } .ss-links__note { diff --git a/A00_Common/spreadsheet/spreadsheet_links.ts b/A00_Common/spreadsheet/spreadsheet_links.ts index 6fec08291..17f0229d3 100644 --- a/A00_Common/spreadsheet/spreadsheet_links.ts +++ b/A00_Common/spreadsheet/spreadsheet_links.ts @@ -585,8 +585,8 @@ export function mountLinks( function openPick(anchor: HTMLElement): void { closePick(); const input = el("input", { - className: "ss-links__search", - attrs: { type: "search", placeholder: TEXT.search }, + className: "ui-input ss-links__search", + attrs: { type: "search", placeholder: TEXT.search, "data-size": "28" }, }) as HTMLInputElement; const list = el("div", { className: "ss-links__list" }); const note = (text: string) => el("div", { className: "ss-links__note", text }); diff --git a/A00_Common/spreadsheet/spreadsheet_menu.ts b/A00_Common/spreadsheet/spreadsheet_menu.ts index c47a50612..14ea72675 100644 --- a/A00_Common/spreadsheet/spreadsheet_menu.ts +++ b/A00_Common/spreadsheet/spreadsheet_menu.ts @@ -59,15 +59,15 @@ export function attachMenu(ctx: SpreadsheetContext): PartHandle { /** 메모 글 입력 — 작은 오버레이(native prompt 안 씀, 자동화 창이 native 창을 자동 취소하는 * 문제는 `showConfirmDialog` 머리 주석과 같은 까닭). 저장을 누르면 `onSave`. */ function openCommentEditor(initial: string, onSave: (text: string) => void): void { - const overlay = el("div", { className: "ss-comment-editor" }); - const panel = el("div", { className: "ss-comment-editor__panel" }); + const overlay = el("div", { className: "ui-confirm ss-comment-editor" }); + const panel = el("div", { className: "ui-confirm__panel" }); const textarea = el("textarea", { - className: "ss-comment-editor__input", + className: "ui-input ss-comment-editor__input", }) as HTMLTextAreaElement; textarea.value = initial; const done = (): void => overlay.remove(); const actions = el("div", { - className: "ss-comment-editor__actions", + className: "ui-confirm__actions", children: [ createButton({ label: "취소", variant: "ghost", onClick: done }), createButton({ diff --git a/A00_Common/spreadsheet/spreadsheet_sort_dialog.ts b/A00_Common/spreadsheet/spreadsheet_sort_dialog.ts index 92effb8cd..e4fb8185c 100644 --- a/A00_Common/spreadsheet/spreadsheet_sort_dialog.ts +++ b/A00_Common/spreadsheet/spreadsheet_sort_dialog.ts @@ -100,12 +100,17 @@ export function openSortDialog(ctx: SpreadsheetContext): () => void { function drawKeys() { list.replaceChildren( ...keys.map((k, i) => { - const col = el("select", { attrs: { "aria-label": t("Column") } }); + const col = el("select", { + className: "ui-select", + attrs: { "aria-label": t("Column"), "data-size": "28" }, + }); for (let c = rg.c0; c <= rg.c1; c++) col.append(el("option", { text: columnLabel(c), attrs: { value: String(c) } })); col.value = String(k.열); col.addEventListener("change", () => (k.열 = Number(col.value))); const dir = el("select", { + className: "ui-select", + attrs: { "data-size": "28" }, children: [ el("option", { text: t("Asc"), attrs: { value: "asc" } }), el("option", { text: t("Desc"), attrs: { value: "desc" } }), diff --git a/A00_Common/spreadsheet/spreadsheet_sortfilter.css b/A00_Common/spreadsheet/spreadsheet_sortfilter.css index 36244d642..821104eac 100644 --- a/A00_Common/spreadsheet/spreadsheet_sortfilter.css +++ b/A00_Common/spreadsheet/spreadsheet_sortfilter.css @@ -7,7 +7,7 @@ display: flex; align-items: center; justify-content: center; - background: rgb(0 0 0 / 18%); + background: var(--color-scrim); } .ss-sort__box, @@ -48,11 +48,6 @@ .ss-sort__row select { flex: 1; - padding: var(--spacing-4); - border: 1px solid var(--color-border); - border-radius: var(--radius-sm); - background: var(--color-canvas); - color: inherit; } .ss-sort__row option { @@ -92,8 +87,8 @@ } .ss-filter__btn.is-on { - color: var(--color-royal-amethyst); - border-color: var(--color-royal-amethyst); + color: var(--color-accent); + border-color: var(--color-accent); } .ss-filter__panel { @@ -130,5 +125,5 @@ } .ss-filter__link:hover { - background: var(--color-mist-violet); + background: var(--color-hover); } diff --git a/A00_Common/spreadsheet/spreadsheet_stage3.css b/A00_Common/spreadsheet/spreadsheet_stage3.css index e50db4efe..2d394bd59 100644 --- a/A00_Common/spreadsheet/spreadsheet_stage3.css +++ b/A00_Common/spreadsheet/spreadsheet_stage3.css @@ -14,7 +14,7 @@ padding: var(--spacing-8); background: var(--color-surface); border: 1px solid var(--color-border); - border-radius: 8px; + border-radius: var(--radius-cards); min-width: 280px; } @@ -89,7 +89,7 @@ } .ss-validation__dropdown-item:hover { - background: var(--color-mist-violet); + background: var(--color-hover); } .ss-statusbar { diff --git a/A00_Common/spreadsheet/spreadsheet_toolbar.css b/A00_Common/spreadsheet/spreadsheet_toolbar.css index 92606abe7..c5c3cb80f 100644 --- a/A00_Common/spreadsheet/spreadsheet_toolbar.css +++ b/A00_Common/spreadsheet/spreadsheet_toolbar.css @@ -215,42 +215,13 @@ /* ── 메모 편집 창(칸 우클릭 [메모 삽입 · 편집]) ──────────────────────────────── */ -.ss-comment-editor { - position: fixed; - inset: 0; - z-index: var(--z-modal); - display: flex; - align-items: center; - justify-content: center; - background: var(--color-scrim); -} - -.ss-comment-editor__panel { - display: flex; - flex-direction: column; - gap: var(--spacing-8); - width: 280px; - padding: var(--spacing-16); - border-radius: var(--radius-cards); - background: var(--color-surface-raised); - box-shadow: var(--shadow-lg); -} - +/* 창 = 공용 확인창(.ui-confirm) · 칸 = 부품 입력(여러 줄) — 여기는 칸 크기만(553-6) */ .ss-comment-editor__input { + display: block; + box-sizing: border-box; + width: 100%; min-height: 80px; - padding: var(--spacing-8); - border: 1px solid var(--color-border); - border-radius: var(--radius-sm); - background: var(--color-canvas); - color: var(--color-text-body); - font: inherit; - resize: vertical; -} - -.ss-comment-editor__actions { - display: flex; - justify-content: flex-end; - gap: var(--spacing-8); + margin-bottom: var(--spacing-16); } /* ⋯ 칸 메뉴(기기대응 3-5) — 터치 모드에서만 */