Skip to content

Commit 23e0c43

Browse files
committed
client v2
1 parent fb72206 commit 23e0c43

4 files changed

Lines changed: 671 additions & 268 deletions

File tree

Lines changed: 76 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,76 @@
11
<template>
2-
<article class="group flex flex-col h-full bg-transparent">
3-
<div class="relative w-full aspect-[16/9] overflow-hidden rounded-lg mb-5 bg-gray-100 dark:bg-gray-800">
4-
<router-link :to="`/posts/${article.id}`" class="block w-full h-full">
5-
<img
6-
v-if="validImage"
7-
:src="article.coverImage"
2+
<article
3+
class="group relative overflow-hidden rounded-2xl border border-zinc-200/70 bg-white/60 shadow-sm backdrop-blur
4+
transition hover:-translate-y-[1px] hover:border-zinc-300 hover:bg-white
5+
dark:border-zinc-800/70 dark:bg-zinc-900/30 dark:hover:border-zinc-700 dark:hover:bg-zinc-900/45"
6+
>
7+
<!-- Cover -->
8+
<router-link :to="`/posts/${article.id}`" class="block">
9+
<div class="relative aspect-[16/10] overflow-hidden border-b border-zinc-200/60 dark:border-zinc-800/60">
10+
<img
11+
v-if="validImage"
12+
:src="article.coverImage"
813
:alt="article.title"
9-
class="w-full h-full object-cover transition-all duration-700 grayscale group-hover:grayscale-0 group-hover:scale-105"
14+
class="h-full w-full object-cover transition-transform duration-700 group-hover:scale-[1.03]"
1015
@error="handleImageError"
1116
/>
12-
<div
13-
v-else
14-
class="w-full h-full flex items-center justify-center bg-[#f0f0f0] dark:bg-[#1a1a1a] relative overflow-hidden"
15-
>
16-
<div class="absolute inset-0 opacity-[0.05] bg-[repeating-linear-gradient(45deg,#000_0px,#000_1px,transparent_1px,transparent_10px)] dark:bg-[repeating-linear-gradient(45deg,#fff_0px,#fff_1px,transparent_1px,transparent_10px)]"></div>
17-
<span class="font-mono text-xs font-bold text-gray-400 border border-gray-400 px-2 py-1">NO SIGNAL</span>
17+
<div v-else class="h-full w-full bg-zinc-100 dark:bg-zinc-900 flex items-center justify-center">
18+
<div class="text-xs uppercase tracking-[0.25em] text-zinc-500 dark:text-zinc-400">
19+
Myshkin451
20+
</div>
1821
</div>
19-
</router-link>
2022

21-
<router-link
22-
v-if="article.category"
23-
:to="`/categories/${article.category.slug || article.category.id}`"
24-
class="absolute top-3 left-3 bg-white/90 dark:bg-black/90 backdrop-blur text-xs font-mono px-2 py-1 border border-gray-200 dark:border-gray-800 hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black transition-colors"
25-
>
26-
{{ article.category.name }}
27-
</router-link>
28-
</div>
23+
<div
24+
class="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100
25+
[background-image:linear-gradient(to_top,rgba(0,0,0,0.20),transparent_60%)]"
26+
></div>
27+
</div>
28+
</router-link>
2929

30-
<div class="flex flex-col flex-grow">
31-
<div class="flex items-center justify-between text-xs font-mono text-gray-500 mb-3 border-b border-gray-100 dark:border-gray-800 pb-2">
32-
<time :datetime="article.createdAt">{{ formatDate(article.createdAt) }}</time>
33-
<span v-if="article.views !== undefined">READ: {{ article.views }}</span>
30+
<!-- Body -->
31+
<div class="p-5">
32+
<div class="flex items-center gap-2 text-xs text-zinc-500 dark:text-zinc-400">
33+
<span>{{ formatDate(article.createdAt) }}</span>
34+
35+
<template v-if="article.category">
36+
<span class="opacity-50">·</span>
37+
<router-link
38+
:to="`/categories/${article.category.slug || article.category.id}`"
39+
class="truncate hover:text-zinc-900 dark:hover:text-white"
40+
>
41+
{{ article.category.name }}
42+
</router-link>
43+
</template>
44+
45+
<span v-if="article.views != null" class="ml-auto opacity-70">
46+
{{ article.views }} views
47+
</span>
3448
</div>
3549

