feat(nav): bouton action intégré dans la navbar v0.4.8

- ActionButtonContext : contexte React permettant aux pages d'injecter
  leur bouton action dans la navbar (Shopping=fa-cart-plus, Todos/Notes=+)
- BottomNav : 5e slot dédié avec dock circulaire visuel permanent ;
  bouton rendu 10px au-dessus du centre du slot (effet soulevé)
- Layout : ActionButtonProvider + overflow visible sur le conteneur nav
- Pages : useEffect enregistre/vide le bouton action — plus de FAB flottant
  sur le contenu, liste entièrement visible

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 10:02:03 +02:00
co-authored by Claude Sonnet 4.6
parent d6d3acd1fe
commit cbb2d81279
7 changed files with 138 additions and 66 deletions
+29 -17
View File
@@ -1,5 +1,5 @@
// frontend/src/pages/ShoppingPage.tsx
import { useState, useEffect, useCallback } from 'react'
import { useState, useEffect, useCallback, useRef } from 'react'
import { matchesSearch } from '../utils/search'
import type { ShoppingListDetail, ShoppingList, Store, Product, ShoppingItem } from '../api/shopping'
import {
@@ -13,6 +13,7 @@ import ItemRow from '../components/shopping/ItemRow'
import CatalogueModal from '../components/shopping/CatalogueModal'
import BoutiquesModal from '../components/shopping/BoutiquesModal'
import { useWakeLock } from '../hooks/useWakeLock'
import { useActionButton } from '../contexts/ActionButtonContext'
const inputStyle: React.CSSProperties = {
width: '100%',
@@ -76,6 +77,33 @@ export default function ShoppingPage() {
useWakeLock(currentList !== null)
const { setActionButton } = useActionButton()
const openAddSheetRef = useRef(openAddSheet)
useEffect(() => { openAddSheetRef.current = openAddSheet })
useEffect(() => {
if (!currentList || showAddSheet) {
setActionButton(null)
return
}
setActionButton(
<button
onClick={() => openAddSheetRef.current()}
aria-label="Ajouter un article"
style={{
width: 56, height: 56, borderRadius: '50%',
background: 'var(--accent)', color: '#1d2021', border: 'none',
fontSize: 22, cursor: 'pointer',
boxShadow: '0 4px 16px rgba(0,0,0,0.5)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
}}
>
<i className="fa-solid fa-cart-plus" />
</button>
)
return () => setActionButton(null)
}, [currentList, showAddSheet, setActionButton])
const loadData = useCallback(async () => {
setLoading(true)
setError(null)
@@ -526,22 +554,6 @@ export default function ShoppingPage() {
)}
</div>
{/* FAB — masqué quand le sheet est ouvert */}
{!showAddSheet && (
<button
onClick={openAddSheet}
aria-label="Ajouter un article"
style={{
position: 'fixed', bottom: 10, right: 12,
width: 56, height: 56, borderRadius: '50%',
background: 'var(--accent)', color: '#1d2021', border: 'none',
fontSize: 22, cursor: 'pointer', boxShadow: '0 4px 12px rgba(0,0,0,0.5)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
}}
>
<i className="fa-solid fa-cart-plus" />
</button>
)}
</>
)}