import { useEffect, useState } from 'react'; import { App as F7App, View, Views, Toolbar, Link } from 'framework7-react'; import Framework7 from 'framework7/lite-bundle'; import Framework7React from 'framework7-react'; import routes from './routes'; import 'framework7/css/bundle'; // The icon font F7's iconIos/iconMd props reference; without it the props // render as their raw names. import 'framework7-icons'; import './f7theme.css'; Framework7.use(Framework7React); /** The five thumb-reachable destinations. Secondary screens are pushed on top * of whichever tab is active, the way an iOS app stacks them. */ const TABS = [ { id: 'today', path: '/', label: '今日', icon: 'square_grid_2x2' }, { id: 'health', path: '/health/', label: '健康', icon: 'heart' }, { id: 'daily', path: '/daily/', label: '每日', icon: 'calendar' }, { id: 'trends', path: '/trends/', label: '趋势', icon: 'chart_bar_alt_fill' }, { id: 'awards', path: '/achievements/', label: '成就', icon: 'rosette' }, ]; /** * Dark mode is a deliberate, validated palette rather than an inversion. The * choice is stamped on for our own tokens, and mirrored onto F7's * `.dark` class so its chrome follows the same switch. */ function useTheme() { const [theme, setTheme] = useState<'light' | 'dark' | 'system'>( () => (localStorage.getItem('ghl_theme') as any) || 'system' ); useEffect(() => { const root = document.documentElement; const media = window.matchMedia('(prefers-color-scheme: dark)'); const apply = () => { if (theme === 'system') root.removeAttribute('data-theme'); else root.setAttribute('data-theme', theme); root.classList.toggle( 'dark', theme === 'dark' || (theme === 'system' && media.matches) ); }; apply(); localStorage.setItem('ghl_theme', theme); media.addEventListener('change', apply); return () => media.removeEventListener('change', apply); }, [theme]); return [theme, setTheme] as const; } function App() { useTheme(); return ( {TABS.map((tab) => ( ))} {/* Each tab keeps its own navigation stack, so pushing a detail screen inside 健康 does not disturb where 趋势 was left. */} {TABS.map((tab) => ( ))} ); } export default App;