Merge remote-tracking branch 'origin/dev' into sub_laptop_3

This commit is contained in:
2026-09-28 18:46:24 +09:00
9 changed files with 43 additions and 24 deletions
+14 -3
View File
@@ -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();
+3 -2
View File
@@ -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 {
@@ -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;
@@ -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 {
@@ -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));
@@ -119,9 +119,9 @@ export function buildSide(opt: SideOptions): SideHandle {
const editButtons = new Map<Kind, { copy: HTMLButtonElement; del: HTMLButtonElement }>();
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);
@@ -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);
+4 -1
View File
@@ -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) {
@@ -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);