Top Bar petits écrans

This commit is contained in:
2026-06-14 17:53:02 +02:00
parent 1bc626e7d5
commit 440f59d86c
2 changed files with 130 additions and 18 deletions
+67 -18
View File
@@ -217,10 +217,22 @@ function IconPlusCircle() {
);
}
const IconBurger = () => (
<svg width="28" height="28" viewBox="0 0 28 28" fill="none"
stroke="currentColor" strokeWidth="2" strokeLinecap="round"
aria-hidden="true">
<line x1="4" y1="8" x2="24" y2="8"/>
<line x1="4" y1="14" x2="24" y2="14"/>
<line x1="4" y1="20" x2="24" y2="20"/>
</svg>
);
export default function Layout() {
const { sidebarCollapsed, setSidebarCollapsed, toggleSidebar, displayMode, setDisplayMode } = useUi();
const navigate = useNavigate();
const [navIcons, setNavIcons] = useState({});
const [burgerOpen, setBurgerOpen] = useState(false);
const burgerRef = useRef(null);
// Auto-collapse en mode portrait sur tablette (7681200px)
useEffect(() => {
@@ -231,6 +243,16 @@ export default function Layout() {
return () => mq.removeEventListener('change', handler);
}, [setSidebarCollapsed]);
// Fermer le burger au clic extérieur
useEffect(() => {
if (!burgerOpen) return;
const handler = (e) => {
if (burgerRef.current && !burgerRef.current.contains(e.target)) setBurgerOpen(false);
};
document.addEventListener('mousedown', handler);
return () => document.removeEventListener('mousedown', handler);
}, [burgerOpen]);
useEffect(() => {
api.get('/icons').then(rows => {
const m = {};
@@ -302,28 +324,55 @@ export default function Layout() {
<div className="topbar topbar-global">
<ProjectSearch />
<div className="topbar-right">
<button
className="btn-add-invest"
onClick={() => navigate('/investissements?new=1')}
>
<IconPlusCircle />
Ajout Investissement
{/* Boutons visibles sur grand écran */}
<button className="btn-add-invest topbar-action-btn" onClick={() => navigate('/investissements?new=1')}>
<IconPlusCircle />Ajout Investissement
</button>
<button
className="btn-add-invest"
onClick={() => navigate('/remboursements?new=1')}
>
<IconPlusCircle />
Nouveau remboursement
<button className="btn-add-invest topbar-action-btn" onClick={() => navigate('/remboursements?new=1')}>
<IconPlusCircle />Nouveau remboursement
</button>
<button
className="btn-add-invest"
onClick={() => navigate('/depots-retraits?new=1')}
>
<IconPlusCircle />
Nouveau dépôt/retrait
<button className="btn-add-invest topbar-action-btn" onClick={() => navigate('/depots-retraits?new=1')}>
<IconPlusCircle />Nouveau dépôt/retrait
</button>
{/* Bouton burger — visible sur tablette/mobile */}
<div className="topbar-burger-wrap" ref={burgerRef}>
<button
className="topbar-burger-btn"
onClick={() => setBurgerOpen(v => !v)}
aria-label="Menu actions"
aria-expanded={burgerOpen}
>
<IconBurger />
</button>
{burgerOpen && (
<div className="topbar-burger-menu">
<button className="topbar-burger-search-item" onClick={() => { setBurgerOpen(false); document.querySelector('.project-search-input')?.focus(); }}>
<svg width="15" height="15" viewBox="0 0 18 18" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" aria-hidden="true"><circle cx="7.5" cy="7.5" r="5.5"/><line x1="11.5" y1="11.5" x2="16" y2="16"/></svg>
Rechercher un projet
</button>
<div className="topbar-burger-sep" />
<button className="topbar-burger-item" onClick={() => { setBurgerOpen(false); navigate('/investissements?new=1'); }}>
<IconPlusCircle />Ajout Investissement
</button>
<button className="topbar-burger-item" onClick={() => { setBurgerOpen(false); navigate('/remboursements?new=1'); }}>
<IconPlusCircle />Nouveau remboursement
</button>
<button className="topbar-burger-item" onClick={() => { setBurgerOpen(false); navigate('/depots-retraits?new=1'); }}>
<IconPlusCircle />Nouveau dépôt/retrait
</button>
<div className="topbar-burger-sep" />
<div className="topbar-burger-toggle">
<span className="topbar-burger-toggle-label">Affichage</span>
<div className="display-toggle" role="group" aria-label="Mode d'affichage">
<button className={`display-toggle-btn${displayMode === 'brut' ? ' active' : ''}`} onClick={() => setDisplayMode('brut')} aria-pressed={displayMode === 'brut'}>Brut</button>
<button className={`display-toggle-btn${displayMode === 'net' ? ' active' : ''}`} onClick={() => setDisplayMode('net')} aria-pressed={displayMode === 'net'}>Net</button>
</div>
</div>
</div>
)}
</div>
<div className="display-toggle" role="group" aria-label="Mode d'affichage">
<button
className={`display-toggle-btn${displayMode === 'brut' ? ' active' : ''}`}