feat: add theme system with light/dark mode support
- Add ThemeStore (Zustand) for reactive theme switching - Add Themes.tsx with THEMES object (defaultLight, defaultDark) - Add Settings screen with theme switcher and logout button - Add BaseButton component for reusable themed buttons - Migrate all components from static currentTheme to useThemeStore() - Add shadowColor to theme (iOS only, Android uses elevation) - All text elements now use theme colors (textPrimary, textSecondary, etc.) - Update tab navigation to include Settings tab - Move logout from Header to Settings screen
This commit is contained in:
72
CLAUDE.md
72
CLAUDE.md
@@ -72,24 +72,26 @@ src/
|
||||
│ ├── login.tsx # Login screen
|
||||
│ ├── register.tsx # Registration screen
|
||||
│ ├── (tabs)/ # Tab navigation group
|
||||
│ │ ├── _layout.tsx # Tab bar configuration
|
||||
│ │ ├── _layout.tsx # Tab bar configuration (themed)
|
||||
│ │ ├── chat.tsx # Chat screen (AI conversation)
|
||||
│ │ └── calendar.tsx # Calendar overview
|
||||
│ │ ├── calendar.tsx # Calendar overview
|
||||
│ │ └── settings.tsx # Settings screen (theme switcher, logout)
|
||||
│ ├── event/
|
||||
│ │ └── [id].tsx # Event detail screen (dynamic route)
|
||||
│ └── note/
|
||||
│ └── [id].tsx # Note editor for event (dynamic route)
|
||||
├── components/
|
||||
│ ├── BaseBackground.tsx # Common screen wrapper
|
||||
│ ├── Header.tsx # Header component with logout button
|
||||
│ ├── AuthButton.tsx # Reusable button for auth screens (with shadow)
|
||||
│ ├── BaseBackground.tsx # Common screen wrapper (themed)
|
||||
│ ├── BaseButton.tsx # Reusable button component (themed, supports children)
|
||||
│ ├── Header.tsx # Header component (themed)
|
||||
│ ├── AuthButton.tsx # Reusable button for auth screens (themed, with shadow)
|
||||
│ ├── ChatBubble.tsx # Reusable chat bubble component (used by ChatMessage & TypingIndicator)
|
||||
│ ├── TypingIndicator.tsx # Animated typing indicator (. .. ...) shown while waiting for AI response
|
||||
│ ├── EventCardBase.tsx # Shared event card layout with icons (used by EventCard & ProposedEventCard)
|
||||
│ ├── EventCard.tsx # Calendar event card (uses EventCardBase + edit/delete buttons)
|
||||
│ ├── EventConfirmDialog.tsx # AI-proposed event confirmation modal
|
||||
│ ├── EventConfirmDialog.tsx # AI-proposed event confirmation modal (skeleton)
|
||||
│ └── ProposedEventCard.tsx # Chat event proposal (uses EventCardBase + confirm/reject buttons)
|
||||
├── Themes.tsx # Centralized color/theme definitions
|
||||
├── Themes.tsx # Theme definitions: THEMES object with defaultLight/defaultDark, Theme type
|
||||
├── logging/
|
||||
│ ├── index.ts # Re-exports
|
||||
│ └── logger.ts # react-native-logs config (apiLogger, storeLogger)
|
||||
@@ -104,10 +106,47 @@ src/
|
||||
├── AuthStore.ts # user, isAuthenticated, isLoading, login(), logout(), loadStoredUser()
|
||||
│ # Uses expo-secure-store (native) / localStorage (web)
|
||||
├── ChatStore.ts # messages[], isWaitingForResponse, addMessage(), addMessages(), updateMessage(), clearMessages(), setWaitingForResponse(), chatMessageToMessageData()
|
||||
└── EventsStore.ts # events[], setEvents(), addEvent(), updateEvent(), deleteEvent()
|
||||
├── EventsStore.ts # events[], setEvents(), addEvent(), updateEvent(), deleteEvent()
|
||||
└── ThemeStore.ts # theme, setTheme() - reactive theme switching with Zustand
|
||||
```
|
||||
|
||||
**Routing:** Tab-based navigation with Chat and Calendar as main screens. Auth screens (login, register) outside tabs. Dynamic routes for event detail and note editing.
|
||||
**Routing:** Tab-based navigation with Chat, Calendar, and Settings as main screens. Auth screens (login, register) outside tabs. Dynamic routes for event detail and note editing.
|
||||
|
||||
### Theme System
|
||||
|
||||
The app supports multiple themes (light/dark) via a reactive Zustand store.
|
||||
|
||||
**Theme Structure (`Themes.tsx`):**
|
||||
```typescript
|
||||
export type Theme = {
|
||||
chatBot, primeFg, primeBg, secondaryBg, messageBorderBg, placeholderBg,
|
||||
calenderBg, confirmButton, rejectButton, disabledButton, buttonText,
|
||||
textPrimary, textSecondary, textMuted, eventIndicator, borderPrimary, shadowColor
|
||||
};
|
||||
|
||||
export const THEMES = {
|
||||
defaultLight: { ... },
|
||||
defaultDark: { ... }
|
||||
} as const satisfies Record<string, Theme>;
|
||||
```
|
||||
|
||||
**Usage in Components:**
|
||||
```typescript
|
||||
import { useThemeStore } from "../stores/ThemeStore";
|
||||
|
||||
const MyComponent = () => {
|
||||
const { theme } = useThemeStore();
|
||||
return <View style={{ backgroundColor: theme.primeBg }} />;
|
||||
};
|
||||
```
|
||||
|
||||
**Theme Switching:**
|
||||
```typescript
|
||||
const { setTheme } = useThemeStore();
|
||||
setTheme("defaultDark"); // or "defaultLight"
|
||||
```
|
||||
|
||||
**Note:** `shadowColor` only works on iOS. Android uses `elevation` with system-defined shadow colors.
|
||||
|
||||
### Backend Architecture (apps/server)
|
||||
|
||||
@@ -376,10 +415,16 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
||||
- `ApiClient`: Automatically injects X-User-Id header for authenticated requests
|
||||
- Login screen: Supports email OR userName login
|
||||
- Register screen: Email validation, checks for existing email/userName
|
||||
- `AuthButton`: Reusable button component with shadow effect
|
||||
- `Header`: Contains logout button on all screens
|
||||
- `AuthButton`: Reusable button component with themed shadow
|
||||
- `Header`: Themed header component (logout moved to Settings)
|
||||
- `index.tsx`: Auth redirect - checks stored user on app start
|
||||
- Tab navigation (Chat, Calendar) implemented with basic UI
|
||||
- **Theme system fully implemented:**
|
||||
- `ThemeStore`: Zustand store with theme state and setTheme()
|
||||
- `Themes.tsx`: THEMES object with defaultLight/defaultDark variants
|
||||
- All components use `useThemeStore()` for reactive theme colors
|
||||
- Settings screen with theme switcher (light/dark)
|
||||
- `BaseButton`: Reusable themed button component
|
||||
- Tab navigation (Chat, Calendar, Settings) implemented with themed UI
|
||||
- Calendar screen fully functional:
|
||||
- Month navigation with grid display and Ionicons (chevron-back/forward)
|
||||
- MonthSelector dropdown with infinite scroll (dynamically loads months, lazy-loaded when modal opens, cleared on close for memory efficiency)
|
||||
@@ -404,9 +449,10 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
||||
- `EventCardBase`: Shared base component with event layout (header, date/time/recurring icons, description) - used by both EventCard and ProposedEventCard
|
||||
- `EventCard`: Uses EventCardBase + edit/delete buttons for calendar display
|
||||
- `ProposedEventCard`: Uses EventCardBase + confirm/reject buttons for chat proposals (supports create/update/delete actions)
|
||||
- `Themes.tsx`: Centralized color definitions including textPrimary, borderPrimary, eventIndicator, secondaryBg
|
||||
- `Themes.tsx`: Theme definitions with THEMES object (defaultLight, defaultDark) including all color tokens (textPrimary, borderPrimary, eventIndicator, secondaryBg, shadowColor, etc.)
|
||||
- `EventsStore`: Zustand store with setEvents(), addEvent(), updateEvent(), deleteEvent() - stores ExpandedEvent[]
|
||||
- `ChatStore`: Zustand store with addMessage(), addMessages(), updateMessage(), clearMessages(), isWaitingForResponse/setWaitingForResponse() for typing indicator - loads from server on mount and persists across tab switches
|
||||
- `ThemeStore`: Zustand store with theme/setTheme() for reactive theme switching across all components
|
||||
- `ChatBubble`: Reusable chat bubble component with Tailwind styling, used by ChatMessage and TypingIndicator
|
||||
- `TypingIndicator`: Animated typing indicator component showing `. → .. → ...` loop while waiting for AI response
|
||||
- Event Detail and Note screens exist as skeletons
|
||||
|
||||
Reference in New Issue
Block a user