"use client" import * as React from "react" import type { ComponentDocSpec } from "@/lib/design-system/component-doc-types" import { SelectGroupsPreview, SelectPreview, SelectScrollablePreview, SelectStatesPreview, } from "@/components/design-system/data-display-previews" import { CalendarDropdownCaptionPreview, CalendarPreview, CalendarRangePreview, CalendarTwoMonthPreview, DatePickerPreview, DateRangePickerPreview, DateTextInputPreview, } from "@/components/design-system/date-previews" import { CheckboxFieldPreview, FieldBasicPreview, FieldDisabledPreview, FieldInvalidPreview, FieldLayoutsPreview, FieldSettingsRowPreview, FormRhfPreview, RadioGroupChoiceCardPreview, RadioGroupDefaultPreview, } from "@/components/design-system/form-previews" import { InputDefaultPreview, InputGroupPreview, InputMaskPreview, LabelPreview, PaymentCardFieldsPreview, SliderPreview, TextareaDefaultPreview, } from "@/components/design-system/input-previews" function ex( section: Omit, children: React.ReactNode, description?: string, ) { return { ...section, description, children } } const formGuidelines: ComponentDocSpec["guidelines"] = { do: [ "Prefer Field + native control for simple settings and hub filters.", "Use Form + FormField + react-hook-form for multi-field submit flows.", "Wire errors to FormMessage or Field invalid state — inline, not toast.", ], dont: [ "Do not use raw Label without Field in product forms.", "Do not skip visible labels on required fields.", ], } const inputGuidelines: ComponentDocSpec["guidelines"] = { do: [ "Wrap text controls in Field (or FormField) so label, help, and error stay linked.", "Use InputGroup for leading/trailing addons; MaskedInput for phone, ZIP, and date shapes.", "Use PaymentCardFieldsGroup for card number / expiry / CVC — one payment-inputs hook.", ], dont: [ "Do not invent local mask formatting when MaskedInput covers the pattern.", "Do not use Label alone when FieldLabel is available in a form row.", ], } export const formComponentDoc: ComponentDocSpec = { slug: "form", summary: "Field composition and react-hook-form: layouts, invalid/disabled, fieldsets, settings rows, and FormField validation.", sections: [ ex( { id: "field", title: "Field layouts" }, , "Toggle top vs left labels. Includes select, date, checkbox, radio, and SettingsFormRow.", ), ex( { id: "field-basic", title: "Basic field" }, , "Label + Input + FieldDescription.", ), ex( { id: "field-invalid", title: "Invalid field" }, , "data-invalid on Field, aria-invalid on the control.", ), ex( { id: "field-disabled", title: "Disabled field" }, , "data-disabled on Field, disabled on the control.", ), ex( { id: "field-set", title: "FieldSet (checkboxes)" }, , "FieldSet + FieldLegend for related options.", ), ex( { id: "field-settings", title: "Settings row" }, , "SettingsFormRow for horizontal settings pages.", ), ex( { id: "rhf", title: "React Hook Form" }, , "FormField + FormMessage on blur.", ), ], anatomy: [ { part: "Field", description: "Label + control + description. Vertical or horizontal.", slug: "field" }, { part: "FieldSet / FieldLegend", description: "Grouped radios or checkboxes with shared legend." }, { part: "FieldDescription", description: "Help text below the control." }, { part: "FieldError", description: "Inline error list under the control." }, { part: "Form", description: "Provider wrapper from react-hook-form." }, { part: "FormField", description: "Connects name to control + message." }, { part: "FormMessage", description: "Inline validation copy." }, ], guidelines: formGuidelines, relatedSlugs: ["input", "select", "checkbox", "radio-group", "dropdown-menu"], extraImports: [ { label: "Field", path: "@exxatdesignux/ui/field" }, ], } export const inputComponentDoc: ComponentDocSpec = { slug: "input", summary: "Text-entry family on one page: Input, Textarea, Input Group, Input Mask, Label, Slider, and Payment Card Fields.", sections: [ ex( { id: "default", title: "Input" }, , "Default, disabled, and invalid. Pair with Field in product UI.", ), ex( { id: "textarea", title: "Textarea" }, , "Multiline stem / notes. Same Field pairing as Input.", ), ex( { id: "input-group", title: "Input group" }, , "Leading icon, trailing unit, and trailing action button.", ), ex( { id: "input-mask", title: "Input mask" }, , "Phone, ZIP, date (MM/DD/YYYY), and custom reference via MaskedInput + exxatMaskPatterns.", ), ex( { id: "label", title: "Label" }, , "Low-level primitive. Prefer FieldLabel inside Field.", ), ex({ id: "slider", title: "Slider" }, ), ex( { id: "payment-card-fields", title: "Payment card fields" }, , "Card number, expiry, and CVC as one group.", ), ], anatomy: [ { part: "Input", description: "Single-line text control." }, { part: "Textarea", description: "Multiline text control.", slug: "textarea" }, { part: "InputGroup", description: "Chrome + addons around InputGroupInput.", slug: "input-group" }, { part: "MaskedInput", description: "Input + use-mask-input patterns.", slug: "input-mask" }, { part: "Label", description: "Standalone label; prefer FieldLabel.", slug: "label" }, { part: "Slider", description: "Range value picker.", slug: "slider" }, { part: "PaymentCardFieldsGroup", description: "Card number / expiry / CVC.", slug: "payment-card-fields" }, ], guidelines: inputGuidelines, relatedSlugs: ["form", "select", "date-picker"], extraImports: [ { label: "Textarea", path: "@exxatdesignux/ui/textarea" }, { label: "InputGroup", path: "@exxatdesignux/ui/input-group" }, { label: "MaskedInput", path: "@exxatdesignux/ui/input-mask" }, { label: "Label", path: "@exxatdesignux/ui/label" }, { label: "Slider", path: "@exxatdesignux/ui/slider" }, { label: "PaymentCardFieldsGroup", path: "@exxatdesignux/ui/payment-card-fields" }, ], } export const selectComponentDoc: ComponentDocSpec = { slug: "select", summary: "Dropdown select (shadcn / Radix): item-aligned or popper, grouped lists, scrollable options, invalid/disabled/sm.", sections: [ ex( { id: "default", title: "Item-aligned (default)" }, , "Selected item sits over the trigger; open uses animate-none.", ), ex( { id: "popper", title: "Popper (edge-aligned)" }, , "Anchors to the trigger edge with a side-aware enter animation.", ), ex( { id: "groups", title: "Groups and separators" }, , "SelectGroup + SelectLabel + SelectSeparator. Disabled items supported.", ), ex( { id: "scrollable", title: "Scrollable list" }, , "Long lists with max-h on SelectContent.", ), ex( { id: "states", title: "Invalid, disabled, and size" }, , ), ], relatedSlugs: ["form", "input", "date-picker", "dropdown-menu"], } export const radioGroupComponentDoc: ComponentDocSpec = { slug: "radio-group", summary: "Radio set, choice cards, and selection tiles for exclusive picks.", sections: [ ex({ id: "default", title: "Horizontal rows" }, ), ex({ id: "choice-card", title: "Choice cards" }, ), ], guidelines: { do: ["Use Field + RadioGroupItem for simple lists.", "Use choice cards when options need descriptions."], dont: ["Do not use Tabs for exclusive single-select — use RadioGroup or segmented control."], }, relatedSlugs: ["form", "checkbox"], } export const datePickerComponentDoc: ComponentDocSpec = { slug: "date-picker", summary: "Calendar grids and date field triggers: single, range, dropdown caption, DatePickerField, DateRangePickerField, DateTextInputField.", sections: [ ex( { id: "calendar", title: "Calendar (label caption)" }, , "Low-level DayPicker grid with month label + chevrons.", ), ex( { id: "calendar-dropdown", title: "Calendar (dropdown caption)" }, , "Month and year Selects in the caption — used inside date fields.", ), ex( { id: "calendar-range", title: "Calendar range (one month)" }, , ), ex( { id: "calendar-two-month", title: "Calendar range (two months)" }, , "Default for DateRangePickerField on wide surfaces.", ), ex( { id: "date-picker", title: "Date picker field" }, , "Popover trigger with formatted value + calendar icon.", ), ex( { id: "date-range", title: "Date range field" }, , "One-month and two-month popover variants.", ), ex( { id: "date-text", title: "Masked date text field" }, , "Type MM/DD/YYYY or open the calendar from the icon.", ), ], anatomy: [ { part: "Calendar", description: "react-day-picker grid primitive.", slug: "calendar" }, { part: "DatePickerField", description: "Single-date popover field." }, { part: "DateRangePickerField", description: "Range popover field." }, { part: "DateTextInputField", description: "Masked input + calendar affordance." }, ], guidelines: { do: [ "Use DatePickerField / DateRangePickerField in forms; bare Calendar only inside custom popovers.", "Prefer captionLayout dropdown when jumping years (placements, compliance windows).", ], dont: [ "Do not use a plain Input for dates when a picker or mask exists.", "Do not put two-month range calendars in narrow sheets — pass numberOfMonths={1}.", ], }, relatedSlugs: ["form", "input", "select"], extraImports: [ { label: "Calendar", path: "@exxatdesignux/ui/calendar" }, { label: "DatePickerField", path: "@exxatdesignux/ui/date-picker-field" }, ], }