Files
HMDesign/packages/sw/ai/examples/ExampleJ-Theme.tsx
shkim4 e31021af2d docs: Noto Sans KR SW default font and Bold scope in AI guides and README
SW AI usage / design rules / composition / viewer docs, example J and the
shared AI_GUIDE (synced to every package with sync:ai-docs) state the
Noto Sans KR default and the 2026-10-20 weight scope.
2026-10-20 18:18:01 +09:00

52 lines
2.9 KiB
TypeScript

// Example J — SW theme tokens (both modes). The only official way to change SW tokens: `style` (or the program's own
// class) on the OUTERMOST SW scope. Here one <SWTheme> wraps the viewer screen, so the header, its dropdowns, More,
// and every panel read the same value. Portals leave the DOM tree: wrap their content in <SWTheme> with the same style.
// The font below is a placeholder for a program decision: the SW default is Noto Sans KR (2026-10-20) and needs no
// token, so only set it when the program has decided on another font. Never copy the Web UI font token here.
import { useState, type CSSProperties } from "react"
import { createPortal } from "react-dom"
import {
SWTheme, SWViewerButton, SWViewerHeader, SWViewerHint, SWViewerPanel, SWViewerSection,
type SWViewerHeaderGroup,
} from "@hm-design/sw"
/** One theme object for the screen and for every portal. Token names only (`--hm-sw-*`), never `hm-sw-*` classes. */
export const appSWTheme = {
"--hm-sw-header-font-family": '"Malgun Gothic", "Apple SD Gothic Neo", sans-serif',
} as CSSProperties
export function ExampleJTheme({ onEvent }: { onEvent?: (name: string) => void }) {
const [options, setOptions] = useState(false)
const [notice, setNotice] = useState(false)
const groups: SWViewerHeaderGroup[] = [
{ id: "file", label: "파일", items: [
{ type: "menu", id: "samples", label: "샘플", collapseBelow: 1180, entries: [
{ type: "item", id: "sample-a", label: "기본 도면 · DWG", onSelect: () => onEvent?.("sample-a") },
] },
] },
{ id: "panels", label: "패널", placement: "end", items: [
{ type: "toggle", id: "options", label: "설정", pressed: options, collapseBelow: 900, onPressedChange: setOptions },
{ type: "button", id: "notice", label: "알림", onSelect: () => setNotice(true) },
] },
]
return (
// Outermost SW scope: header, dropdown, More and panel inherit `appSWTheme`.
<SWTheme style={appSWTheme}>
<SWViewerHeader documentTitle="BasicSample.dwg" groups={groups} onCommand={command => onEvent?.(command.id)} />
<SWViewerPanel title="옵션" open={options} onClose={() => setOptions(false)} width={320} height="auto">
<SWViewerSection title="표시"><SWViewerHint>Header와 같은 토큰 값을 씁니다.</SWViewerHint></SWViewerSection>
</SWViewerPanel>
{/* A program portal renders outside the scope above: give it its own <SWTheme> with the same style. */}
{notice && createPortal(
<SWTheme style={{ ...appSWTheme, position: "fixed", right: 24, bottom: 24 }}>
<SWViewerSection title="알림">
<SWViewerHint>Portal 안에서도 같은 SW 토큰이 적용됩니다.</SWViewerHint>
<SWViewerButton variant="primary" onClick={() => setNotice(false)}>확인</SWViewerButton>
</SWViewerSection>
</SWTheme>,
document.body,
)}
</SWTheme>
)
}