Skip to content

Commit

Permalink
feat(theme-yun): add animation for tags/categories
Browse files Browse the repository at this point in the history
  • Loading branch information
YunYouJun committed Oct 5, 2024
1 parent 1974245 commit 74e7259
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 55 deletions.
12 changes: 6 additions & 6 deletions demo/yun/theme.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ export default defineThemeConfig({
icon: 'i-ri-link',
// color: 'dodgerblue',
},
// {
// name: '老婆列表',
// url: '/girls/',
// icon: 'i-ri-women-line',
// color: 'hotpink',
// },
{
name: '老婆列表',
url: '/girls/',
icon: 'i-ri-women-line',
// color: 'hotpink',
},
],

footer: {
Expand Down
3 changes: 2 additions & 1 deletion packages/valaxy-theme-yun/components/YunCategories.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ const categoryList = computed(() => {
<template>
<div flex="~ col">
<ul
v-for="category in categories.values()"
v-for="(category, i) in categories.values()"
:key="category.name"
class="category-list"
>
<YunCategory
:i="i"
:parent-key="category.name"
:category="category"
:level="level + 1"
Expand Down
60 changes: 23 additions & 37 deletions packages/valaxy-theme-yun/components/YunCategory.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'
import { onMounted, ref } from 'vue'
import type { CategoryList, Post } from 'valaxy'
import { isCategoryList, useInvisibleElement } from 'valaxy'
import { useInvisibleElement } from 'valaxy'
import { useI18n } from 'vue-i18n'
import { useRoute, useRouter } from 'vue-router'
import { useRouter } from 'vue-router'
import { useYunSpringAnimation } from '../composables/animation'
const props = withDefaults(defineProps<{
i?: number
parentKey: string
// to eliminate the warning
category: Post | CategoryList
Expand All @@ -20,24 +22,10 @@ const props = withDefaults(defineProps<{
})
const router = useRouter()
const route = useRoute()
const categoryList = computed(() => {
const c = (route.query.category as string) || ''
return Array.isArray(c) ? [c] : c.split('/')
})
const collapse = ref(props.collapsable)
const { t } = useI18n()
/**
* i18n
*/
const { locale } = useI18n()
function getTitle(post: Post | any) {
const lang = locale.value === 'zh-CN' ? 'zh' : locale.value
return post[`title_${lang}`] ? post[`title_${lang}`] : post.title
}
const postCollapseElRef = ref<HTMLElement>()
const { show } = useInvisibleElement(postCollapseElRef)
/**
Expand All @@ -61,11 +49,21 @@ onMounted(() => {
if (postCollapseEl)
postCollapseElRef.value = postCollapseEl
})
const categoryRef = ref<HTMLElement>()
if (props.level === 1) {
useYunSpringAnimation(categoryRef, {
i: props.i || 0,
y: 20,
duration: 200,
})
}
</script>

<template>
<li
class="category-list-item inline-flex items-center cursor-pointer w-full gap-2 transition px-3 py-2 rounded"
ref="categoryRef"
class="category-list-item inline-flex items-center cursor-pointer w-full gap-2 px-3 py-2 rounded"
hover="bg-black/5"
>
<span
Expand Down Expand Up @@ -98,28 +96,16 @@ onMounted(() => {
>
<ul v-if="!collapse">
<li
v-for="categoryItem, i in category.children.values()" :key="i"
v-for="categoryItem, cI in category.children.values()"
:key="cI"
class="post-list-item text-$va-c-text" m="l-4"
hover="text-$va-c-primary-lighter"
>
<template v-if="isCategoryList(categoryItem)">
<YunCategory
:parent-key="parentKey ? `${parentKey}/${categoryItem.name}` : categoryItem.name"
:category="categoryItem"
:collapsable="!categoryList.includes(categoryItem.name)"
/>
</template>

<template v-else>
<RouterLink
v-if="categoryItem.title" :to="categoryItem.path || ''"
class="inline-flex items-center gap-2 px-3 py-2 w-full rounded transition"
hover="bg-black/5"
>
<div i-ri-file-text-line />
<span font="serif black">{{ getTitle(categoryItem) }}</span>
</RouterLink>
</template>
<YunCategoryChildItem
:i="cI"
:category-item="categoryItem"
:parent-key="parentKey"
/>
</li>
</ul>
</Transition>
Expand Down
49 changes: 49 additions & 0 deletions packages/valaxy-theme-yun/components/YunCategoryChildItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script setup lang="ts">
import type { Post } from 'valaxy'
import { isCategoryList } from 'valaxy'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
defineProps<{
i?: number
categoryItem: any
parentKey?: string
}>()
/**
* i18n
*/
const { locale } = useI18n()
function getTitle(post: Post | any) {
const lang = locale.value === 'zh-CN' ? 'zh' : locale.value
return post[`title_${lang}`] ? post[`title_${lang}`] : post.title
}
const route = useRoute()
const categoryList = computed(() => {
const c = (route.query.category as string) || ''
return Array.isArray(c) ? [c] : c.split('/')
})
</script>

<template>
<template v-if="isCategoryList(categoryItem)">
<YunCategory
:parent-key="parentKey ? `${parentKey}/${categoryItem.name}` : categoryItem.name"
:category="categoryItem"
:collapsable="!categoryList.includes(categoryItem.name)"
/>
</template>

<template v-else>
<RouterLink
v-if="categoryItem.title"
:to="categoryItem.path || ''"
class="inline-flex items-center gap-2 px-3 py-2 w-full rounded"
hover="bg-black/5"
>
<div i-ri-file-text-line />
<span font="serif black">{{ getTitle(categoryItem) }}</span>
</RouterLink>
</template>
</template>
12 changes: 11 additions & 1 deletion packages/valaxy-theme-yun/components/YunLayoutPostTag.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
<script lang="ts" setup>
defineProps<{
import { ref } from 'vue'
import { useYunSpringAnimation } from '../composables/animation'
const props = defineProps<{
i?: number
title: string
count: number
}>()
const tagRef = ref<HTMLElement>()
useYunSpringAnimation(tagRef, {
i: props.i || 0,
})
</script>

<template>
<span
ref="tagRef"
inline-flex my="2" p="1"
class="post-tag cursor-pointer items-baseline leading-4"
>
Expand Down
8 changes: 5 additions & 3 deletions packages/valaxy-theme-yun/components/YunPostCollapse.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ const sortedYears = computed(() => {

<template>
<div class="post-collapse px-10 lt-sm:px-5 max-w-3xl" relative>
<div w="full" text="center" class="yun-text-light" p="2">
{{ t('counter.archives', posts.length) }}
</div>
<Transition appear enter-active-class="animate-fade-in animate-duration-400">
<div w="full" text="center" class="yun-text-light" p="2">
{{ t('counter.archives', posts.length) }}
</div>
</Transition>

<div class="post-collapse-action" text="center">
<button class="yun-icon-btn shadow hover:shadow-md" @click="isDesc = !isDesc">
Expand Down
33 changes: 33 additions & 0 deletions packages/valaxy-theme-yun/composables/animation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useMotion } from '@vueuse/motion'
import type { MaybeRef } from 'vue'
import { cubicBezier } from '../client/constants'

/**
* 统一的弹跳出现动画
*/
export function useYunSpringAnimation(target: MaybeRef<HTMLElement | undefined>, options: {
/**
* index order
*/
i: number
y?: number
duration?: number
}) {
useMotion(target, {
initial: {
opacity: 0,
y: options.y || 40,
},
enter: {
opacity: 1,
y: 0,
transition: {
delay: options.i * 50,
type: 'spring',
ease: cubicBezier.easeIn,
damping: 8,
duration: options.duration || 400,
},
},
})
}
11 changes: 8 additions & 3 deletions packages/valaxy-theme-yun/layouts/categories.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,14 @@ useSchemaOrg([
/>
</template>
<template #main-content>
<div text="center" class="yun-text-light" p="2">
{{ t('counter.categories', Array.from(categories.children).length) }}
</div>
<Transition
enter-active-class="animate-fade-in animate-duration-400"
appear
>
<div text="center" class="yun-text-light" p="2">
{{ t('counter.categories', Array.from(categories.children).length) }}
</div>
</Transition>
<YunCategories :categories="categories.children" />
<RouterView />
</template>
Expand Down
15 changes: 11 additions & 4 deletions packages/valaxy-theme-yun/layouts/tags.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function displayTag(tag: string) {
}
const title = usePostTitle(frontmatter)
const tagArr = computed(() => Array.from(tags.value).sort())
// use flex to fix `overflow-wrap: break-words;` not working in Safari
</script>
Expand All @@ -72,14 +73,20 @@ const title = usePostTitle(frontmatter)
/>
</template>
<template #main-content>
<div class="yun-text-light" text="center" p="2">
{{ t('counter.tags', Array.from(tags).length) }}
</div>
<Transition
enter-active-class="animate-fade-in animate-duration-400"
appear
>
<div class="yun-text-light" text="center" p="2">
{{ t('counter.tags', tagArr.length) }}
</div>
</Transition>

<div class="justify-center items-end" flex="~ wrap" gap="1">
<YunLayoutPostTag
v-for="[key, tag] in Array.from(tags).sort()"
v-for="([key, tag], i) in tagArr"
:key="key"
:i="i"
:title="key"
:count="tag.count"
:style="getTagStyle(tag.count)"
Expand Down

0 comments on commit 74e7259

Please sign in to comment.