Skip to content

Commit e50cc13

Browse files
committed
chore: fix dark mode and update layout on web
1 parent ecbb326 commit e50cc13

10 files changed

+137
-25
lines changed

app/_layout.web.tsx

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import {Button} from "@/components/ui";
2+
import {DatabaseProvider} from "@/db/provider";
3+
import {Link, Slot, Stack} from "expo-router";
4+
// This is a general react-dom library and only requires the framework support server rendering.
5+
// Adding it will ensure the body tag has the class="dark" injected when dark mode is enabled,
6+
// this is required for tailwind css/shadcn to style correctly in dark mode.
7+
import {ThemeProvider, useTheme} from "next-themes";
8+
import {Text} from "@/components/ui/text";
9+
import {SettingsIcon} from "lucide-react-native";
10+
import {ListBullets} from "@/lib/icons/ListBullets"
11+
import {ThemeToggle} from "@/components/ThemeToggle";
12+
import {View} from "react-native";
13+
const TopNav = () => {
14+
return (
15+
<nav className="flex h-14 px-4 flex-row justify-end bg-background border-b dark:border-border/60">
16+
<ThemeToggle />
17+
</nav>
18+
);
19+
}
20+
export default function RootLayout() {
21+
return (
22+
<ThemeProvider
23+
attribute="class"
24+
defaultTheme="system"
25+
enableSystem
26+
disableTransitionOnChange
27+
>
28+
<DatabaseProvider>
29+
30+
31+
<div className="flex flex-1 flex-col md:flex-row bg-background">
32+
33+
<div className=" p-6 flex flex-col justify-between w-[240px] border-r dark:border-border/60">
34+
<div className="space-y-4">
35+
36+
<nav className="flex flex-col justify-start gap-y-5 mt-11">
37+
<Link href="/" asChild>
38+
<Button
39+
size="sm"
40+
variant="ghost"
41+
className="flex-row gap-2 justify-start"
42+
>
43+
<ListBullets className="text-foreground" />
44+
<Text className="text-base">Habits</Text>
45+
</Button>
46+
</Link>
47+
<Link href="/settings" asChild>
48+
<Button
49+
size="sm"
50+
variant="ghost"
51+
className="flex-row gap-2 justify-start"
52+
>
53+
<SettingsIcon />
54+
<Text className="text-base">Settings</Text>
55+
</Button>
56+
</Link>
57+
</nav>
58+
</div>
59+
60+
</div>
61+
<div className="flex flex-1 flex-col">
62+
<TopNav />
63+
<View className="flex h-[700px]">
64+
<Slot />
65+
</View>
66+
67+
</div>
68+
</div>
69+
</DatabaseProvider>
70+
</ThemeProvider>
71+
72+
);
73+
}

app/create.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,17 @@ export default function FormScreen() {
115115
}
116116
return (
117117
<ScrollView
118-
ref={scrollRef}
119118
contentContainerClassName="p-6 mx-auto w-full max-w-xl"
120-
showsVerticalScrollIndicator={false}
119+
showsVerticalScrollIndicator={true}
120+
className="bg-background"
121+
121122
automaticallyAdjustContentInsets={false}
122123
contentInset={{top: 12}}
123124
>
124125
<Stack.Screen
125126
options={{
126127
title: "New Habit",
128+
headerShadowVisible: true,
127129
headerRight: () => Platform.OS !== "web" && <Pressable onPress={() => router.dismiss()}><X /></Pressable>
128130
}}
129131
/>

app/index.tsx

+19-12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {Pressable, View} from "react-native";
77
import {ThemeToggle} from "@/components/ThemeToggle";
88
import {Button} from "@/components/ui/button";
99
import {useLiveQuery} from "drizzle-orm/expo-sqlite";
10+
import {useTheme} from "next-themes";
1011

1112
import {Progress} from "@/components/ui/progress";
1213
import {Text} from "@/components/ui/text";
@@ -44,11 +45,11 @@ export default function Screen() {
4445
function ScreenContent() {
4546
const {db} = useDatabase();
4647
const {data: habits, error} = useLiveQuery(db?.select().from(habitTable));
47-
48+
const {theme, setTheme} = useTheme()
49+
// console.log("theme", theme)
4850
const ref = React.useRef(null);
4951
useScrollToTop(ref);
5052

51-
const router = useRouter();
5253

5354
const renderItem = React.useCallback(
5455
({item}: {item: Habit}) => <HabitCard {...item} />,
@@ -63,17 +64,22 @@ function ScreenContent() {
6364
);
6465
}
6566
return (
66-
<View className="flex-1 gap-5 p-6 bg-secondary/30">
67+
<View className="flex flex-col basis-full bg-background p-8">
68+
69+
{/* <Button onPress={() => setTheme("light")}>
70+
<Text>Light mode</Text>
71+
</Button>
6772
73+
<Button onPress={() => setTheme('dark')}>
74+
<Text>Dark mode</Text>
75+
</Button> */}
6876
<Stack.Screen
6977
options={{
7078
title: "Habits",
79+
// headerTitleStyle: {
80+
// color: "hsl(var(--foreground))"
81+
// },
7182
headerRight: () => <ThemeToggle />,
72-
headerLeft: () => (
73-
<Button variant="link" onPress={() => router.navigate("settings")}>
74-
<SettingsIcon />
75-
</Button>
76-
),
7783
}}
7884
/>
7985
<FlashList
@@ -94,14 +100,15 @@ function ScreenContent() {
94100
</Text>
95101
</Text>
96102
</View>
97-
)}
103+
)
104+
}
98105
ItemSeparatorComponent={() => <View className="p-2" />}
99106
data={habits}
100107
renderItem={renderItem}
101108
keyExtractor={(_, index) => `item-${ index }`}
102-
ListFooterComponent={<View className="py-4" />}
109+
ListFooterComponent={< View className="py-4" />}
103110
/>
104-
<View className="absolute bottom-10 right-8">
111+
<View className="absolute web:bottom-20 bottom-10 right-8" >
105112
<Link href="/create" asChild>
106113
<Pressable>
107114
<View className="bg-primary justify-center rounded-full h-[45px] w-[45px]">
@@ -110,6 +117,6 @@ function ScreenContent() {
110117
</Pressable>
111118
</Link>
112119
</View>
113-
</View>
120+
</View >
114121
);
115122
}

