Выделил карточку блога в компонент
This commit is contained in:
parent
224187422a
commit
be6615ff48
3 changed files with 103 additions and 40 deletions
100
src/lib/components/BlogCard.svelte
Normal file
100
src/lib/components/BlogCard.svelte
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
<script lang="ts" module>
|
||||||
|
export enum BlogCardSize {
|
||||||
|
Short,
|
||||||
|
Long,
|
||||||
|
Both
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Icon from '@iconify/svelte';
|
||||||
|
|
||||||
|
export let post: App.BlogPost;
|
||||||
|
export let size: BlogCardSize = BlogCardSize.Both;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rndtrash: пришлось дублировать классы с модификатором и без, потому что Tailwind ОЧЕНЬ не любит,
|
||||||
|
* когда его классы склеивают из нескольких частей
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает список классов для полноразмерной плашки.
|
||||||
|
*
|
||||||
|
* Возвращает пустую строку, если плашка может быть только короткой
|
||||||
|
* @param classes
|
||||||
|
* @param modClasses
|
||||||
|
*/
|
||||||
|
function fullClass(classes: string, modClasses: string): string {
|
||||||
|
if (size === BlogCardSize.Short) return '';
|
||||||
|
return size === BlogCardSize.Both ? modClasses : classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает список классов для короткой карточки.
|
||||||
|
*
|
||||||
|
* Возвращает пустую строку, если плашка может быть только полноразмерной
|
||||||
|
* @param classes
|
||||||
|
*/
|
||||||
|
function shortClass(classes: string): string {
|
||||||
|
return size === BlogCardSize.Long ? '' : classes;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/blog/{post.slug}"
|
||||||
|
class="blog-card
|
||||||
|
{shortClass('flex-col justify-baseline')}
|
||||||
|
{fullClass('flex-row justify-stretch', 'sm:flex-row sm:justify-stretch')}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="relative w-full basis-auto overflow-hidden
|
||||||
|
{shortClass('h-32')}
|
||||||
|
{fullClass('h-auto basis-1/3', 'sm:h-auto sm:basis-1/3')}"
|
||||||
|
>
|
||||||
|
{#if post.thumbnail}
|
||||||
|
<img
|
||||||
|
class="thumbnail"
|
||||||
|
src={`/blog/${post.slug}/${post.thumbnail}`}
|
||||||
|
alt={post.thumbnailAlt ?? 'Миниатюра поста'}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="flex w-full flex-col justify-center p-4 break-words md:p-8">
|
||||||
|
<div class="flex flex-row flex-wrap justify-between gap-4 pb-4">
|
||||||
|
<div class="flex items-center text-lg font-bold">
|
||||||
|
<Icon icon="material-symbols:calendar-today" class="mr-3" width={24} height={24} />
|
||||||
|
<p>
|
||||||
|
{new Date(post.date!).toLocaleString('default', {
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
year: 'numeric'
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-3xl font-bold">{post.title}</h2>
|
||||||
|
|
||||||
|
{#if post.description}
|
||||||
|
<p>{post.description}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import '$src/app.css';
|
||||||
|
|
||||||
|
.blog-card {
|
||||||
|
@apply flex w-full max-w-5xl overflow-hidden rounded-lg bg-slate-100 text-slate-950 drop-shadow-xl transition-all hover:drop-shadow-2xl;
|
||||||
|
|
||||||
|
img.thumbnail {
|
||||||
|
@apply absolute h-full w-full object-cover transition-transform;
|
||||||
|
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover img.thumbnail {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import Icon from '@iconify/svelte';
|
|
||||||
import SocialHyperlink from '$src/lib/components/SocialHyperlink.svelte';
|
import SocialHyperlink from '$src/lib/components/SocialHyperlink.svelte';
|
||||||
import InfoBlock from '$src/lib/components/InfoBlock.svelte';
|
import InfoBlock from '$src/lib/components/InfoBlock.svelte';
|
||||||
|
import BlogCard from '$src/lib/components/BlogCard.svelte';
|
||||||
|
|
||||||
function groupPostsByMonthYear(posts: App.BlogPost[]) {
|
function groupPostsByMonthYear(posts: App.BlogPost[]) {
|
||||||
const groupedPosts = new Map<string, App.BlogPost[]>();
|
const groupedPosts = new Map<string, App.BlogPost[]>();
|
||||||
|
|
@ -48,44 +48,7 @@
|
||||||
</h1>
|
</h1>
|
||||||
<div class="flex flex-col flex-wrap items-center gap-4">
|
<div class="flex flex-col flex-wrap items-center gap-4">
|
||||||
{#each postsInMonthYear as post, i}
|
{#each postsInMonthYear as post, i}
|
||||||
<a
|
<BlogCard {post} />
|
||||||
href="/blog/{post.slug}"
|
|
||||||
class="flex w-full max-w-5xl flex-col justify-baseline overflow-hidden rounded-lg bg-slate-100 text-slate-950 drop-shadow-xl transition-all hover:drop-shadow-2xl sm:flex-row sm:justify-stretch"
|
|
||||||
>
|
|
||||||
<div class="relative h-32 w-full basis-auto sm:h-auto sm:basis-1/3">
|
|
||||||
{#if post.thumbnail}
|
|
||||||
<img
|
|
||||||
class="absolute h-full w-full object-cover"
|
|
||||||
src={`/blog/${post.slug}/${post.thumbnail}`}
|
|
||||||
alt={post.thumbnailAlt ?? 'Миниатюра поста'}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div class="flex w-full flex-col justify-center p-4 break-words md:p-8">
|
|
||||||
<div class="flex flex-row flex-wrap justify-between gap-4 pb-4">
|
|
||||||
<div class="flex items-center text-lg font-bold">
|
|
||||||
<Icon
|
|
||||||
icon="material-symbols:calendar-today"
|
|
||||||
class="mr-3"
|
|
||||||
style="transform: scale( 1.3 )"
|
|
||||||
/>
|
|
||||||
<p>
|
|
||||||
{new Date(post.date!).toLocaleString('default', {
|
|
||||||
month: 'short',
|
|
||||||
day: 'numeric',
|
|
||||||
year: 'numeric'
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 class="text-3xl font-bold">{post.title}</h2>
|
|
||||||
|
|
||||||
{#if post.description}
|
|
||||||
<p>{post.description}</p>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ const config = {
|
||||||
},
|
},
|
||||||
extensions: ['.svelte', '.md'],
|
extensions: ['.svelte', '.md'],
|
||||||
preprocess: [
|
preprocess: [
|
||||||
vitePreprocess(),
|
vitePreprocess({ script: true }),
|
||||||
mdsvex({
|
mdsvex({
|
||||||
extensions: ['.md'],
|
extensions: ['.md'],
|
||||||
layout: join(__dirname, "./src/lib/components/MdsvexLayout.svelte")
|
layout: join(__dirname, "./src/lib/components/MdsvexLayout.svelte")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue