SW package 0.2.0 integrated improvement (Task A, steps 1-8). All new props are
optional; existing SW Stories are pixel-identical to the previous build (28/28).
- Build reproducibility: dist text normalized to LF, dist/build-info.json
(commit, dirty, tool versions, no timestamp), packages/sw/.gitattributes
(eol=lf). LF checkouts give identical dist and tarball.
- SWHeader: documentOpenPlacement ("menu" default | "header": Open right of
the logo in the existing document-button look, reusing onDocumentOpen and
documentOpenLabel, no duplicate Open in the dropdown), leading slot,
hiddenControls sub-items documentNew / documentOpen / layerFreeze /
layerLock. Open moves into More on measured overflow (with hysteresis).
- showNew / showOpen (SWHeaderDocumentTitle), showFreeze / showLock (layer
menu, field, property window list).
- SWToolButton (text / pill / document) and SWToolGroup (radio selection),
reusing the existing toggle, pill and file-name looks.
- SWPopup / SWPopupSection / SWPopupRow on the shared property window frame;
SWHeaderPropertyPanel gains children, title, autoFocus and optional
selection / properties / groups. Escape stack for several popups.
- Field dropdowns inside a popup use the shared fixed overlay
(useSWFixedDropdownPosition), so the scrolling body no longer clips them.
- AI guide, examples E/F, README, Storybook (SW/Header/Options, SW/Tool,
SW/Popup) and verification record docs/sw/sw-integrated-improvement-2026-10-19.md.
- Regression scripts rescoped for the intended changes (unused-removal 81/81,
overview 52/54 with the two pre-existing historical assertions).
Known limitation (unresolved): tools / leading content (incl. SWToolGroup)
does not move into More. With a wide tool bar the configured fields shrink
instead; in Example F the document name and layer field reach 0px at 390px.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
51 lines
2.7 KiB
TypeScript
51 lines
2.7 KiB
TypeScript
// Example F — a viewer header: logo → Open → file → layer → color → K, plus a tool bar (Model / Layout, 2.5D,
|
|
// Fit) after the menus. Everything is SWHeader props, so the existing responsive More serves the whole layout
|
|
// (Open moves into More when the measured header has no room). No freeze / lock, no "+ New" in this product.
|
|
import { useState } from "react"
|
|
import { SWHeader, SWToolButton, SWToolGroup } from "@hm-design/sw"
|
|
import { colors, documents, layers } from "./sample-data"
|
|
|
|
// The program supplies its icons (24 x 23 box of a pill button). Colors: the existing print icon fill #B6D0C9,
|
|
// hover --hm-sw-header-selected-color (#FFC600), as in DESIGN_RULES §2.
|
|
const FitIcon = ({ color }: { color: string }) => (
|
|
<svg viewBox="0 0 24 23" width="24" height="23" aria-hidden="true">
|
|
<path d="M2 8V2h6M16 2h6v6M22 15v6h-6M8 21H2v-6" fill="none" stroke={color} strokeWidth="2" />
|
|
</svg>
|
|
)
|
|
|
|
export function ExampleFViewerToolbar({ onEvent }: { onEvent?: (name: string) => void }) {
|
|
const [activeLayerId, setActiveLayerId] = useState("0")
|
|
const [view, setView] = useState<"model" | "layout">("model")
|
|
const [depth, setDepth] = useState(false)
|
|
return (
|
|
<SWHeader
|
|
documentTitle={documents[0].name}
|
|
documents={documents}
|
|
activeDocumentId="doc-1"
|
|
documentOpenPlacement="header"
|
|
documentOpenLabel="파일 열기"
|
|
onDocumentOpen={() => onEvent?.("document:open")}
|
|
onDocumentSelect={document => onEvent?.(`document:${document.id}`)}
|
|
controls={[{ id: "document" }, { id: "layer" }, { id: "color" }, { id: "popupGuide" }]}
|
|
hiddenControls={["documentNew", "layerFreeze", "layerLock"]}
|
|
layers={layers}
|
|
activeLayerId={activeLayerId}
|
|
onLayerSelect={layer => { setActiveLayerId(layer.id); onEvent?.(`layer:${layer.id}`) }}
|
|
colors={colors}
|
|
onColorSelect={option => onEvent?.(`color:${option.id}`)}
|
|
tools={<>
|
|
<SWToolGroup label="보기" selection="single">
|
|
<SWToolButton pressed={view === "model"} onClick={() => { setView("model"); onEvent?.("view:model") }}>Model</SWToolButton>
|
|
<SWToolButton pressed={view === "layout"} onClick={() => { setView("layout"); onEvent?.("view:layout") }}>Layout</SWToolButton>
|
|
</SWToolGroup>
|
|
<SWToolGroup label="표시">
|
|
<SWToolButton pressed={depth} onClick={() => { setDepth(!depth); onEvent?.(`2.5d:${!depth}`) }}>2.5D</SWToolButton>
|
|
</SWToolGroup>
|
|
<SWToolGroup appearance="pill" aria-label="화면">
|
|
<SWToolButton appearance="pill" icon={<FitIcon color="#B6D0C9" />} hoverIcon={<FitIcon color="var(--hm-sw-header-selected-color)" />} onClick={() => onEvent?.("fit")}>화면 맞춤</SWToolButton>
|
|
</SWToolGroup>
|
|
</>}
|
|
/>
|
|
)
|
|
}
|