fixed theming issues
This commit is contained in:
@@ -23,6 +23,8 @@ struct AppState {
|
||||
struct SiteConfig {
|
||||
title: String,
|
||||
subtitle: String,
|
||||
welcome_title: String,
|
||||
welcome_subtitle: String,
|
||||
footer: String,
|
||||
favicon: String,
|
||||
theme: String,
|
||||
@@ -34,6 +36,8 @@ impl Default for SiteConfig {
|
||||
Self {
|
||||
title: "Narlblog".to_string(),
|
||||
subtitle: "A clean, modern blog".to_string(),
|
||||
welcome_title: "Welcome to my blog".to_string(),
|
||||
welcome_subtitle: "Thoughts on software, design, and building things with Rust and Astro.".to_string(),
|
||||
footer: "Built with Rust & Astro".to_string(),
|
||||
favicon: "/favicon.svg".to_string(),
|
||||
theme: "mocha".to_string(),
|
||||
|
||||
@@ -9,33 +9,6 @@ import Layout from '../../layouts/Layout.astro';
|
||||
<script is:inline src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script>
|
||||
<script is:inline src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/markdown/markdown.min.js"></script>
|
||||
<script is:inline src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/keymap/vim.min.js"></script>
|
||||
|
||||
<style is:global>
|
||||
.CodeMirror {
|
||||
height: auto;
|
||||
min-height: 400px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
border-radius: 0.5rem;
|
||||
background: var(--crust);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--surface1);
|
||||
padding: 1rem;
|
||||
}
|
||||
.CodeMirror-focused {
|
||||
border-color: var(--mauve);
|
||||
}
|
||||
.CodeMirror-scroll {
|
||||
min-height: 400px;
|
||||
}
|
||||
.cm-s-default .cm-header { color: var(--mauve); font-weight: bold; }
|
||||
.cm-s-default .cm-string { color: var(--green); }
|
||||
.cm-s-default .cm-link { color: var(--blue); text-decoration: underline; }
|
||||
.cm-s-default .cm-url { color: var(--sky); }
|
||||
.cm-s-default .cm-comment { color: var(--subtext0); font-style: italic; }
|
||||
.cm-s-default .cm-quote { color: var(--peach); }
|
||||
.cm-fat-cursor .CodeMirror-cursor { background: var(--text); }
|
||||
.cm-animate-fat-cursor { background-color: var(--text); }
|
||||
</style>
|
||||
|
||||
<div class="glass p-12 mb-12" id="editor-content" style="display: none;">
|
||||
<header class="mb-12 border-b border-white/5 pb-12 flex justify-between items-center">
|
||||
@@ -406,3 +379,31 @@ import Layout from '../../layouts/Layout.astro';
|
||||
}
|
||||
</script>
|
||||
</Layout>
|
||||
ect slug on edit
|
||||
delBtn?.classList.remove('hidden');
|
||||
fetch(`/api/posts/${encodeURIComponent(editSlug)}`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.content) {
|
||||
editor.setValue(data.content);
|
||||
}
|
||||
})
|
||||
.catch(() => showAlert('Failed to load post.', 'error'));
|
||||
}
|
||||
|
||||
function showAlert(msg: string, type: 'success' | 'error') {
|
||||
const alertEl = document.getElementById('alert');
|
||||
if (alertEl) {
|
||||
alertEl.textContent = msg;
|
||||
alertEl.className = `p-4 rounded-lg mb-6 ${type === 'success' ? 'bg-green/20 text-green border border-green/30' : 'bg-red/20 text-red border border-red/30'}`;
|
||||
alertEl.classList.remove('hidden');
|
||||
setTimeout(() => { alertEl.classList.add('hidden'); }, 4000);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</Layout>
|
||||
setTimeout(() => { alertEl.classList.add('hidden'); }, 4000);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</Layout>
|
||||
|
||||
@@ -22,14 +22,20 @@ import Layout from '../../layouts/Layout.astro';
|
||||
<h2 class="text-xl font-bold text-lavender border-l-4 border-lavender pl-4">General Identity</h2>
|
||||
<div class="grid md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="title" class="block text-sm font-medium text-subtext1 mb-2">Blog Title</label>
|
||||
<label for="title" class="block text-sm font-medium text-subtext1 mb-2">Blog Title (Nav)</label>
|
||||
<input type="text" id="title" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
|
||||
<p class="text-[10px] text-subtext0 mt-1">Main name of your blog.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="subtitle" class="block text-sm font-medium text-subtext1 mb-2">Subtitle</label>
|
||||
<label for="subtitle" class="block text-sm font-medium text-subtext1 mb-2">Nav Subtitle</label>
|
||||
<input type="text" id="subtitle" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
|
||||
<p class="text-[10px] text-subtext0 mt-1">Short description shown under the title.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="welcome_title" class="block text-sm font-medium text-subtext1 mb-2">Welcome Title (Frontpage)</label>
|
||||
<input type="text" id="welcome_title" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="welcome_subtitle" class="block text-sm font-medium text-subtext1 mb-2">Welcome Subtitle</label>
|
||||
<input type="text" id="welcome_subtitle" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -10,14 +10,26 @@ interface Post {
|
||||
|
||||
let posts: Post[] = [];
|
||||
let error = '';
|
||||
let siteConfig = {
|
||||
welcome_title: "Welcome to my blog",
|
||||
welcome_subtitle: "Thoughts on software, design, and building things with Rust and Astro."
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/api/posts`);
|
||||
if (response.ok) {
|
||||
posts = await response.json();
|
||||
const [postsRes, configRes] = await Promise.all([
|
||||
fetch(`${API_URL}/api/posts`),
|
||||
fetch(`${API_URL}/api/config`)
|
||||
]);
|
||||
|
||||
if (postsRes.ok) {
|
||||
posts = await postsRes.json();
|
||||
} else {
|
||||
error = 'Failed to fetch posts';
|
||||
}
|
||||
|
||||
if (configRes.ok) {
|
||||
siteConfig = await configRes.json();
|
||||
}
|
||||
} catch (e) {
|
||||
const cause = (e as any)?.cause;
|
||||
error = `Could not connect to backend at ${API_URL}: ${e instanceof Error ? e.message : String(e)}${cause ? ' (Cause: ' + (cause.message || cause.code || JSON.stringify(cause)) + ')' : ''}`;
|
||||
@@ -25,6 +37,7 @@ try {
|
||||
}
|
||||
|
||||
function formatSlug(slug: string) {
|
||||
if (!slug) return '';
|
||||
return slug
|
||||
.split('-')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
@@ -36,10 +49,10 @@ function formatSlug(slug: string) {
|
||||
<div class="space-y-6 md:space-y-8">
|
||||
<section class="text-center py-6 md:py-12">
|
||||
<h1 class="text-3xl md:text-5xl font-extrabold mb-3 md:mb-4 pb-2 md:pb-4 leading-tight bg-clip-text text-transparent bg-gradient-to-r from-mauve via-blue to-teal">
|
||||
Welcome to my blog
|
||||
{siteConfig.welcome_title}
|
||||
</h1>
|
||||
<p class="text-subtext1 text-base md:text-lg max-w-2xl mx-auto px-4 md:px-0">
|
||||
Thoughts on software, design, and building things with Rust and Astro.
|
||||
{siteConfig.welcome_subtitle}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@@ -49,9 +62,9 @@ function formatSlug(slug: string) {
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{posts.length === 0 && !error && (
|
||||
<div class="glass p-8 md:p-12 text-center text-subtext0 text-sm md:text-base">
|
||||
<div class="glass p-8 md:p-12 text-center text-subtext1 text-sm md:text-base">
|
||||
<p>No posts found yet. Add some .md files to the data/posts directory!</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -63,7 +76,7 @@ function formatSlug(slug: string) {
|
||||
<h2 class="text-xl md:text-3xl font-bold text-lavender group-hover:text-mauve transition-colors mb-2 md:mb-3">
|
||||
{formatSlug(post.slug)}
|
||||
</h2>
|
||||
<p class="text-subtext1 text-sm md:text-base leading-relaxed line-clamp-3">
|
||||
<p class="text-text text-sm md:text-base leading-relaxed line-clamp-3">
|
||||
{post.excerpt || `Read more about ${formatSlug(post.slug)}...`}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -66,10 +66,10 @@
|
||||
}
|
||||
|
||||
.latte {
|
||||
--crust: #dce0e8; --mantle: #e6e9ef; --base: #eff1f5;
|
||||
--surface0: #ccd0da; --surface1: #bcc0cc; --surface2: #acb0be;
|
||||
--crust: #e6e9ef; --mantle: #dce0e8; --base: #eff1f5;
|
||||
--surface0: #e6e9ef; --surface1: #bcc0cc; --surface2: #acb0be;
|
||||
--overlay0: #9ca0b0; --overlay1: #8c8fa1; --overlay2: #7c7f93;
|
||||
--text: #4c4f69; --subtext0: #5c5f77; --subtext1: #6c6f85;
|
||||
--text: #1e1e2e; --subtext0: #4c4f69; --subtext1: #5c5f77;
|
||||
--blue: #1e66f5; --lavender: #7287fd; --sapphire: #209fb5;
|
||||
--sky: #04a5e5; --teal: #179299; --green: #40a02b;
|
||||
--yellow: #df8e1d; --peach: #fe640b; --maroon: #e64553;
|
||||
@@ -84,6 +84,24 @@ body {
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
/* Dynamic CodeMirror Theme */
|
||||
.cm-s-narlblog.CodeMirror {
|
||||
background: var(--crust);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--surface1);
|
||||
}
|
||||
.cm-s-narlblog .cm-header { color: var(--mauve); font-weight: bold; }
|
||||
.cm-s-narlblog .cm-string { color: var(--green); }
|
||||
.cm-s-narlblog .cm-link { color: var(--blue); text-decoration: underline; }
|
||||
.cm-s-narlblog .cm-url { color: var(--sky); }
|
||||
.cm-s-narlblog .cm-comment { color: var(--subtext0); font-style: italic; }
|
||||
.cm-s-narlblog .cm-quote { color: var(--peach); }
|
||||
.cm-s-narlblog .CodeMirror-cursor { border-left-color: var(--text); }
|
||||
.cm-s-narlblog.cm-fat-cursor .CodeMirror-cursor { background: var(--text); }
|
||||
.cm-s-narlblog .CodeMirror-selected { background: var(--surface2); }
|
||||
.cm-s-narlblog .CodeMirror-line::selection, .cm-s-narlblog .CodeMirror-line > span::selection, .cm-s-narlblog .CodeMirror-line > span > span::selection { background: var(--surface2); }
|
||||
.cm-s-narlblog .CodeMirror-line::-moz-selection, .cm-s-narlblog .CodeMirror-line > span::-moz-selection, .cm-s-narlblog .CodeMirror-line > span > span::-moz-selection { background: var(--surface2); }
|
||||
|
||||
/* Typography styles for Markdown */
|
||||
.prose h1 { @apply text-3xl md:text-4xl font-bold mb-4 md:mb-6 text-mauve; }
|
||||
.prose h2 { @apply text-2xl md:text-3xl font-semibold mb-3 md:mb-4 mt-6 md:mt-8 text-lavender; }
|
||||
|
||||
Reference in New Issue
Block a user