"use client"
/**
* Form previews for Design System docs — shadcn Field + RadioGroup patterns.
* @see https://ui.shadcn.com/docs/components/radio-group
*/
import * as React from "react"
import { useForm } from "react-hook-form"
import { SettingsFormRow } from "@/components/settings-form-row"
import { Button } from "@/components/ui/button"
import { Checkbox, CheckboxLabel } from "@/components/ui/checkbox"
import { DatePickerField } from "@/components/ui/date-picker-field"
import {
Field,
FieldContent,
FieldDescription,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSet,
FieldTitle,
} from "@/components/ui/field"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { Textarea } from "@/components/ui/textarea"
import { ToggleSwitch } from "@/components/ui/toggle-switch"
import { ViewSegmentedControl } from "@/components/ui/view-segmented-control"
import { cn } from "@/lib/utils"
const PLAN_OPTIONS = [
{ value: "monthly", label: "Monthly ($9.99/month)", id: "plan-monthly" },
{ value: "yearly", label: "Yearly ($99.99/year)", id: "plan-yearly" },
{ value: "lifetime", label: "Lifetime ($299.99)", id: "plan-lifetime" },
] as const
const SPACING_OPTIONS = [
{
value: "default",
label: "Default",
description: "Standard spacing for most use cases.",
id: "spacing-default",
},
{
value: "comfortable",
label: "Comfortable",
description: "More space between elements.",
id: "spacing-comfortable",
},
{
value: "compact",
label: "Compact",
description: "Minimal spacing for dense layouts.",
id: "spacing-compact",
},
] as const
const CHOICE_OPTIONS = [
{ value: "plus", title: "Plus", description: "For individuals and small teams.", id: "plus-plan" },
{ value: "pro", title: "Pro", description: "For growing businesses.", id: "pro-plan" },
{
value: "enterprise",
title: "Enterprise",
description: "For large teams and enterprises.",
id: "enterprise-plan",
},
] as const
/** shadcn default — RadioGroup + Field horizontal rows. */
export function RadioGroupDefaultPreview() {
return (
{SPACING_OPTIONS.map((opt) => (
{opt.label}
))}
)
}
/** shadcn fieldset — FieldSet + FieldLegend + RadioGroup + Field per option. */
export function RadioGroupFieldsetPreview() {
const [value, setValue] = React.useState("monthly")
return (
)
}
/** shadcn description — FieldContent with label + description per option. */
export function RadioGroupDescriptionPreview() {
return (
{SPACING_OPTIONS.map((opt) => (
{opt.label}
{opt.description}
))}
)
}
/** shadcn choice card — FieldLabel wraps the whole Field row. */
export function RadioGroupChoiceCardPreview() {
return (
{CHOICE_OPTIONS.map((opt) => (
{opt.title}
{opt.description}
))}
)
}
/** shadcn invalid — aria-invalid on items + data-invalid on Field. */
export function RadioGroupInvalidPreview() {
return (
)
}
type FieldLayout = "top" | "left"
const LAYOUT_OPTIONS = [
{ value: "top", label: "Top label", icon: "fa-light fa-arrow-down" },
{ value: "left", label: "Left label", icon: "fa-light fa-arrow-right" },
] as const
export function FieldLayoutsPreview({ className }: { className?: string }) {
const [layout, setLayout] = React.useState("top")
const [questionType, setQuestionType] = React.useState("monthly")
const [notifications, setNotifications] = React.useState(true)
const [date, setDate] = React.useState(new Date())
return (
setLayout(v as FieldLayout)}
aria-label="Field label layout"
options={[...LAYOUT_OPTIONS]}
/>
{layout === "top" ? (
Question stem
Shown to learners during delivery.
Program
setNotifications(v === true)}
/>
Email coordinators when published
Review by
) : (
Question stem
Label left, control right.
Question type
{PLAN_OPTIONS.map((opt) => (
{opt.label}
))}
Notifications
Email when published
)}
)
}
export function FormRhfPreview({ className }: { className?: string }) {
const form = useForm<{ email: string; notes: string }>({
defaultValues: { email: "", notes: "" },
})
return (
)
}
const EXPORT_CHECKBOX_OPTIONS = [
{ id: "archived", label: "Include archived questions" },
{ id: "metadata", label: "Include question metadata" },
{ id: "rubrics", label: "Include rubric attachments" },
] as const
export function CheckboxFieldPreview() {
const [values, setValues] = React.useState({
archived: true,
metadata: false,
rubrics: false,
})
return (
)
}
const CHECKBOX_VARIANTS = [
"default",
"outline",
"secondary",
"success",
"destructive",
"warning",
"muted",
] as const
const CHECKBOX_SIZES = ["sm", "default", "lg"] as const
const CHECKBOX_MOTIONS = ["none", "pop", "glow", "pop-glow"] as const
function PreviewCaption({ children }: { children: React.ReactNode }) {
return {children}
}
function CheckboxPreviewCell({
label,
children,
}: {
label: string
children: React.ReactNode
}) {
return (
)
}
export function CheckboxVariantsPreview() {
return (
{CHECKBOX_VARIANTS.map((variant) => (
))}
)
}
export function CheckboxSizesPreview() {
return (
{CHECKBOX_SIZES.map((size) => (
))}
)
}
export function CheckboxMotionPreview() {
return (
{CHECKBOX_MOTIONS.map((motion) => (
))}
)
}
export function CheckboxStatesPreview() {
return (
)
}
export function CheckboxLabelPreview() {
const [newsletter, setNewsletter] = React.useState(false)
return (
setNewsletter(v === true)}
/>
Email weekly placement digest
)
}
export function CheckboxWithDescriptionPreview() {
const [values, setValues] = React.useState({
default: true,
comfortable: false,
compact: false,
})
return (
{SPACING_OPTIONS.map((opt) => (
setValues((prev) => ({ ...prev, [opt.value]: v === true }))
}
/>
{opt.label}
{opt.description}
))}
)
}
export function CheckboxChoiceCardPreview() {
const [values, setValues] = React.useState({
plus: true,
pro: false,
enterprise: false,
})
return (
{CHOICE_OPTIONS.map((opt) => (
{opt.title}
{opt.description}
setValues((prev) => ({ ...prev, [opt.value]: v === true }))
}
/>
))}
)
}
const CHECKBOX_TABLE_BULK_ROW_IDS = ["q_101", "q_102", "q_103"] as const
const CHECKBOX_TABLE_BULK_ROW_LABELS: Record<(typeof CHECKBOX_TABLE_BULK_ROW_IDS)[number], string> = {
q_101: "Diaphragm innervation",
q_102: "Brachial plexus roots",
q_103: "Cranial nerve functions",
}
export function CheckboxTableBulkPreview() {
const [selected, setSelected] = React.useState>(new Set(["q_101"]))
const allSelected = selected.size === CHECKBOX_TABLE_BULK_ROW_IDS.length
const someSelected = selected.size > 0 && !allSelected
const toggleAll = () => {
setSelected(allSelected ? new Set() : new Set(CHECKBOX_TABLE_BULK_ROW_IDS))
}
const toggleRow = (id: string) => {
setSelected((prev) => {
const next = new Set(prev)
if (next.has(id)) next.delete(id)
else next.add(id)
return next
})
}
return (
Question
{CHECKBOX_TABLE_BULK_ROW_IDS.map((id) => (
-
toggleRow(id)}
aria-label={CHECKBOX_TABLE_BULK_ROW_LABELS[id]}
/>
{CHECKBOX_TABLE_BULK_ROW_LABELS[id]}
))}
)
}
export function CheckboxInvalidPreview() {
return (
)
}