v1.2.9: 라이브 에디터·홈 피드·메인 커버 개선

라이브 모드 코드/콜아웃/토글 편집, 슬래시 명령, 홈 Latest List·Compact·Cards 보기,
사이트 설정 메인 화면 커버(720px) 및 HomeHero 반영.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-18 16:57:30 +09:00
parent 666bd304fc
commit 3fb8a40031
34 changed files with 3823 additions and 443 deletions

View File

@@ -0,0 +1,58 @@
<script setup>
const props = defineProps({
/** 커버 이미지 URL */
imageUrl: {
type: String,
default: ''
},
/** 오버레이 제목 */
title: {
type: String,
default: ''
},
/** 오버레이 본문 */
text: {
type: String,
default: ''
}
})
/** @type {import('vue').ComputedRef<boolean>} */
const hasOverlay = computed(() => Boolean(props.title?.trim() || props.text?.trim()))
</script>
<template>
<section
v-if="imageUrl"
class="home-hero relative mx-auto w-full max-w-[720px] overflow-hidden rounded-[10px]"
data-home-hero
>
<div class="home-hero__frame relative aspect-[720/215] w-full bg-[var(--site-panel)]">
<img
class="home-hero__cover absolute inset-0 h-full w-full object-cover"
:src="imageUrl"
alt=""
loading="eager"
>
<div
v-if="hasOverlay"
class="home-hero__overlay pointer-events-none absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/70 via-black/35 to-transparent px-4 pb-4 pt-12 sm:px-5 sm:pb-5"
>
<div class="home-hero__overlay-inner flex flex-col items-start gap-1 text-left">
<h2
v-if="title"
class="home-hero__title text-base font-semibold leading-snug text-white sm:text-lg"
>
{{ title }}
</h2>
<p
v-if="text"
class="home-hero__text max-w-[32rem] text-sm leading-relaxed text-white/85"
>
{{ text }}
</p>
</div>
</div>
</div>
</section>
</template>

View File

@@ -8,16 +8,15 @@ defineProps({
</script>
<template>
<article class="post-card site-section site-panel-hover">
<article class="post-card site-section site-panel-hover group">
<div class="post-card__body site-section-body flex gap-4">
<img
v-if="post.featuredImage"
class="post-card__thumb h-20 w-36 shrink-0 rounded-lg bg-surface object-cover"
:src="post.featuredImage"
:alt="post.title"
loading="lazy"
>
<div v-else class="post-card__thumb h-20 w-36 shrink-0 rounded-lg bg-[linear-gradient(135deg,#06333a,#f4a261)]" />
<PostCardMedia
:to="post.to"
:title="post.title"
:featured-image="post.featuredImage"
link-class="h-20 w-36 shrink-0"
aspect-class="h-full w-full"
/>
<div class="post-card__content min-w-0">
<h2 class="post-card__title text-base font-semibold leading-tight">
<NuxtLink class="post-card__title-link site-interactive hover:opacity-70" :to="post.to">

View File

@@ -0,0 +1,62 @@
<script setup>
defineProps({
/** 게시물 링크 */
to: {
type: String,
required: true
},
/** 게시물 제목 */
title: {
type: String,
required: true
},
/** 대표 이미지 URL */
featuredImage: {
type: String,
default: ''
},
/** 썸네일 비율·크기 Tailwind 클래스 */
aspectClass: {
type: String,
default: 'aspect-square sm:aspect-video'
},
/** 링크 래퍼 추가 클래스 */
linkClass: {
type: String,
default: ''
},
/** 이미지 추가 클래스 */
imageClass: {
type: String,
default: ''
}
})
</script>
<template>
<NuxtLink
:to="to"
class="post-card-media relative block"
:class="linkClass"
data-post-card-media
>
<figure class="post-card-media__figure overflow-hidden rounded-[10px]">
<img
v-if="featuredImage"
class="post-card-media__image w-full rounded-[inherit] object-cover transition-opacity duration-200 group-hover:opacity-90"
:class="[aspectClass, imageClass]"
:src="featuredImage"
:alt="title"
loading="lazy"
>
<span
v-else
class="post-card-media__placeholder flex w-full items-center justify-center rounded-[inherit] bg-[#F7F4EF] p-4 text-center text-xs leading-snug text-[var(--site-muted)] transition-opacity duration-200 group-hover:opacity-90"
:class="aspectClass"
:aria-label="title"
>
<span class="post-card-media__placeholder-text line-clamp-4">{{ title }}</span>
</span>
</figure>
</NuxtLink>
</template>

View File

@@ -166,14 +166,6 @@ onBeforeUnmount(() => {
@click.prevent="toggleMenu"
>
<span v-if="menuOpen" class="site-header__menu-icon pointer-events-none">
<svg class="block h-6 w-6 group-hover:hidden" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M6 21a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6Zm12-16h-8v14h8a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1Z" />
</svg>
<svg class="hidden h-6 w-6 group-hover:block" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M18 3a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h12Zm0 2h-9v14h9a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1Zm-2.3 4.3a1 1 0 0 1 0 1.4L14.4 12l1.3 1.3a1 1 0 0 1-1.4 1.4l-2-2a1 1 0 0 1 0-1.4l2-2a1 1 0 0 1 1.4 0Z" />
</svg>
</span>
<span v-else class="site-header__menu-icon pointer-events-none">
<svg class="block h-6 w-6 group-hover:hidden" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6Z" />
<path d="M9 4v16" />
@@ -184,6 +176,14 @@ onBeforeUnmount(() => {
<path d="m14 10 2 2-2 2" />
</svg>
</span>
<span v-else class="site-header__menu-icon pointer-events-none">
<svg class="block h-6 w-6 group-hover:hidden" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M6 21a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6Zm12-16h-8v14h8a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1Z" />
</svg>
<svg class="hidden h-6 w-6 group-hover:block" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M18 3a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h12Zm0 2h-9v14h9a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1Zm-2.3 4.3a1 1 0 0 1 0 1.4L14.4 12l1.3 1.3a1 1 0 0 1-1.4 1.4l-2-2a1 1 0 0 1 0-1.4l2-2a1 1 0 0 1 1.4 0Z" />
</svg>
</span>
</button>
<span class="min-w-0 truncate">{{ siteSettings.title }}</span>
</NuxtLink>
@@ -195,7 +195,13 @@ onBeforeUnmount(() => {
aria-label="검색 열기"
@click="openSearchModal"
>
<span class="site-header__search-icon mr-2 text-lg leading-none"></span>
<span class="site-header__search-icon mr-2 text-lg leading-none">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-search" width="16" height="16" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<circle cx="10" cy="10" r="7"></circle>
<line x1="21" y1="21" x2="15" y2="15"></line>
</svg>
</span>
<span class="site-header__search-text site-soft">Search</span>
<span class="site-header__search-key ml-auto rounded-md px-2 text-xs site-soft site-input">/</span>
</button>