Bandeau des alternatives appliquées à la trace : leur liste, l’écart total de distance et de dénivelé, le téléchargement du GPX modifié et le retour à l’original.
stableÀ valider
// Titre : Deux alternatives appliquées
import EditBanner from '@pathou/components/EditBanner';
import type { AppliedDetour } from '@pathou/lib/edit/compose';
// seuls les champs affichés comptent ici : position, écart de distance et de D+
const applied = [
{ id: 'a', fromIdx: 0, toIdx: 0, path: [], km: 12.4, toKm: 13.1, extraM: 380, extraGain: 22 },
{ id: 'b', fromIdx: 0, toIdx: 0, path: [], km: 27.9, toKm: 28.6, extraM: -120, extraGain: -8 },
] satisfies AppliedDetour[];
export default function Exemple() {
return (
<div style={{ width: 340 }}>
<EditBanner applied={applied} onRemove={() => {}} onReset={() => {}} onDownload={() => {}} />
</div>
);
}
Installation
Copie le fichier dans ton projet, ainsi que les tokens qu’il utilise.
import type { AppliedDetour } from '../lib/edit/compose';
import { formatDelta } from '../lib/detour/result';
import { fmt } from '../lib/format';
/** Alternatives appliquées à la trace : liste, écart total, téléchargement et retour à l'original. */
export default function EditBanner({ applied, onRemove, onReset, onDownload }: { applied: AppliedDetour[]; onRemove: (id: string) => void; onReset: () => void; onDownload: () => void }) {
if (applied.length === 0) return null;
const extraM = applied.reduce((s, a) => s + a.extraM, 0);
const gain = Math.round(applied.reduce((s, a) => s + a.extraGain, 0));
const n = applied.length;
return (
<section className="edit-banner" aria-label="Trace modifiée">
<div className="edit-head">
<b>Trace modifiée</b>
<span>
{n} alternative{n > 1 ? 's' : ''} appliquée{n > 1 ? 's' : ''} · {formatDelta(extraM)} · {gain < 0 ? '−' : '+'}
{Math.abs(gain)} m D+
</span>
</div>
<ul className="edit-list">
{[...applied].sort((a, b) => a.km - b.km).map((a) => (
<li key={a.id}>
<span>
km {fmt(a.km, 1)} → {fmt(a.toKm, 1)} · {formatDelta(a.extraM)}
</span>
<button type="button" className="ghost" onClick={() => onRemove(a.id)}>
Retirer
</button>
</li>
))}
</ul>
<div className="edit-actions">
<button type="button" className="primary" onClick={onDownload}>
Télécharger le GPX
</button>
<button type="button" className="ghost" onClick={onReset}>
Revenir à l’original
</button>
</div>
</section>
);
}
Tokens : --panel --muted --accent --accent-ink --chip --replaced
Utilisation
import EditBanner from './components/EditBanner';
<EditBanner applied={applied} onRemove={removeDetour} onReset={resetEdit} onDownload={downloadGpx} />Anatomie
| # | Élément | Rôle |
|---|---|---|
| 1 | En-tête | « Trace modifiée » et le bilan (nombre d’alternatives, écart de distance, écart de D+). |
| 2 | Liste | Une ligne par alternative, triée par kilomètre, avec son bouton « Retirer ». |
| 3 | Actions | « Télécharger le GPX » (principal) et « Revenir à l’original ». |
Guidelines
- MUSTN’afficher le bandeau que lorsqu’au moins une alternative est appliquée ; le composant ne rend rien sinon.
- SHOULDGarder le téléchargement du GPX en action principale ; c’est le seul moyen de conserver la trace modifiée.
Référence de l’API
| Prop | Type | Défaut |
|---|---|---|
applied | AppliedDetour[] | requis |
onRemove | (id: string) => void | requis |
onReset | () => void | requis |
onDownload | () => void | requis |