Files
HMDesign/packages/sw/ai/examples/ExampleF-ViewerToolbar.tsx
T
shkim4andClaude Opus 5.5 55179b4577 feat(sw): integrated improvement 0.2.0 (popup content, header open, tool buttons)
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>
2026-10-19 14:49:19 +09:00

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>
</>}
/>
)
}