Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dark mode #56

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions app/(dashboard)/dashboard/activity/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default async function ActivityPage() {

return (
<section className="flex-1 p-4 lg:p-8">
<h1 className="text-lg lg:text-2xl font-medium text-gray-900 mb-6">
<h1 className="text-lg lg:text-2xl font-medium text-foreground/90 mb-6">
Activity Log
</h1>
<Card>
Expand All @@ -91,15 +91,15 @@ export default async function ActivityPage() {

return (
<li key={log.id} className="flex items-center space-x-4">
<div className="bg-orange-100 rounded-full p-2">
<Icon className="w-5 h-5 text-orange-600" />
<div className="bg-orange-100 dark:bg-orange-900 rounded-full p-2">
<Icon className="w-5 h-5 text-orange-600 dark:text-orange-400" />
</div>
<div className="flex-1">
<p className="text-sm font-medium text-gray-900">
<p className="text-sm font-medium text-foreground/90">
{formattedAction}
{log.ipAddress && ` from IP ${log.ipAddress}`}
</p>
<p className="text-xs text-gray-500">
<p className="text-xs text-muted-foreground">
{getRelativeTime(new Date(log.timestamp))}
</p>
</div>
Expand All @@ -110,10 +110,10 @@ export default async function ActivityPage() {
) : (
<div className="flex flex-col items-center justify-center text-center py-12">
<AlertCircle className="h-12 w-12 text-orange-500 mb-4" />
<h3 className="text-lg font-semibold text-gray-900 mb-2">
<h3 className="text-lg font-semibold text-foreground/90 mb-2">
No activity yet
</h3>
<p className="text-sm text-gray-500 max-w-sm">
<p className="text-sm text-muted-foreground max-w-sm">
When you perform actions like signing in or updating your
account, they'll appear here.
</p>
Expand Down
2 changes: 1 addition & 1 deletion app/(dashboard)/dashboard/general/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default function GeneralPage() {

return (
<section className="flex-1 p-4 lg:p-8">
<h1 className="text-lg lg:text-2xl font-medium text-gray-900 mb-6">
<h1 className="text-lg lg:text-2xl font-medium text-foreground/90 mb-6">
General Settings
</h1>

Expand Down
11 changes: 6 additions & 5 deletions app/(dashboard)/dashboard/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function DashboardLayout({
return (
<div className="flex flex-col min-h-[calc(100dvh-68px)] max-w-7xl mx-auto w-full">
{/* Mobile header */}
<div className="lg:hidden flex items-center justify-between bg-white border-b border-gray-200 p-4">
<div className="lg:hidden bg-background flex items-center justify-between border-b p-4">
<div className="flex items-center">
<span className="font-medium">Settings</span>
</div>
Expand All @@ -41,7 +41,10 @@ export default function DashboardLayout({
<div className="flex flex-1 overflow-hidden h-full">
{/* Sidebar */}
<aside
className={`w-64 bg-white lg:bg-gray-50 border-r border-gray-200 lg:block ${
className={`w-64 border-r lg:block
${isSidebarOpen ? 'bg-background' : 'bg-gray-50 dark:bg-gray-900'}
lg:bg-gray-50 lg:dark:bg-gray-900
${
isSidebarOpen ? 'block' : 'hidden'
} lg:relative absolute inset-y-0 left-0 z-40 transform transition-transform duration-300 ease-in-out lg:translate-x-0 ${
isSidebarOpen ? 'translate-x-0' : '-translate-x-full'
Expand All @@ -52,9 +55,7 @@ export default function DashboardLayout({
<Link key={item.href} href={item.href} passHref>
<Button
variant={pathname === item.href ? 'secondary' : 'ghost'}
className={`my-1 w-full justify-start ${
pathname === item.href ? 'bg-gray-100' : ''
}`}
className={`my-1 w-full justify-start`}
onClick={() => setIsSidebarOpen(false)}
>
<item.icon className="mr-2 h-4 w-4" />
Expand Down
4 changes: 2 additions & 2 deletions app/(dashboard)/dashboard/security/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default function SecurityPage() {

return (
<section className="flex-1 p-4 lg:p-8">
<h1 className="text-lg lg:text-2xl font-medium bold text-gray-900 mb-6">
<h1 className="text-lg lg:text-2xl font-medium bold text-foreground/90 mb-6">
Security Settings
</h1>
<Card className="mb-8">
Expand Down Expand Up @@ -127,7 +127,7 @@ export default function SecurityPage() {
<CardTitle>Delete Account</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-500 mb-4">
<p className="text-sm text-muted-foreground mb-4">
Account deletion is non-reversable. Please proceed with caution.
</p>
<form onSubmit={handleDeleteSubmit} className="space-y-4">
Expand Down
8 changes: 5 additions & 3 deletions app/(dashboard)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { useUser } from '@/lib/auth';
import { signOut } from '@/app/(login)/actions';
import { useRouter } from 'next/navigation';
import DarkModeToggle from '@/components/dark-mode-toggle'

function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
Expand All @@ -27,16 +28,16 @@ function Header() {
}

return (
<header className="border-b border-gray-200">
<header className="border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
<Link href="/" className="flex items-center">
<CircleIcon className="h-6 w-6 text-orange-500" />
<span className="ml-2 text-xl font-semibold text-gray-900">ACME</span>
<span className="ml-2 text-xl font-semibold text-foreground/90">ACME</span>
</Link>
<div className="flex items-center space-x-4">
<Link
href="/pricing"
className="text-sm font-medium text-gray-700 hover:text-gray-900"
className="text-sm font-medium text-foreground/70 hover:text-foreground/90"
>
Pricing
</Link>
Expand Down Expand Up @@ -78,6 +79,7 @@ function Header() {
<Link href="/sign-up">Sign Up</Link>
</Button>
)}
<DarkModeToggle />
</div>
</div>
</header>
Expand Down
24 changes: 12 additions & 12 deletions app/(dashboard)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ export default function HomePage() {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="lg:grid lg:grid-cols-12 lg:gap-8">
<div className="sm:text-center md:max-w-2xl md:mx-auto lg:col-span-6 lg:text-left">
<h1 className="text-4xl font-bold text-gray-900 tracking-tight sm:text-5xl md:text-6xl">
<h1 className="text-4xl font-bold text-foreground/90 tracking-tight sm:text-5xl md:text-6xl">
Build Your SaaS
<span className="block text-orange-500">Faster Than Ever</span>
</h1>
<p className="mt-3 text-base text-gray-500 sm:mt-5 sm:text-xl lg:text-lg xl:text-xl">
<p className="mt-3 text-base text-foreground/60 sm:mt-5 sm:text-xl lg:text-lg xl:text-xl">
Launch your SaaS product in record time with our powerful,
ready-to-use template. Packed with modern technologies and
essential integrations.
Expand All @@ -37,7 +37,7 @@ export default function HomePage() {
</div>
</section>

<section className="py-16 bg-white w-full">
<section className="py-16 bg-background/50 w-full">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="lg:grid lg:grid-cols-3 lg:gap-8">
<div>
Expand All @@ -50,10 +50,10 @@ export default function HomePage() {
</svg>
</div>
<div className="mt-5">
<h2 className="text-lg font-medium text-gray-900">
<h2 className="text-lg font-medium text-foreground">
Next.js and React
</h2>
<p className="mt-2 text-base text-gray-500">
<p className="mt-2 text-base text-foreground/50">
Leverage the power of modern web technologies for optimal
performance and developer experience.
</p>
Expand All @@ -65,10 +65,10 @@ export default function HomePage() {
<Database className="h-6 w-6" />
</div>
<div className="mt-5">
<h2 className="text-lg font-medium text-gray-900">
<h2 className="text-lg font-medium text-foreground">
Postgres and Drizzle ORM
</h2>
<p className="mt-2 text-base text-gray-500">
<p className="mt-2 text-base text-foreground/50">
Robust database solution with an intuitive ORM for efficient
data management and scalability.
</p>
Expand All @@ -80,10 +80,10 @@ export default function HomePage() {
<CreditCard className="h-6 w-6" />
</div>
<div className="mt-5">
<h2 className="text-lg font-medium text-gray-900">
<h2 className="text-lg font-medium text-foreground">
Stripe Integration
</h2>
<p className="mt-2 text-base text-gray-500">
<p className="mt-2 text-base text-foreground/50">
Seamless payment processing and subscription management with
industry-leading Stripe integration.
</p>
Expand All @@ -93,14 +93,14 @@ export default function HomePage() {
</div>
</section>

<section className="py-16 bg-gray-50">
<section className="py-16 bg-gray-50 dark:bg-gray-900">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="lg:grid lg:grid-cols-2 lg:gap-8 lg:items-center">
<div>
<h2 className="text-3xl font-bold text-gray-900 sm:text-4xl">
<h2 className="text-3xl font-bold text-foreground/90 sm:text-4xl">
Ready to launch your SaaS?
</h2>
<p className="mt-3 max-w-3xl text-lg text-gray-500">
<p className="mt-3 max-w-3xl text-lg text-foreground/50">
Our template provides everything you need to get your SaaS up
and running quickly. Don't waste time on boilerplate - focus on
what makes your product unique.
Expand Down
10 changes: 5 additions & 5 deletions app/(dashboard)/pricing/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,21 @@ function PricingCard({
}) {
return (
<div className="pt-6">
<h2 className="text-2xl font-medium text-gray-900 mb-2">{name}</h2>
<p className="text-sm text-gray-600 mb-4">
<h2 className="text-2xl font-medium text-foreground/90 mb-2">{name}</h2>
<p className="text-sm text-foreground/60 mb-4">
with {trialDays} day free trial
</p>
<p className="text-4xl font-medium text-gray-900 mb-6">
<p className="text-4xl font-medium text-foreground/90 mb-6">
${price / 100}{' '}
<span className="text-xl font-normal text-gray-600">
<span className="text-xl font-normal text-foreground/60">
per user / {interval}
</span>
</p>
<ul className="space-y-4 mb-8">
{features.map((feature, index) => (
<li key={index} className="flex items-start">
<Check className="h-5 w-5 text-orange-500 mr-2 mt-0.5 flex-shrink-0" />
<span className="text-gray-700">{feature}</span>
<span className="text-foreground/70">{feature}</span>
</li>
))}
</ul>
Expand Down
2 changes: 1 addition & 1 deletion app/(dashboard)/terminal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function Terminal() {
};

return (
<div className="w-full rounded-lg shadow-lg overflow-hidden bg-gray-900 text-white font-mono text-sm relative">
<div className="w-full rounded-lg shadow-lg overflow-hidden bg-gray-900 dark:bg-background text-white font-mono text-sm relative">
<div className="p-4">
<div className="flex justify-between items-center mb-4">
<div className="flex space-x-2">
Expand Down
20 changes: 11 additions & 9 deletions app/(login)/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { CircleIcon, Loader2 } from 'lucide-react';
import { signIn, signUp } from './actions';
import { ActionState } from '@/lib/auth/middleware';

const inputSharedStyles = 'appearance-none rounded-full relative block w-full px-3 py-2 border placeholder-gray-500 text-foreground/90 focus:outline-none focus:ring-orange-500 focus:border-orange-500 focus:z-10 sm:text-sm appearance-none rounded-full relative block w-full px-3 py-2 border placeholder-gray-500 text-foreground/90 focus:outline-none focus:ring-orange-500 focus:border-orange-500 focus:z-10 sm:text-sm';

export function Login({ mode = 'signin' }: { mode?: 'signin' | 'signup' }) {
const searchParams = useSearchParams();
const redirect = searchParams.get('redirect');
Expand All @@ -21,12 +23,12 @@ export function Login({ mode = 'signin' }: { mode?: 'signin' | 'signup' }) {
);

return (
<div className="min-h-[100dvh] flex flex-col justify-center py-12 px-4 sm:px-6 lg:px-8 bg-gray-50">
<div className="min-h-[100dvh] flex flex-col justify-center py-12 px-4 sm:px-6 lg:px-8 bg-gray-50 dark:bg-gray-900">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<div className="flex justify-center">
<CircleIcon className="h-12 w-12 text-orange-500" />
</div>
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
<h2 className="mt-6 text-center text-3xl font-extrabold text-foreground/90">
{mode === 'signin'
? 'Sign in to your account'
: 'Create your account'}
Expand All @@ -41,7 +43,7 @@ export function Login({ mode = 'signin' }: { mode?: 'signin' | 'signup' }) {
<div>
<Label
htmlFor="email"
className="block text-sm font-medium text-gray-700"
className="block text-sm font-medium text-foreground/70"
>
Email
</Label>
Expand All @@ -53,7 +55,7 @@ export function Login({ mode = 'signin' }: { mode?: 'signin' | 'signup' }) {
autoComplete="email"
required
maxLength={50}
className="appearance-none rounded-full relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-orange-500 focus:border-orange-500 focus:z-10 sm:text-sm"
className={inputSharedStyles}
placeholder="Enter your email"
/>
</div>
Expand All @@ -62,7 +64,7 @@ export function Login({ mode = 'signin' }: { mode?: 'signin' | 'signup' }) {
<div>
<Label
htmlFor="password"
className="block text-sm font-medium text-gray-700"
className="block text-sm font-medium text-foreground/70"
>
Password
</Label>
Expand All @@ -77,7 +79,7 @@ export function Login({ mode = 'signin' }: { mode?: 'signin' | 'signup' }) {
required
minLength={8}
maxLength={100}
className="appearance-none rounded-full relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-orange-500 focus:border-orange-500 focus:z-10 sm:text-sm"
className={inputSharedStyles}
placeholder="Enter your password"
/>
</div>
Expand Down Expand Up @@ -110,10 +112,10 @@ export function Login({ mode = 'signin' }: { mode?: 'signin' | 'signup' }) {
<div className="mt-6">
<div className="relative">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-gray-300" />
<div className="w-full border-t" />
</div>
<div className="relative flex justify-center text-sm">
<span className="px-2 bg-gray-50 text-gray-500">
<span className="px-2 bg-gray-50 dark:bg-gray-900 text-foreground/50">
{mode === 'signin'
? 'New to our platform?'
: 'Already have an account?'}
Expand All @@ -126,7 +128,7 @@ export function Login({ mode = 'signin' }: { mode?: 'signin' | 'signup' }) {
href={`${mode === 'signin' ? '/sign-up' : '/sign-in'}${
redirect ? `?redirect=${redirect}` : ''
}${priceId ? `&priceId=${priceId}` : ''}`}
className="w-full flex justify-center py-2 px-4 border border-gray-300 rounded-full shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500"
className="w-full flex justify-center py-2 px-4 border rounded-full shadow-sm text-sm font-medium text-foreground/70 bg-background hover:bg-background/20 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500"
>
{mode === 'signin'
? 'Create an account'
Expand Down
20 changes: 18 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Metadata, Viewport } from 'next';
import { Manrope } from 'next/font/google';
import { UserProvider } from '@/lib/auth';
import { getUser } from '@/lib/db/queries';
import { cookies } from 'next/headers'

export const metadata: Metadata = {
title: 'Next.js SaaS Starter',
Expand All @@ -20,14 +21,29 @@ export default function RootLayout({
}: {
children: React.ReactNode;
}) {
const storedTheme = cookies().get('next-sass-starter-theme')?.value
let userPromise = getUser();

return (
<html
lang="en"
className={`bg-white dark:bg-gray-950 text-black dark:text-white ${manrope.className}`}
className={`${manrope.className}`}
>
<body className="min-h-[100dvh] bg-gray-50">
<head>
<script
dangerouslySetInnerHTML={{
__html: `
(function() {
if (${storedTheme === 'dark'} || (${!storedTheme} && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
document.documentElement.style.setProperty('color-scheme', 'dark')
}
})();
`,
}}
/>
</head>
<body className="min-h-[100dvh] bg-gray-50 dark:bg-gray-900">
<UserProvider userPromise={userPromise}>{children}</UserProvider>
</body>
</html>
Expand Down
4 changes: 2 additions & 2 deletions app/not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ export default function NotFound() {
<div className="flex justify-center">
<CircleIcon className="size-12 text-orange-500" />
</div>
<h1 className="text-4xl font-bold text-gray-900 tracking-tight">
<h1 className="text-4xl font-bold text-foreground/90 tracking-tight">
Page Not Found
</h1>
<p className="text-base text-gray-500">
<p className="text-muted-foreground">
The page you are looking for might have been removed, had its name
changed, or is temporarily unavailable.
</p>
Expand Down
Loading