mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-13 23:16:47 +00:00
matery主题支持algolia;hexo组件名微调
This commit is contained in:
187
themes/hexo/components/Header.js
Normal file
187
themes/hexo/components/Header.js
Normal file
@@ -0,0 +1,187 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import throttle from 'lodash.throttle'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import CONFIG from '../config'
|
||||
import CategoryGroup from './CategoryGroup'
|
||||
import Logo from './Logo'
|
||||
import { MenuListTop } from './MenuListTop'
|
||||
import SearchButton from './SearchButton'
|
||||
import SearchDrawer from './SearchDrawer'
|
||||
import SideBar from './SideBar'
|
||||
import SideBarDrawer from './SideBarDrawer'
|
||||
import TagGroups from './TagGroups'
|
||||
|
||||
let windowTop = 0
|
||||
|
||||
/**
|
||||
* 顶部导航
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const Header = props => {
|
||||
const searchDrawer = useRef()
|
||||
const { tags, currentTag, categories, currentCategory } = props
|
||||
const { locale } = useGlobal()
|
||||
const router = useRouter()
|
||||
const [isOpen, changeShow] = useState(false)
|
||||
const showSearchButton = siteConfig('HEXO_MENU_SEARCH', false, CONFIG)
|
||||
|
||||
const toggleMenuOpen = () => {
|
||||
changeShow(!isOpen)
|
||||
}
|
||||
|
||||
const toggleSideBarClose = () => {
|
||||
changeShow(false)
|
||||
}
|
||||
|
||||
// 监听滚动
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', topNavStyleHandler)
|
||||
router.events.on('routeChangeComplete', topNavStyleHandler)
|
||||
topNavStyleHandler()
|
||||
return () => {
|
||||
router.events.off('routeChangeComplete', topNavStyleHandler)
|
||||
window.removeEventListener('scroll', topNavStyleHandler)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const throttleMs = 200
|
||||
|
||||
const topNavStyleHandler = useCallback(
|
||||
throttle(() => {
|
||||
const scrollS = window.scrollY
|
||||
const nav = document.querySelector('#sticky-nav')
|
||||
// 首页和文章页会有头图
|
||||
const header = document.querySelector('#header')
|
||||
// 导航栏和头图是否重叠
|
||||
const scrollInHeader =
|
||||
header && (scrollS < 10 || scrollS < header?.clientHeight - 50) // 透明导航条的条件
|
||||
|
||||
// const textWhite = header && scrollInHeader
|
||||
|
||||
if (scrollInHeader) {
|
||||
nav && nav.classList.replace('bg-white', 'bg-none')
|
||||
nav && nav.classList.replace('border', 'border-transparent')
|
||||
nav && nav.classList.replace('drop-shadow-md', 'shadow-none')
|
||||
nav && nav.classList.replace('dark:bg-hexo-black-gray', 'transparent')
|
||||
} else {
|
||||
nav && nav.classList.replace('bg-none', 'bg-white')
|
||||
nav && nav.classList.replace('border-transparent', 'border')
|
||||
nav && nav.classList.replace('shadow-none', 'drop-shadow-md')
|
||||
nav && nav.classList.replace('transparent', 'dark:bg-hexo-black-gray')
|
||||
}
|
||||
|
||||
if (scrollInHeader) {
|
||||
nav && nav.classList.replace('text-black', 'text-white')
|
||||
} else {
|
||||
nav && nav.classList.replace('text-white', 'text-black')
|
||||
}
|
||||
|
||||
// 导航栏不在头图里,且页面向下滚动一定程度 隐藏导航栏
|
||||
const showNav =
|
||||
scrollS <= windowTop ||
|
||||
scrollS < 5 ||
|
||||
(header && scrollS <= header.clientHeight + 100)
|
||||
if (!showNav) {
|
||||
nav && nav.classList.replace('top-0', '-top-20')
|
||||
windowTop = scrollS
|
||||
} else {
|
||||
nav && nav.classList.replace('-top-20', 'top-0')
|
||||
windowTop = scrollS
|
||||
}
|
||||
}, throttleMs)
|
||||
)
|
||||
|
||||
const searchDrawerSlot = (
|
||||
<>
|
||||
{categories && (
|
||||
<section className='mt-8'>
|
||||
<div className='text-sm flex flex-nowrap justify-between font-light px-2'>
|
||||
<div className='text-gray-600 dark:text-gray-200'>
|
||||
<i className='mr-2 fas fa-th-list' />
|
||||
{locale.COMMON.CATEGORY}
|
||||
</div>
|
||||
<Link
|
||||
href={'/category'}
|
||||
passHref
|
||||
className='mb-3 text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
</Link>
|
||||
</div>
|
||||
<CategoryGroup
|
||||
currentCategory={currentCategory}
|
||||
categories={categories}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{tags && (
|
||||
<section className='mt-4'>
|
||||
<div className='text-sm py-2 px-2 flex flex-nowrap justify-between font-light dark:text-gray-200'>
|
||||
<div className='text-gray-600 dark:text-gray-200'>
|
||||
<i className='mr-2 fas fa-tag' />
|
||||
{locale.COMMON.TAGS}
|
||||
</div>
|
||||
<Link
|
||||
href={'/tag'}
|
||||
passHref
|
||||
className='text-gray-400 hover:text-black dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
</Link>
|
||||
</div>
|
||||
<div className='p-2'>
|
||||
<TagGroups tags={tags} currentTag={currentTag} />
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<div id='top-nav' className='z-40'>
|
||||
<SearchDrawer cRef={searchDrawer} slot={searchDrawerSlot} />
|
||||
|
||||
{/* 导航栏 */}
|
||||
<div
|
||||
id='sticky-nav'
|
||||
style={{ backdropFilter: 'blur(3px)' }}
|
||||
className={
|
||||
'top-0 duration-300 transition-all shadow-none fixed bg-none dark:bg-hexo-black-gray dark:text-gray-200 text-black w-full z-20 transform border-transparent dark:border-transparent'
|
||||
}>
|
||||
<div className='w-full flex justify-between items-center px-4 py-2'>
|
||||
<div className='flex'>
|
||||
<Logo {...props} />
|
||||
</div>
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 flex justify-end items-center '>
|
||||
<div className='hidden lg:flex'>
|
||||
{' '}
|
||||
<MenuListTop {...props} />
|
||||
</div>
|
||||
<div
|
||||
onClick={toggleMenuOpen}
|
||||
className='w-8 justify-center items-center h-8 cursor-pointer flex lg:hidden'>
|
||||
{isOpen ? (
|
||||
<i className='fas fa-times' />
|
||||
) : (
|
||||
<i className='fas fa-bars' />
|
||||
)}
|
||||
</div>
|
||||
{showSearchButton && <SearchButton />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 折叠侧边栏 */}
|
||||
<SideBarDrawer isOpen={isOpen} onClose={toggleSideBarClose}>
|
||||
<SideBar {...props} />
|
||||
</SideBarDrawer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Header
|
||||
@@ -1,85 +0,0 @@
|
||||
import Link from 'next/link'
|
||||
import TagItemMini from './TagItemMini'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { formatDateFmt } from '@/lib/utils/formatDate'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
|
||||
export default function PostHeader({ post, siteInfo }) {
|
||||
const { locale, fullWidth } = useGlobal()
|
||||
|
||||
if (!post) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
// 文章全屏隐藏标头
|
||||
if (fullWidth) {
|
||||
return <div className='my-8'/>
|
||||
}
|
||||
|
||||
const headerImage = post?.pageCover ? post.pageCover : siteInfo?.pageCover
|
||||
|
||||
return (
|
||||
<div id="header" className="w-full h-96 relative md:flex-shrink-0 z-10" >
|
||||
<LazyImage priority={true} src={headerImage} className='w-full h-full object-cover object-center absolute top-0'/>
|
||||
|
||||
<header id='article-header-cover'
|
||||
className="bg-black bg-opacity-70 absolute top-0 w-full h-96 py-10 flex justify-center items-center ">
|
||||
|
||||
<div className='mt-10'>
|
||||
<div className='mb-3 flex justify-center'>
|
||||
{post.category && <>
|
||||
<Link href={`/category/${post.category}`} passHref legacyBehavior>
|
||||
<div className="cursor-pointer px-2 py-1 mb-2 border rounded-sm dark:border-white text-sm font-medium hover:underline duration-200 shadow-text-md text-white">
|
||||
{post.category}
|
||||
</div>
|
||||
</Link>
|
||||
</>}
|
||||
</div>
|
||||
|
||||
{/* 文章Title */}
|
||||
<div className="leading-snug font-bold xs:text-4xl sm:text-4xl md:text-5xl md:leading-snug text-4xl shadow-text-md flex justify-center text-center text-white">
|
||||
{siteConfig('POST_TITLE_ICON') && <NotionIcon icon={post.pageIcon} className='text-4xl mx-1' />}{post.title}
|
||||
</div>
|
||||
|
||||
<section className="flex-wrap shadow-text-md flex text-sm justify-center mt-4 text-white dark:text-gray-400 font-light leading-8">
|
||||
|
||||
<div className='flex justify-center dark:text-gray-200 text-opacity-70'>
|
||||
{post?.type !== 'Page' && (
|
||||
<>
|
||||
<Link
|
||||
href={`/archive#${formatDateFmt(post?.publishDate, 'yyyy-MM')}`}
|
||||
passHref
|
||||
className="pl-1 mr-2 cursor-pointer hover:underline">
|
||||
|
||||
{locale.COMMON.POST_TIME}: {post?.publishDay}
|
||||
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
<div className="pl-1 mr-2">
|
||||
{locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedDay}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{JSON.parse(siteConfig('ANALYTICS_BUSUANZI_ENABLE')) && <div className="busuanzi_container_page_pv font-light mr-2">
|
||||
<span className="mr-2 busuanzi_value_page_pv" />
|
||||
{locale.COMMON.VIEWS}
|
||||
</div>}
|
||||
</section>
|
||||
|
||||
<div className='mt-4 mb-1'>
|
||||
{post.tagItems && (
|
||||
<div className="flex justify-center flex-nowrap overflow-x-auto">
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
99
themes/hexo/components/PostHero.js
Normal file
99
themes/hexo/components/PostHero.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { formatDateFmt } from '@/lib/utils/formatDate'
|
||||
import Link from 'next/link'
|
||||
import TagItemMini from './TagItemMini'
|
||||
|
||||
/**
|
||||
* 文章详情页的Hero块
|
||||
*/
|
||||
export default function PostHero({ post, siteInfo }) {
|
||||
const { locale, fullWidth } = useGlobal()
|
||||
|
||||
if (!post) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
// 文章全屏隐藏标头
|
||||
if (fullWidth) {
|
||||
return <div className='my-8' />
|
||||
}
|
||||
|
||||
const headerImage = post?.pageCover ? post.pageCover : siteInfo?.pageCover
|
||||
|
||||
return (
|
||||
<div id='header' className='w-full h-96 relative md:flex-shrink-0 z-10'>
|
||||
<LazyImage
|
||||
priority={true}
|
||||
src={headerImage}
|
||||
className='w-full h-full object-cover object-center absolute top-0'
|
||||
/>
|
||||
|
||||
<header
|
||||
id='article-header-cover'
|
||||
className='bg-black bg-opacity-70 absolute top-0 w-full h-96 py-10 flex justify-center items-center '>
|
||||
<div className='mt-10'>
|
||||
<div className='mb-3 flex justify-center'>
|
||||
{post.category && (
|
||||
<>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div className='cursor-pointer px-2 py-1 mb-2 border rounded-sm dark:border-white text-sm font-medium hover:underline duration-200 shadow-text-md text-white'>
|
||||
{post.category}
|
||||
</div>
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 文章Title */}
|
||||
<div className='leading-snug font-bold xs:text-4xl sm:text-4xl md:text-5xl md:leading-snug text-4xl shadow-text-md flex justify-center text-center text-white'>
|
||||
{siteConfig('POST_TITLE_ICON') && (
|
||||
<NotionIcon icon={post.pageIcon} className='text-4xl mx-1' />
|
||||
)}
|
||||
{post.title}
|
||||
</div>
|
||||
|
||||
<section className='flex-wrap shadow-text-md flex text-sm justify-center mt-4 text-white dark:text-gray-400 font-light leading-8'>
|
||||
<div className='flex justify-center dark:text-gray-200 text-opacity-70'>
|
||||
{post?.type !== 'Page' && (
|
||||
<>
|
||||
<Link
|
||||
href={`/archive#${formatDateFmt(post?.publishDate, 'yyyy-MM')}`}
|
||||
passHref
|
||||
className='pl-1 mr-2 cursor-pointer hover:underline'>
|
||||
{locale.COMMON.POST_TIME}: {post?.publishDay}
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
<div className='pl-1 mr-2'>
|
||||
{locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedDay}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{JSON.parse(siteConfig('ANALYTICS_BUSUANZI_ENABLE')) && (
|
||||
<div className='busuanzi_container_page_pv font-light mr-2'>
|
||||
<span className='mr-2 busuanzi_value_page_pv' />
|
||||
{locale.COMMON.VIEWS}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<div className='mt-4 mb-1'>
|
||||
{post.tagItems && (
|
||||
<div className='flex justify-center flex-nowrap overflow-x-auto'>
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import CategoryGroup from './CategoryGroup'
|
||||
import Logo from './Logo'
|
||||
import SearchDrawer from './SearchDrawer'
|
||||
import TagGroups from './TagGroups'
|
||||
import { MenuListTop } from './MenuListTop'
|
||||
import throttle from 'lodash.throttle'
|
||||
import SideBar from './SideBar'
|
||||
import SideBarDrawer from './SideBarDrawer'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import SearchButton from './SearchButton'
|
||||
import CONFIG from '../config'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
let windowTop = 0
|
||||
|
||||
/**
|
||||
* 顶部导航
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const TopNav = props => {
|
||||
const searchDrawer = useRef()
|
||||
const { tags, currentTag, categories, currentCategory } = props
|
||||
const { locale } = useGlobal()
|
||||
const router = useRouter()
|
||||
const [isOpen, changeShow] = useState(false)
|
||||
const showSearchButton = siteConfig('HEXO_MENU_SEARCH', false, CONFIG)
|
||||
|
||||
const toggleMenuOpen = () => {
|
||||
changeShow(!isOpen)
|
||||
}
|
||||
|
||||
const toggleSideBarClose = () => {
|
||||
changeShow(false)
|
||||
}
|
||||
|
||||
// 监听滚动
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', topNavStyleHandler)
|
||||
router.events.on('routeChangeComplete', topNavStyleHandler)
|
||||
topNavStyleHandler()
|
||||
return () => {
|
||||
router.events.off('routeChangeComplete', topNavStyleHandler)
|
||||
window.removeEventListener('scroll', topNavStyleHandler)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const throttleMs = 200
|
||||
|
||||
const topNavStyleHandler = useCallback(throttle(() => {
|
||||
const scrollS = window.scrollY
|
||||
const nav = document.querySelector('#sticky-nav')
|
||||
// 首页和文章页会有头图
|
||||
const header = document.querySelector('#header')
|
||||
// 导航栏和头图是否重叠
|
||||
const scrollInHeader = header && (scrollS < 10 || scrollS < header?.clientHeight - 50) // 透明导航条的条件
|
||||
|
||||
// const textWhite = header && scrollInHeader
|
||||
|
||||
if (scrollInHeader) {
|
||||
nav && nav.classList.replace('bg-white', 'bg-none')
|
||||
nav && nav.classList.replace('border', 'border-transparent')
|
||||
nav && nav.classList.replace('drop-shadow-md', 'shadow-none')
|
||||
nav && nav.classList.replace('dark:bg-hexo-black-gray', 'transparent')
|
||||
} else {
|
||||
nav && nav.classList.replace('bg-none', 'bg-white')
|
||||
nav && nav.classList.replace('border-transparent', 'border')
|
||||
nav && nav.classList.replace('shadow-none', 'drop-shadow-md')
|
||||
nav && nav.classList.replace('transparent', 'dark:bg-hexo-black-gray')
|
||||
}
|
||||
|
||||
if (scrollInHeader) {
|
||||
nav && nav.classList.replace('text-black', 'text-white')
|
||||
} else {
|
||||
nav && nav.classList.replace('text-white', 'text-black')
|
||||
}
|
||||
|
||||
// 导航栏不在头图里,且页面向下滚动一定程度 隐藏导航栏
|
||||
const showNav = scrollS <= windowTop || scrollS < 5 || (header && scrollS <= header.clientHeight + 100)
|
||||
if (!showNav) {
|
||||
nav && nav.classList.replace('top-0', '-top-20')
|
||||
windowTop = scrollS
|
||||
} else {
|
||||
nav && nav.classList.replace('-top-20', 'top-0')
|
||||
windowTop = scrollS
|
||||
}
|
||||
}, throttleMs)
|
||||
)
|
||||
|
||||
const searchDrawerSlot = <>
|
||||
{categories && (
|
||||
<section className='mt-8'>
|
||||
<div className='text-sm flex flex-nowrap justify-between font-light px-2'>
|
||||
<div className='text-gray-600 dark:text-gray-200'><i className='mr-2 fas fa-th-list' />{locale.COMMON.CATEGORY}</div>
|
||||
<Link
|
||||
href={'/category'}
|
||||
passHref
|
||||
className='mb-3 text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
<CategoryGroup currentCategory={currentCategory} categories={categories} />
|
||||
</section>
|
||||
)}
|
||||
|
||||
{tags && (
|
||||
<section className='mt-4'>
|
||||
<div className='text-sm py-2 px-2 flex flex-nowrap justify-between font-light dark:text-gray-200'>
|
||||
<div className='text-gray-600 dark:text-gray-200'><i className='mr-2 fas fa-tag' />{locale.COMMON.TAGS}</div>
|
||||
<Link
|
||||
href={'/tag'}
|
||||
passHref
|
||||
className='text-gray-400 hover:text-black dark:hover:text-white hover:underline cursor-pointer'>
|
||||
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
<div className='p-2'>
|
||||
<TagGroups tags={tags} currentTag={currentTag} />
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</>
|
||||
|
||||
return (<div id='top-nav' className='z-40'>
|
||||
<SearchDrawer cRef={searchDrawer} slot={searchDrawerSlot} />
|
||||
|
||||
{/* 导航栏 */}
|
||||
<div id='sticky-nav' style={{ backdropFilter: 'blur(3px)' }} className={'top-0 duration-300 transition-all shadow-none fixed bg-none dark:bg-hexo-black-gray dark:text-gray-200 text-black w-full z-20 transform border-transparent dark:border-transparent'}>
|
||||
<div className='w-full flex justify-between items-center px-4 py-2'>
|
||||
<div className='flex'>
|
||||
<Logo {...props} />
|
||||
</div>
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 flex justify-end items-center '>
|
||||
<div className='hidden lg:flex'> <MenuListTop {...props} /></div>
|
||||
<div onClick={toggleMenuOpen} className='w-8 justify-center items-center h-8 cursor-pointer flex lg:hidden'>
|
||||
{isOpen ? <i className='fas fa-times' /> : <i className='fas fa-bars' />}
|
||||
</div>
|
||||
{showSearchButton && <SearchButton />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 折叠侧边栏 */}
|
||||
<SideBarDrawer isOpen={isOpen} onClose={toggleSideBarClose}>
|
||||
<SideBar {...props} />
|
||||
</SideBarDrawer>
|
||||
</div>)
|
||||
}
|
||||
|
||||
export default TopNav
|
||||
@@ -19,9 +19,10 @@ import BlogPostListPage from './components/BlogPostListPage'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import Card from './components/Card'
|
||||
import Footer from './components/Footer'
|
||||
import Header from './components/Header'
|
||||
import Hero from './components/Hero'
|
||||
import JumpToCommentButton from './components/JumpToCommentButton'
|
||||
import PostHeader from './components/PostHeader'
|
||||
import PostHero from './components/PostHero'
|
||||
import RightFloatArea from './components/RightFloatArea'
|
||||
import SearchNav from './components/SearchNav'
|
||||
import SideRight from './components/SideRight'
|
||||
@@ -29,7 +30,6 @@ import SlotBar from './components/SlotBar'
|
||||
import TagItemMini from './components/TagItemMini'
|
||||
import TocDrawer from './components/TocDrawer'
|
||||
import TocDrawerButton from './components/TocDrawerButton'
|
||||
import TopNav from './components/TopNav'
|
||||
import CONFIG from './config'
|
||||
import { Style } from './style'
|
||||
|
||||
@@ -54,7 +54,7 @@ const LayoutBase = props => {
|
||||
|
||||
const router = useRouter()
|
||||
const headerSlot = post ? (
|
||||
<PostHeader {...props} />
|
||||
<PostHero {...props} />
|
||||
) : router.route === '/' &&
|
||||
siteConfig('HEXO_HOME_BANNER_ENABLE', null, CONFIG) ? (
|
||||
<Hero {...props} />
|
||||
@@ -89,7 +89,7 @@ const LayoutBase = props => {
|
||||
<Style />
|
||||
|
||||
{/* 顶部导航 */}
|
||||
<TopNav {...props} />
|
||||
<Header {...props} />
|
||||
|
||||
{/* 顶部嵌入 */}
|
||||
<Transition
|
||||
|
||||
190
themes/matery/components/Header.js
Normal file
190
themes/matery/components/Header.js
Normal file
@@ -0,0 +1,190 @@
|
||||
import SideBarDrawer from '@/components/SideBarDrawer'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import throttle from 'lodash.throttle'
|
||||
import Link from 'next/link'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import CONFIG from '../config'
|
||||
import CategoryGroup from './CategoryGroup'
|
||||
import Logo from './Logo'
|
||||
import { MenuListTop } from './MenuListTop'
|
||||
import SearchButton from './SearchButton'
|
||||
import SearchDrawer from './SearchDrawer'
|
||||
import SideBar from './SideBar'
|
||||
import TagGroups from './TagGroups'
|
||||
|
||||
let windowTop = 0
|
||||
|
||||
/**
|
||||
* 顶部导航(页头)
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const Header = props => {
|
||||
const { tags, currentTag, categories, currentCategory } = props
|
||||
const { locale } = useGlobal()
|
||||
const searchDrawer = useRef()
|
||||
const { isDarkMode } = useGlobal()
|
||||
const throttleMs = 200
|
||||
const showSearchButton = siteConfig('MATERY_MENU_SEARCH', false, CONFIG)
|
||||
|
||||
const scrollTrigger = useCallback(
|
||||
throttle(() => {
|
||||
requestAnimationFrame(() => {
|
||||
const scrollS = window.scrollY
|
||||
const nav = document.querySelector('#sticky-nav')
|
||||
const header = document.querySelector('#header')
|
||||
const showNav =
|
||||
scrollS <= windowTop ||
|
||||
scrollS < 5 ||
|
||||
(header && scrollS <= header.clientHeight * 2) // 非首页无大图时影藏顶部 滚动条置顶时隐藏// 非首页无大图时影藏顶部 滚动条置顶时隐藏
|
||||
// 是否将导航栏透明
|
||||
const navTransparent = header && scrollS < 300 // 透明导航条的条件
|
||||
|
||||
if (navTransparent) {
|
||||
nav && nav.classList.replace('bg-indigo-700', 'bg-none')
|
||||
nav && nav.classList.replace('text-black', 'text-white')
|
||||
nav && nav.classList.replace('shadow-xl', 'shadow-none')
|
||||
nav && nav.classList.replace('dark:bg-hexo-black-gray', 'transparent')
|
||||
} else {
|
||||
nav && nav.classList.replace('bg-none', 'bg-indigo-700')
|
||||
nav && nav.classList.replace('text-white', 'text-black')
|
||||
nav && nav.classList.replace('shadow-none', 'shadow-xl')
|
||||
nav && nav.classList.replace('transparent', 'dark:bg-hexo-black-gray')
|
||||
}
|
||||
|
||||
if (!showNav) {
|
||||
nav && nav.classList.replace('top-0', '-top-20')
|
||||
windowTop = scrollS
|
||||
} else {
|
||||
nav && nav.classList.replace('-top-20', 'top-0')
|
||||
windowTop = scrollS
|
||||
}
|
||||
navDarkMode()
|
||||
})
|
||||
}, throttleMs)
|
||||
)
|
||||
|
||||
const navDarkMode = () => {
|
||||
const nav = document.getElementById('sticky-nav')
|
||||
const header = document.querySelector('#header')
|
||||
if (!isDarkMode && nav && header) {
|
||||
if (window.scrollY < header.clientHeight) {
|
||||
nav?.classList?.add('dark')
|
||||
} else {
|
||||
nav?.classList?.remove('dark')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 监听滚动
|
||||
useEffect(() => {
|
||||
scrollTrigger()
|
||||
|
||||
window.addEventListener('scroll', scrollTrigger)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', scrollTrigger)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const [isOpen, changeShow] = useState(false)
|
||||
|
||||
const toggleMenuOpen = () => {
|
||||
changeShow(!isOpen)
|
||||
}
|
||||
|
||||
const toggleMenuClose = () => {
|
||||
changeShow(false)
|
||||
}
|
||||
|
||||
const searchDrawerSlot = (
|
||||
<>
|
||||
{categories && (
|
||||
<section className='mt-8'>
|
||||
<div className='text-sm flex flex-nowrap justify-between font-light px-2'>
|
||||
<div className='text-gray-600 dark:text-gray-200'>
|
||||
<i className='mr-2 fas fa-th-list' />
|
||||
{locale.COMMON.CATEGORY}
|
||||
</div>
|
||||
<Link
|
||||
href={'/category'}
|
||||
passHref
|
||||
className='mb-3 text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
</Link>
|
||||
</div>
|
||||
<CategoryGroup
|
||||
currentCategory={currentCategory}
|
||||
categories={categories}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{tags && (
|
||||
<section className='mt-4'>
|
||||
<div className='text-sm py-2 px-2 flex flex-nowrap justify-between font-light dark:text-gray-200'>
|
||||
<div className='text-gray-600 dark:text-gray-200'>
|
||||
<i className='mr-2 fas fa-tag' />
|
||||
{locale.COMMON.TAGS}
|
||||
</div>
|
||||
<Link
|
||||
href={'/tag'}
|
||||
passHref
|
||||
className='text-gray-400 hover:text-black dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
</Link>
|
||||
</div>
|
||||
<div className='p-2'>
|
||||
<TagGroups tags={tags} currentTag={currentTag} />
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<div id='top-nav'>
|
||||
<SearchDrawer cRef={searchDrawer} slot={searchDrawerSlot} />
|
||||
{/* 导航栏 */}
|
||||
<div
|
||||
id='sticky-nav'
|
||||
className={
|
||||
'flex justify-center top-0 shadow-none fixed bg-none dark:bg-hexo-black-gray text-gray-200 w-full z-30 transform transition-all duration-200'
|
||||
}>
|
||||
<div className='w-full max-w-6xl flex justify-between items-center px-4 py-2'>
|
||||
{/* 左侧功能 */}
|
||||
<div className='justify-start items-center block lg:hidden '>
|
||||
<div
|
||||
onClick={toggleMenuOpen}
|
||||
className='w-8 justify-center items-center h-8 cursor-pointer flex lg:hidden'>
|
||||
{isOpen ? (
|
||||
<i className='fas fa-times' />
|
||||
) : (
|
||||
<i className='fas fa-bars' />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex'>
|
||||
<Logo {...props} />
|
||||
</div>
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 justify-end items-center flex'>
|
||||
<div className='hidden lg:flex'>
|
||||
{' '}
|
||||
<MenuListTop {...props} />
|
||||
</div>
|
||||
{showSearchButton && <SearchButton />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SideBarDrawer isOpen={isOpen} onClose={toggleMenuClose}>
|
||||
<SideBar {...props} />
|
||||
</SideBarDrawer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Header
|
||||
@@ -5,7 +5,7 @@ import { siteConfig } from '@/lib/config'
|
||||
/**
|
||||
* 文章背景图
|
||||
*/
|
||||
export default function PostHeader({ post, siteInfo }) {
|
||||
export default function PostHero({ post, siteInfo }) {
|
||||
const headerImage = post?.pageCoverThumbnail
|
||||
? post?.pageCoverThumbnail
|
||||
: siteInfo?.pageCover
|
||||
34
themes/matery/components/SearchButton.js
Normal file
34
themes/matery/components/SearchButton.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useMateryGlobal } from '..'
|
||||
|
||||
/**
|
||||
* 搜索按钮
|
||||
* @returns
|
||||
*/
|
||||
export default function SearchButton(props) {
|
||||
const { locale } = useGlobal()
|
||||
const router = useRouter()
|
||||
const { searchModal } = useMateryGlobal()
|
||||
|
||||
function handleSearch() {
|
||||
if (siteConfig('ALGOLIA_APP_ID')) {
|
||||
searchModal.current.openSearch()
|
||||
} else {
|
||||
router.push('/search')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
onClick={handleSearch}
|
||||
title={locale.NAV.SEARCH}
|
||||
alt={locale.NAV.SEARCH}
|
||||
className='cursor-pointer dark:text-white hover:bg-black hover:bg-opacity-10 rounded-full w-10 h-10 flex justify-center items-center duration-200 transition-all'>
|
||||
<i title={locale.NAV.SEARCH} className='fa-solid fa-magnifying-glass' />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import CategoryGroup from './CategoryGroup'
|
||||
import Logo from './Logo'
|
||||
import SearchDrawer from './SearchDrawer'
|
||||
import TagGroups from './TagGroups'
|
||||
import { MenuListTop } from './MenuListTop'
|
||||
import SideBarDrawer from '@/components/SideBarDrawer'
|
||||
import SideBar from './SideBar'
|
||||
import throttle from 'lodash.throttle'
|
||||
|
||||
let windowTop = 0
|
||||
|
||||
/**
|
||||
* 顶部导航
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const TopNav = props => {
|
||||
const { tags, currentTag, categories, currentCategory } = props
|
||||
const { locale } = useGlobal()
|
||||
const searchDrawer = useRef()
|
||||
const { isDarkMode } = useGlobal()
|
||||
const throttleMs = 200
|
||||
const scrollTrigger = useCallback(throttle(() => {
|
||||
requestAnimationFrame(() => {
|
||||
const scrollS = window.scrollY
|
||||
const nav = document.querySelector('#sticky-nav')
|
||||
const header = document.querySelector('#header')
|
||||
const showNav = scrollS <= windowTop || scrollS < 5 || (header && scrollS <= header.clientHeight * 2)// 非首页无大图时影藏顶部 滚动条置顶时隐藏// 非首页无大图时影藏顶部 滚动条置顶时隐藏
|
||||
// 是否将导航栏透明
|
||||
const navTransparent = header && scrollS < 300 // 透明导航条的条件
|
||||
|
||||
if (navTransparent) {
|
||||
nav && nav.classList.replace('bg-indigo-700', 'bg-none')
|
||||
nav && nav.classList.replace('text-black', 'text-white')
|
||||
nav && nav.classList.replace('shadow-xl', 'shadow-none')
|
||||
nav && nav.classList.replace('dark:bg-hexo-black-gray', 'transparent')
|
||||
} else {
|
||||
nav && nav.classList.replace('bg-none', 'bg-indigo-700')
|
||||
nav && nav.classList.replace('text-white', 'text-black')
|
||||
nav && nav.classList.replace('shadow-none', 'shadow-xl')
|
||||
nav && nav.classList.replace('transparent', 'dark:bg-hexo-black-gray')
|
||||
}
|
||||
|
||||
if (!showNav) {
|
||||
nav && nav.classList.replace('top-0', '-top-20')
|
||||
windowTop = scrollS
|
||||
} else {
|
||||
nav && nav.classList.replace('-top-20', 'top-0')
|
||||
windowTop = scrollS
|
||||
}
|
||||
navDarkMode()
|
||||
})
|
||||
}, throttleMs))
|
||||
|
||||
const navDarkMode = () => {
|
||||
const nav = document.getElementById('sticky-nav')
|
||||
const header = document.querySelector('#header')
|
||||
if (!isDarkMode && nav && header) {
|
||||
if (window.scrollY < header.clientHeight) {
|
||||
nav?.classList?.add('dark')
|
||||
} else {
|
||||
nav?.classList?.remove('dark')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 监听滚动
|
||||
useEffect(() => {
|
||||
scrollTrigger()
|
||||
|
||||
window.addEventListener('scroll', scrollTrigger)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', scrollTrigger)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const [isOpen, changeShow] = useState(false)
|
||||
|
||||
const toggleMenuOpen = () => {
|
||||
changeShow(!isOpen)
|
||||
}
|
||||
|
||||
const toggleMenuClose = () => {
|
||||
changeShow(false)
|
||||
}
|
||||
|
||||
const searchDrawerSlot = <>
|
||||
{categories && (
|
||||
<section className='mt-8'>
|
||||
<div className='text-sm flex flex-nowrap justify-between font-light px-2'>
|
||||
<div className='text-gray-600 dark:text-gray-200'><i className='mr-2 fas fa-th-list' />{locale.COMMON.CATEGORY}</div>
|
||||
<Link
|
||||
href={'/category'}
|
||||
passHref
|
||||
className='mb-3 text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
<CategoryGroup currentCategory={currentCategory} categories={categories} />
|
||||
</section>
|
||||
)}
|
||||
|
||||
{tags && (
|
||||
<section className='mt-4'>
|
||||
<div className='text-sm py-2 px-2 flex flex-nowrap justify-between font-light dark:text-gray-200'>
|
||||
<div className='text-gray-600 dark:text-gray-200'><i className='mr-2 fas fa-tag' />{locale.COMMON.TAGS}</div>
|
||||
<Link
|
||||
href={'/tag'}
|
||||
passHref
|
||||
className='text-gray-400 hover:text-black dark:hover:text-white hover:underline cursor-pointer'>
|
||||
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
<div className='p-2'>
|
||||
<TagGroups tags={tags} currentTag={currentTag} />
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</>
|
||||
|
||||
return (
|
||||
<div id='top-nav'>
|
||||
<SearchDrawer cRef={searchDrawer} slot={searchDrawerSlot} />
|
||||
{/* 导航栏 */}
|
||||
<div id='sticky-nav' className={'flex justify-center top-0 shadow-none fixed bg-none dark:bg-hexo-black-gray text-gray-200 w-full z-30 transform transition-all duration-200'}>
|
||||
<div className='w-full max-w-6xl flex justify-between items-center px-4 py-2'>
|
||||
{/* 左侧功能 */}
|
||||
<div className='justify-start items-center block lg:hidden '>
|
||||
<div onClick={toggleMenuOpen} className='w-8 justify-center items-center h-8 cursor-pointer flex lg:hidden'>
|
||||
{isOpen ? <i className='fas fa-times' /> : <i className='fas fa-bars' />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex'>
|
||||
<Logo {...props} />
|
||||
</div>
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 justify-end items-center '>
|
||||
<div className='hidden lg:flex'> <MenuListTop {...props} /></div>
|
||||
<div className='block lg:hidden'><Link href={'/search'} passHref>
|
||||
<i className='fas fa-search' />
|
||||
</Link></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<SideBarDrawer isOpen={isOpen} onClose={toggleMenuClose}>
|
||||
<SideBar {...props} />
|
||||
</SideBarDrawer>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default TopNav
|
||||
@@ -9,9 +9,10 @@ import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { loadWowJS } from '@/lib/plugins/wow'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
import { createContext, useContext, useEffect, useRef } from 'react'
|
||||
import Announcement from './components/Announcement'
|
||||
import ArticleAdjacent from './components/ArticleAdjacent'
|
||||
import ArticleCopyright from './components/ArticleCopyright'
|
||||
@@ -24,16 +25,25 @@ import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import Card from './components/Card'
|
||||
import CatalogWrapper from './components/CatalogWrapper'
|
||||
import Footer from './components/Footer'
|
||||
import Header from './components/Header'
|
||||
import Hero from './components/Hero'
|
||||
import JumpToCommentButton from './components/JumpToCommentButton'
|
||||
import PostHeader from './components/PostHeader'
|
||||
import PostHero from './components/PostHero'
|
||||
import RightFloatButtons from './components/RightFloatButtons'
|
||||
import SearchNave from './components/SearchNav'
|
||||
import TagItemMiddle from './components/TagItemMiddle'
|
||||
import TopNav from './components/TopNav'
|
||||
import CONFIG from './config'
|
||||
import { Style } from './style'
|
||||
|
||||
const AlgoliaSearchModal = dynamic(
|
||||
() => import('@/components/AlgoliaSearchModal'),
|
||||
{ ssr: false }
|
||||
)
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalMatery = createContext()
|
||||
export const useMateryGlobal = () => useContext(ThemeGlobalMatery)
|
||||
|
||||
/**
|
||||
* 基础布局
|
||||
* 采用左右两侧布局,移动端使用顶部导航栏
|
||||
@@ -60,74 +70,59 @@ const LayoutBase = props => {
|
||||
router.route === '/' ? (
|
||||
<Hero {...props} />
|
||||
) : post && !fullWidth ? (
|
||||
<PostHeader {...props} />
|
||||
<PostHero {...props} />
|
||||
) : null
|
||||
|
||||
const floatRightBottom = post ? <JumpToCommentButton /> : null
|
||||
|
||||
// Algolia搜索框
|
||||
const searchModal = useRef(null)
|
||||
|
||||
return (
|
||||
<div
|
||||
id='theme-matery'
|
||||
className={`${siteConfig('FONT_STYLE')} min-h-screen flex flex-col justify-between bg-hexo-background-gray dark:bg-black w-full scroll-smooth`}>
|
||||
<Style />
|
||||
<ThemeGlobalMatery.Provider value={{ searchModal }}>
|
||||
<div
|
||||
id='theme-matery'
|
||||
className={`${siteConfig('FONT_STYLE')} min-h-screen flex flex-col justify-between bg-hexo-background-gray dark:bg-black w-full scroll-smooth`}>
|
||||
<Style />
|
||||
|
||||
{/* 顶部导航栏 */}
|
||||
<TopNav {...props} />
|
||||
{/* 顶部导航栏 */}
|
||||
<Header {...props} />
|
||||
|
||||
{/* 顶部嵌入 */}
|
||||
{/* <Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 -translate-y-16"
|
||||
enterTo="opacity-100 w-full"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 translate-y-16"
|
||||
unmount={false}
|
||||
> */}
|
||||
{headerSlot}
|
||||
{/* </Transition> */}
|
||||
{/* 顶部嵌入 */}
|
||||
{headerSlot}
|
||||
|
||||
<main
|
||||
id='wrapper'
|
||||
className={`${siteConfig('MATERY_HOME_BANNER_ENABLE', null, CONFIG) ? '' : 'pt-16'} flex-1 w-full py-8 md:px-8 lg:px-24 relative`}>
|
||||
{/* 嵌入区域 */}
|
||||
<div
|
||||
id='container-slot'
|
||||
className={`w-full ${fullWidth ? '' : 'max-w-6xl'} ${post && ' lg:max-w-3xl 2xl:max-w-4xl '} mt-6 px-3 mx-auto lg:flex lg:space-x-4 justify-center relative z-10`}>
|
||||
{containerSlot}
|
||||
<main
|
||||
id='wrapper'
|
||||
className={`${siteConfig('MATERY_HOME_BANNER_ENABLE', null, CONFIG) ? '' : 'pt-16'} flex-1 w-full py-8 md:px-8 lg:px-24 relative`}>
|
||||
{/* 嵌入区域 */}
|
||||
<div
|
||||
id='container-slot'
|
||||
className={`w-full ${fullWidth ? '' : 'max-w-6xl'} ${post && ' lg:max-w-3xl 2xl:max-w-4xl '} mt-6 px-3 mx-auto lg:flex lg:space-x-4 justify-center relative z-10`}>
|
||||
{containerSlot}
|
||||
</div>
|
||||
|
||||
<div
|
||||
id='container-inner'
|
||||
className={`w-full min-h-fit ${fullWidth ? '' : 'max-w-6xl'} mx-auto lg:flex lg:space-x-4 justify-center relative z-10`}>
|
||||
{children}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{/* 左下角悬浮 */}
|
||||
<div className='bottom-4 -left-14 fixed justify-end z-40'>
|
||||
<Live2D />
|
||||
</div>
|
||||
|
||||
<div
|
||||
id='container-inner'
|
||||
className={`w-full min-h-fit ${fullWidth ? '' : 'max-w-6xl'} mx-auto lg:flex lg:space-x-4 justify-center relative z-10`}>
|
||||
{/* <Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter='transition ease-in-out duration-700 transform order-first'
|
||||
enterFrom='opacity-0 translate-y-16'
|
||||
enterTo='opacity-100 w-full'
|
||||
leave='transition ease-in-out duration-300 transform'
|
||||
leaveFrom='opacity-100 translate-y-0'
|
||||
leaveTo='opacity-0 -translate-y-16'
|
||||
unmount={false}> */}
|
||||
{children}
|
||||
{/* </Transition> */}
|
||||
</div>
|
||||
</main>
|
||||
{/* 右下角悬浮 */}
|
||||
<RightFloatButtons {...props} floatRightBottom={floatRightBottom} />
|
||||
|
||||
{/* 左下角悬浮 */}
|
||||
<div className='bottom-4 -left-14 fixed justify-end z-40'>
|
||||
<Live2D />
|
||||
{/* 全文搜索 */}
|
||||
<AlgoliaSearchModal cRef={searchModal} {...props} />
|
||||
|
||||
{/* 页脚 */}
|
||||
<Footer title={siteConfig('TITLE')} />
|
||||
</div>
|
||||
|
||||
{/* 右下角悬浮 */}
|
||||
<RightFloatButtons {...props} floatRightBottom={floatRightBottom} />
|
||||
|
||||
{/* 页脚 */}
|
||||
<Footer title={siteConfig('TITLE')} />
|
||||
</div>
|
||||
</ThemeGlobalMatery.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user