fix(storybook): show Dropdown directly under Header

This commit is contained in:
shkim4 committed 2026-10-19 12:36:10 +09:00
1 parent 9482d45f34
commit c705a1fc59
36 files changed
+8837 -42

No files matched your search

+3 -3
View File
@@ -3,14 +3,14 @@ import { ComposedDemo } from "./sw-header.stories"
import "./sw-composed-controls.css"
const meta = {
title: "SW/Header/Dropdown",
// Keep existing bookmarks while placing the single example under Dropdown.
title: "SW/Header",
// Keep existing bookmarks; Dropdown is a Story directly under Header.
id: "sw-header",
parameters: { layout: "fullscreen", controls: { disable: true } },
} satisfies Meta
export default meta
export const ComposedControls: StoryObj<typeof meta> = {
name: "Composed Controls",
name: "Dropdown",
render: () => <ComposedDemo />,
}
+32 -30
View File
@@ -376,7 +376,7 @@ export function ComposedDemo() {
}
const panelProperties = properties.map(item => ({ ...item, disabled, ...(item.id === "layer" ? { options: availableLayers.map(layer => ({ ...layer, id: layer.name })) } : {}) }))
return <StoryPage className="sw-composed-controls">
<StoryPageHeader kicker={KICKER} title="Composed Controls" description="SW Header의 레이어·색상·선스타일·문자스타일·치수스타일과 상세보기를 직접 조작합니다. 메뉴의 상세 버튼은 기존 호스트 Callback을 호출하며 CAD 상세 화면은 생성하지 않습니다." />
<StoryPageHeader kicker={KICKER} title="Dropdown" description="SW Header의 레이어·색상·선스타일·문자스타일·치수스타일과 상세보기를 직접 조작합니다. 메뉴의 상세 버튼은 기존 호스트 Callback을 호출하며 CAD 상세 화면은 생성하지 않습니다." />
<details className="sw-composed-controls__settings">
<summary>시연 설정</summary>
<div className="sw-composed-controls__settings-content">
@@ -388,36 +388,38 @@ export function ComposedDemo() {
<label><input type="checkbox" checked={detailCallbacks} onChange={event => setDetailCallbacks(event.target.checked)} />메뉴 상세 Callback 연결</label>
</div>
</details>
<SWTheme>
<div className="sw-story-composed" role="group" aria-label="조합 컨트롤" data-composed-controls="">
<SWHeaderLayerMenu {...menuProps("layer")} value={{ name: value("layer") }} layers={availableLayers} activeLayerId={currentLayer?.id}
onLayerSelect={layer => change("layer", layer.name, "onLayerSelect")} onDetail={detail("Layer")}
onVisibilityChange={scenario === "normal" ? menus.onLayerVisibilityChange : undefined} onFreezeChange={scenario === "normal" ? menus.onLayerFreezeChange : undefined} onLockChange={scenario === "normal" ? menus.onLayerLockChange : undefined} />
<SWHeaderColorMenu {...menuProps("color")} value={{ value: colorMode === "byLayer" ? "ByLayer" : colorMode === "byBlock" ? "ByBlock" : value("color"), swatch: color?.hex }}
colors={FIGMA_COLORS} userColors={menus.userColors} mode={colorMode}
onColorSelect={item => change("color", item.value ?? parseSWHeaderColor(item.color)?.value ?? item.color, "onColorSelect")}
onColorInput={next => change("color", next.value, "onColorInput")} onModeChange={mode => { setColorMode(mode); record(`onColorModeChange(${mode})`) }}
onPick={() => record("onColorPick")} onDetail={detail("Color")} />
<SWHeaderLineStyleMenu {...menuProps("lineStyle")} value={{ name: value("line"), weight: currentWeight?.value === undefined ? currentWeight?.name ?? value("weight") : value("weight"), scale: value("scale") }}
lineTypes={FIGMA_LINE_TYPES} lineWeights={weights} activeLineWeightId={weightId}
onLineTypeSelect={item => change("line", item.name, "onLineTypeSelect")} onLineWeightSelect={chooseWeight} onLineWeightValueChange={changeWeight}
onScaleChange={next => change("scale", next, "onLineScaleChange")} onDetail={detail("LineStyle")} />
<SWHeaderTextStyleMenu {...menuProps("textStyle")} value={textStyle} textStyles={FIGMA_TEXT_STYLES}
onTextStyleSelect={item => { setTextStyle({ font: item.font, name: item.name }); record(`onTextStyleSelect(${item.id})`) }} onDetail={detail("TextStyle")} />
<SWHeaderDimensionStyleMenu {...menuProps("dimensionStyle")} value={dimensionStyle} dimensionStyles={FIGMA_DIMENSION_STYLES}
onDimensionStyleSelect={item => { setDimensionStyle({ name: item.name }); record(`onDimensionStyleSelect(${item.id})`) }} onDetail={detail("DimensionStyle")} />
<div ref={detailRef}>
<SWHeaderProperties disabled={disabled} barOpen={bar} panelOpen={panel} panelId={panelId}
onBarToggle={() => { setActiveMenu(null); setBar(next => !next); record(`onPropertyBarOpenChange(${!bar})`) }}
onPanelToggle={() => { setActiveMenu(null); setPanel(next => !next); record(`onPropertyPanelOpenChange(${!panel})`) }} />
<StorySection title="Composed Controls">
<SWTheme>
<div className="sw-story-composed" role="group" aria-label="Composed Controls" data-composed-controls="">
<SWHeaderLayerMenu {...menuProps("layer")} value={{ name: value("layer") }} layers={availableLayers} activeLayerId={currentLayer?.id}
onLayerSelect={layer => change("layer", layer.name, "onLayerSelect")} onDetail={detail("Layer")}
onVisibilityChange={scenario === "normal" ? menus.onLayerVisibilityChange : undefined} onFreezeChange={scenario === "normal" ? menus.onLayerFreezeChange : undefined} onLockChange={scenario === "normal" ? menus.onLayerLockChange : undefined} />
<SWHeaderColorMenu {...menuProps("color")} value={{ value: colorMode === "byLayer" ? "ByLayer" : colorMode === "byBlock" ? "ByBlock" : value("color"), swatch: color?.hex }}
colors={FIGMA_COLORS} userColors={menus.userColors} mode={colorMode}
onColorSelect={item => change("color", item.value ?? parseSWHeaderColor(item.color)?.value ?? item.color, "onColorSelect")}
onColorInput={next => change("color", next.value, "onColorInput")} onModeChange={mode => { setColorMode(mode); record(`onColorModeChange(${mode})`) }}
onPick={() => record("onColorPick")} onDetail={detail("Color")} />
<SWHeaderLineStyleMenu {...menuProps("lineStyle")} value={{ name: value("line"), weight: currentWeight?.value === undefined ? currentWeight?.name ?? value("weight") : value("weight"), scale: value("scale") }}
lineTypes={FIGMA_LINE_TYPES} lineWeights={weights} activeLineWeightId={weightId}
onLineTypeSelect={item => change("line", item.name, "onLineTypeSelect")} onLineWeightSelect={chooseWeight} onLineWeightValueChange={changeWeight}
onScaleChange={next => change("scale", next, "onLineScaleChange")} onDetail={detail("LineStyle")} />
<SWHeaderTextStyleMenu {...menuProps("textStyle")} value={textStyle} textStyles={FIGMA_TEXT_STYLES}
onTextStyleSelect={item => { setTextStyle({ font: item.font, name: item.name }); record(`onTextStyleSelect(${item.id})`) }} onDetail={detail("TextStyle")} />
<SWHeaderDimensionStyleMenu {...menuProps("dimensionStyle")} value={dimensionStyle} dimensionStyles={FIGMA_DIMENSION_STYLES}
onDimensionStyleSelect={item => { setDimensionStyle({ name: item.name }); record(`onDimensionStyleSelect(${item.id})`) }} onDetail={detail("DimensionStyle")} />
<div ref={detailRef}>
<SWHeaderProperties disabled={disabled} barOpen={bar} panelOpen={panel} panelId={panelId}
onBarToggle={() => { setActiveMenu(null); setBar(next => !next); record(`onPropertyBarOpenChange(${!bar})`) }}
onPanelToggle={() => { setActiveMenu(null); setPanel(next => !next); record(`onPropertyPanelOpenChange(${!panel})`) }} />
</div>
</div>
</div>
{bar && <SWHeaderPropertyBar selection={propertySelection("circle")} properties={panelProperties.filter(item => BAR_FIXTURE.some(barItem => barItem.id === item.id))}
onPropertyChange={(property, next) => change(property.id, next, "onPropertyChange")} />}
{panel && <SWHeaderPropertyPanel id={panelId} anchorRef={detailRef} selection={propertySelection("circle")} properties={panelProperties} groups={PROPERTY_GROUPS}
menus={{ ...menus, layers: availableLayers.map(layer => ({ ...layer, id: layer.name })) }}
onPropertyChange={(property, next) => change(property.id, next, "onPropertyChange")} onClose={closePanel} />}
</SWTheme>
{bar && <SWHeaderPropertyBar selection={propertySelection("circle")} properties={panelProperties.filter(item => BAR_FIXTURE.some(barItem => barItem.id === item.id))}
onPropertyChange={(property, next) => change(property.id, next, "onPropertyChange")} />}
{panel && <SWHeaderPropertyPanel id={panelId} anchorRef={detailRef} selection={propertySelection("circle")} properties={panelProperties} groups={PROPERTY_GROUPS}
menus={{ ...menus, layers: availableLayers.map(layer => ({ ...layer, id: layer.name })) }}
onPropertyChange={(property, next) => change(property.id, next, "onPropertyChange")} onClose={closePanel} />}
</SWTheme>
</StorySection>
<div className="sw-composed-controls__status">
<output data-style-state="">레이어: {value("layer")} · 색상: {colorMode ?? value("color")} · 선: {value("line")} / {value("weight")} / {value("scale")} · 문자: {textStyle.name} · 치수: {dimensionStyle.name}</output>
<output aria-live="polite" data-callback-log="">Callback: {log.length ? log.join(" → ") : "없음"}</output>