@@ -4,6 +4,7 @@ import { Form, Link, NavLink, Outlet, useLoaderData } from "@remix-run/react";
4
4
import { getNoteListItems } from "~/models/note.server" ;
5
5
import { requireUserId } from "~/session.server" ;
6
6
import { useUser } from "~/utils" ;
7
+ import React , { useState } from 'react' ;
7
8
8
9
export const loader = async ( { request } : LoaderFunctionArgs ) => {
9
10
const userId = await requireUserId ( request ) ;
@@ -14,38 +15,81 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
14
15
export default function NotesPage ( ) {
15
16
const data = useLoaderData < typeof loader > ( ) ;
16
17
const user = useUser ( ) ;
18
+ const [ isSidebarOpen , setIsSidebarOpen ] = useState ( false ) ;
17
19
18
20
return (
19
21
< div className = "flex h-full min-h-screen flex-col" >
20
- < main className = "flex h-full bg-white" >
21
- < div className = "h-full w-80 border-r bg-gray-50" >
22
- < Link to = "new" className = "block p-4 text-xl text-blue-500" >
23
- + New Note
24
- </ Link >
25
-
26
- < hr />
27
-
28
- { data . noteListItems . length === 0 ? (
29
- < p className = "p-4" > No notes yet</ p >
30
- ) : (
31
- < ol >
32
- { data . noteListItems . map ( ( note ) => (
33
- < li key = { note . id } >
34
- < NavLink
35
- className = { ( { isActive } ) =>
36
- `block border-b p-4 text-xl ${ isActive ? "bg-white" : "" } `
37
- }
38
- to = { note . id }
39
- >
40
- 📝 { note . title }
41
- </ NavLink >
42
- </ li >
43
- ) ) }
44
- </ ol >
22
+ { /* Main container with padding-top to account for header */ }
23
+ < main className = "flex-1 flex flex-col md:flex-row-reverse h-full bg-white" style = { { paddingTop : '64px' } } >
24
+ { /* Hamburger menu button for mobile only, positioned below header on the right, hides when sidebar is open */ }
25
+ { ! isSidebarOpen && (
26
+ < button
27
+ onClick = { ( ) => setIsSidebarOpen ( true ) }
28
+ className = "md:hidden fixed top-16 right-4 z-50 p-4 text-blue-500 focus:outline-none"
29
+ >
30
+ < svg className = "h-6 w-6" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
31
+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = "2" d = "M4 6h16M4 12h16m-7 6h7" />
32
+ </ svg >
33
+ </ button >
34
+ ) }
35
+
36
+ { /* Sidebar for notes list - hidden on mobile by default, fixed width on desktop, now on the right */ }
37
+ < div className = { `
38
+ fixed inset-y-0 right-0 transform ${ isSidebarOpen ? 'translate-x-0' : 'translate-x-full' }
39
+ md:relative md:translate-x-0 md:flex md:w-80 md:border-l md:bg-gray-50 md:shadow
40
+ transition-transform duration-300 ease-in-out z-40
41
+ h-full
42
+ ` } style = { { top : '64px' , boxShadow : '-2px 0 5px rgba(0, 0, 0, 0.1)' } } >
43
+ < div className = "h-full w-full overflow-y-auto" >
44
+ < Link to = "new" className = "block p-4 text-xl text-black" >
45
+ + New Note
46
+ </ Link >
47
+
48
+ < hr />
49
+
50
+ { data . noteListItems . length === 0 ? (
51
+ < p className = "p-4" > No notes yet</ p >
52
+ ) : (
53
+ < ol className = "space-y-2" >
54
+ { data . noteListItems . map ( ( note ) => (
55
+ < li key = { note . id } >
56
+ < NavLink
57
+ className = { ( { isActive } ) =>
58
+ `block p-3 text-lg hover:bg-gray-100 ${ isActive ? "bg-white border-r-4 border-blue-500" : "" } `
59
+ }
60
+ to = { note . id }
61
+ >
62
+ 📝 { note . title }
63
+ </ NavLink >
64
+ </ li >
65
+ ) ) }
66
+ </ ol >
67
+ ) }
68
+ </ div >
69
+
70
+ { /* Close button for mobile sidebar - now on the right when sidebar is open */ }
71
+ { isSidebarOpen && (
72
+ < button
73
+ onClick = { ( ) => setIsSidebarOpen ( false ) }
74
+ className = "md:hidden absolute top-4 right-4 text-gray-500 hover:text-gray-800 focus:outline-none"
75
+ >
76
+ < svg className = "h-6 w-6" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
77
+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = "2" d = "M6 18L18 6M6 6l12 12" />
78
+ </ svg >
79
+ </ button >
45
80
) }
46
81
</ div >
47
82
48
- < div className = "flex-1 p-6" >
83
+ { /* Overlay for mobile when sidebar is open - now covers left side */ }
84
+ { isSidebarOpen && (
85
+ < div
86
+ className = "fixed inset-0 bg-black opacity-50 md:hidden z-30"
87
+ onClick = { ( ) => setIsSidebarOpen ( false ) }
88
+ > </ div >
89
+ ) }
90
+
91
+ { /* Main content area - adjusts for sidebar width on desktop, now on the left */ }
92
+ < div className = "flex-1 p-4 md:p-6" style = { { marginRight : '320px' , transition : 'margin-right 300ms ease-in-out' } } >
49
93
< Outlet />
50
94
</ div >
51
95
</ main >
0 commit comments