Composants/Gestionnaire de dialogues

Gestionnaire de dialogues

Système global pour les confirmations, saisies et fenêtres personnalisées avec chargement automatique.

Le gestionnaire de dialogues affiche facilement des confirmations, des demandes de saisie ou des contenus personnalisés.

Installation

Il est déjà intégré à NowStack. Vérifiez que DialogManagerRenderer est présent dans le layout principal.

Importation

import { dialogManager } from "@/features/dialog-manager/dialog-manager";

Dialogue de confirmation

Pour afficher une confirmation avec des boutons d’action et d’annulation :

<Button
  variant="destructive"
  onClick={() => {
    dialogManager.confirm({
      title: "Supprimer le profil",
      description: "Voulez-vous vraiment supprimer votre profil ?",
      action: {
        label: "Supprimer",
        variant: "destructive",
        onClick: async () => {
          await deleteAccountAction(null);
          toast.success("Votre profil a été supprimé.");
        },
      },
    });
  }}
>
  Supprimer
</Button>

Options de confirmation

OptionTypeDescription
titlestringTitre
descriptionReactNodeDescription ou contenu personnalisé
iconLucideIconIcône affichée dans un cercle
variant"default" | "destructive" | "warning"Style visuel
size"sm" | "md" | "lg"Taille
style"default" | "centered"Alignement du contenu
confirmTextstringTexte à saisir pour confirmer
actionDialogActionConfiguration du bouton d’action
cancelDialogCancelConfiguration du bouton d’annulation

Confirmation par saisie

Pour une action critique, demandez à l’utilisateur de saisir un texte :

dialogManager.confirm({
  title: "Supprimer l’organisation",
  description: "Cette action est irréversible.",
  confirmText: "SUPPRIMER",
  action: {
    label: "Supprimer",
    variant: "destructive",
    onClick: async () => {
      await deleteOrganization();
    },
  },
});

Le bouton ne s’active qu’après la saisie exacte de « SUPPRIMER ».

Dialogue de saisie

Pour demander une valeur :

dialogManager.input({
  title: "Renommer l’élément",
  description: "Saisissez le nouveau nom.",
  input: {
    label: "Nom",
    defaultValue: currentName,
    placeholder: "Saisissez un nom…",
  },
  action: {
    label: "Enregistrer",
    onClick: async (inputValue) => {
      await renameItem(id, inputValue);
      toast.success("Élément renommé.");
    },
  },
});

Options de saisie

OptionTypeDescription
inputInputConfigConfiguration du champ

InputConfig :

OptionTypeDescription
labelstringLibellé
defaultValuestringValeur par défaut
placeholderstringTexte indicatif

Dialogue personnalisé

Pour un contenu entièrement personnalisé :

import { AlertDialogCancel } from "@/components/ui/alert-dialog";

dialogManager.custom({
  title: "Dialogue personnalisé",
  size: "lg",
  children: (
    <div className="flex flex-col gap-4">
      <p>Contenu personnalisé</p>
      <AlertDialogCancel>Fermer</AlertDialogCancel>
    </div>
  ),
});

Important : ajoutez AlertDialogCancel ou utilisez dialogManager.closeAll() pour permettre la fermeture.

Fermer les dialogues

// Fermer un dialogue par son identifiant
const dialogId = dialogManager.confirm({ ... });
dialogManager.close(dialogId);

// Fermer tous les dialogues
dialogManager.closeAll();

Gestion automatique du chargement

Les boutons d’action affichent automatiquement un état de chargement pendant l’exécution de la promesse onClick.

dialogManager.confirm({
  title: "Enregistrer",
  action: {
    label: "Enregistrer",
    onClick: async () => {
      // Le bouton affiche un indicateur pendant l’opération
      await saveData();
      // Le dialogue se ferme automatiquement après la réussite
    },
  },
});

Si onClick lève une erreur, le dialogue reste ouvert et une notification d’erreur apparaît.

Exemple complet avec icône et contenu centré

import { Trash2 } from "lucide-react";

dialogManager.confirm({
  title: "Supprimer le fichier",
  description: "Cette action supprimera définitivement le fichier.",
  icon: Trash2,
  variant: "destructive",
  style: "centered",
  action: {
    label: "Supprimer",
    variant: "destructive",
    onClick: async () => {
      await deleteFile(fileId);
      toast.success("Fichier supprimé.");
    },
  },
  cancel: {
    label: "Annuler",
  },
});
Composants de contactComposants de mise en page