ba-cafe

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 39eefbde4d451dc89ff2c216d4e8d9268c86d879
parent 6e559640019d77d2219bd406fca4b5888ed0f06a
Author: Sunny <kajimalu10@gmail.com>
Date:   Thu, 14 Aug 2025 10:40:32 +0900

adjust style

Diffstat:
Msrc/app/globals.css | 26++++++++++++--------------
Msrc/app/layout.tsx | 5++++-
Msrc/app/page.tsx | 2+-
Msrc/components/Header.tsx | 17+++++++++++------
Msrc/components/StatsGraph.tsx | 28++++++++++++++++++++++++----
Asrc/components/ThemeToggleButton.tsx | 31+++++++++++++++++++++++++++++++
Asrc/hooks/useTheme.tsx | 47+++++++++++++++++++++++++++++++++++++++++++++++
Atailwind.config.ts | 16++++++++++++++++
8 files changed, 146 insertions(+), 26 deletions(-)

diff --git a/src/app/globals.css b/src/app/globals.css @@ -21,24 +21,22 @@ --muted-foreground: 107 114 128; /* Subtle text */ } -@media (prefers-color-scheme: dark) { - :root { - /* ダークモードの色定義 (RGB値) */ - --background: 18 18 18; - --foreground: 250 250 250; +.dark { + /* ダークモードの色定義 (RGB値) */ + --background: 18 18 18; + --foreground: 250 250 250; - --card: 24 24 27; - --card-foreground: 250 250 250; + --card: 24 24 27; + --card-foreground: 250 250 250; - --primary: 59 130 246; - --primary-foreground: 250 250 250; + --primary: 59 130 246; + --primary-foreground: 250 250 250; - --secondary: 30 30 33; - --secondary-foreground: 250 250 250; + --secondary: 30 30 33; + --secondary-foreground: 250 250 250; - --muted: 30 30 33; - --muted-foreground: 156 163 175; - } + --muted: 30 30 33; + --muted-foreground: 156 163 175; } /* ================================== */ diff --git a/src/app/layout.tsx b/src/app/layout.tsx @@ -3,6 +3,7 @@ import { useState } from 'react'; import { GoogleOAuthProvider } from '@react-oauth/google'; import { AuthProvider, useAuth } from '@/hooks/useAuth'; +import { ThemeProvider } from '@/hooks/useTheme'; import Header from '@/components/Header'; import SidePane from '@/components/SidePane'; import "./globals.css"; @@ -37,7 +38,9 @@ export default function RootLayout({ children }: { children: React.ReactNode }) <body> <GoogleOAuthProvider clientId={clientId}> <AuthProvider> - <AppLayout>{children}</AppLayout> + <ThemeProvider> + <AppLayout>{children}</AppLayout> + </ThemeProvider> </AuthProvider> </GoogleOAuthProvider> </body> diff --git a/src/app/page.tsx b/src/app/page.tsx @@ -122,7 +122,7 @@ export default function Home() { } return ( - <main className="flex flex-col items-center p-4 sm:p-8 text-gray-800"> + <main className="flex flex-col items-center p-4 sm:p-8 text-foreground"> <div className="w-full max-w-md mx-auto"> {!user ? ( <div className="card text-center"> diff --git a/src/components/Header.tsx b/src/components/Header.tsx @@ -1,5 +1,7 @@ "use client"; +import ThemeToggleButton from './ThemeToggleButton'; + // ハンバーガーメニューアイコン const MenuIcon = () => ( <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}> @@ -8,16 +10,19 @@ const MenuIcon = () => ( ); interface HeaderProps { - onMenuClick: () => void; // メニューボタンがクリックされたことを親に伝える + onMenuClick: () => void; } export default function Header({ onMenuClick }: HeaderProps) { return ( - <header className="fixed top-0 left-0 right-0 z-20 flex items-center justify-between p-4 bg-slate-100/80 backdrop-blur-sm shadow-sm"> - <h1 className="text-xl font-bold text-blue-600">カフェタイマー</h1> - <button onClick={onMenuClick} className="p-2"> - <MenuIcon /> - </button> + <header className="fixed top-0 left-0 right-0 z-20 flex items-center h-12 justify-between p-4 backdrop-blur-md shadow-md"> + <h1 className="text-lg font-bold text-foreground">カフェタイマー</h1> + <div className="flex items-center gap-2"> + <ThemeToggleButton /> + <button onClick={onMenuClick} className="p-2 rounded-md hover:bg-secondary"> + <MenuIcon /> + </button> + </div> </header> ); } \ No newline at end of file diff --git a/src/components/StatsGraph.tsx b/src/components/StatsGraph.tsx @@ -60,8 +60,28 @@ export default function StatsGraph({ tapHistory }: StatsGraphProps) { const commonOptions: ChartOptions<'line'> = { responsive: true, maintainAspectRatio: false, - plugins: { legend: { position: 'top' } }, - scales: { y: { beginAtZero: true, ticks: { stepSize: 2 } } }, + plugins: { + legend: { + position: 'top', + labels: { + color: '#999999' + } + } + }, + scales: { + y: { + beginAtZero: true, + ticks: { + stepSize: 2, + color: '#999999', + }, + }, + x: { + ticks: { + color: '#999999', + }, + }, + }, }; let navLabelText = ''; @@ -125,7 +145,7 @@ export default function StatsGraph({ tapHistory }: StatsGraphProps) { <div className="space-y-6"> {/* サマリー表示 */} <div> - <h3 className="text-lg font-bold mb-2 text-slate-700">サマリー</h3> + <h3 className="text-lg font-bold mb-2 text-foreground">サマリー</h3> <div className="grid grid-cols-2 gap-4 text-center"> <div className="p-4 bg-secondary rounded-lg"> <div className="text-sm text-muted-foreground">今日</div> @@ -148,7 +168,7 @@ export default function StatsGraph({ tapHistory }: StatsGraphProps) { {/* グラフ表示エリア */} <div> - <h3 className="text-lg font-bold mb-2 text-slate-700">タップ履歴グラフ</h3> + <h3 className="text-lg font-bold mb-2 text-foreground">タップ履歴グラフ</h3> <div className="my-4 flex justify-center gap-2"> <button onClick={() => setView('daily')} diff --git a/src/components/ThemeToggleButton.tsx b/src/components/ThemeToggleButton.tsx @@ -0,0 +1,30 @@ +"use client"; + +import { useTheme } from '@/hooks/useTheme'; + +const SunIcon = () => ( + <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}> + <path strokeLinecap="round" strokeLinejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" /> + </svg> +); + +const MoonIcon = () => ( + <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}> + <path strokeLinecap="round" strokeLinejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" /> + </svg> +); + + +export default function ThemeToggleButton() { + const { theme, setTheme } = useTheme(); + + const toggleTheme = () => { + setTheme(theme === 'light' ? 'dark' : 'light'); + }; + + return ( + <button onClick={toggleTheme} className="p-2 rounded-md hover:bg-secondary"> + {theme === 'light' ? <MoonIcon /> : <SunIcon />} + </button> + ); +}+ \ No newline at end of file diff --git a/src/hooks/useTheme.tsx b/src/hooks/useTheme.tsx @@ -0,0 +1,46 @@ +"use client"; + +import { createContext, useContext, useEffect, useState, ReactNode } from 'react'; + +type Theme = 'light' | 'dark'; + +interface ThemeContextType { + theme: Theme; + setTheme: (theme: Theme) => void; +} + +const ThemeContext = createContext<ThemeContextType | undefined>(undefined); + +export const ThemeProvider = ({ children }: { children: ReactNode }) => { + const [theme, setTheme] = useState<Theme>('light'); + + useEffect(() => { + // 初回読み込み時にlocalStorageからテーマを取得、なければ'light' + const storedTheme = localStorage.getItem('theme') as Theme | null; + if (storedTheme) { + setTheme(storedTheme); + } + }, []); + + useEffect(() => { + // themeが変更されたら<html>のクラスとlocalStorageを更新 + const root = window.document.documentElement; + root.classList.remove('light', 'dark'); + root.classList.add(theme); + localStorage.setItem('theme', theme); + }, [theme]); + + return ( + <ThemeContext.Provider value={{ theme, setTheme }}> + {children} + </ThemeContext.Provider> + ); +}; + +export const useTheme = () => { + const context = useContext(ThemeContext); + if (context === undefined) { + throw new Error('useTheme must be used within a ThemeProvider'); + } + return context; +};+ \ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts @@ -0,0 +1,15 @@ +import type { Config } from 'tailwindcss' + +const config: Config = { + + darkMode: 'class', + + content: [ + './src/pages/**/*.{js,ts,jsx,tsx,mdx}', + './src/components/**/*.{js,ts,jsx,tsx,mdx}', + './src/app/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: {}, + plugins: [], +} +export default config+ \ No newline at end of file