"use client"
import type { ReactNode } from "react"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { Checkbox } from "@/components/ui/checkbox"
import { cn } from "@/lib/utils"
/**
* Settings UI kit — composants unifiés pour les interfaces de réglages
* (/admin/* et /settings). Centralise cards, champs, lignes à bascule,
* grilles et hints afin d'homogénéiser typographies, paddings et alignements.
*/
/** Surface card commune (réglages admin + mail) — alignée sur la card mail. */
export const SETTINGS_CARD_SURFACE_CLASS = cn(
"rounded-xl border border-mail-border bg-mail-surface shadow-sm",
"dark:bg-mail-surface-elevated dark:shadow-[0_1px_4px_rgba(0,0,0,0.35)]",
)
export const SETTINGS_CARD_TITLE_CLASS = "text-sm font-semibold text-foreground"
export const SETTINGS_CARD_DESCRIPTION_CLASS =
"text-[13px] leading-relaxed text-muted-foreground"
export const SETTINGS_FIELD_LABEL_CLASS = "text-xs font-medium text-muted-foreground"
/** Carte de réglages : en-tête (titre + description + action) puis corps. */
export function SettingsCard({
title,
description,
hint,
action,
badges,
footer,
children,
className,
bodyClassName,
contentClassName,
divider = true,
}: {
title?: ReactNode
description?: ReactNode
/** Élément aligné à droite de l'en-tête (Switch, bouton, badge…). */
action?: ReactNode
/** Ligne d'indications/badges sous la description. */
badges?: ReactNode
hint?: ReactNode
footer?: ReactNode
children?: ReactNode
className?: string
/** Classe sur le wrapper interne (padding). */
bodyClassName?: string
/** Classe sur le conteneur du corps (children). */
contentClassName?: string
/** Séparateur entre en-tête et corps. */
divider?: boolean
}) {
const hasHeader = Boolean(title || description || action || badges || hint)
return (
{hasHeader ? (
{title ?
{title}
: null}
{description ? (
{description}
) : null}
{badges ?
{badges}
: null}
{hint ?
{hint}
: null}
{action ?
{action}
: null}
) : null}
{children ? (
{children}
) : null}
{footer ?
{footer}
: null}
)
}
/** Champ de formulaire : label + contrôle + hint/erreur. */
export function SettingsField({
label,
htmlFor,
hint,
error,
required,
children,
className,
labelClassName,
labelAction,
}: {
label?: ReactNode
htmlFor?: string
hint?: ReactNode
error?: ReactNode
required?: boolean
children: ReactNode
className?: string
labelClassName?: string
/** Élément aligné à droite du label (lien, bouton…). */
labelAction?: ReactNode
}) {
return (
{label ? (
{labelAction}
) : null}
{children}
{hint ? (
{hint}
) : null}
{error ? (
{error}
) : null}
)
}
/** Ligne à bascule : titre + description + Switch. */
export function SettingsToggleRow({
title,
description,
checked,
onCheckedChange,
disabled,
hint,
variant = "bordered",
className,
}: {
title: ReactNode
description?: ReactNode
checked: boolean
onCheckedChange: (checked: boolean) => void
disabled?: boolean
/** Indication sous la ligne (ex. verrou déploiement). */
hint?: ReactNode
variant?: "bordered" | "plain"
className?: string
}) {
const row = (
)
if (!hint) return row
return (
{row}
{hint}
)
}
/** Ligne à cocher : titre + description + Checkbox. */
export function SettingsCheckboxRow({
title,
description,
checked,
onCheckedChange,
disabled,
variant = "plain",
className,
}: {
title: ReactNode
description?: ReactNode
checked: boolean
onCheckedChange: (checked: boolean) => void
disabled?: boolean
variant?: "bordered" | "plain"
className?: string
}) {
return (
)
}
/** Grille de champs responsive (1 ou 2 colonnes). */
export function SettingsGrid({
columns = 2,
children,
className,
}: {
columns?: 1 | 2
children: ReactNode
className?: string
}) {
return (
{children}
)
}
/** Indication brève (texte muted) sous un champ ou une carte. */
export function SettingsHint({
children,
tone = "muted",
className,
}: {
children: ReactNode
tone?: "muted" | "warning" | "danger"
className?: string
}) {
return (
{children}
)
}