36-
<router-link :to="`/posts/${article.id}`" class="block group-hover:opacity-70 transition-opacity">
37-
<h3 class="text-xl font-serif font-medium leading-snug text-gray-900 dark:text-gray-100 mb-3">
50+
<router-link :to="`/posts/${article.id}`" class="block">
51+
<h3
52+
class="mt-3 text-lg font-semibold tracking-tight text-zinc-900 dark:text-zinc-50
53+
decoration-zinc-300 underline-offset-4 group-hover:underline"
54+
>
3855
{{ article.title }}
3956
</h3>
4057
</router-link>
4158

42-
<p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed line-clamp-2 mb-4">
59+
<p class="mt-2 text-sm leading-relaxed text-zinc-600 dark:text-zinc-300 line-clamp-3">
4360
{{ article.excerpt || stripHtml(article.content) }}
4461
</p>
4562

46-
<div class="mt-auto pt-2 flex flex-wrap gap-2">
47-
<span v-for="tag in (article.tags || []).slice(0, 3)" :key="tag.id" class="text-xs font-mono text-gray-400 before:content-['#']">
48-
{{ tag.name }}
49-
</span>
63+
<div v-if="article.tags && article.tags.length" class="mt-4 flex flex-wrap gap-2">
64+
<router-link
65+
v-for="tag in article.tags.slice(0, 4)"
66+
:key="tag.id"
67+
:to="`/tags/${tag.slug || tag.id}`"
68+
class="rounded-full border border-zinc-200/70 bg-white/70 px-2.5 py-1 text-xs text-zinc-700
69+
transition hover:bg-white hover:border-zinc-300
70+
dark:border-zinc-800/70 dark:bg-zinc-950/30 dark:text-zinc-200 dark:hover:bg-zinc-900/60"
71+
>
72+
# {{ tag.name }}
73+
</router-link>
5074
</div>
5175
</div>
5276
</article>
@@ -56,29 +80,38 @@
5680
import { defineProps, ref, computed } from 'vue';
5781
5882
const props = defineProps({
59-
article: { type: Object, required: true, default: () => ({ tags: [] }) }
83+
article: {
84+
type: Object,
85+
required: true,
86+
default: () => ({ tags: [] })
87+
}
6088
});
6189
6290
const imageLoadError = ref(false);
6391
6492
const validImage = computed(() => {
65-
return props.article.coverImage &&
66-
props.article.coverImage.trim() !== '' &&
67-
!imageLoadError.value;
93+
return props.article.coverImage &&
94+
props.article.coverImage.trim() !== '' &&
95+
!imageLoadError.value;
6896
});
6997
70-
const handleImageError = () => { imageLoadError.value = true; };
98+
const handleImageError = () => {
99+
imageLoadError.value = true;
100+
};
71101
72102
const formatDate = (dateString) => {
73103
if (!dateString) return '';
74-
const d = new Date(dateString);
75-
return `${d.getFullYear()}.${String(d.getMonth() + 1).padStart(2, '0')}.${String(d.getDate()).padStart(2, '0')}`;
104+
return new Date(dateString).toLocaleDateString('en-US', {
105+
year: 'numeric',
106+
month: 'short',
107+
day: 'numeric'
108+
});
76109
};
77110
78111
const stripHtml = (html) => {
79112
if (!html) return '';
80-
const tmp = document.createElement("DIV");
113+
const tmp = document.createElement('DIV');
81114
tmp.innerHTML = html;
82-
return tmp.textContent || tmp.innerText || "";
115+
return tmp.textContent || tmp.innerText || '';
83116
};
84-
</script>
117+
</script>

