feat: Implement light theme, mobile menu, font and image fallback
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@theme {
|
||||
/* Default Custom Properties (Dark Theme) */
|
||||
--bg-primary: var(--color-gray-900);
|
||||
--bg-secondary: var(--color-gray-800);
|
||||
--bg-tertiary: var(--color-gray-700);
|
||||
--text-primary: var(--color-gray-100);
|
||||
--text-secondary: var(--color-gray-400);
|
||||
--text-tertiary: var(--color-gray-300);
|
||||
--brand-primary: var(--color-indigo-600);
|
||||
--brand-secondary: var(--color-indigo-700);
|
||||
|
||||
--color-gray-900: #1a1a1a;
|
||||
--color-gray-800: #2b2b2b;
|
||||
--color-gray-700: #3c3c3c;
|
||||
@@ -10,12 +20,31 @@
|
||||
--color-gray-100: #f5f5f5;
|
||||
--color-indigo-600: #4f46e5;
|
||||
--color-indigo-700: #4338ca;
|
||||
--font-family-sans: "Inter", sans-serif;
|
||||
|
||||
/* Font Families */
|
||||
--font-family-body: "Montserrat", sans-serif;
|
||||
--font-family-heading: "Playfair Display", serif;
|
||||
}
|
||||
|
||||
/* Light Theme Overrides (outside @theme block) */
|
||||
html[data-theme='light'] {
|
||||
--bg-primary: var(--color-gray-100);
|
||||
--bg-secondary: var(--color-gray-200);
|
||||
--bg-tertiary: var(--color-gray-300);
|
||||
--text-primary: var(--color-gray-900);
|
||||
--text-secondary: var(--color-gray-600);
|
||||
--text-tertiary: var(--color-gray-700);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
@apply bg-gray-900 text-gray-100;
|
||||
background-color: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
font-family: var(--font-family-body); /* Apply default body font */
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-family-heading); /* Apply heading font */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,3 +75,4 @@
|
||||
#lightbox.show {
|
||||
animation: fadeIn 0.3s ease-out forwards;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('Palina theme loaded!');
|
||||
|
||||
const htmlElement = document.documentElement;
|
||||
// Remove 'hidden' class from html to prevent FOUC
|
||||
htmlElement.classList.remove('hidden');
|
||||
|
||||
// Staggered fade-in animation for post grid
|
||||
const gridItems = document.querySelectorAll('.post-grid-item');
|
||||
gridItems.forEach((item, index) => {
|
||||
@@ -40,4 +44,50 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Theme Switcher
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
// const htmlElement = document.documentElement; // Already defined above
|
||||
|
||||
const currentTheme = localStorage.getItem('theme');
|
||||
if (currentTheme) {
|
||||
htmlElement.setAttribute('data-theme', currentTheme);
|
||||
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) {
|
||||
// Default to light theme if system preference is light
|
||||
htmlElement.setAttribute('data-theme', 'light');
|
||||
}
|
||||
|
||||
if (themeToggle) {
|
||||
themeToggle.addEventListener('click', () => {
|
||||
let newTheme = htmlElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
||||
htmlElement.setAttribute('data-theme', newTheme);
|
||||
localStorage.setItem('theme', newTheme);
|
||||
});
|
||||
}
|
||||
|
||||
// Mobile Menu
|
||||
const mobileMenuToggle = document.getElementById('mobile-menu-toggle');
|
||||
const mobileMenuClose = document.getElementById('mobile-menu-close');
|
||||
const mobileMenu = document.getElementById('mobile-menu');
|
||||
|
||||
if (mobileMenuToggle && mobileMenu && mobileMenuClose) {
|
||||
mobileMenuToggle.addEventListener('click', () => {
|
||||
mobileMenu.classList.remove('-translate-x-full');
|
||||
mobileMenu.classList.add('translate-x-0');
|
||||
});
|
||||
|
||||
mobileMenuClose.addEventListener('click', () => {
|
||||
mobileMenu.classList.remove('translate-x-0');
|
||||
mobileMenu.classList.add('-translate-x-full');
|
||||
});
|
||||
|
||||
// Close menu if a link is clicked
|
||||
const mobileNavLinks = mobileMenu.querySelectorAll('a');
|
||||
mobileNavLinks.forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
mobileMenu.classList.remove('translate-x-0');
|
||||
mobileMenu.classList.add('-translate-x-full');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{@site.lang}}">
|
||||
<html lang="{{@site.lang}}" data-theme="dark" class="hidden">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{meta_title}}</title>
|
||||
<link rel="stylesheet" href="{{asset "built/screen.css"}}">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet">
|
||||
{{ghost_head}}
|
||||
</head>
|
||||
<body class="{{body_class}} font-sans bg-gray-900 text-gray-100 antialiased">
|
||||
<body class="{{body_class}} font-sans antialiased">
|
||||
|
||||
<div class="min-h-screen flex flex-col">
|
||||
{{> header}}
|
||||
@@ -19,6 +20,8 @@
|
||||
{{> footer}}
|
||||
</div>
|
||||
|
||||
{{> mobile-menu}}
|
||||
|
||||
<div id="lightbox" class="hidden fixed inset-0 bg-black bg-opacity-80 z-50 flex items-center justify-center">
|
||||
<button id="lightbox-close" class="absolute top-4 right-4 text-white text-3xl">×</button>
|
||||
<img id="lightbox-image" src="" alt="Lightbox image" class="max-w-full max-h-full">
|
||||
|
||||
12
index.hbs
12
index.hbs
@@ -1,15 +1,15 @@
|
||||
{{!< default}}
|
||||
|
||||
<header class="container mx-auto px-4 py-8 text-center">
|
||||
<h1 class="text-5xl font-bold tracking-tight text-white">Palina Photo Blog</h1>
|
||||
<p class="mt-2 text-xl text-gray-400">{{@site.description}}</p>
|
||||
<h1 class="text-5xl font-bold tracking-tight text-[var(--text-primary)]">Palina Photo Blog</h1>
|
||||
<p class="mt-2 text-xl text-[var(--text-secondary)]">{{@site.description}}</p>
|
||||
</header>
|
||||
|
||||
<div class="container mx-auto px-4">
|
||||
{{#if posts}}
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
||||
{{#foreach posts}}
|
||||
<article class="post-grid-item opacity-0 relative bg-gray-800 rounded-lg shadow-lg overflow-hidden group">
|
||||
<article class="post-grid-item opacity-0 relative bg-[var(--bg-secondary)] rounded-lg shadow-lg overflow-hidden group">
|
||||
<a href="{{url}}" class="block">
|
||||
{{#if feature_image}}
|
||||
<img
|
||||
@@ -24,10 +24,10 @@
|
||||
loading="lazy"
|
||||
>
|
||||
{{else}}
|
||||
<div class="w-full h-72 flex items-center justify-center bg-gray-700 text-gray-300 text-2xl">No Image</div>
|
||||
<div class="w-full h-72 flex items-center justify-center bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] text-2xl">No Image</div>
|
||||
{{/if}}
|
||||
<div class="absolute inset-0 bg-black bg-opacity-50 flex items-end p-4 opacity-0 group-hover:opacity-100 transition-opacity duration-300 ease-in-out">
|
||||
<h2 class="text-white text-xl font-semibold leading-tight">{{title}}</h2>
|
||||
<h2 class="text-[var(--text-primary)] text-xl font-semibold leading-tight">{{title}}</h2>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
@@ -36,6 +36,6 @@
|
||||
|
||||
{{pagination}}
|
||||
{{else}}
|
||||
<p class="text-center text-gray-400 text-2xl py-20">No posts found.</p>
|
||||
<p class="text-center text-[var(--text-secondary)] text-2xl py-20">No posts found.</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<footer class="text-gray-400 bg-gray-900 body-font">
|
||||
<footer class="text-[var(--text-secondary)] bg-[var(--bg-primary)] body-font">
|
||||
<div class="container px-5 py-8 mx-auto flex items-center sm:flex-row flex-col">
|
||||
<a href="{{@site.url}}" class="flex title-font font-medium items-center md:justify-start justify-center text-white">
|
||||
<a href="{{@site.url}}" class="flex title-font font-medium items-center md:justify-start justify-center text-[var(--text-primary)]">
|
||||
<span class="ml-3 text-xl">{{@site.title}}</span>
|
||||
</a>
|
||||
<p class="text-sm text-gray-500 sm:ml-4 sm:pl-4 sm:border-l-2 sm:border-gray-800 sm:py-2 sm:mt-0 mt-4">
|
||||
<p class="text-sm text-[var(--text-secondary)] sm:ml-4 sm:pl-4 sm:border-l-2 sm:border-[var(--bg-secondary)] sm:py-2 sm:mt-0 mt-4">
|
||||
© {{date format="YYYY"}} {{@site.title}} — Powered by Ghost
|
||||
</p>
|
||||
<span class="inline-flex sm:ml-auto sm:mt-0 mt-4 justify-center sm:justify-start">
|
||||
{{#if @site.facebook}}
|
||||
<a href="{{@site.facebook_url}}" class="text-gray-500 hover:text-white transition duration-200">
|
||||
<a href="{{@site.facebook_url}}" class="text-[var(--text-secondary)] hover:text-[var(--text-primary)] transition duration-200">
|
||||
<svg fill="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="w-5 h-5" viewBox="0 0 24 24">
|
||||
<path d="M18 2h-3a5 5 0 00-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 011-1h3z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
{{/if}}
|
||||
{{#if @site.twitter}}
|
||||
<a href="{{@site.twitter_url}}" class="ml-3 text-gray-500 hover:text-white transition duration-200">
|
||||
<a href="{{@site.twitter_url}}" class="ml-3 text-[var(--text-secondary)] hover:text-[var(--text-primary)] transition duration-200">
|
||||
<svg fill="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="w-5 h-5" viewBox="0 0 24 24">
|
||||
<path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2c9 5 20 0 20-11.5a4.5 4.5 0 00-.08-.83A7.72 7.72 0 0023 3z"></path>
|
||||
</svg>
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
<header class="text-gray-100 body-font shadow-lg bg-gray-900">
|
||||
<div class="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center">
|
||||
<a href="{{@site.url}}" class="flex title-font font-medium items-center text-white mb-4 md:mb-0">
|
||||
<header class="text-[var(--text-primary)] body-font shadow-lg bg-[var(--bg-primary)]">
|
||||
<div class="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center justify-between">
|
||||
<a href="{{@site.url}}" class="flex title-font font-medium items-center text-[var(--text-primary)] mb-4 md:mb-0">
|
||||
<span class="ml-3 text-xl">{{@site.title}}</span>
|
||||
</a>
|
||||
<nav class="md:ml-auto flex flex-wrap items-center text-base justify-center">
|
||||
|
||||
<div class="flex items-center">
|
||||
<nav class="hidden md:flex flex-wrap items-center text-base justify-center">
|
||||
{{navigation type="primary"}}
|
||||
<button id="theme-toggle" class="ml-4 p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5">
|
||||
<path fill-rule="evenodd" d="M9.528 1.718a.75.75 0 01.178 1.043l-4.243 4.243a.75.75 0 01-1.061 0L.952 2.761a.75.75 0 011.06-1.06l3.52 3.52 3.712-3.712a.75.75 0 011.042-.178zM16.292 7.625a.75.75 0 01.132 1.056l-3.903 4.171c.466 1.102.615 2.373.13 3.673-.393 1.077-.665 2.164-.707 2.296-.135.347-.216.593-.216.593H12.75a.75.75 0 010-1.5h.084c.007-.022.036-.094.09-.253.307-.872.502-1.78.544-2.701.328-1.55-.145-2.915-.756-3.83A6.064 6.064 0 0015.6 9a.75.75 0 01.692-.375zM12.75 22.5c-2.935 0-5.696-1.07-7.795-2.997a.75.75 0 011.061-1.061 9 9 0 0013.868 0 .75.75 0 011.06-1.061C18.446 21.43 15.685 22.5 12.75 22.5z" clip-rule="evenodd" />
|
||||
<path fill-rule="evenodd" d="M15.6 13.5a3.6 3.6 0 11-7.2 0 3.6 3.6 0 017.2 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<button id="mobile-menu-toggle" class="md:hidden p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
12
partials/mobile-menu.hbs
Normal file
12
partials/mobile-menu.hbs
Normal file
@@ -0,0 +1,12 @@
|
||||
<div id="mobile-menu" class="fixed inset-0 z-40 bg-[var(--bg-primary)] transform -translate-x-full transition-transform duration-300 ease-in-out md:hidden">
|
||||
<div class="flex justify-end p-5">
|
||||
<button id="mobile-menu-close" class="p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<nav class="flex flex-col items-center justify-center h-full space-y-8 text-2xl">
|
||||
{{navigation type="primary"}}
|
||||
</nav>
|
||||
</div>
|
||||
16
post.hbs
16
post.hbs
@@ -2,12 +2,12 @@
|
||||
|
||||
<article class="container mx-auto px-4 py-12">
|
||||
<header class="text-center mb-8">
|
||||
<h1 class="text-6xl font-bold tracking-tight text-white mb-4">{{title}}</h1>
|
||||
<section class="post-meta text-gray-400 text-lg">
|
||||
<h1 class="text-6xl font-bold tracking-tight text-[var(--text-primary)] mb-4">{{title}}</h1>
|
||||
<section class="post-meta text-[var(--text-secondary)] text-lg">
|
||||
<time datetime="{{date format="YYYY-MM-DD"}}">{{date format="MMMM DD, YYYY"}}</time>
|
||||
{{#if primary_tag}}
|
||||
<span class="mx-2">•</span>
|
||||
<a href="{{primary_tag.url}}" class="text-gray-400 hover:text-white transition duration-200">{{primary_tag.name}}</a>
|
||||
<a href="{{primary_tag.url}}" class="text-[var(--text-secondary)] hover:text-[var(--text-primary)] transition duration-200">{{primary_tag.name}}</a>
|
||||
{{/if}}
|
||||
</section>
|
||||
</header>
|
||||
@@ -23,14 +23,18 @@
|
||||
alt="{{title}}"
|
||||
>
|
||||
</figure>
|
||||
{{else}}
|
||||
<div class="mb-12 rounded-lg overflow-hidden shadow-xl w-full h-96 flex items-center justify-center bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] text-3xl">
|
||||
No Feature Image
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<section class="post-content max-w-3xl mx-auto text-gray-200 leading-relaxed text-lg prose prose-invert">
|
||||
<section class="post-content max-w-3xl mx-auto text-[var(--text-primary)] leading-relaxed text-lg prose prose-invert">
|
||||
{{content}}
|
||||
</section>
|
||||
|
||||
<footer class="mt-12 pt-8 border-t border-gray-700 text-center">
|
||||
<a href="/" class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition duration-200">
|
||||
<footer class="mt-12 pt-8 border-t border-[var(--bg-tertiary)] text-center">
|
||||
<a href="/" class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-[var(--text-primary)] bg-[var(--brand-primary)] hover:bg-[var(--brand-secondary)] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--brand-primary)] transition duration-200">
|
||||
← Back to Home
|
||||
</a>
|
||||
</footer>
|
||||
|
||||
Reference in New Issue
Block a user