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
+19 -21
View File
@@ -5,6 +5,7 @@ import { fetchTodos, createTodo, updateTodo, deleteTodo, postponeTodo } from '..
import SwipeableRow from '../components/todos/SwipeableRow'
import TodoForm, { DOMAIN_COLORS } from '../components/todos/TodoForm'
import Modal from '../components/Modal'
import { useActionButton } from '../contexts/ActionButtonContext'
type EditingTodo = Todo | null
@@ -41,6 +42,24 @@ export default function TodosPage() {
const [editingTodo, setEditingTodo] = useState<EditingTodo>(null)
const [filters, setFilters] = useState<TodoFilters>({ status: 'pending' })
const { setActionButton } = useActionButton()
useEffect(() => {
setActionButton(
<button
onClick={() => setShowForm(true)}
aria-label="Nouvelle tâche"
style={{
width: 56, height: 56, borderRadius: '50%',
background: 'var(--accent)', color: '#1d2021', border: 'none',
fontSize: 24, cursor: 'pointer',
boxShadow: '0 4px 16px rgba(0,0,0,0.5)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
}}
>+</button>
)
return () => setActionButton(null)
}, [setActionButton])
const load = useCallback(async () => {
setLoading(true)
setError(null)
@@ -395,27 +414,6 @@ export default function TodosPage() {
)}
</div>
{/* FAB création — mobile : au-dessus de la barre de nav ; laptop : coin bas-droit */}
<button
className="fixed bottom-[10px] right-3 lg:bottom-6 lg:right-6"
onClick={() => setShowForm(true)}
aria-label="Nouvelle tâche"
style={{
width: 56,
height: 56,
borderRadius: '50%',
background: 'var(--accent)',
color: '#1d2021',
border: 'none',
fontSize: 28,
cursor: 'pointer',
boxShadow: '0 4px 12px rgba(0,0,0,0.5)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
lineHeight: 1,
}}
>+</button>
</div>
)
}