diff --git a/M01_MasterData/M01_MasterData_UI_Combo.ts b/M01_MasterData/M01_MasterData_UI_Combo.ts index fa94820a..9eb01737 100644 --- a/M01_MasterData/M01_MasterData_UI_Combo.ts +++ b/M01_MasterData/M01_MasterData_UI_Combo.ts @@ -238,7 +238,7 @@ export function mountM01Combo( memo.input.value = row.메모 ?? ""; memo.input.addEventListener("input", () => (row.메모 = memo.input.value || null)); const name = el("button", { - className: "ui-btn ui-btn--ghost", + className: "ui-btn ui-btn--ghost ui-btn--sm", text: info?.이름 ?? row.로직, attrs: { type: "button", title: tc("Open") }, }); @@ -249,11 +249,22 @@ export function mountM01Combo( const btns = el("div", { className: "m01-logic__chips", children: [ - createButton({ label: tc("Up"), variant: "ghost", onClick: () => move(i, -1) }), - createButton({ label: tc("Down"), variant: "ghost", onClick: () => move(i, 1) }), + createButton({ + label: tc("Up"), + variant: "ghost", + size: "sm", + onClick: () => move(i, -1), + }), + createButton({ + label: tc("Down"), + variant: "ghost", + size: "sm", + onClick: () => move(i, 1), + }), createButton({ label: tc("Remove"), variant: "ghost", + size: "sm", onClick: () => { combo.담은로직.splice(i, 1); drawTable(); diff --git a/M01_MasterData/M01_MasterData_UI_Rows.ts b/M01_MasterData/M01_MasterData_UI_Rows.ts index 07f5b564..a3b5d24d 100644 --- a/M01_MasterData/M01_MasterData_UI_Rows.ts +++ b/M01_MasterData/M01_MasterData_UI_Rows.ts @@ -248,12 +248,13 @@ export function renderRows(host: HTMLElement, pick: Pick, q: string): () => void } function actionCell(label: string, onClick: () => void): HTMLTableCellElement { - return el("td", { children: [createButton({ label, variant: "ghost", onClick })] }); + return el("td", { children: [createButton({ label, variant: "ghost", size: "sm", onClick })] }); } type Put = (row: Row) => void; -const rowBtn = (label: string): HTMLButtonElement => createButton({ label, variant: "ghost" }); +const rowBtn = (label: string): HTMLButtonElement => + createButton({ label, variant: "ghost", size: "sm" }); /** 품셈재료 — 가격 연결(자재품목 키 · 후보 조건 · 없음) · 고르기 모달. */ function linkedCell(row: Row, cur: Row, put?: Put): HTMLTableCellElement { diff --git a/M01_MasterData/M01_MasterData_UI_Style.css b/M01_MasterData/M01_MasterData_UI_Style.css index 6d2983e3..2b909b1b 100644 --- a/M01_MasterData/M01_MasterData_UI_Style.css +++ b/M01_MasterData/M01_MasterData_UI_Style.css @@ -162,12 +162,6 @@ padding: 2px var(--spacing-4); } -/* 표 칸 안 공용 단추 — 줄 높이에 맞춰 작게 */ -.m01-master__grid .ui-btn { - padding: 2px var(--spacing-8); - font-size: var(--text-caption); -} - .m01-master__pager { display: flex; align-items: center; diff --git a/M02_MasterTemplete/M02_MasterTemplete_Structure.css b/M02_MasterTemplete/M02_MasterTemplete_Structure.css index 104ed6ac..e291744e 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Structure.css +++ b/M02_MasterTemplete/M02_MasterTemplete_Structure.css @@ -54,13 +54,19 @@ min-width: 0; } +/* 머리 = 번호 · [수정] 한 줄, 이름은 그 아래 전체 폭 — 긴 이름도 잘리지 않게 줄바꿈 */ +.m02-struct__head { + flex-wrap: wrap; +} + .m02-struct__title { + order: 1; + flex: 1 0 100%; + min-width: 0; margin: 0; - overflow: hidden; color: var(--color-text); font-size: var(--text-body); - text-overflow: ellipsis; - white-space: nowrap; + overflow-wrap: anywhere; /* 이름이 길어도 잘리지 않게 줄바꿈 */ } .m02-struct__no { diff --git a/M02_MasterTemplete/M02_MasterTemplete_Structure.ts b/M02_MasterTemplete/M02_MasterTemplete_Structure.ts index b95e356c..a52ae745 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Structure.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Structure.ts @@ -264,7 +264,7 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane const columnName = el("span", { className: "m02-struct__title" }); const number = el("span", { className: "m02-struct__no" }); - const edit = createButton({ label: TEXT.edit, variant: "filled" }); + const edit = createButton({ label: TEXT.edit, variant: "filled", size: "sm" }); const previewHost = el("div", { className: "m02-struct__preview" }); const infoCard = card( TEXT.drawingInfo, @@ -288,6 +288,7 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane const editButton = createButton({ label: fill(TEXT.editSheet, PARTS[kind].word), variant: "ghost", + size: "sm", }); const host = el("div", { className: "m02-struct__sheet" }); editButton.addEventListener("click", () => void openEdit(kind)); diff --git a/M02_MasterTemplete/M02_MasterTemplete_UI_Side.ts b/M02_MasterTemplete/M02_MasterTemplete_UI_Side.ts index 80b5c960..e1bbec82 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_UI_Side.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_UI_Side.ts @@ -119,9 +119,9 @@ export function buildSide(opt: SideOptions): SideHandle { const editButtons = new Map(); const actionRow = (kind: Kind): HTMLElement[] => { if (!canEdit(layer, opt.isAdmin)) return []; - const btnNew = createButton({ label: L("M02_New"), variant: "filled" }); - const copy = createButton({ label: L("M02_Copy"), variant: "ghost" }); - const del = createButton({ label: L("M02_Delete"), variant: "danger" }); + const btnNew = createButton({ label: L("M02_New"), variant: "filled", size: "sm" }); + const copy = createButton({ label: L("M02_Copy"), variant: "ghost", size: "sm" }); + const del = createButton({ label: L("M02_Delete"), variant: "danger", size: "sm" }); editButtons.set(kind, { copy, del }); btnNew.addEventListener("click", () => newTemplate(kind)); copy.addEventListener("click", copyTemplate); diff --git a/M02_MasterTemplete/M02_MasterTemplete_UI_Style.css b/M02_MasterTemplete/M02_MasterTemplete_UI_Style.css index 5c3ae7ed..cb26dc9c 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_UI_Style.css +++ b/M02_MasterTemplete/M02_MasterTemplete_UI_Style.css @@ -26,7 +26,7 @@ .m02-main__head { display: flex; - flex-wrap: nowrap; + flex-wrap: wrap; align-items: center; gap: var(--spacing-12); } @@ -34,10 +34,7 @@ .m02-main__title { flex: 0 1 auto; min-width: 3rem; - max-width: 9rem; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + overflow-wrap: anywhere; /* 번호 + 이름 — 잘리지 않게 줄바꿈 */ margin: 0; color: var(--color-text); font-size: var(--text-body); diff --git a/ui_template/ui_template_elements.ts b/ui_template/ui_template_elements.ts index cb8fc767..4bd498b4 100644 --- a/ui_template/ui_template_elements.ts +++ b/ui_template/ui_template_elements.ts @@ -24,11 +24,14 @@ export { el } from "./ui_template_elements_base"; * -------------------------------------------------------------------------- */ export type ButtonVariant = "filled" | "ghost" | "pill" | "danger" | "glass"; +export type ButtonSize = "md" | "sm"; export interface ButtonOptions { /** 표시 텍스트 (i18n 결과 문자열을 전달) */ label: string; variant?: ButtonVariant; + /** 크기 — 기본 md · sm = 표 칸·카드 머리용 작은 단추(글자 캡션 크기) */ + size?: ButtonSize; /** 이벤트 핸들러 (frontend.md §4: on[페이지]_[기능]_[액션] 명명) */ onClick?: (ev: MouseEvent) => void; disabled?: boolean; @@ -40,7 +43,7 @@ export interface ButtonOptions { export function createButton(opts: ButtonOptions): HTMLButtonElement { const variant = opts.variant ?? "filled"; const btn = el("button", { - className: `ui-btn ui-btn--${variant}`, + className: `ui-btn ui-btn--${variant}${opts.size === "sm" ? " ui-btn--sm" : ""}`, attrs: { type: opts.type ?? "button" }, }); if (opts.iconStart) { diff --git a/ui_template/ui_template_elements_styles.ts b/ui_template/ui_template_elements_styles.ts index 598b4df1..5a1dd3d1 100644 --- a/ui_template/ui_template_elements_styles.ts +++ b/ui_template/ui_template_elements_styles.ts @@ -33,6 +33,12 @@ const BASE_CSS = ` .ui-btn:disabled { opacity: 0.5; cursor: not-allowed; } .ui-btn__icon { display: inline-flex; width: 16px; height: 16px; } +/* 작은 크기 — 다섯 모양 모두에 먹음(padding · 글자만 바꿈) */ +.ui-btn--sm { + padding: 2px var(--spacing-8); + font-size: var(--text-caption); +} + .ui-btn--filled { background-color: var(--color-primary); color: var(--color-primary-text);