Files
HMDesign/src/foundation/reference.tsx
T
shkim4 da0e647b49 docs(storybook): simplify sidebar Story pages around the UI
Drop the category kicker from the 83 sidebar Stories (kicker is now optional;
hidden verification Stories keep it) and shorten or remove repeated, obvious
or internal page/section descriptions. Required specs, limits, virtual-data
and undecided-value notices stay. Story IDs, exports, fixtures, shared state
notes and package code are unchanged. Record: docs/reports/storybook-ui-simplification-2026-10-22.md
2026-10-22 16:13:58 +09:00

47 lines
2.7 KiB
TypeScript

import { useEffect, useRef, useState, type ReactNode } from "react"
import { StoryPage, StoryPageHeader, StorySection } from "@/components/story-page"
import "./foundation.css"
export function useResolvedProperties(properties: readonly string[]) {
const [values, setValues] = useState<Record<string, string>>({})
useEffect(() => {
let frame = 0
const read = () => {
cancelAnimationFrame(frame)
frame = requestAnimationFrame(() => {
const style = getComputedStyle(document.documentElement)
const next = Object.fromEntries(properties.map(property => [property, style.getPropertyValue(property).trim()]))
setValues(previous => properties.every(property => previous[property] === next[property]) ? previous : next)
})
}
read()
const observer = new MutationObserver(read)
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["style", "class", "data-hm-theme"] })
window.addEventListener("resize", read)
return () => { observer.disconnect(); window.removeEventListener("resize", read); cancelAnimationFrame(frame) }
}, [properties])
return values
}
// The page frame, title and sections are the common Story page (src/components/story-page.tsx); .hm-foundation styles the reference content.
export function ReferencePage({ title, intro, children }: { title: string; intro: string; children: ReactNode }) {
return <StoryPage className="hm-foundation"><StoryPageHeader title={title} description={intro} />{children}</StoryPage>
}
export function ReferenceSection({ title, note, children, id }: { title: string; note: string; children: ReactNode; id?: string }) {
return <StorySection id={id} title={title} description={note}>{children}</StorySection>
}
export function Specimen({ label, size, line, weight }: { label: string; size: string; line: string; weight?: string }) {
const ref = useRef<HTMLDivElement>(null)
const [metrics, setMetrics] = useState("")
useEffect(() => {
let mounted = true
void document.fonts.ready.then(() => {
if (!mounted || !ref.current) return
const style = getComputedStyle(ref.current)
setMetrics(`${style.fontSize} / ${style.lineHeight} / ${style.fontWeight} · letter-spacing: ${style.letterSpacing}`)
})
return () => { mounted = false }
}, [])
return <div className="hm-foundation-specimen" ref={ref} data-typography-sample={label} style={{ fontSize: `var(${size})`, lineHeight: `var(${line})`, fontWeight: weight ? `var(${weight})` : "normal" }}><p lang="ko">가나다라마바사 아자차카타파하 · 한맥 프로젝트</p><p lang="en">ABCDEFGHIJKLMNOPQRSTUVWXYZ<br />abcdefghijklmnopqrstuvwxyz</p><p>0123456789</p><small className="hm-foundation-note" data-typography-metrics>{metrics}</small></div>
}