import { useState, type ReactNode } from "react" import type { Meta, StoryObj } from "@storybook/react-vite" import { Slider } from "@hm-design/ui" import { StateBoard } from "@/components/story-board" import { STORY_KICKER, StoryPage, StoryPageHeader, StorySection } from "@/components/story-page" // The representative Story shows each Slider mode with real, draggable controls; the same specimens also exist as Stories tagged // `verification` (hidden from the sidebar). The value label is the Story's composition (Slider has no built-in label). // Names (`aria-label`) are provided by the consumer. function Labeled({ label, children, valueText }: { label: string; children: ReactNode; valueText: string }) { return (
{label} {valueText}
{children}
) } function Single() { const [value, setValue] = useState([40]) return ( ) } function Range() { const [value, setValue] = useState([25, 75]) return ( ) } function Step() { const [value, setValue] = useState([50]) return ( ) } function Disabled() { return } function Vertical() { return (
) } const sections = [ { id: "single", label: "Single", node: }, { id: "range", label: "Range (two thumbs)", node: }, { id: "step", label: "Step", node: }, { id: "disabled", label: "Disabled", node: }, { id: "vertical", label: "Vertical", node: }, ] const meta = { title: "Components/Form/Slider", component: Slider, parameters: { layout: "padded" } } satisfies Meta export default meta type Story = StoryObj const board = (...ids: string[]) => ( ids.includes(s.id)).map((s) => ({ id: s.id, label: s.label, children: s.node }))} /> ) // Representative Story: the common Story page; the sections group the same specimens. export const All: Story = { name: "Slider", parameters: { layout: "fullscreen", controls: { disable: true } }, render: () => ( {board("single")} {board("range", "step", "vertical")} {board("disabled")} ), } export const SingleValue: Story = { tags: ["verification"], name: "Single", render: () => } export const RangeValue: Story = { tags: ["verification"], name: "Range", render: () => } export const DisabledSlider: Story = { tags: ["verification"], name: "Disabled", render: () => } export const Focus: Story = { tags: ["verification"], render: () => (
), play: async ({ canvasElement }) => { const thumb = canvasElement.querySelector('[data-slot="slider-thumb"]')! const disabled = canvasElement.querySelector('[data-disabled] [data-slot="slider-thumb"]')! const result = canvasElement.querySelector('[data-testid="slider-focus-result"]')! const states: Record = {} const read = (name: string, element = thumb) => { states[name] = getComputedStyle(element).boxShadow } const assert = (condition: boolean, message: string) => { if (!condition) throw Error(message) } thumb.blur() read("Default") // Existing Storybook pseudo-state mirroring preserves production selector order/specificity. thumb.setAttribute("data-sb-hover", "") read("Hover") thumb.setAttribute("data-sb-active", "") read("Drag") thumb.removeAttribute("data-sb-hover") thumb.removeAttribute("data-sb-active") thumb.focus() assert(thumb.matches(":focus-visible"), "Keyboard focus must be visible") read("Focus") thumb.setAttribute("data-sb-hover", "") read("Focus + Hover") thumb.setAttribute("data-sb-active", "") read("Focus + Drag") disabled.setAttribute("data-sb-hover", "") disabled.setAttribute("data-sb-active", "") disabled.focus() read("Disabled", disabled) assert(document.activeElement !== disabled, "Disabled thumb cannot receive focus") assert(states.Default === "none" && states.Disabled === "none", "Default/Disabled have no halo") assert(states.Hover.includes("4px") && states.Drag === states.Hover.replace("4px", "6px"), "Interaction keeps 4/6px and its color") assert(states.Focus.includes("4px") && states["Focus + Hover"] === states.Focus, "Hover cannot mask Focus") assert(states["Focus + Drag"] === states.Focus.replace("4px", "6px"), "Drag keeps 6px without masking Focus color") for (const element of [thumb, disabled]) { element.removeAttribute("data-sb-hover") element.removeAttribute("data-sb-active") } thumb.focus() result.textContent = JSON.stringify(states) }, }