mobile: consistent dark theme as desktop
This commit is contained in:
@@ -9,7 +9,7 @@ const config: ExpoConfig = {
|
||||
orientation: "portrait",
|
||||
icon: "./assets/icon.png",
|
||||
scheme: "flowy",
|
||||
userInterfaceStyle: "automatic",
|
||||
userInterfaceStyle: "dark",
|
||||
newArchEnabled: true,
|
||||
splash: {
|
||||
image: "./assets/icon.png",
|
||||
|
||||
@@ -31,7 +31,7 @@ export default function App() {
|
||||
<RootNavigator />
|
||||
</NavigationContainer>
|
||||
<Toaster />
|
||||
<StatusBar style="auto" />
|
||||
<StatusBar style="light" />
|
||||
</SafeAreaProvider>
|
||||
</PusherProvider>
|
||||
</QueryClientProvider>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,10 @@
|
||||
import { View } from "react-native";
|
||||
|
||||
/**
|
||||
* Inset hairline separator for edge-to-edge list rows. Pass to a FlatList
|
||||
* via `ItemSeparatorComponent` so it renders only between rows, not after
|
||||
* the last one. Mirrors desktop's <Separator className="mx-4" /> pattern.
|
||||
*/
|
||||
export function ListSeparator() {
|
||||
return <View className="bg-border mx-4 h-px" />;
|
||||
}
|
||||
@@ -13,6 +13,8 @@ import { useNetworks } from "@/hooks/use-networks";
|
||||
import { useAuthStore } from "@/stores/auth-store";
|
||||
import { toUserMessage } from "@/lib/errors";
|
||||
import type { RootStackScreenProps } from "@/navigation/types";
|
||||
import { FlowyLogo } from "@/components/FlowyLogo";
|
||||
import { ListSeparator } from "@/components/ListSeparator";
|
||||
import { Drawer } from "./Drawer";
|
||||
|
||||
export function NetworkListScreen({
|
||||
@@ -48,7 +50,7 @@ export function NetworkListScreen({
|
||||
{initials}
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Text className="text-foreground text-base font-semibold">Flowy</Text>
|
||||
<FlowyLogo />
|
||||
<View className="w-9" />
|
||||
</View>
|
||||
|
||||
@@ -71,10 +73,10 @@ export function NetworkListScreen({
|
||||
<FlatList
|
||||
data={data}
|
||||
keyExtractor={(item) => item.id}
|
||||
contentContainerClassName="p-4 gap-2"
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
|
||||
}
|
||||
ItemSeparatorComponent={ListSeparator}
|
||||
renderItem={({ item }) => (
|
||||
<NetworkCard
|
||||
network={item}
|
||||
@@ -106,10 +108,10 @@ function NetworkCard({
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
className="bg-card border-border active:bg-accent rounded-lg border px-4 py-4 flex-row items-center justify-between"
|
||||
className="active:bg-accent flex-row items-center justify-between px-4 py-4"
|
||||
>
|
||||
<View className="flex-1">
|
||||
<Text className="text-card-foreground text-base font-semibold">
|
||||
<Text className="text-foreground text-base font-semibold">
|
||||
{network.name}
|
||||
</Text>
|
||||
<Text className="text-muted-foreground text-sm">
|
||||
|
||||
@@ -96,10 +96,7 @@ export const StreamCard = memo(function StreamCard({
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
android_ripple={{ color: "rgba(0,0,0,0.05)" }}
|
||||
className={cn(
|
||||
"bg-card border-b px-3.5 py-3 flex-row items-center gap-3 active:bg-accent",
|
||||
isUnseen ? "border-primary" : "border-border",
|
||||
)}
|
||||
className="bg-card flex-row items-center gap-3 px-4 py-3 active:bg-accent"
|
||||
>
|
||||
<View
|
||||
className={cn(
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
View,
|
||||
} from "react-native";
|
||||
import { SafeAreaView } from "react-native-safe-area-context";
|
||||
import { ListSeparator } from "@/components/ListSeparator";
|
||||
import { toUserMessage } from "@/lib/errors";
|
||||
import { particlePath } from "@/lib/particle-path";
|
||||
import { useNetwork } from "@/hooks/use-networks";
|
||||
@@ -43,7 +44,7 @@ export function StreamListScreen({
|
||||
<FlatList
|
||||
data={streams}
|
||||
keyExtractor={(s) => s.id}
|
||||
contentContainerClassName=""
|
||||
ItemSeparatorComponent={ListSeparator}
|
||||
renderItem={({ item }) => (
|
||||
<StreamCard
|
||||
particle={item}
|
||||
|
||||
@@ -1,45 +1,44 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
// Tokens mirror js/desktop/src/styles/globals.css. Desktop authors values in
|
||||
// OKLCH; React Native's color parser is not guaranteed to handle oklch(), so
|
||||
// we ship hex equivalents here and keep the OKLCH source in comments.
|
||||
// Tokens mirror js/desktop/src/styles/globals.css `.dark` palette. Desktop
|
||||
// authors values in OKLCH; React Native's color parser is not guaranteed to
|
||||
// handle oklch(), so we ship hex/rgba equivalents here and keep the OKLCH
|
||||
// source in comments.
|
||||
//
|
||||
// Names match desktop 1:1 — components written against `bg-background`,
|
||||
// `text-foreground`, etc. behave identically.
|
||||
// Mobile is dark-only by design — names match desktop 1:1 so components
|
||||
// written against `bg-background`, `text-foreground`, etc. behave identically
|
||||
// to the desktop app in dark mode.
|
||||
module.exports = {
|
||||
content: ["./index.ts", "./src/**/*.{ts,tsx}"],
|
||||
presets: [require("nativewind/preset")],
|
||||
darkMode: "class",
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
// ---- Light tokens (desktop :root) ----
|
||||
background: { DEFAULT: "#ffffff", dark: "#252525" }, // oklch(1 0 0) / oklch(0.145 0 0)
|
||||
foreground: { DEFAULT: "#252525", dark: "#fafafa" }, // oklch(0.145 0 0) / oklch(0.985 0 0)
|
||||
card: { DEFAULT: "#ffffff", dark: "#363636" }, // oklch(1 0 0) / oklch(0.205 0 0)
|
||||
"card-foreground": { DEFAULT: "#252525", dark: "#fafafa" },
|
||||
popover: { DEFAULT: "#ffffff", dark: "#363636" },
|
||||
"popover-foreground": { DEFAULT: "#252525", dark: "#fafafa" },
|
||||
primary: { DEFAULT: "#363636", dark: "#ebebeb" }, // oklch(0.205 0 0) / oklch(0.922 0 0)
|
||||
"primary-foreground": { DEFAULT: "#fafafa", dark: "#363636" },
|
||||
secondary: { DEFAULT: "#f4f4f4", dark: "#454545" }, // oklch(0.97 0 0) / oklch(0.269 0 0)
|
||||
"secondary-foreground": { DEFAULT: "#363636", dark: "#fafafa" },
|
||||
muted: { DEFAULT: "#f4f4f4", dark: "#454545" },
|
||||
"muted-foreground": { DEFAULT: "#878787", dark: "#a6a6a6" }, // oklch(0.556 0 0) / oklch(0.708 0 0)
|
||||
accent: { DEFAULT: "#f4f4f4", dark: "#454545" },
|
||||
"accent-foreground": { DEFAULT: "#363636", dark: "#fafafa" },
|
||||
destructive: { DEFAULT: "#dc2626", dark: "#ef4444" }, // oklch(0.577 0.245 27.325) / oklch(0.704 0.191 22.216)
|
||||
border: { DEFAULT: "#dcdcdc", dark: "rgba(255,255,255,0.1)" },
|
||||
input: { DEFAULT: "#dcdcdc", dark: "rgba(255,255,255,0.15)" },
|
||||
ring: { DEFAULT: "#a6a6a6", dark: "#878787" }, // oklch(0.708 0 0) / oklch(0.556 0 0)
|
||||
// Sidebar (drawer) tokens — desktop also defines these
|
||||
sidebar: { DEFAULT: "#fafafa", dark: "#363636" },
|
||||
"sidebar-foreground": { DEFAULT: "#252525", dark: "#fafafa" },
|
||||
"sidebar-primary": { DEFAULT: "#363636", dark: "#6366f1" }, // chart-1 dark = oklch(0.488 0.243 264.376)
|
||||
"sidebar-primary-foreground": { DEFAULT: "#fafafa", dark: "#fafafa" },
|
||||
"sidebar-accent": { DEFAULT: "#f4f4f4", dark: "#454545" },
|
||||
"sidebar-accent-foreground": { DEFAULT: "#363636", dark: "#fafafa" },
|
||||
"sidebar-border": { DEFAULT: "#dcdcdc", dark: "rgba(255,255,255,0.1)" },
|
||||
"sidebar-ring": { DEFAULT: "#a6a6a6", dark: "#878787" },
|
||||
background: "#252525", // oklch(0.145 0 0)
|
||||
foreground: "#fafafa", // oklch(0.985 0 0)
|
||||
card: "#363636", // oklch(0.205 0 0)
|
||||
"card-foreground": "#fafafa",
|
||||
popover: "#363636",
|
||||
"popover-foreground": "#fafafa",
|
||||
primary: "#ebebeb", // oklch(0.922 0 0)
|
||||
"primary-foreground": "#363636",
|
||||
secondary: "#454545", // oklch(0.269 0 0)
|
||||
"secondary-foreground": "#fafafa",
|
||||
muted: "#454545",
|
||||
"muted-foreground": "#a6a6a6", // oklch(0.708 0 0)
|
||||
accent: "#454545",
|
||||
"accent-foreground": "#fafafa",
|
||||
destructive: "#ef4444", // oklch(0.704 0.191 22.216)
|
||||
border: "rgba(255,255,255,0.1)", // oklch(1 0 0 / 10%)
|
||||
input: "rgba(255,255,255,0.15)", // oklch(1 0 0 / 15%)
|
||||
ring: "#878787", // oklch(0.556 0 0)
|
||||
sidebar: "#363636",
|
||||
"sidebar-foreground": "#fafafa",
|
||||
"sidebar-primary": "#6366f1", // chart-1 dark = oklch(0.488 0.243 264.376)
|
||||
"sidebar-primary-foreground": "#fafafa",
|
||||
"sidebar-accent": "#454545",
|
||||
"sidebar-accent-foreground": "#fafafa",
|
||||
"sidebar-border": "rgba(255,255,255,0.1)",
|
||||
"sidebar-ring": "#878787",
|
||||
},
|
||||
borderRadius: {
|
||||
lg: "10px", // --radius: 0.625rem
|
||||
|
||||
Reference in New Issue
Block a user