feat(theme-yun): overall UI optimization to enhance responsiveness (#574)

* feat(theme-yun): mobile post page optimization

* feat(theme-yun): card and markdown body optimization

* feat(theme-yun): code block full screen width on mobile

* feat(theme-press): code block full screen width on mobile

* feat(theme-yun): mobile post page title icon customizability
This commit is contained in:
JasonXuDeveloper - 傑 2025-07-15 01:16:32 +10:00 committed by GitHub
parent 219ca5e59c
commit 55c65b6227
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 128 additions and 97 deletions

View File

@ -5,6 +5,7 @@ title:
categories:
- $locale:category.test
- Markdown
excerpt_type: html
---
::: tip
@ -26,6 +27,7 @@ More info see [Markdown Extensions](https://valaxy.site/guide/markdown).
:tada: :100:
A [list of all emojis](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.json) is available.
<!-- more -->
## Table of Contents

View File

@ -4,7 +4,7 @@ import pkg from '../../package.json'
<template>
<div class="p-4" text="white sm" bg="dark" rounded-lg>
<pre>
<pre class="overflow-scroll">
🌌 Valaxy <span text-blue>v{{ pkg.version }}</span>
<span text-cyan>?</span> Select a type: <span op="70"> - Use arrow-keys. Return to submit.</span>

View File

@ -4,7 +4,7 @@ defineProps<{ cover?: string }>()
<template>
<div
class="yun-card flex-center rounded" flex="col"
class="yun-card flex-center rounded-2" flex="col"
min-h="100px"
bg="$va-c-bg-light"
>

View File

@ -24,76 +24,58 @@ const postTitleClass = computed(() => {
</script>
<template>
<YunCard
class="w-full"
m="auto"
:class="post.cover ? 'post-card-image' : 'post-card'"
overflow="hidden" :style="styles"
>
<div class="flex flex-1 of-hidden justify-start items-start post-card-info" w="full">
<img
v-if="post.cover"
:src="post.cover"
:alt="t('post.cover')"
width="320" height="180"
w="40%" h="54"
class="cover object-cover object-center md:shadow"
loading="lazy"
>
<div class="flex flex-col items-center relative px-6" :class="post.cover && 'h-54'" w="full">
<AppLink
class="post-title-link cursor-pointer"
:to="post.path || ''"
m="t-3"
:class="postTitleClass"
>
<div
class="flex-center title text-2xl"
text="center" font="serif black"
>
<div v-if="post.type" class="inline-flex" m="r-1" :class="icon" />
<span>{{ $tO(post.title) }}</span>
</div>
</AppLink>
<YunPostMeta :frontmatter="post" />
<div flex="~ grow col" w="full" justify="center" items="center">
<div v-if="post.excerpt_type === 'text'" py="1" />
<div v-if="post.excerpt" class="markdown-body" op="90" text="left" w="full" p="x-6 lt-sm:4 y-2" v-html="post.excerpt" />
<div v-else m="b-5" />
</div>
<!-- <div m="b-5" /> -->
<YunExcerptBottomGradient v-if="post.excerpt" />
<a
v-if="post.url"
:href="post.url"
class="post-link-btn shadow hover:shadow-md z-2"
rounded
target="_blank"
m="b-4"
>
{{ t('post.view_link') }}
</a>
</div>
</div>
<!-- always show -->
<div
w="full" class="yun-card-actions flex justify-between px-6"
min-h="10"
text="sm"
<a class="w-full flex-center post-card-link" :href="post.path || ''">
<YunCard
class="w-full hover:scale-102 hover:z-1" mx="4" :class="post.cover ? 'post-card-image' : 'post-card'"
overflow="hidden" :style="styles"
>
<div class="post-categories inline-flex" flex="wrap 1" items="center">
<YunPostCategories m="l-1" :categories="post.categories" />
<div class="flex flex-1 of-hidden justify-start items-start post-card-info" w="full">
<img
v-if="post.cover" :src="post.cover" :alt="t('post.cover')" width="320" height="180" w="40%" h="54"
class="cover object-cover object-center md:shadow" loading="lazy"
>
<div class="flex flex-col items-center relative" :class="post.cover && 'h-54'" w="full">
<AppLink class="post-title-link cursor-pointer" :to="post.path || ''" m="t-3" :class="postTitleClass">
<div class="flex-center title text-2xl" text="center" font="serif black">
<div v-if="post.type" class="inline-flex" m="r-1" :class="icon" />
<span>{{ $tO(post.title) }}</span>
</div>
</AppLink>
<YunPostMeta :frontmatter="post" />
<div flex="~ grow col" w="full" justify="center" items="center">
<div v-if="post.excerpt_type === 'text'" py="1" />
<div
v-if="post.excerpt" class="markdown-body" op="90" text="left" w="full" p="x-8 y-2"
v-html="post.excerpt"
/>
<div v-else m="b-5" />
</div>
<!-- <div m="b-5" /> -->
<YunExcerptBottomGradient v-if="post.excerpt" />
<a
v-if="post.url" :href="post.url" class="post-link-btn shadow hover:shadow-md z-2" rounded target="_blank"
m="b-4"
>
{{ t('post.view_link') }}
</a>
</div>
</div>
<YunPostTags v-if="post.tags" m="1" :tags="post.tags" />
</div>
</YunCard>
<!-- always show -->
<div w="full" class="yun-card-actions flex justify-between p-4" min-h="10" text="sm">
<div class="post-categories inline-flex" flex="wrap 1" items="center">
<YunPostCategories m="l-1" :categories="post.categories" />
</div>
<YunPostTags v-if="post.tags" m="1" :tags="post.tags" />
</div>
</YunCard>
</a>
</template>
<style lang="scss">
@ -104,6 +86,28 @@ const postTitleClass = computed(() => {
// animation-range: entry, exit;
}
.post-card-link {
text-decoration: none;
color: inherit;
&:hover {
text-decoration: none;
color: inherit;
}
&:visited {
color: inherit;
}
&:focus {
outline: none;
}
}
.post-card-link :hover {
cursor: var(--cursor-pointer), pointer;
}
@keyframes card-appear {
0% {
opacity: 0;

View File

@ -61,7 +61,7 @@ function goToLink() {
<div class="gap-1" flex="~">
<div
class="size-4"
:class="fm.icon || 'i-ri-article-line'"
:class="fm.icon || ''"
/>
<span class="truncate"> {{ $tO(fm.title || '') }}</span>
</div>

View File

@ -1,6 +1,6 @@
<template>
<div
w="full" h="10"
w="full" h="30%"
class="absolute bottom-0 bg-gradient-to-t from-$va-c-bg-light to-transparent z-1"
/>
</template>

View File

@ -2,7 +2,7 @@ import { defineConfig } from 'unocss'
export default defineConfig({
shortcuts: [
['yun-card', 'transition yun-transition shadow hover:shadow-lg'],
['yun-card', 'transition-all yun-transition shadow hover:shadow-2xl'],
],
rules: [
[

View File

@ -18,22 +18,41 @@ html:not(.dark) .vp-code-dark {
@include mobile {
.markdown-body {
div[class*="language-"] {
margin: 0 var(--va-code-mobile-margin-x, -1rem);
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw !important;
margin-right: -50vw !important;
width: 100vw !important;
margin-top: 16px;
margin-bottom: 0;
height: auto;
}
}
}
@media (width >= 640px) {
@media (width >=640px) {
.markdown-body div[class*="language-"] {
border-radius: 6px;
margin: 16px 0;
}
}
@media (width <= 639.9px) {
@media (width <=639.9px) {
.markdown-body li div[class*="language-"] {
border-radius: 6px 0 0 6px;
}
.markdown-body .vp-code-group .tabs,
.markdown-body .vp-code-group div[class*="language-"] {
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw !important;
margin-right: -50vw !important;
width: 100vw !important;
height: auto;
}
}
.markdown-body {
@ -101,7 +120,7 @@ html:not(.dark) .vp-code-dark {
}
// copy
[class*='language-'] > button.copy {
[class*='language-']>button.copy {
/* rtl:ignore */
direction: ltr;
position: absolute;
@ -126,28 +145,28 @@ html:not(.dark) .vp-code-dark {
background-color 0.25s,
opacity 0.25s;
}
[class*='language-']:hover > button.copy,
[class*='language-'] > button.copy:focus {
[class*='language-']:hover>button.copy,
[class*='language-']>button.copy:focus {
opacity: 1;
}
[class*='language-'] > button.copy:hover,
[class*='language-'] > button.copy.copied {
[class*='language-']>button.copy:hover,
[class*='language-']>button.copy.copied {
border-color: var(--va-code-copy-code-hover-border-color);
background-color: var(--va-code-copy-code-hover-bg);
}
[class*='language-'] > button.copy.copied,
[class*='language-'] > button.copy:hover.copied {
[class*='language-']>button.copy.copied,
[class*='language-']>button.copy:hover.copied {
/* rtl:ignore */
border-radius: 0 4px 4px 0;
background-color: var(--va-code-copy-code-hover-bg);
background-image: var(--va-icon-copied);
}
[class*='language-'] > button.copy.copied::before,
[class*='language-'] > button.copy:hover.copied::before {
[class*='language-']>button.copy.copied::before,
[class*='language-']>button.copy:hover.copied::before {
position: relative;
top: -1px;
@ -173,7 +192,7 @@ html:not(.dark) .vp-code-dark {
content: var(--va-code-copy-copied-text-content);
}
[class*='language-'] > span.lang {
[class*='language-']>span.lang {
position: absolute;
top: 2px;
@ -187,9 +206,9 @@ html:not(.dark) .vp-code-dark {
color 0.4s,
opacity 0.4s;
}
[class*='language-']:hover > button.copy + span.lang,
[class*='language-'] > button.copy:focus + span.lang {
[class*='language-']:hover>button.copy+span.lang,
[class*='language-']>button.copy:focus+span.lang {
opacity: 0;
}
@ -227,7 +246,7 @@ html:not(.dark) .vp-code-dark {
}
// collapse
[class*='language-'] > button.collapse {
[class*='language-']>button.collapse {
display: none;
position: absolute;
z-index: 10;
@ -237,7 +256,7 @@ html:not(.dark) .vp-code-dark {
height: 24px;
opacity: 1;
cursor: pointer;
background-image: linear-gradient(-180deg,rgb(0 0 0 / 0) 0%,var(--va-c-bg-dark) 100%);
background-image: linear-gradient(-180deg, rgb(0 0 0 / 0) 0%, var(--va-c-bg-dark) 100%);
&::before {
display: block;
@ -251,7 +270,7 @@ html:not(.dark) .vp-code-dark {
}
}
[class*='language-'].folded > button.collapse {
[class*='language-'].folded>button.collapse {
display: block;
}
}
}

View File

@ -1,6 +1,7 @@
@use "sass:map";
.markdown-body {
h1,
h2,
h3,
@ -94,7 +95,7 @@
}
@media (width >= 768px) {
@media (width >=768px) {
.markdown-body h1 {
letter-spacing: -0.02em;
line-height: 40px;
@ -102,3 +103,8 @@
}
}
@media (width <=767.9px) {
.markdown-body {
padding: 1rem;
}
}