LeaveConfirm

←→

Confirmation avant de quitter la trace affichée, pour qu’un clic de travers sur « Nouvelle trace » ne fasse pas perdre l’analyse ni les alternatives appliquées.

stableÀ valider
// Titre : Avec deux alternatives appliquées
import { useState } from 'react';
import LeaveConfirm from '@pathou/components/LeaveConfirm';

export default function Exemple() {
  const [open, setOpen] = useState(true);
  return (
    <div style={{ minHeight: 320 }}>
      <button type="button" onClick={() => setOpen(true)}>
        Nouvelle trace
      </button>
      {open && <LeaveConfirm lost={2} onStay={() => setOpen(false)} onLeave={() => setOpen(false)} />}
    </div>
  );
}

Installation

Copie le fichier dans ton projet, ainsi que les tokens qu’il utilise.

src/components/LeaveConfirm.tsx
import Modal from './Modal';

/**
 * Confirmation avant de quitter la trace : un clic de travers sur « Nouvelle trace » ne fait plus perdre l'analyse.
 * Le focus est sur « Rester sur la trace » : Entrée, Échap, ✕ et un clic sur le fond laissent la trace affichée.
 */
export default function LeaveConfirm({ lost, onStay, onLeave }: { lost: number; onStay: () => void; onLeave: () => void }) {
  return (
    <Modal title="Revenir à l’accueil ?" onClose={onStay} small>
      {(close) => (
        <>
          <p className="modal-lead">La trace affichée sera fermée. Pour la revoir, il faudra la charger à nouveau et attendre son analyse.</p>
          {lost > 0 && (
            <p className="modal-lead">
              <strong>{lost === 1 ? 'L’alternative appliquée sera perdue.' : `Les ${lost} alternatives appliquées seront perdues.`}</strong> Reste sur la trace et télécharge le GPX
              avant si tu veux {lost === 1 ? 'la' : 'les'} garder.
            </p>
          )}
          <div className="modal-actions">
            <button type="button" className="secondary" onClick={onLeave}>
              Revenir à l’accueil
            </button>
            {/* l'attribut natif `autofocus` désigne le bouton à la showModal() : le prop React ne le pose pas */}
            <button type="button" className="primary" onClick={close} ref={(el) => el?.setAttribute('autofocus', '')}>
              Rester sur la trace
            </button>
          </div>
        </>
      )}
    </Modal>
  );
}

Tokens : --bg --panel --text --muted --accent --accent-ink --chip --ease-out

Utilisation

import LeaveConfirm from './components/LeaveConfirm';

{confirm && <LeaveConfirm lost={applied.length} onStay={() => setConfirm(false)} onLeave={goHome} />}

Exemples

Sans alternative appliquée

// Titre : Sans alternative appliquée
import { useState } from 'react';
import LeaveConfirm from '@pathou/components/LeaveConfirm';

export default function Exemple() {
  const [open, setOpen] = useState(true);
  return (
    <div style={{ minHeight: 280 }}>
      <button type="button" onClick={() => setOpen(true)}>
        Nouvelle trace
      </button>
      {open && <LeaveConfirm lost={0} onStay={() => setOpen(false)} onLeave={() => setOpen(false)} />}
    </div>
  );
}

Anatomie

#ÉlémentRôle
1QuestionLe titre « Revenir à l’accueil ? », dans une petite fenêtre Modal.
2ConséquenceCe qui sera perdu ; la phrase sur les alternatives n’apparaît que si lost est supérieur à zéro.
3PartirBouton secondaire « Revenir à l’accueil », qui appelle onLeave.
4ResterBouton principal « Rester sur la trace », qui a le focus à l’ouverture.

Guidelines

  • MUST
    Faire de « rester » l’action par défaut : Entrée, Échap, la croix et un clic sur le fond ne doivent jamais faire perdre la trace.
  • SHOULD
    Dire précisément ce qui sera perdu (nombre d’alternatives) et comment le garder (télécharger le GPX).

Clavier

ToucheEffet
EntréeReste sur la trace (le focus est sur ce bouton à l’ouverture).
ÉchapReste sur la trace.

Référence de l’API

PropTypeDéfaut
lostnumberrequis
onStay() => voidrequis
onLeave() => voidrequis