commit c4c747ba679c54096aa6a56d478be2b6d0267b25
parent bf2c42d1d07b6f1fb412e0268eaa73f3bf4ae2de
Author: Sunny <kajimalu10@gmail.com>
Date: Wed, 20 Aug 2025 15:40:01 +0900
add fonts
Diffstat:
8 files changed, 161 insertions(+), 102 deletions(-)
diff --git a/src/app/globals.css b/src/app/globals.css
@@ -4,39 +4,33 @@
/* Theming & Color Palette (RGB) */
/* ================================== */
:root {
- /* ライトモードの色定義 (RGB値) */
- --background: 255 255 255; /* Main background */
- --foreground: 10 10 10; /* Main text */
-
- --card: 255 255 255; /* Card background */
- --card-foreground: 10 10 10; /* Card text */
-
- --primary: 37 99 235; /* Primary buttons, links */
- --primary-foreground: 250 250 250; /* Text on primary buttons */
-
- --secondary: 244 245 246; /* Secondary backgrounds */
- --secondary-foreground: 20 20 20; /* Text on secondary backgrounds */
-
- --muted: 229 231 235; /* Subtle backgrounds, borders */
- --muted-foreground: 107 114 128; /* Subtle text */
+ --background: #fbfbfb; /* Main background */
+ --foreground: #000000; /* Main text */
+ --card: #ffffff; /* Card background */
+ --card-foreground: #000000; /* Card text */
+ --primary: #00aee1; /* Primary buttons, links */
+ --primary-foreground: #ffffff; /* Text on primary buttons */
+ --secondary: #f259ce; /* Secondary backgrounds */
+ --secondary-foreground: #ffffff; /* Text on secondary backgrounds */
+ --invite: #333333; /* Secondary backgrounds */
+ --invite-foreground: #ffffff; /* Text on secondary backgrounds */
+ --muted: #eeeeee; /* Subtle backgrounds, borders */
+ --muted-foreground: #666666; /* Subtle text */
}
.dark {
- /* ダークモードの色定義 (RGB値) */
- --background: 18 18 18;
- --foreground: 250 250 250;
-
- --card: 24 24 27;
- --card-foreground: 250 250 250;
-
- --primary: 59 130 246;
- --primary-foreground: 250 250 250;
-
- --secondary: 30 30 33;
- --secondary-foreground: 250 250 250;
-
- --muted: 30 30 33;
- --muted-foreground: 156 163 175;
+ --background: #000000;
+ --foreground: #ffffff;
+ --card: #222222;
+ --card-foreground: #ffffff;
+ --primary: #4336db;
+ --primary-foreground: #dddddd;
+ --secondary: #a80e84;
+ --secondary-foreground: #dddddd;
+ --invite: #dddddd;
+ --invite-foreground: #333333;
+ --muted: #444444;
+ --muted-foreground: #aaaaaa;
}
/* ================================== */
@@ -44,14 +38,16 @@
/* ================================== */
body {
- background-color: rgb(var(--background));
- color: rgb(var(--foreground));
- font-family: Arial, Helvetica, sans-serif; /* フォントは指定通り */
+ background-color: var(--background);
+ color: var(--foreground);
+ font-family: sans-serif;
+ font-weight: 700;
+ font-style: normal;
}
.card {
- background-color: rgb(var(--card));
- color: rgb(var(--card-foreground));
+ background-color: var(--card);
+ color: var(--card-foreground);
padding: 1.5rem; /* p-6 */
border-radius: 0.5rem; /* rounded-lg */
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); /* shadow-md */
@@ -67,7 +63,7 @@ body {
margin-bottom: 0.75rem; /* mb-3 */
padding-bottom: 0.5rem; /* pb-2 */
border-bottom-width: 1px; /* border-b */
- border-bottom-color: rgb(var(--muted)); /* 線の色を指定 */
+ border-bottom-color: var(--muted); /* 線の色を指定 */
}
/* ================================== */
@@ -92,49 +88,49 @@ body {
/* 1. プライマリボタン(塗りつぶし) */
.btn-primary {
- background-color: rgb(var(--primary));
- color: rgb(var(--primary-foreground));
+ background-color: var(--primary);
+ color: var(--primary-foreground);
border-color: transparent;
}
.btn-primary:hover {
filter: brightness(0.9); /* 少し暗くするホバー効果 */
}
.btn-primary:disabled {
- background-color: rgb(var(--muted));
- color: rgb(var(--muted-foreground));
+ background-color: var(--muted);
+ color: var(--muted-foreground);
cursor: not-allowed;
}
/* 2. アウトラインボタン */
.btn-outline {
background-color: transparent;
- border-color: rgb(var(--muted));
- color: rgb(var(--foreground));
+ border-color: var(--muted);
+ color: var(--foreground);
}
.btn-outline:hover {
- background-color: rgb(var(--secondary));
- border-color: rgb(var(--muted));
+ background-color: var(--secondary);
+ border-color: var(--muted);
}
/* アウトラインボタンが選択中のスタイル */
/* .btn-outline.btn-outline-active のように両方のクラスを持つ要素に適用 */
.btn-outline.btn-outline-active {
- background-color: rgb(var(--primary));
- border-color: rgb(var(--primary));
- color: rgb(var(--primary-foreground));
+ background-color: var(--primary);
+ border-color: var(--primary);
+ color: var(--primary-foreground);
}
/* 3. ゴーストボタン(透明) */
.btn-ghost {
background-color: transparent;
border-color: transparent;
- color: rgb(var(--primary));
+ color: var(--primary);
}
.btn-ghost:hover {
- background-color: rgb(var(--secondary));
+ background-color: var(--secondary);
}
.btn-ghost:disabled {
- color: rgb(var(--muted-foreground));
+ color: var(--muted-foreground);
cursor: not-allowed;
}
@@ -152,40 +148,96 @@ body {
/* Side Pane Button Style */
/* ================================== */
.btn-sidepane {
- @apply w-full flex items-center p-2 rounded-md text-slate-300 hover:bg-gray-700 hover:text-white transition-colors duration-200;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ padding: 0.5rem;
+ border-radius: 0.375rem;
+ color: var(--muted-foreground);
+ background-color: transparent;
+ transition: background 0.2s, color 0.2s;
+}
+.btn-sidepane:hover {
+ background-color: var(--muted);
+ color: var(--foreground);
}
/* ================================== */
/* New Timer UI Styles */
/* ================================== */
.timer-dashboard-bg {
- @apply bg-gray-900 text-gray-200;
+ background-color: var(--background);
+ color: var(--foreground);
}
.timer-card {
- @apply bg-gray-800/50 border border-gray-700 rounded-2xl p-6 backdrop-blur-sm;
+ background-color: var(--card);
+ color: var(--card-foreground);
+ border: 1px solid var(--muted);
+ border-radius: 1rem;
+ padding: 1.5rem;
+ backdrop-filter: blur(6px);
+ margin-bottom: 1.5rem;
}
.timer-card-title {
- @apply text-sm font-semibold text-gray-400 mb-2;
+ font-size: 0.875rem;
+ font-weight: 600;
+ color: var(--muted-foreground);
+ margin-bottom: 0.5rem;
}
.countdown-text {
- @apply text-4xl font-mono font-bold tracking-wider;
+ font-size: 2.25rem;
+ font-weight: 700;
+ font-style: normal;
+ letter-spacing: 0.05em;
}
.timer-sub-info {
- @apply text-xs text-gray-500 mt-2 flex items-center gap-2;
+ font-size: 0.75rem;
+ color: var(--muted-foreground);
+ margin-top: 0.5rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
}
.btn-timer {
- @apply w-full py-3 rounded-lg font-bold transition-colors duration-200 disabled:bg-gray-700 disabled:text-gray-500 disabled:cursor-not-allowed;
+ width: 100%;
+ padding: 0.75rem 0;
+ border-radius: 0.5rem;
+ font-weight: bold;
+ transition: background 0.2s, color 0.2s;
+ background-color: var(--primary);
+ color: var(--primary-foreground);
+}
+.btn-timer:disabled {
+ background-color: var(--muted);
+ color: var(--muted-foreground);
+ cursor: not-allowed;
}
-.btn-timer-action {
- @apply bg-blue-600 text-white hover:bg-blue-700;
+.btn-timer-tap {
+ background-color: var(--primary);
+ color: var(--primary-foreground);
+}
+.btn-timer-tap:hover {
+ filter: brightness(0.9);
}
.btn-timer-fave {
- @apply bg-pink-600 text-white hover:bg-pink-700;
+ background-color: var(--secondary);
+ color: var(--secondary-foreground);
+}
+.btn-timer-fave:hover {
+ filter: brightness(0.9);
+}
+
+.btn-timer-inv {
+ background-color: var(--invite);
+ color: var(--invite-foreground);
+}
+.btn-timer-inv:hover {
+ filter: brightness(0.9);
}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
@@ -9,6 +9,9 @@ import { ThemeProvider } from '@/hooks/useTheme';
import Header from '@/components/Header';
import SidePane from '@/components/SidePane';
import "./globals.css";
+import { Noto_Sans_JP } from "next/font/google";
+const NotoSansJPFont400 = Noto_Sans_JP({ weight: "400", subsets: ["latin"] });
+const NotoSansJPFont700 = Noto_Sans_JP({ weight: "700", subsets: ["latin"] });
function AppLayout({ children }: { children: React.ReactNode }) {
const { user, logout } = useAuth();
@@ -37,7 +40,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
return (
<html lang="ja">
- <body>
+ <body className={`${NotoSansJPFont700.className}`}>
<GoogleOAuthProvider clientId={clientId}>
<AuthProvider>
<ThemeProvider>
diff --git a/src/app/page.tsx b/src/app/page.tsx
@@ -163,15 +163,15 @@ export default function Home() {
}
return (
- <div className="timer-dashboard-bg min-h-screen">
+ <div className="bg-background min-h-screen">
{!user ? (
<div className="flex flex-col items-center justify-center h-screen p-8">
- <div className="card text-center !bg-gray-800 border border-gray-700">
- <h2 className="text-xl font-bold mb-4 text-white">ようこそ!</h2>
- <p className="mb-6 text-gray-400">タイマー機能を利用するには、Googleアカウントでログインしてください。</p>
+ <div className="card text-center !bg-card border border-muted">
+ <h2 className="text-xl font-bold mb-4">ようこそ!</h2>
+ <p className="mb-6 text-muted-foreground">タイマー機能を利用するには、Googleアカウントでログインしてください。</p>
<button
onClick={() => login()}
- className="btn btn-primary inline-flex items-center justify-center whitespace-nowrap"
+ className="btn btn-primary"
>
<span>Googleでログイン</span>
</button>
diff --git a/src/components/CountdownDisplay.tsx b/src/components/CountdownDisplay.tsx
@@ -3,6 +3,8 @@
export const runtime = "edge";
import { useMemo } from 'react';
+import { Lekton } from "next/font/google";
+const LektonFont = Lekton({ weight: "700", subsets: ["latin"] });
interface CountdownDisplayProps {
milliseconds: number;
@@ -18,7 +20,7 @@ export default function CountdownDisplay({ milliseconds }: CountdownDisplayProps
}, [milliseconds]);
return (
- <div className="countdown-text">
+ <div className={`countdown-text ${LektonFont.className}`}>
<span>{hours}</span>:
<span>{minutes}</span>:
<span>{seconds}</span>
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
@@ -17,8 +17,8 @@ interface HeaderProps {
export default function Header({ onMenuClick }: HeaderProps) {
return (
- <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>
+ <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 bg-background">
+ <h1 className="text-lg font-bold" style={{ color: "var(--foreground)" }}>カフェタイマー</h1>
<div className="flex items-center gap-2">
<ThemeToggleButton />
<button onClick={onMenuClick} className="p-2 rounded-md hover:bg-secondary">
diff --git a/src/components/SidePane.tsx b/src/components/SidePane.tsx
@@ -31,9 +31,11 @@ export default function SidePane({ isOpen, onClose, user, logout }: SidePaneProp
return (
<main>
<div className={`fixed inset-0 bg-black/50 z-30 transition-opacity ${isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'}`} onClick={onClose}></div>
- <aside className={`fixed top-0 right-0 h-full w-72 bg-gray-800 text-white shadow-lg transform transition-transform z-40 ${isOpen ? 'translate-x-0' : 'translate-x-full'}`}>
+ <aside
+ className={`fixed top-0 right-0 h-full w-72 shadow-lg transform transition-transform z-40 ${isOpen ? 'translate-x-0' : 'translate-x-full'}`}
+ style={{ background: "var(--card)", color: "var(--card-foreground)" }}
+ >
<nav className="p-4 flex flex-col h-full">
-
<ul className="space-y-1">
{menuItems.map(item => (
<li key={item}>
@@ -44,14 +46,12 @@ export default function SidePane({ isOpen, onClose, user, logout }: SidePaneProp
</li>
))}
</ul>
-
<div className="mt-8">
- <p className="text-sm text-gray-400 mb-2 px-2">Language</p>
+ <p className="text-sm" style={{ color: "var(--muted-foreground)" }}>Language</p>
<div className="flex space-x-3 px-2">
<span>🇯🇵</span><span>🇺🇸</span><span>🇨🇳</span><span>🇰🇷</span>
</div>
</div>
-
<div className="mt-auto">
{user && (
<>
diff --git a/src/components/StatsGraph.tsx b/src/components/StatsGraph.tsx
@@ -149,21 +149,21 @@ export default function StatsGraph({ tapHistory }: StatsGraphProps) {
<div>
<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>
- <div className="text-xl font-bold text-foreground">{allTapsToday} <span className="text-pink-600">({oshiTapsToday})</span></div>
+ <div className="p-4 rounded-lg" style={{ background: "var(--secondary)" }}>
+ <div className="text-sm" style={{ color: "var(--muted-foreground)" }}>今日</div>
+ <div className="text-xl font-bold" style={{ color: "var(--foreground)" }}>{allTapsToday} <span style={{ color: "#db2777" }}>({oshiTapsToday})</span></div>
</div>
- <div className="p-4 bg-secondary rounded-lg">
- <div className="text-sm text-muted-foreground">今週</div>
- <div className="text-xl font-bold text-foreground">{allTapsThisWeek} <span className="text-pink-600">({oshiTapsThisWeek})</span></div>
+ <div className="p-4 rounded-lg" style={{ background: "var(--secondary)" }}>
+ <div className="text-sm" style={{ color: "var(--muted-foreground)" }}>今週</div>
+ <div className="text-xl font-bold" style={{ color: "var(--foreground)" }}>{allTapsThisWeek} <span style={{ color: "#db2777" }}>({oshiTapsThisWeek})</span></div>
</div>
- <div className="p-4 bg-secondary rounded-lg">
- <div className="text-sm text-muted-foreground">今月</div>
- <div className="text-xl font-bold text-foreground">{allTapsThisMonth} <span className="text-pink-600">({oshiTapsThisMonth})</span></div>
+ <div className="p-4 rounded-lg" style={{ background: "var(--secondary)" }}>
+ <div className="text-sm" style={{ color: "var(--muted-foreground)" }}>今月</div>
+ <div className="text-xl font-bold" style={{ color: "var(--foreground)" }}>{allTapsThisMonth} <span style={{ color: "#db2777" }}>({oshiTapsThisMonth})</span></div>
</div>
- <div className="p-4 bg-secondary rounded-lg">
- <div className="text-sm text-muted-foreground">今年</div>
- <div className="text-xl font-bold text-foreground">{allTapsThisYear} <span className="text-pink-600">({oshiTapsThisYear})</span></div>
+ <div className="p-4 rounded-lg" style={{ background: "var(--secondary)" }}>
+ <div className="text-sm" style={{ color: "var(--muted-foreground)" }}>今年</div>
+ <div className="text-xl font-bold" style={{ color: "var(--foreground)" }}>{allTapsThisYear} <span style={{ color: "#db2777" }}>({oshiTapsThisYear})</span></div>
</div>
</div>
</div>
diff --git a/src/components/TimerDashboard.tsx b/src/components/TimerDashboard.tsx
@@ -4,7 +4,6 @@ export const runtime = "edge";
import { useState, useEffect, useMemo } from 'react';
import { addHours, differenceInMilliseconds } from 'date-fns';
-import TimerCard from './TimerCard';
import CountdownDisplay from './CountdownDisplay';
// propsの型定義
@@ -63,22 +62,24 @@ export default function TimerDashboard({
return (
- <div className="p-4 sm:p-8 space-y-6">
- <TimerCard title="Next Students Change">
- <CountdownDisplay milliseconds={studentsChangeRemaining} />
+ <div className="p-4 sm:p-8 space-y-6 max-w-md mx-auto timer-dashboard-bg">
+ <div className="timer-card">
+ <h2 className="timer-card-title">Next Students Change</h2>
+ <div className="countdown-text"><CountdownDisplay milliseconds={studentsChangeRemaining} /></div>
<div className="timer-sub-info">
- <span>🔄</span>
+ <span>▶</span>
<span>{now.getHours() < 4 || now.getHours() >= 16 ? "04:00" : "16:00"}</span>
</div>
- </TimerCard>
+ </div>
- <TimerCard title="Next Cafe Tap">
- <CountdownDisplay milliseconds={cafeTapRemaining} />
+ <div className="timer-card">
+ <h2 className="timer-card-title">Next Cafe Tap</h2>
+ <div className="countdown-text"><CountdownDisplay milliseconds={cafeTapRemaining} /></div>
<div className="grid grid-cols-2 gap-4 mt-4">
<button
onClick={() => onTap(false)}
disabled={cafeTapRemaining > 0 || isSyncing}
- className="btn-timer btn-timer-action"
+ className="btn-timer btn-timer-tap"
>{ isSyncing ? '保存中…' : 'Tap' }</button>
<button
onClick={() => onTap(true)}
@@ -86,26 +87,27 @@ export default function TimerDashboard({
className="btn-timer btn-timer-fave"
>{ isSyncing ? '保存中…' : 'Fave Tap' }</button>
</div>
- </TimerCard>
+ </div>
- <TimerCard title="Next Invitation">
+ <div className="timer-card">
+ <h2 className="timer-card-title">Next Invitation</h2>
<div className="grid grid-cols-2 gap-4">
- <CountdownDisplay milliseconds={ticket1Remaining} />
- <CountdownDisplay milliseconds={ticket2Remaining} />
+ <div className="countdown-text"><CountdownDisplay milliseconds={ticket1Remaining} /></div>
+ <div className="countdown-text"><CountdownDisplay milliseconds={ticket2Remaining} /></div>
</div>
<div className="grid grid-cols-2 gap-4 mt-4">
<button
onClick={() => onInvite(1)}
disabled={ticket1Remaining > 0 || isSyncing}
- className="btn-timer btn-timer-action"
+ className="btn-timer btn-timer-inv"
>{ isSyncing ? '保存中…' : 'Ticket 1' }</button>
<button
onClick={() => onInvite(2)}
disabled={ticket2Remaining > 0 || isSyncing}
- className="btn-timer btn-timer-action"
+ className="btn-timer btn-timer-inv"
>{ isSyncing ? '保存中…' : 'Ticket 2' }</button>
</div>
- </TimerCard>
+ </div>
</div>
);
}
\ No newline at end of file