client/src/components/Footer.vue

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,37 @@
11
<template>
2-
<footer class="bg-white dark:bg-[#050505] border-t border-gray-200 dark:border-gray-800 pt-20 pb-10 transition-colors duration-500">
3-
<div class="container mx-auto px-6 max-w-6xl">
4-
5-
<div class="grid grid-cols-1 md:grid-cols-4 gap-12 mb-20">
6-
<div class="md:col-span-2 space-y-6">
7-
<h4 class="font-serif text-2xl font-bold">Myshkin451</h4>
8-
<p class="text-gray-500 dark:text-gray-400 max-w-sm leading-relaxed">
9-
A digital garden exploring the intersection of backend engineering, distributed systems, and artificial intelligence.
10-
</p>
11-
</div>
12-
2+
<footer class="border-t border-zinc-200/70 bg-white/50 py-12 dark:border-zinc-800/70 dark:bg-zinc-950/40">
3+
<div class="mx-auto max-w-6xl px-6">
4+
<div class="flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
135
<div>
14-
<h5 class="font-mono text-xs font-bold text-gray-900 dark:text-white mb-4 uppercase tracking-wider">Navigation</h5>
15-
<ul class="space-y-3 text-sm text-gray-500 dark:text-gray-400">
16-
<li><router-link to="/" class="hover:text-black dark:hover:text-white transition-colors">Home</router-link></li>
17-
<li><router-link to="/categories" class="hover:text-black dark:hover:text-white transition-colors">Categories</router-link></li>
18-
<li><router-link to="/guestbook" class="hover:text-black dark:hover:text-white transition-colors">Guestbook</router-link></li>
19-
</ul>
6+
<div class="text-sm font-semibold tracking-tight text-zinc-900 dark:text-zinc-50">Myshkin451</div>
7+
<div class="mt-2 text-sm text-zinc-600 dark:text-zinc-300">
8+
&copy; {{ new Date().getFullYear() }} · Built with Node.js & Vue 3
9+
</div>
2010
</div>
2111

22-
<div>
23-
<h5 class="font-mono text-xs font-bold text-gray-900 dark:text-white mb-4 uppercase tracking-wider">Social</h5>
24-
<ul class="space-y-3 text-sm text-gray-500 dark:text-gray-400">
25-
<li><a href="https://github.com/Achernar-Eridani" target="_blank" class="hover:text-black dark:hover:text-white transition-colors">GitHub</a></li>
26-
<li><a href="#" class="hover:text-black dark:hover:text-white transition-colors">RSS Feed</a></li>
27-
</ul>
28-
</div>
29-
</div>
12+
<div class="flex items-center gap-4">
13+
<a
14+
href="https://github.com/Achernar-Eridani"
15+
target="_blank"
16+
rel="noopener noreferrer"
17+
class="inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-white/70 px-4 py-2 text-sm text-zinc-800
18+
transition hover:bg-white dark:border-zinc-800 dark:bg-zinc-950/40 dark:text-zinc-200 dark:hover:bg-zinc-900/60"
19+
>
20+
GitHub
21+
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
22+
<path
23+
fill-rule="evenodd"
24+
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.866-.013-1.7-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0 1 12 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.338 4.695-4.566 4.943.359.309.678.92.678 1.852 0 1.336-.012 2.415-.012 2.743 0 .268.18.58.688.482A10.019 10.019 0 0 0 22 12.017C22 6.484 17.522 2 12 2z"
25+
clip-rule="evenodd"
26+
/>
27+
</svg>
28+
</a>
3029

31-
<div class="flex flex-col md:flex-row justify-between items-end border-t border-gray-100 dark:border-gray-800 pt-10">
32-
<div class="text-[10vw] leading-none font-bold text-gray-100 dark:text-[#111] select-none pointer-events-none -ml-2">
33-
M/451
34-
</div>
35-
<div class="text-xs font-mono text-gray-400 mb-2">
36-
&copy; {{ new Date().getFullYear() }} SHENZHEN / HANGZHOU.
30+
<div class="text-xs text-zinc-500 dark:text-zinc-400">
31+
Clean layout, readable typography.
32+
</div>
3733
</div>
3834
</div>
39-
4035
</div>
4136
</footer>
42-
</template>
37+
</template>

0 commit comments

Comments
 (0)