style(sw): drop the 취소 / 적용 footer from the viewer options popup
Deploy Storybook / deploy (push) Successful in 1m11s
Deploy Storybook / deploy (push) Successful in 1m11s
Options already apply on every toggle, input and slider change, so the footer only recorded an event and closed the popup. The options panel no longer passes footer (no empty footer area or divider); reset stays in the title bar. The 축척 지정 input popup keeps its footer. VIEWER.md §4.1, the composition pattern and Example H follow.
This commit is contained in:
1 parent
84d70f5cdf
commit
6f031cab18
5 files changed
+8
-9
No files matched your search
@@ -155,8 +155,7 @@ const groups: SWViewerHeaderGroup[] = [
|
||||
<SWViewerStatus state={fileName ? "ready" : "idle"} />
|
||||
<SWViewerHeaderButton iconOnly icon={icons.info} label="정보" onClick={() => setAbout(true)} />
|
||||
</>} />
|
||||
<SWViewerPanel title="옵션" open={optionsOpen} onClose={() => setOptionsOpen(false)} width={340} height="auto"
|
||||
footer={<SWViewerButton variant="primary" onClick={apply}>적용</SWViewerButton>}>
|
||||
<SWViewerPanel title="옵션" open={optionsOpen} onClose={() => setOptionsOpen(false)} width={340} height="auto">
|
||||
<SWViewerSection title="표시">
|
||||
<SWViewerField label="그리드">{id => <SWViewerSwitch id={id} checked={grid} onCheckedChange={setGrid} />}</SWViewerField>
|
||||
<SWViewerField label="줌 속도" layout="stacked" below={<SWViewerSlider aria-label="줌 속도" value={zoom} min={0.2} max={3} step={0.1} onValueChange={setZoom} />}>
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
- 클릭하면 그 레이어 하나의 가시성만 바꾸고 프로그램의 가시성 Callback·상태를 그대로 호출합니다. 아이콘만 그리고 기능을 빼지 않습니다.
|
||||
- 전체 레이어 Switch(2026-10-22 제목 형식): `<SWViewerSection surface="plain" title="전체 레이어" className="app-…"><SWViewerSwitch aria-label="전체 레이어" checked={allVisible} onCheckedChange={setAll} /></SWViewerSection>`. 제목은 기존 Section 제목(`.hm-sw-viewer-section__title`, 12px 700)을 그대로 쓰고 별도 제목 CSS·Prop을 만들지 않습니다. 제목과 Switch를 한 줄에 두는 것은 소비 앱 자기 class(예: `section.app-viewer-all-layers { flex-direction: row; align-items: center; justify-content: space-between; min-height: 20px }`, 예제 `example-layout.css`)로 하고 `hm-sw-viewer-*` class는 덮지 않습니다. `checked`는 모든 레이어가 표시 중일 때만 `true`이고, 일부만 표시 중이면 `false`로 보이며 누르면 전체 표시가 됩니다. ON → 전체 표시, OFF → 전체 숨김. 별도 상태를 두지 않고 레이어 가시성 상태에서 계산하므로 개별 전환 시 자동으로 맞춰집니다. 이전의 `전체 켜기`·`전체 끄기` 버튼 두 개는 쓰지 않습니다.
|
||||
- 그 밖의 `SWViewerSwitch`는 옵션 패널의 ON/OFF 설정(그리드·2.5D 등)에 씁니다.
|
||||
- **옵션(설정) 패널(2026-10-22):** 하단 `취소`·`적용` 버튼이 없습니다(`footer` 미사용 → Footer 영역·구분선도 없음). 토글·Input·Slider는 바뀌는 즉시 프로그램 상태에 반영하고, 기본값 복원은 제목 막대의 초기화(`headerActions`) 버튼입니다. 확인이 필요한 입력 팝업(축척 지정 등)의 `footer`는 그대로 씁니다.
|
||||
|
||||
### 4.2 패널 콘텐츠 글자 기준 (2026-10-22)
|
||||
|
||||
|
||||
@@ -98,8 +98,7 @@ export function ExampleHViewerMode({ onEvent }: { onEvent?: (name: string) => vo
|
||||
</SWViewerSection>
|
||||
</SWViewerPanel>
|
||||
|
||||
<SWViewerPanel title="옵션" open={panels.options} onClose={() => setPanels({ ...panels, options: false })} width={340} height="auto" inset={{ side: 356 }}
|
||||
footer={<SWViewerButton variant="primary" onClick={() => { onEvent?.("options:apply"); setPanels({ ...panels, options: false }) }}>적용</SWViewerButton>}>
|
||||
<SWViewerPanel title="옵션" open={panels.options} onClose={() => setPanels({ ...panels, options: false })} width={340} height="auto" inset={{ side: 356 }}>
|
||||
<SWViewerSection title="표시">
|
||||
<SWViewerField label="그리드">{id => <SWViewerSwitch id={id} checked={grid} onCheckedChange={setGrid} />}</SWViewerField>
|
||||
<SWViewerField label="줌 속도" layout="stacked" below={<SWViewerSlider aria-label="줌 속도" value={zoomSpeed} min={0.2} max={3} step={0.1} onValueChange={setZoomSpeed} />}>
|
||||
|
||||
@@ -157,13 +157,13 @@ function SliderRow({ label, unit, value, min, max, step, disabled, onChange }: {
|
||||
)
|
||||
}
|
||||
|
||||
export function OptionsPanel({ demo, footer, ...placement }: { demo: ViewerDemo; footer?: boolean } & PanelPlacement) {
|
||||
export function OptionsPanel({ demo, ...placement }: { demo: ViewerDemo } & PanelPlacement) {
|
||||
const { options, setOptions } = demo
|
||||
const set = (patch: Partial<ViewerOptions>) => setOptions({ ...options, ...patch })
|
||||
return (
|
||||
<SWViewerPanel title="옵션" open={demo.panels.options} onClose={() => demo.toggle("options", false)} width={340} height={520} {...placement}
|
||||
headerActions={<SWViewerButton variant="ghost" aria-label="기본값으로" title="기본값으로" onClick={() => { setOptions(DEFAULT_OPTIONS); demo.record("options:reset") }}><RotateCcw size={16} /></SWViewerButton>}
|
||||
footer={footer ? <><SWViewerButton onClick={() => demo.toggle("options", false)}>취소</SWViewerButton><SWViewerButton variant="primary" onClick={() => { demo.record("options:apply"); demo.toggle("options", false) }}>적용</SWViewerButton></> : undefined}>
|
||||
headerActions={<SWViewerButton variant="ghost" aria-label="기본값으로" title="기본값으로" onClick={() => { setOptions(DEFAULT_OPTIONS); demo.record("options:reset") }}><RotateCcw size={16} /></SWViewerButton>}>
|
||||
{/* 2026-10-22: no 취소 / 적용 footer — every toggle, input and slider applies at once. */}
|
||||
<SWViewerSection title="선가중치">
|
||||
{/* 2026-10-22 options image: LWDISPLAY toggle; scale input + px/mm unit on the label row, slider below. */}
|
||||
<SWViewerField label="표시 (LWDISPLAY)">{id => <SWViewerSwitch id={id} checked={options.lineweightOn} onCheckedChange={lineweightOn => set({ lineweightOn })} />}</SWViewerField>
|
||||
|
||||
@@ -261,7 +261,7 @@ export const SettingsPanel: Story = {
|
||||
<StoryPageHeader kicker={KICKER} title="SW Viewer — 설정창 (SWViewerPanel)" />
|
||||
<Log lines={demo.log} />
|
||||
<ViewerFrame header={<SWViewerHeader documentTitle={demo.documentName} {...demo.fileProps} groups={demo.groups} trailing={demo.trailing} onCommand={demo.onCommand} />}>
|
||||
<OptionsPanel demo={demo} strategy="absolute" footer />
|
||||
<OptionsPanel demo={demo} strategy="absolute" />
|
||||
</ViewerFrame>
|
||||
</StoryPage>
|
||||
)
|
||||
@@ -291,7 +291,7 @@ export const ContentVariants: Story = {
|
||||
<SWViewerField label="단위">{id => <SWSelect id={id} defaultValue="mm" options={[{ value: "mm" }, { value: "m" }]} onValueChange={value => demo.record(`unit=${value}`)} data-sw-select="unit" />}</SWViewerField>
|
||||
</SWViewerSection>
|
||||
</SWViewerPanel>
|
||||
<OptionsPanel demo={demo} strategy="absolute" defaultPosition={{ left: 712, top: 16 }} footer />
|
||||
<OptionsPanel demo={demo} strategy="absolute" defaultPosition={{ left: 712, top: 16 }} />
|
||||
{!inputOpen && <button type="button" className="sw-viewer-story-reopen" onClick={() => setInputOpen(true)}>축척 지정 다시 열기</button>}
|
||||
</ViewerFrame>
|
||||
</StoryPage>
|
||||
|
||||
Reference in new issue
Block a user