app/settings/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {Plus, PlusCircle} from "@/components/Icons";
99

1010
export default function Settings() {
1111
return (
12-
<View className="flex-1 w-full px-6 pt-4 bg-muted gap-y-6">
12+
<View className="flex-1 w-full px-6 pt-4 bg-background gap-y-6">
1313

1414
<List>
1515
<ListHeader>

bun.lockb

448 Bytes
Binary file not shown.

components/ThemeToggle.tsx

+17-6
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,28 @@ import {MoonStar, Sun} from "@/components/Icons";
44
import {setAndroidNavigationBar} from "@/lib/android-navigation-bar";
55
import {useColorScheme} from "@/lib/useColorScheme";
66
import {cn} from "@/lib/utils";
7+
import {useTheme} from "next-themes";
8+
import {Platform} from "react-native";
79

810
export function ThemeToggle() {
911
const {isDarkColorScheme, setColorScheme} = useColorScheme();
12+
const {theme, setTheme} = useTheme()
13+
14+
const handleToggleTheme = () => {
15+
const newTheme = isDarkColorScheme ? "light" : "dark";
16+
17+
if (Platform.OS === "web") {
18+
setTheme(theme === "dark" ? "light" : "dark")
19+
} else {
20+
setColorScheme(newTheme);
21+
setAndroidNavigationBar(newTheme);
22+
AsyncStorage.setItem("theme", newTheme);
23+
}
24+
25+
}
1026
return (
1127
<Pressable
12-
onPress={() => {
13-
const newTheme = isDarkColorScheme ? "light" : "dark";
14-
setColorScheme(newTheme);
15-
setAndroidNavigationBar(newTheme);
16-
AsyncStorage.setItem("theme", newTheme);
17-
}}
28+
onPress={() => handleToggleTheme()}
1829
className="web:ring-offset-background web:transition-colors web:focus-visible:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2"
1930
>
2031
{({pressed}) => (

lib/icons/ListBullets.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import ListBullets from "phosphor-react-native/src/icons/ListBullets";
2+
import {iconWithClassName} from './iconWithClassName';
3+
iconWithClassName(ListBullets);
4+
export {ListBullets};

lib/icons/iconWithClassName.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { LucideIcon } from "lucide-react-native";
2+
import { cssInterop } from "nativewind";
3+
import type { IconProps } from "phosphor-react-native/src/lib";
4+
5+
export function iconWithClassName(icon: LucideIcon | IconProps) {
6+
cssInterop(icon, {
7+
className: {
8+
target: "style",
9+
nativeStyleToProp: {
10+
color: true,
11+
opacity: true,
12+
width: true,
13+
height: true,
14+
},
15+
},
16+
});
17+
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"expo-system-ui": "~3.0.4",
5454
"lucide-react-native": "^0.314.0",
5555
"nativewind": "^4.0.36",
56+
"next-themes": "^0.3.0",
5657
"phosphor-react-native": "^2.0.0",
5758
"react": "18.2.0",
5859
"react-dom": "18.2.0",

tailwind.config.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ import { hairlineWidth } from "nativewind/theme";
44

55
export default {
66
darkMode: "class",
7-
content: [
8-
"./app/**/*.{ts,tsx}",
9-
"./components/**/*.{ts,tsx}",
10-
],
7+
content: ["./app/**/*.{ts,tsx}", "./components/**/*.{ts,tsx}"],
118
presets: [nativewind],
129
theme: {
1310
extend: {

0 commit comments

Comments
 (0)