feat: layout responsive mobile (bottom nav) / laptop (sidebar) + page d'accueil
This commit is contained in:
@@ -0,0 +1,45 @@
|
|||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
|
||||||
|
const NAV_ITEMS = [
|
||||||
|
{ to: '/', icon: 'house', label: 'Accueil' },
|
||||||
|
{ to: '/todos', icon: 'list-check', label: 'Todos' },
|
||||||
|
{ to: '/shopping', icon: 'cart-shopping', label: 'Courses' },
|
||||||
|
{ to: '/notes', icon: 'note-sticky', label: 'Notes' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function BottomNav() {
|
||||||
|
return (
|
||||||
|
<nav style={{
|
||||||
|
display: 'flex',
|
||||||
|
background: 'var(--bg-2)',
|
||||||
|
borderTop: '1px solid var(--border-2)',
|
||||||
|
paddingBottom: 'env(safe-area-inset-bottom)',
|
||||||
|
}}>
|
||||||
|
{NAV_ITEMS.map((item) => (
|
||||||
|
<NavLink
|
||||||
|
key={item.to}
|
||||||
|
to={item.to}
|
||||||
|
end={item.to === '/'}
|
||||||
|
style={({ isActive }) => ({
|
||||||
|
flex: 1,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
minHeight: 56,
|
||||||
|
gap: 4,
|
||||||
|
color: isActive ? 'var(--accent)' : 'var(--ink-3)',
|
||||||
|
textDecoration: 'none',
|
||||||
|
fontSize: 10,
|
||||||
|
fontFamily: 'var(--font-ui)',
|
||||||
|
letterSpacing: '0.05em',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<i className={`fa-solid fa-${item.icon}`} style={{ fontSize: 20 }} />
|
||||||
|
{item.label}
|
||||||
|
</NavLink>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,4 +1,24 @@
|
|||||||
import { Outlet } from 'react-router-dom'
|
import { Outlet } from 'react-router-dom'
|
||||||
|
import BottomNav from './BottomNav'
|
||||||
|
import SideNav from './SideNav'
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
return <div><Outlet /></div>
|
return (
|
||||||
|
<div style={{ display: 'flex', height: '100dvh', background: 'var(--bg-1)' }}>
|
||||||
|
{/* Sidebar — visible uniquement sur laptop (lg et +) */}
|
||||||
|
<div className="hidden lg:flex" style={{ flexShrink: 0 }}>
|
||||||
|
<SideNav />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Contenu principal */}
|
||||||
|
<main style={{ flex: 1, overflow: 'auto', paddingBottom: 0 }} className="lg:pb-0 pb-14">
|
||||||
|
<Outlet />
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{/* Navigation bas — visible uniquement sur mobile */}
|
||||||
|
<div className="lg:hidden" style={{ position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: 50 }}>
|
||||||
|
<BottomNav />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
|
||||||
|
const NAV_ITEMS = [
|
||||||
|
{ to: '/', icon: 'house', label: 'Accueil' },
|
||||||
|
{ to: '/todos', icon: 'list-check', label: 'Todos' },
|
||||||
|
{ to: '/shopping', icon: 'cart-shopping', label: 'Courses' },
|
||||||
|
{ to: '/notes', icon: 'note-sticky', label: 'Notes' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function SideNav() {
|
||||||
|
return (
|
||||||
|
<nav style={{
|
||||||
|
width: 220,
|
||||||
|
background: 'var(--bg-2)',
|
||||||
|
borderRight: '1px solid var(--border-1)',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
padding: '16px 0',
|
||||||
|
height: '100%',
|
||||||
|
}}>
|
||||||
|
<div style={{ padding: '0 16px 16px', borderBottom: '1px solid var(--border-1)', marginBottom: 8 }}>
|
||||||
|
<span style={{ color: 'var(--accent)', fontFamily: 'var(--font-mono)', fontWeight: 700, fontSize: 16 }}>
|
||||||
|
HomeHub
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{NAV_ITEMS.map((item) => (
|
||||||
|
<NavLink
|
||||||
|
key={item.to}
|
||||||
|
to={item.to}
|
||||||
|
end={item.to === '/'}
|
||||||
|
style={({ isActive }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 12,
|
||||||
|
padding: '10px 16px',
|
||||||
|
color: isActive ? 'var(--accent)' : 'var(--ink-2)',
|
||||||
|
background: isActive ? 'var(--accent-tint)' : 'transparent',
|
||||||
|
borderLeft: isActive ? '2px solid var(--accent)' : '2px solid transparent',
|
||||||
|
textDecoration: 'none',
|
||||||
|
fontFamily: 'var(--font-ui)',
|
||||||
|
fontSize: 14,
|
||||||
|
minHeight: 40,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<i className={`fa-solid fa-${item.icon}`} style={{ width: 18 }} />
|
||||||
|
{item.label}
|
||||||
|
</NavLink>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,3 +1,30 @@
|
|||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
return <div>HomeHub</div>
|
return (
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="glass" style={{ padding: 20, borderRadius: 10, marginBottom: 16 }}>
|
||||||
|
<h1 style={{ color: 'var(--accent)', fontFamily: 'var(--font-mono)', margin: 0 }}>
|
||||||
|
HomeHub
|
||||||
|
</h1>
|
||||||
|
<p style={{ color: 'var(--ink-2)', marginTop: 8 }}>
|
||||||
|
Application d'organisation personnelle
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))', gap: 12 }}>
|
||||||
|
{[
|
||||||
|
{ label: 'Todos', icon: 'list', path: '/todos' },
|
||||||
|
{ label: 'Courses', icon: 'cart-shopping', path: '/shopping' },
|
||||||
|
{ label: 'Notes', icon: 'note-sticky', path: '/notes' },
|
||||||
|
].map((item) => (
|
||||||
|
<div
|
||||||
|
key={item.path}
|
||||||
|
className="glass interactive"
|
||||||
|
style={{ padding: 20, borderRadius: 10, textAlign: 'center', cursor: 'pointer', minHeight: 80, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 8 }}
|
||||||
|
>
|
||||||
|
<i className={`fa-solid fa-${item.icon}`} style={{ fontSize: 24, color: 'var(--accent)' }} />
|
||||||
|
<span style={{ color: 'var(--ink-1)', fontFamily: 'var(--font-ui)', fontSize: 14 }}>{item.label}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user