Skip to content

Commit 2cc3968

Browse files
committed
refactor(react-remix-example): enhance app structure and add ScrollRestoration
- Updated root component to include language attribute and meta tags for better accessibility. - Integrated Nav component for navigation and wrapped Outlet in a main container. - Added ScrollRestoration for improved user experience. - Enhanced links function to include a stylesheet from Pico CSS for better styling.
1 parent 36b0686 commit 2cc3968

7 files changed

Lines changed: 566 additions & 103 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { NavLink } from "@remix-run/react"
2+
3+
export function Nav() {
4+
return (
5+
<nav
6+
className="container-fluid"
7+
style={{
8+
position: "sticky",
9+
top: 0,
10+
zIndex: 10,
11+
backdropFilter: "saturate(180%) blur(6px)",
12+
}}
13+
>
14+
<ul>
15+
<li>
16+
<NavLink end to="/" style={{ fontWeight: 600 }}>
17+
Effectify
18+
</NavLink>
19+
</li>
20+
</ul>
21+
<ul>
22+
<li>
23+
<NavLink end to="/">
24+
Home
25+
</NavLink>
26+
</li>
27+
<li>
28+
<NavLink end to="/todos">
29+
Todos
30+
</NavLink>
31+
</li>
32+
</ul>
33+
</nav>
34+
)
35+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
export type TodoStatus = "PENDING" | "COMPLETED"
2+
3+
export type Todo = {
4+
id: string
5+
title: string
6+
content: string
7+
status: TodoStatus
8+
createdAt: string
9+
}
10+
11+
// Module-scoped in-memory storage
12+
const mockStore: Todo[] = [
13+
{
14+
id: "1",
15+
title: "Learn Effect",
16+
content: "Study Effect library fundamentals and patterns",
17+
status: "PENDING",
18+
createdAt: new Date().toISOString(),
19+
},
20+
{
21+
id: "2",
22+
title: "Build Remix App",
23+
content: "Create a CRUD application with Remix and Effect",
24+
status: "PENDING",
25+
createdAt: new Date().toISOString(),
26+
},
27+
{
28+
id: "3",
29+
title: "Write Tests",
30+
content: "Add comprehensive test coverage for the application",
31+
status: "COMPLETED",
32+
createdAt: new Date().toISOString(),
33+
},
34+
]
35+
36+
export const getTodos = (): Todo[] => {
37+
return [...mockStore]
38+
}
39+
40+
export const getTodo = (id: string): Todo | undefined => {
41+
return mockStore.find((todo) => todo.id === id)
42+
}
43+
44+
export const createTodo = (data: Omit<Todo, "id" | "createdAt">): Todo => {
45+
const newTodo: Todo = {
46+
...data,
47+
id: crypto.randomUUID(),
48+
createdAt: new Date().toISOString(),
49+
}
50+
mockStore.push(newTodo)
51+
return newTodo
52+
}
53+
54+
export const updateTodo = (
55+
id: string,
56+
data: Partial<Omit<Todo, "id" | "createdAt">>,
57+
): Todo | undefined => {
58+
const index = mockStore.findIndex((todo) => todo.id === id)
59+
if (index === -1) return undefined
60+
61+
mockStore[index] = {
62+
...mockStore[index],
63+
...data,
64+
}
65+
return mockStore[index]
66+
}
67+
68+
export const deleteTodo = (id: string): boolean => {
69+
const index = mockStore.findIndex((todo) => todo.id === id)
70+
if (index === -1) return false
71+
72+
mockStore.splice(index, 1)
73+
return true
74+
}
75+
76+
export const toggleTodo = (id: string): Todo | undefined => {
77+
const todo = getTodo(id)
78+
if (!todo) return undefined
79+
80+
return updateTodo(id, {
81+
status: todo.status === "PENDING" ? "COMPLETED" : "PENDING",
82+
})
83+
}
Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
import type { HtmlLinkDescriptor } from "@remix-run/react"
2-
import { Links, Meta, Outlet, Scripts } from "@remix-run/react"
2+
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react"
3+
import { Nav } from "./components/Nav.js"
34

45
export default function App() {
56
return (
6-
<html>
7+
<html lang="en">
78
<head>
9+
<meta charSet="utf-8" />
10+
<meta name="viewport" content="width=device-width, initial-scale=1" />
811
<Meta />
912
<Links />
1013
</head>
1114
<body>
12-
<h1>Hello world!</h1>
13-
<Outlet />
15+
<Nav />
16+
<main className="container">
17+
<Outlet />
18+
</main>
19+
<ScrollRestoration />
1420
<Scripts />
1521
</body>
1622
</html>
1723
)
1824
}
1925

2026
export function links(): HtmlLinkDescriptor[] {
21-
return [{ rel: "icon", href: "data:image/x-icon;base64,AA" }]
27+
return [
28+
{ rel: "icon", href: "data:image/x-icon;base64,AA" },
29+
{
30+
rel: "stylesheet",
31+
href: "https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.min.css",
32+
integrity: "sha384-NZhm4G1I7BpEGdjDKnzEfy3d78xvy7ECKUwwnKTYi036z42IyF056PbHfpQLIYgL",
33+
crossOrigin: "anonymous",
34+
},
35+
]
2236
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Link } from "@remix-run/react"
2+
3+
export default function Index() {
4+
return (
5+
<article>
6+
<h1>Welcome to Effectify + Remix</h1>
7+
<p>
8+
This is a demonstration application showing how to integrate <strong>Effect</strong> with <strong>Remix</strong>
9+
{" "}
10+
using the <code>@effectify/react-remix</code> package.
11+
</p>
12+
13+
<h2>Features</h2>
14+
<ul>
15+
<li>Type-safe functional programming with Effect</li>
16+
<li>Full CRUD operations with mock data storage</li>
17+
<li>PicoCSS classless styling</li>
18+
<li>Effect runtime wrappers for loaders and actions</li>
19+
</ul>
20+
21+
<h2>Get Started</h2>
22+
<p>
23+
Check out the{" "}
24+
<Link to="/todos" style={{ color: "#007bff" }}>
25+
Todo App
26+
</Link>{" "}
27+
to see Effect in action with Remix!
28+
</p>
29+
30+
<hr />
31+
32+
<h3>Existing Routes</h3>
33+
<ul>
34+
<li>
35+
<Link to="/test">/test</Link> - Form demonstration with validation
36+
</li>
37+
<li>
38+
<Link to="/demo">/demo</Link> - Response type demonstrations
39+
</li>
40+
<li>
41+
<Link to="/api/docs">/api/docs</Link> - API documentation (Scalar)
42+
</li>
43+
</ul>
44+
</article>
45+
)
46+
}

0 commit comments

Comments
 (0)