Paramètres
Paramètres pour un produit d’IA, présentés comme dans Cursor et Claude. Une barre latérale pleine avec recherche, groupes et liens externes, des cartes de lignes avec sélecteurs discrets et options imbriquées, un îlot d’enregistrement sombre qui n’apparaît que si quelque chose a changé, ⌘S pour enregistrer, des erreurs de champ issues de vos contrôles ou de votre serveur, et des états de chargement qui épousent la forme du contenu.
Cursor, Claude et Codex ont tous adopté la même page de paramètres : une barre latérale pleine avec recherche et quelques sections groupées, et à droite des cartes de lignes avec un libellé et une description à gauche et un contrôle discret à droite. Settings est cette page. Il contient vos sections et gère ce que toutes les pages de paramètres ratent : modifications perdues, double enregistrement, et le passage d’une barre latérale sur ordinateur à une liste sur mobile.
Les lignes acceptent n’importe quel contrôle. SettingsSelect est le sélecteur de valeur compact qu’utilisent ces applications, un petit bouton à contour qui ouvre un menu de choix, et SettingsNumber est un stepper que l’on peut maintenir pour répéter. Les deux sont nommés par leur ligne, donc les lecteurs d’écran entendent « Chat font, Serif ». SettingsLink est une ligne qui ouvre autre chose, avec un chevron ou une flèche pour les liens qui quittent l’application. SettingsNested ouvre en glissant des options dépendantes sous un switch, comme l’accès réseau sous Run code. La recherche filtre la barre latérale par libellé, description et mots-clés, et Enter ouvre la première correspondance. SettingsChoice transforme un choix en cartes illustrées, pour que l’on choisisse un thème ou une densité d’après son apparence.
Rien n’est enregistré tant que vous ne le dites pas. Dès qu’une valeur diffère de ce qui est enregistré, un îlot sombre monte du bas avec Discard et Save, et l’entrée de la section dans la barre latérale reçoit un point. Remettez la valeur d’origine et la barre disparaît. Essayez d’ouvrir une autre section, de revenir en arrière sur mobile ou de fermer l’onglet, et le changement est bloqué : la barre vibre et indique d’enregistrer ou d’abandonner d’abord, et le navigateur demande confirmation avant la fermeture de l’onglet. ⌘S ou Ctrl+S enregistre de n’importe où.
L’enregistrement affiche sa progression dans le bouton, puis l’îlot se réduit en coche Saved et glisse hors de vue. Si vos vérifications échouent, les champs affichent leurs erreurs, le focus passe au premier et la barre indique combien en corriger. Si le serveur refuse, retournez des erreurs pour les champs ou levez une erreur, et le brouillon reste exactement tel que saisi. Continuez à écrire pendant l’enregistrement et la barre reste affichée pour les modifications plus récentes.
Sur mobile, la barre latérale devient une liste groupée avec descriptions et chevrons. Toucher une section la fait glisser par-dessus la liste avec un bouton de retour, et le focus passe à son titre. Pendant le chargement des données d’une section, elle affiche un skeleton en forme de lignes de switches, ou le vôtre via la prop skeleton, et une erreur avec Try again si le chargement échoue.
Ajouter le registre Pro à components.json
components.json Ajouter votre token
Créez un token sur votre page de compte et placez-le dans
.env.localsous le nomHEXTAUI_PRO_TOKEN.Ajouter le block
pnpm dlx shadcn@latest add @hextaui-pro/settings
Reliez une section à votre API
useSettingsForm conserve un brouillon des valeurs que vous passez. Retournez des erreurs de champ depuis onSave pour les afficher sous le champ, ou levez une erreur pour afficher le message dans la barre d’enregistrement. Dans les deux cas, le brouillon est conservé.
Une route par section
Contrôlez la section active avec value et onValueChange pour donner à chaque section sa propre URL. La coque bloque toujours le changement tant que quelque chose n’est pas enregistré, donc onValueChange ne se déclenche que lorsqu’il est sûr de partir.
Chargement et erreurs
Passez status pendant le chargement des données d’une section. Le skeleton attend 150ms pour que les chargements rapides ne clignotent jamais, et un état d’erreur propose Try again via onRetry.
Anatomie
Les parties à composer, de l’extérieur vers l’intérieur.
| Partie | Description |
|---|---|
SettingsShell | La page : la navigation des sections, la colonne de contenu, la barre d’enregistrement et la protection contre le départ avec des modifications non enregistrées. |
SettingsSection | Une section. Ne s’affiche que lorsqu’elle est ouverte, avec son titre, des actions facultatives et des états de chargement ou d’erreur. |
SettingsGroup | Une carte titrée de lignes, avec un pied de page facultatif pour une note sur le groupe. |
SettingsRow | Un libellé, une description et un contrôle, reliés pour les lecteurs d’écran, avec l’erreur du champ en dessous. |
SettingsSelect | Un sélecteur discret pour choisir une valeur dans une courte liste. |
SettingsLink | Une ligne qui ouvre une page, une boîte de dialogue ou un lien externe. |
SettingsNested | Des options dépendantes qui s’ouvrent en glissant tant qu’un switch parent est activé. |
SettingsNumber | Un stepper numérique avec − et + qui se répètent lorsqu’on les maintient, construit sur le Number Field de Base UI. |
SettingsChoice | Des cartes illustrées pour choisir une option, comme un thème ou une densité, avec une sémantique radio. |
SettingsSkeleton | Le placeholder de chargement, configurable par lignes par groupe et forme du contrôle. |
useSettingsForm | Le brouillon d’une section. Suit ce qui a changé, valide, enregistre et relie la section à la barre d’enregistrement. |
useSettingsNavigate | Ouvre une section depuis l’intérieur du contenu, avec la même protection que la barre latérale. |
SettingsShell
Accepte aussi toutes les props de div.
| Prop | Type | Par défaut |
|---|---|---|
sections{ id, label, description?, icon?, group?, keywords?, href? }. Les éléments consécutifs ayant le même group partagent un titre. keywords aide la recherche à trouver une section, et href fait de l’élément un lien externe. | SettingsSectionItem[] | – |
valueLa section ouverte, lorsque vous la contrôlez. | string | – |
defaultValueLa section ouverte au départ. | string | first section |
onValueChangeAppelé quand quelqu’un ouvre une autre section. Jamais appelé tant que quelque chose n’est pas enregistré ou en cours d’enregistrement. | (value: string) => void | – |
titleLe titre de la page au-dessus de la navigation, et le libellé du bouton de retour sur mobile. | ReactNode | "Settings" |
descriptionUne ligne sous le titre. | ReactNode | – |
navHeaderContenu en haut de la barre latérale, comme un lien Back vers l’application. | ReactNode | – |
searchableAjoute un champ de recherche au-dessus des sections. | boolean | false |
navFooterContenu épinglé en bas de la barre latérale, comme l’utilisateur connecté. | ReactNode | – |
groupLabelsAffiche le nom de chaque groupe au-dessus de lui. Désactivez pour séparer les groupes par l’espace seul ; les noms continuent de libeller les groupes pour les lecteurs d’écran. | boolean | true |
SettingsSection
Accepte aussi toutes les props de section.
| Prop | Type | Par défaut |
|---|---|---|
idCorrespond à un id de sections. | string | – |
titleLe titre. | ReactNode | the section's label |
descriptionLa ligne sous le titre. | ReactNode | the section's description |
actionsBoutons à côté du titre. | ReactNode | – |
statusAffiche un skeleton ou une erreur à la place des enfants. | "ready" | "loading" | "error" | "ready" |
skeletonCe qu’il faut afficher tant que status vaut loading. | ReactNode | <SettingsSkeleton /> |
errorLe message de l’état d’erreur. | ReactNode | – |
onRetryAjoute Try again à l’état d’erreur. | () => void | – |
| Prop | Type | Par défaut |
|---|---|---|
titleTitre au-dessus de la carte. | ReactNode | – |
descriptionUne ligne discrète sous le titre, pour dire de quoi parle le groupe. | ReactNode | – |
footerUne bande discrète en bas de la carte, pour des notes comme ce qu’un changement affecte. | ReactNode | – |
| Prop | Type | Par défaut |
|---|---|---|
labelLibelle le contrôle dans la ligne. | ReactNode | – |
descriptionTexte d’aide, lu avec le contrôle. | ReactNode | – |
errorMarque le contrôle comme invalide et affiche le message sous la ligne. | string | – |
layoutauto place le contrôle à côté du libellé quand la carte est large et en dessous quand elle est étroite. inline le garde à côté du libellé, pour les switches. stacked le place toujours en dessous, pour les zones de texte. | "auto" | "inline" | "stacked" | "auto" |
disabledDésactive le champ de la ligne. | boolean | false |
SettingsSelect
Accepte aussi toutes les props de Button.
| Prop | Type | Par défaut |
|---|---|---|
valueLa valeur choisie. | string | – |
onValueChangeAppelé avec la nouvelle valeur. | (value: string) => void | – |
optionsLes choix, dans l’ordre. | { value, label }[] | – |
SettingsChoice
Un radio group, donc les flèches passent d’une carte à l’autre. Accepte aussi toutes les props de RadioGroup de Base UI.
| Prop | Type | Par défaut |
|---|---|---|
valueL’option choisie. | string | – |
onValueChangeAppelé avec la nouvelle option. | (value: string) => void | – |
optionsL’image de chaque carte et le nom en dessous. | { value, label, preview }[] | – |
columnsCartes par ligne. 4 passe à 2 quand la ligne est étroite. | 2 | 3 | 4 | 3 |
ratioAperçus en 16:10, ou 2:1 pour des aperçus plus courts. | "card" | "wide" | "card" |
SettingsNumber
Accepte aussi toutes les props de NumberField.Root de Base UI, comme format et smallStep.
| Prop | Type | Par défaut |
|---|---|---|
valueLe nombre actuel. | number | null | – |
onValueChangeAppelé à chaque changement du nombre. | (value: number | null) => void | – |
minValeur minimale. Le bouton − s’y désactive. | number | – |
maxValeur maximale. Le bouton + s’y désactive. | number | – |
stepDe combien chaque appui ou chaque flèche la modifie. | number | 1 |
SettingsLink
Accepte aussi toutes les props d’ancre. Rend un bouton quand il n’y a pas de href.
| Prop | Type | Par défaut |
|---|---|---|
labelLe titre de la ligne. | ReactNode | – |
descriptionUne ligne sous le titre. | ReactNode | – |
externalOuvre href dans un nouvel onglet et affiche une flèche au lieu d’un chevron. | boolean | false |
| Prop | Type | Par défaut |
|---|---|---|
openAffiche les options. Généralement la valeur du switch parent. | boolean | – |
| Prop | Type | Par défaut |
|---|---|---|
groupsNombre de lignes de chaque groupe de placeholders. | number[] | [3, 2] |
controlLa forme à droite de chaque ligne. | "switch" | "select" | "input" | "switch" |
useSettingsForm
Renvoie { values, setValue, errors, dirty, status, save, discard }.
| Prop | Type | Par défaut |
|---|---|---|
valuesCe qui est enregistré actuellement. Quand cela change et qu’il n’y a pas de modifications, le brouillon le suit. | Values | – |
onSaveEnregistre le brouillon. Retournez { field: message } pour afficher des erreurs de champ, ou levez une erreur pour afficher le message dans la barre d’enregistrement. | (values) => void | errors | Promise<void | errors> | – |
validateS’exécute avant onSave. Toute erreur arrête l’enregistrement et place le focus sur le premier champ invalide. | (values) => errors | undefined | – |
useSettingsNavigate
Renvoie une fonction qui ouvre une section depuis n’importe où dans la coque, comme le bouton Open d’une bannière. Elle respecte les modifications non enregistrées comme le fait la barre latérale.
| Prop | Type | Par défaut |
|---|---|---|
navigateOuvre la section, ou fait vibrer la barre d’enregistrement si quelque chose n’est pas enregistré. | (id: string) => void | – |
| Touche | Action |
|---|---|
| Tab | Parcourt la navigation, puis la section, puis la barre d’enregistrement quand elle est ouverte. |
| Enter | Ouvre la section ayant le focus. |
| ↑↓ | Dans un stepper, change le nombre d’un pas. Shift le change de dix. |
| Enter | Dans le champ de recherche, ouvre la première section correspondante. Escape efface la recherche. |
| ⌘S | Enregistre tant que quelque chose n’est pas enregistré. Ctrl+S sous Windows et Linux. |
- La navigation est un landmark, et la section ouverte est marquée comme page courante.
- Chaque section est une région nommée par son titre. Sur mobile, le focus passe au titre à l’ouverture d’une section et revient à sa ligne au retour.
- Les lignes utilisent Field, donc libellés, descriptions et erreurs sont attachés au contrôle.
- La navigation bloquée est annoncée poliment, et un enregistrement échoué est annoncé comme une alerte.
- La barre d’enregistrement et tout panneau masqué sont inertes, donc ils sortent de l’ordre de tabulation et sont cachés aux lecteurs d’écran.
- Avec réduction des animations, les panneaux s’estompent au lieu de glisser et la vibration de la barre d’enregistrement devient un anneau.
Construit avec
Les composants HextaUI gratuits dont Settings est constitué. Chacun s’installe séparément.
Code
6 fichiers, ajoutés à components/blocks/settings.