---
name: menus-actions-sur-les-tableaux-et-blocs
description: "Pattern menu contextuel fixe (position: fixed + backdrop + icônes SVG) sur tableaux et headers de blocs ; voir aussi [[feedback_menu_actions_format]]"
metadata: 
  node_type: memory
  type: project
  originSessionId: 2fef7a75-e0f3-4f7d-9c80-79c3be16af03
---

Menus d'action ⋮ sur les tableaux :

| Page | Tableau | Actions disponibles |
|---|---|---|
| DepotsRetraits | Mouvements | Modifier / Correction de solde / Supprimer |
| Remboursements | Remboursements | Modifier / Supprimer |
| Investissements | Investissements | Voir le détail / Modifier / Supprimer |
| InvestissementDetail | Remboursements enregistrés | Modifier / Supprimer |
| InvestissementDetail | Réinvestissements complémentaires | Supprimer |
| AdminPlateformes — ReferentielSection | Référentiel plateformes | Modifier / Pousser (douce) / Pousser (forcée) / Supprimer |
| AdminPlateformes — RefListSection | Catégories d'investissement | Renommer / Fusionner avec… / Supprimer |
| AdminPlateformes — RefListSection | Secteurs d'investissement | Renommer / Fusionner avec… / Supprimer |

Menus ⋮ sur les **headers de blocs** (InvestissementDetail) — bouton 30×30 px, border var(--border), 3 cercles SVG, état séparé de `openMenu` :

| Bloc | État | Actions |
|---|---|---|
| Informations du projet | `cardMenu` | Modifier / Réinvestir / Exporter / Désactiver auto-reinvest (si actif) / Supprimer |
| Remboursements enregistrés | `rembMenu` | Ajouter un remboursement / Supprimer tous les remboursements |
| Réinvestissements complémentaires | `reinvMenu` | Ajouter un réinvestissement / Supprimer tous les réinvestissements |
| Projections de remboursements | `simulMenu` | Régénérer l'échéancier |

**Fermeture au scroll :** `useEffect` avec `window.addEventListener('scroll', closeAll, true)` — implémenté sur InvestissementDetail, DepotsRetraits, Investissements, Remboursements, AdminPlateformes. À reproduire sur toute nouvelle page avec menu contextuel.

**Pattern technique (version avec icônes — format actuel de référence) :**
```jsx
// Icônes SVG locales (13×13 px)
function IconEdit() { return <svg .../>; }
function IconTrash() { return <svg .../>; }

// État
const [openMenu, setOpenMenu] = useState(null); // { row, x, y }

// Fermeture scroll
useEffect(() => {
  if (!openMenu) return;
  const close = () => setOpenMenu(null);
  window.addEventListener('scroll', close, true);
  return () => window.removeEventListener('scroll', close, true);
}, [openMenu]);

// Ouverture
const handleMenuOpen = (e, row) => {
  e.stopPropagation();
  const rect = e.currentTarget.getBoundingClientRect();
  setOpenMenu({ row, x: rect.right, y: rect.bottom + 4 });
};

// Rendu
{openMenu && (
  <>
    <div style={{ position: 'fixed', inset: 0, zIndex: 299 }} onClick={() => setOpenMenu(null)} />
    <div style={{ position: 'fixed', left: openMenu.x, top: openMenu.y,
      transform: 'translateX(-100%) translateY(4px)', zIndex: 300,
      background: 'var(--surface)', border: '1px solid var(--border)',
      borderRadius: 8, boxShadow: '0 4px 20px rgba(0,0,0,0.15)', padding: '4px 0', minWidth: 180 }}>
      {[
        { icon: <IconEdit />, label: 'Modifier', onClick: () => { ... } },
        { icon: <IconTrash />, label: 'Supprimer', color: 'var(--danger)', onClick: () => { ... } },
      ].map(({ icon, label, onClick, disabled, color }) => (
        <button key={label} disabled={disabled}
          style={{ display: 'flex', alignItems: 'center', gap: 8, width: '100%', padding: '8px 14px',
            background: 'none', border: 'none', cursor: disabled ? 'default' : 'pointer',
            fontSize: 'var(--fs-sm)', color: color || 'var(--text)', opacity: disabled ? 0.5 : 1 }}
          onMouseEnter={e => { if (!disabled) e.currentTarget.style.background = 'var(--surface-2)'; }}
          onMouseLeave={e => e.currentTarget.style.background = 'none'}
          onClick={disabled ? undefined : onClick}>
          <span style={{ opacity: 0.7, flexShrink: 0, display: 'flex' }}>{icon}</span>
          {label}
        </button>
      ))}
    </div>
  </>
)}
```

**Why:** Actions inline remplacées par menus contextuels compacts pour garder les tableaux lisibles. Les icônes ont été ajoutées suite à la demande d'Olivier pour aligner avec le style de l'image de référence.
