fix(sw): 2026-10-21 SW design review and responsive header without More from 760px

User-approved design review (2026-10-21):
- SW Header: from 760px up nothing moves into More; the five menus stay with their
  titles (titles and values ellipsize), file name shrinks to 96px. Open next to the
  logo no longer blocks field shrinking above 760px (760/768 overflow fixed, also for
  configured `controls` headers). Dropdown yellow ring inside the button, black seam.
- Property Bar values as read-only red text; property popup "=" labels, read-only
  black values, per-entry hover with pointer.
- Home Menu recent files (3 rows, path + name caption, empty preview), Footer + slot
  guide off by default, Viewer file list without icons, Storybook widths 1920-760.
- Tests: old More expectations (integrated-improvement, keyboard-dismiss,
  footer-popup-viewer-refinement, storybook-cleanup-stage1) moved to the new rule;
  functional checks kept.
This commit is contained in:
shkim4 committed 2026-10-21 17:29:25 +09:00
1 parent a25d2b31c5
commit 2fc1b3e108
37 files changed
+447 -211

No files matched your search

+16 -4
View File
@@ -1,7 +1,7 @@
import { useRef, useState, type ReactNode } from "react"
import type { Meta, StoryObj } from "@storybook/react-vite"
import {
SWHeader, SWSelect, SWViewerButton, SWViewerField, SWViewerHeader, SWViewerHint, SWViewerInput, SWViewerMenu, SWViewerPanel, SWViewerSection, SWViewerSwitch,
SWHeader, SWHeaderWindowControls, SWSelect, SWViewerButton, SWViewerField, SWViewerHeader, SWViewerHint, SWViewerInput, SWViewerMenu, SWViewerPanel, SWViewerSection, SWViewerSwitch,
type SWViewerHeaderGroup, type SWViewerMenuEntry,
} from "@hm-design/sw"
import "@hm-design/sw/styles.css"
@@ -58,12 +58,21 @@ function AboutPanel({ demo }: { demo: ViewerDemo }) {
)
}
function ViewerScreen({ width = 1440, initialDocument = SAMPLES[1].name as string | null, open = [] as ("layers" | "options" | "properties")[] }) {
function ViewerScreen({ width = 1440, initialDocument = SAMPLES[1].name as string | null, open = [] as ("layers" | "options" | "properties")[], windowControls = false }) {
const demo = useViewerDemo({ initialDocument, initialPanels: open })
// 2026-10-21 new viewer version: SWHeader's own minimize / close (SWHeaderWindowControls, same icons, size, hover)
// at the right end after the existing trailing items (the `trailing` slot, no new API). The program owns the real
// window actions (onMinimize / onClose, as in SWHeader); the Story only logs them.
const trailing = windowControls ? (
<>
{demo.trailing}
<SWHeaderWindowControls showWindowMove={false} onMinimize={() => demo.record("minimize")} onClose={() => demo.record("close")} />
</>
) : demo.trailing
return (
<>
<Log lines={demo.log} />
<ViewerFrame width={width} header={<SWViewerHeader documentTitle={demo.documentName} {...demo.fileProps} groups={demo.groups} trailing={demo.trailing} onCommand={demo.onCommand} />}>
<ViewerFrame width={width} header={<SWViewerHeader documentTitle={demo.documentName} {...demo.fileProps} groups={demo.groups} trailing={trailing} onCommand={demo.onCommand} />}>
<LayerPanel demo={demo} strategy="absolute" />
<OptionsPanel demo={demo} strategy="absolute" inset={{ side: 356 }} />
<PropertiesPanel demo={demo} strategy="absolute" inset={{ side: 24, top: 488 }} />
@@ -81,6 +90,9 @@ export const ViewerHeader: Story = {
<StorySection title="기본형 (1440px, 도면 열림)">
<ViewerScreen />
</StorySection>
<StorySection title="최소화 · 닫기 버튼 (1440px, 도면 열림)" description="SWHeader의 최소화·닫기 버튼(SWHeaderWindowControls)을 trailing 오른쪽 끝에 그대로 둔 버전입니다. 실제 창 최소화·닫기는 프로그램이 처리합니다.">
<div data-viewer-window-controls=""><ViewerScreen windowControls /></div>
</StorySection>
</StoryPage>
),
}
@@ -324,7 +336,7 @@ export const Responsive: Story = {
<StoryPageHeader kicker={KICKER} title="SW Viewer — 화면 너비" />
<Log lines={demo.log} />
<div className="sw-story-stack">
{[1440, 1100, 860, 520].map(width => (
{[1920, 1440, 1280, 950, 860, 760, 520].map(width => (
<StorySection key={width} title={`${width}px`}>
<div className="sw-story-scroller sw-viewer-story-menu-row"><div style={{ width }} data-width={width}><SWViewerHeader documentTitle={demo.documentName} {...demo.fileProps} groups={demo.groups} trailing={demo.trailing} onCommand={demo.onCommand} /></div></div>
</StorySection>