Files
SeaGateway-App/THEME_GUIDE.md
2025-11-17 17:01:42 +07:00

235 lines
5.8 KiB
Markdown

# Theme System Documentation
## Tổng quan
Hệ thống theme đã được cấu hình để hỗ trợ Light Mode, Dark Mode và System Mode (tự động theo hệ thống). Theme được lưu trữ trong AsyncStorage và sẽ được khôi phục khi khởi động lại ứng dụng.
## Cấu trúc Theme
### 1. Colors Configuration (`constants/theme.ts`)
```typescript
export const Colors = {
light: {
text: "#11181C",
textSecondary: "#687076",
background: "#fff",
backgroundSecondary: "#f5f5f5",
surface: "#ffffff",
surfaceSecondary: "#f8f9fa",
primary: "#007AFF",
secondary: "#5AC8FA",
success: "#34C759",
warning: "#FF9500",
error: "#FF3B30",
// ... more colors
},
dark: {
text: "#ECEDEE",
textSecondary: "#8E8E93",
background: "#000000",
backgroundSecondary: "#1C1C1E",
surface: "#1C1C1E",
surfaceSecondary: "#2C2C2E",
primary: "#0A84FF",
secondary: "#64D2FF",
success: "#30D158",
warning: "#FF9F0A",
error: "#FF453A",
// ... more colors
},
};
```
### 2. Theme Context (`hooks/use-theme-context.tsx`)
Cung cấp theme state và functions cho toàn bộ app:
```typescript
interface ThemeContextType {
themeMode: ThemeMode; // 'light' | 'dark' | 'system'
colorScheme: ColorScheme; // 'light' | 'dark'
colors: typeof Colors.light;
setThemeMode: (mode: ThemeMode) => Promise<void>;
getColor: (colorName: ColorName) => string;
}
```
## Cách sử dụng Theme
### 1. Sử dụng Themed Components
```tsx
import { ThemedText } from "@/components/themed-text";
import { ThemedView } from "@/components/themed-view";
function MyComponent() {
return (
<ThemedView>
<ThemedText type="title">Title Text</ThemedText>
<ThemedText type="default">Regular Text</ThemedText>
</ThemedView>
);
}
```
### 2. Sử dụng Theme Hook
```tsx
import { useThemeContext } from "@/hooks/use-theme-context";
function MyComponent() {
const { colors, colorScheme, setThemeMode } = useThemeContext();
return (
<View style={{ backgroundColor: colors.background }}>
<Text style={{ color: colors.text }}>Current theme: {colorScheme}</Text>
</View>
);
}
```
### 3. Sử dụng App Theme Hook (Recommended)
```tsx
import { useAppTheme } from "@/hooks/use-app-theme";
function MyComponent() {
const { colors, styles, utils } = useAppTheme();
return (
<View style={styles.container}>
<TouchableOpacity style={styles.primaryButton}>
<Text style={styles.primaryButtonText}>Button</Text>
</TouchableOpacity>
<View
style={[
styles.surface,
{
backgroundColor: utils.getOpacityColor("primary", 0.1),
},
]}
>
<Text style={{ color: colors.text }}>
Theme is {utils.isDark ? "Dark" : "Light"}
</Text>
</View>
</View>
);
}
```
### 4. Sử dụng useThemeColor Hook
```tsx
import { useThemeColor } from "@/hooks/use-theme-color";
function MyComponent() {
// Override colors for specific themes
const backgroundColor = useThemeColor(
{ light: "#ffffff", dark: "#1C1C1E" },
"surface"
);
const textColor = useThemeColor({}, "text");
return (
<View style={{ backgroundColor }}>
<Text style={{ color: textColor }}>Text</Text>
</View>
);
}
```
## Theme Toggle Component
Sử dụng `ThemeToggle` component để cho phép user chọn theme:
```tsx
import { ThemeToggle } from "@/components/theme-toggle";
function SettingsScreen() {
return (
<View>
<ThemeToggle />
</View>
);
}
```
## Available Styles từ useAppTheme
```typescript
const { styles } = useAppTheme();
// Container styles
styles.container; // Flex 1 container với background
styles.surface; // Card surface với padding
styles.card; // Card với shadow và border radius
// Button styles
styles.primaryButton; // Primary button style
styles.secondaryButton; // Secondary button với border
styles.primaryButtonText; // White text cho primary button
styles.secondaryButtonText; // Theme text cho secondary button
// Input styles
styles.textInput; // Text input với border và padding
// Status styles
styles.successContainer; // Success status container
styles.warningContainer; // Warning status container
styles.errorContainer; // Error status container
// Utility
styles.separator; // Line separator
```
## Theme Utilities
```typescript
const { utils } = useAppTheme();
utils.isDark; // boolean - kiểm tra dark mode
utils.isLight; // boolean - kiểm tra light mode
utils.toggleTheme(); // function - toggle giữa light/dark
utils.getOpacityColor(colorName, opacity); // Tạo màu với opacity
```
## Lưu trữ Theme Preference
Theme preference được tự động lưu trong AsyncStorage với key `'theme_mode'`. Khi app khởi động, theme sẽ được khôi phục từ storage.
## Best Practices
1. **Sử dụng `useAppTheme`** thay vì access colors trực tiếp
2. **Sử dụng pre-defined styles** từ `useAppTheme().styles`
3. **Kiểm tra theme** bằng `utils.isDark` thay vì check colorScheme
4. **Sử dụng opacity colors** cho backgrounds: `utils.getOpacityColor('primary', 0.1)`
5. **Tận dụng ThemedText và ThemedView** cho các component đơn giản
## Migration từ theme cũ
Nếu bạn đang sử dụng theme cũ:
```tsx
// Cũ
const colorScheme = useColorScheme();
const backgroundColor = colorScheme === "dark" ? "#000" : "#fff";
// Mới
const { colors } = useAppTheme();
const backgroundColor = colors.background;
```
## Troubleshooting
1. **Theme không được lưu**: Kiểm tra AsyncStorage permissions
2. **Flash khi khởi động**: ThemeProvider sẽ chờ load theme trước khi render
3. **Colors không đúng**: Đảm bảo component được wrap trong ThemeProvider
## Examples
Xem `components/theme-example.tsx` để biết các cách sử dụng theme khác nhau.