import type { ColorSchemeMode } from "@charcuterie/logic"
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
import type { Meta, StoryObj } from "@storybook/react"
import { useState } from "react"
import {
controlSizeArgType,
intentArgType,
} from "../argTypes.storyHelpers.ts"
import {
ContainerBoard,
StoryCell,
StoryGrid,
StoryRow,
StorySection,
} from "../board.storyHelpers.tsx"
import {
MonitorIcon,
MoonIcon,
SunIcon,
} from "../icons.storyHelpers.tsx"
import type { ColorSchemeIcons } from "./ColorSchemeToggle.tsx"
import { ColorSchemeToggle } from "./ColorSchemeToggle.tsx"
/**
* The library ships **no icons** — these are the story-only
* hand-drawn SVGs an app would replace with lucide `Sun` / `Moon` /
* `Monitor`.
*/
const ICONS: ColorSchemeIcons = {
dark: ,
light: ,
system: ,
}
const meta = {
title: "Utilities/ColorSchemeToggle",
component: ColorSchemeToggle,
parameters: { layout: "padded" },
argTypes: {
intent: intentArgType,
// `mode` is `ColorSchemeMode` from @charcuterie/logic — a bare
// specifier docgen cannot enumerate, so it gets an explicit
// radio rather than falling through to the object control.
mode: {
control: "radio",
options: ["light", "dark", "system"],
},
size: controlSizeArgType,
},
args: {
appearance: "ghost",
icons: ICONS,
intent: "neutral",
isDisabled: false,
mode: "system",
onCycle: () => {},
size: "md",
},
} satisfies Meta
export default meta
type Story = StoryObj
/**
* Controlled and self-contained: this story owns the mode in local
* state and advances it on each press, which is what a plain
* consumer wires up. `` wires the same
* `onCycle` to the `useColorScheme` hook instead.
*
* The accessible name states the current mode and the next one, so
* it changes as the button cycles — that is what the test asserts.
*/
export const Playground: Story = {
parameters: playgroundParameters,
render: (toggleProps) => {
const [mode, setMode] =
useState("system")
return (
)
},
}
/**
* Each mode's icon, held fixed so the three glyphs are visible at
* once — light is the sun, dark the moon, system the monitor.
*/
export const AllModes: Story = {
render: (toggleProps) => (
{}}
/>
{}}
/>
{}}
/>
),
}
/**
* The tone is **neutral by default** — a scheme switcher is toolbar
* chrome, so its ghost hover is `hover:bg-intent-neutral-surface` and
* its icon `text-intent-neutral-content`, which read as chrome on a
* normal surface rather than as an accent action. A consumer that
* wants it to draw attention passes `intent="accent"` (or any tone).
*/
export const Intents: Story = {
render: (toggleProps) => (
{}}
/>
{}}
/>
),
}
export const Sizes: Story = {
render: (toggleProps) => (
{}}
size="sm"
/>
{}}
size="md"
/>
{}}
size="lg"
/>
),
}
export const Responsive: Story = {
render: (toggleProps) => (
{}}
/>
),
}