mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-29 23:16:51 +00:00
加入transition过度动画
This commit is contained in:
@@ -4,7 +4,7 @@ import Link from 'next/link'
|
||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
|
||||
const BlogPostCard = ({ post }) => {
|
||||
const showPageCover = CONFIG_EXAMPLE.POST_LIST_COVER
|
||||
const showPageCover = CONFIG_EXAMPLE.POST_LIST_COVER && post?.pageCoverThumbnail
|
||||
|
||||
return <article className={`${showPageCover ? 'flex md:flex-row flex-col-reverse' : ''} replace mb-12 `}>
|
||||
<div className={`${showPageCover ? 'md:w-7/12' : ''}`}>
|
||||
|
||||
@@ -26,7 +26,7 @@ export const MenuItemDrop = ({ link }) => {
|
||||
{/* 子菜单 */}
|
||||
{hasSubMenu && <ul className={`${show ? 'visible opacity-100 top-12' : 'invisible opacity-0 top-10'} border-gray-100 bg-white dark:bg-black dark:border-gray-800 transition-all duration-300 z-20 absolute block drop-shadow-lg `}>
|
||||
{link.subMenus.map((sLink, index) => {
|
||||
return <li key={index} className='not:last-child:border-b-0 border-b text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-2'>
|
||||
return <li key={index} className='not:last-child:border-b-0 border-b text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-3'>
|
||||
<Link href={sLink.to}>
|
||||
<span className='text-sm text-nowrap font-extralight'>{link?.icon && <i className={sLink?.icon} > </i>}{sLink.title}</span>
|
||||
</Link>
|
||||
|
||||
@@ -21,11 +21,11 @@ import ShareBar from '@/components/ShareBar'
|
||||
import SearchInput from './components/SearchInput'
|
||||
import Mark from 'mark.js'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import LoadingCover from './components/LoadingCover'
|
||||
import BlogListGroupByDate from './components/BlogListGroupByDate'
|
||||
import CategoryItem from './components/CategoryItem'
|
||||
import TagItem from './components/TagItem'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
/**
|
||||
* 基础布局框架
|
||||
@@ -38,6 +38,14 @@ const LayoutBase = props => {
|
||||
const { children, meta, slotTop } = props
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
// 增加一个状态以触发 Transition 组件的动画
|
||||
// const [showTransition, setShowTransition] = useState(true)
|
||||
// useEffect(() => {
|
||||
// // 当 location 或 children 发生变化时,触发动画
|
||||
// setShowTransition(false)
|
||||
// setTimeout(() => setShowTransition(true), 5)
|
||||
// }, [onLoading])
|
||||
|
||||
return (
|
||||
<div id='theme-example' className='dark:text-gray-300 bg-white dark:bg-black'>
|
||||
{/* 网页SEO信息 */}
|
||||
@@ -59,9 +67,21 @@ const LayoutBase = props => {
|
||||
|
||||
{/* 内容 */}
|
||||
<div className='w-full max-w-3xl xl:px-14 lg:px-4 '>
|
||||
{/* 嵌入模块 */}
|
||||
{slotTop}
|
||||
{onLoading ? <LoadingCover /> : children}
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{/* 嵌入模块 */}
|
||||
{slotTop}
|
||||
{children}
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
{/* 侧边栏 */}
|
||||
|
||||
@@ -28,11 +28,10 @@ export default function ArticleDetail(props) {
|
||||
<img alt={post.title} src={post?.pageCover} className='object-center w-full' />
|
||||
</div>
|
||||
)}
|
||||
<article itemScope itemType="https://schema.org/Movie"
|
||||
className="subpixel-antialiased overflow-y-hidden py-10 px-5 lg:pt-24 md:px-32 dark:border-gray-700 bg-white dark:bg-hexo-black-gray"
|
||||
>
|
||||
|
||||
<header className='animate__slideInDown animate__animated'>
|
||||
<article itemScope itemType="https://schema.org/Movie" className="subpixel-antialiased overflow-y-hidden py-10 px-5 lg:pt-24 md:px-32 dark:border-gray-700 bg-white dark:bg-hexo-black-gray" >
|
||||
|
||||
<header>
|
||||
|
||||
{/* 文章Title */}
|
||||
<div className="font-bold text-4xl text-black dark:text-white">
|
||||
@@ -41,7 +40,6 @@ export default function ArticleDetail(props) {
|
||||
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
|
||||
{post?.category && (<>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
|
||||
@@ -37,7 +37,7 @@ const TopNav = props => {
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 flex justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
|
||||
<div onClick={toggleMenuOpen} className='cursor-pointer'>
|
||||
<div onClick={toggleMenuOpen} className='cursor-pointer text-lg p-2'>
|
||||
{isOpen ? <i className='fas fa-times' /> : <i className='fas fa-bars' />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@ const FUKA_CONFIG = {
|
||||
MENU_ARCHIVE: true, // 显示归档
|
||||
MENU_SEARCH: false, // 显示搜索
|
||||
|
||||
SIDEBAR_COLLAPSE_DEFAULT: false // 侧边栏默认折叠
|
||||
SIDEBAR_OPEN_SATUS_DEFAULT: true // 侧边栏默认开启
|
||||
|
||||
}
|
||||
export default FUKA_CONFIG
|
||||
|
||||
@@ -8,7 +8,6 @@ import Live2D from '@/components/Live2D'
|
||||
import BLOG from '@/blog.config'
|
||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import LoadingCover from './components/LoadingCover'
|
||||
import BlogListPage from './components/BlogListPage'
|
||||
import BlogListScroll from './components/BlogListScroll'
|
||||
import BlogArchiveItem from './components/BlogPostArchive'
|
||||
@@ -16,9 +15,10 @@ import ArticleDetail from './components/ArticleDetail'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import TagItemMini from './components/TagItemMini'
|
||||
import { useRouter } from 'next/router'
|
||||
import { createContext, useContext, useEffect, useMemo, useState } from 'react'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import Mark from 'mark.js'
|
||||
import Link from 'next/link'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalFukasawa = createContext()
|
||||
@@ -42,21 +42,14 @@ const LayoutBase = (props) => {
|
||||
const { children, headerSlot, meta } = props
|
||||
const leftAreaSlot = <Live2D />
|
||||
const { onLoading } = useGlobal()
|
||||
// 侧边栏折叠从 本地存储中获取 open 状态的初始值
|
||||
|
||||
// 侧边栏折叠从 本地存储中获取 open 状态的初始值
|
||||
const [open, setOpen] = useState(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
return localStorage.getItem('fukasawa-sidebarOpen') === 'true' || FUKA_CONFIG.SIDEBAR_COLLAPSE_DEFAULT
|
||||
return localStorage.getItem('fukasawa-sidebarOpen') === 'true' || FUKA_CONFIG.SIDEBAR_OPEN_SATUS_DEFAULT
|
||||
}
|
||||
return FUKA_CONFIG.SIDEBAR_COLLAPSE_DEFAULT
|
||||
return FUKA_CONFIG.SIDEBAR_OPEN_SATUS_DEFAULT
|
||||
})
|
||||
const memoizedOpen = useMemo(() => open, [])
|
||||
|
||||
console.log('base', FUKA_CONFIG.SIDEBAR_COLLAPSE_DEFAULT, open, memoizedOpen)
|
||||
|
||||
if (isBrowser()) {
|
||||
loadExternalResource('/css/theme-fukasawa.css', 'css')
|
||||
}
|
||||
|
||||
// 在组件卸载时保存 open 状态到本地存储中
|
||||
useEffect(() => {
|
||||
@@ -65,6 +58,18 @@ const LayoutBase = (props) => {
|
||||
}
|
||||
}, [open])
|
||||
|
||||
// 增加一个状态以触发 Transition 组件的动画
|
||||
const [showTransition, setShowTransition] = useState(true)
|
||||
useEffect(() => {
|
||||
// 当 location 或 children 发生变化时,触发动画
|
||||
setShowTransition(false)
|
||||
setTimeout(() => setShowTransition(true), 5)
|
||||
}, [onLoading])
|
||||
|
||||
if (isBrowser()) {
|
||||
loadExternalResource('/css/theme-fukasawa.css', 'css')
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeGlobalFukasawa.Provider value={{ open, setOpen }}>
|
||||
|
||||
@@ -78,8 +83,23 @@ const LayoutBase = (props) => {
|
||||
|
||||
<main id='wrapper' className='relative flex w-full py-8 justify-center bg-day dark:bg-night'>
|
||||
<div id='container-inner' className='2xl:max-w-6xl md:max-w-4xl w-full relative z-10'>
|
||||
<div> {headerSlot} </div>
|
||||
<div> {onLoading ? <LoadingCover /> : children} </div>
|
||||
|
||||
<Transition
|
||||
show={showTransition}
|
||||
appear={true}
|
||||
className="w-full"
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
<div> {headerSlot} </div>
|
||||
<div> {children} </div>
|
||||
|
||||
</Transition>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ export const MenuItemDrop = ({ link }) => {
|
||||
{/* 子菜单 */}
|
||||
{hasSubMenu && <ul className={`${show ? 'visible opacity-100 top-12 ' : 'invisible opacity-0 top-10 '} border-gray-100 bg-white dark:bg-black dark:border-gray-800 transition-all duration-300 z-20 absolute block drop-shadow-lg `}>
|
||||
{link?.subMenus?.map((sLink, index) => {
|
||||
return <li key={index} className='not:last-child:border-b-0 border-b text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-2'>
|
||||
return <li key={index} className='not:last-child:border-b-0 border-b text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-3'>
|
||||
<Link href={sLink.to}>
|
||||
<span className='text-xs font-extralight'>{link?.icon && <i className={sLink?.icon} > </i>}{sLink.title}</span>
|
||||
</Link>
|
||||
|
||||
@@ -19,7 +19,6 @@ import PageNavDrawer from './components/PageNavDrawer'
|
||||
import FloatTocButton from './components/FloatTocButton'
|
||||
import { AdSlot } from '@/components/GoogleAdsense'
|
||||
import JumpToTopButton from './components/JumpToTopButton'
|
||||
import LoadingCover from './components/LoadingCover'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import CategoryItem from './components/CategoryItem'
|
||||
import TagItemMini from './components/TagItemMini'
|
||||
@@ -28,6 +27,7 @@ import Comment from '@/components/Comment'
|
||||
import TocDrawer from './components/TocDrawer'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
// 主题全局变量
|
||||
const ThemeGlobalGitbook = createContext()
|
||||
@@ -81,7 +81,20 @@ const LayoutBase = (props) => {
|
||||
<div id='container-inner' className='w-full px-7 max-w-3xl justify-center mx-auto'>
|
||||
{slotTop}
|
||||
<AdSlot type='in-article' />
|
||||
{onLoading ? <LoadingCover /> : children}
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{children}
|
||||
</Transition>
|
||||
|
||||
<AdSlot type='in-article' />
|
||||
{/* 回顶按钮 */}
|
||||
<JumpToTopButton />
|
||||
@@ -89,7 +102,7 @@ const LayoutBase = (props) => {
|
||||
|
||||
{/* 底部 */}
|
||||
<div className='md:hidden'>
|
||||
<Footer {...props}/>
|
||||
<Footer {...props} />
|
||||
</div>
|
||||
<div className='text-center'>
|
||||
<AdSlot type='native' />
|
||||
@@ -144,22 +157,21 @@ const LayoutBase = (props) => {
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
router.push(CONFIG_GITBOOK.INDEX_PAGE).then(() => {
|
||||
// console.log('跳转到指定首页', CONFIG_GITBOOK.INDEX_PAGE)
|
||||
setTimeout(() => {
|
||||
if (isBrowser()) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
console.log('请检查您的Notion数据库中是否包含此slug页面: ', CONFIG_GITBOOK.INDEX_PAGE)
|
||||
const containerInner = document.getElementById('container-inner')
|
||||
const newHTML = `<h1 class="text-3xl pt-12 dark:text-gray-300">配置有误</h1><blockquote class="notion-quote notion-block-ce76391f3f2842d386468ff1eb705b92"><div>请在您的notion中添加一个slug为${CONFIG_GITBOOK.INDEX_PAGE}的文章</div></blockquote>`
|
||||
containerInner?.insertAdjacentHTML('afterbegin', newHTML)
|
||||
}
|
||||
router.push(CONFIG_GITBOOK.INDEX_PAGE).then(() => {
|
||||
// console.log('跳转到指定首页', CONFIG_GITBOOK.INDEX_PAGE)
|
||||
setTimeout(() => {
|
||||
if (isBrowser()) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
console.log('请检查您的Notion数据库中是否包含此slug页面: ', CONFIG_GITBOOK.INDEX_PAGE)
|
||||
const containerInner = document.getElementById('container-inner')
|
||||
const newHTML = `<h1 class="text-3xl pt-12 dark:text-gray-300">配置有误</h1><blockquote class="notion-quote notion-block-ce76391f3f2842d386468ff1eb705b92"><div>请在您的notion中添加一个slug为${CONFIG_GITBOOK.INDEX_PAGE}的文章</div></blockquote>`
|
||||
containerInner?.insertAdjacentHTML('afterbegin', newHTML)
|
||||
}
|
||||
}, 7 * 1000)
|
||||
})
|
||||
}, [])
|
||||
}
|
||||
}, 7 * 1000)
|
||||
})
|
||||
|
||||
return <LayoutBase {...props}></LayoutBase>
|
||||
}
|
||||
|
||||
|
||||
@@ -21,18 +21,10 @@ export default function HeaderArticle({ post, siteInfo }) {
|
||||
return (
|
||||
<div
|
||||
id="header"
|
||||
data-aos="fade-down"
|
||||
data-aos-duration="300"
|
||||
data-aos-once="true"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
className="w-full h-96 relative md:flex-shrink-0 overflow-hidden bg-cover bg-center bg-no-repeat z-10"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
>
|
||||
<header id='article-header-cover'
|
||||
data-aos="fade-down"
|
||||
data-aos-duration="300"
|
||||
data-aos-once="true"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
className="bg-black bg-opacity-70 absolute top-0 w-full h-96 py-10 flex justify-center items-center ">
|
||||
|
||||
<div className='mt-10'>
|
||||
|
||||
@@ -3,22 +3,30 @@ import { useRouter } from 'next/router'
|
||||
import Card from './Card'
|
||||
import SocialButton from './SocialButton'
|
||||
import MenuGroupCard from './MenuGroupCard'
|
||||
export function InfoCard (props) {
|
||||
|
||||
/**
|
||||
* 社交信息卡
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
export function InfoCard(props) {
|
||||
const { className, siteInfo } = props
|
||||
const router = useRouter()
|
||||
return <Card className={className}>
|
||||
<div
|
||||
className='justify-center items-center flex py-6 dark:text-gray-100 transform duration-200 cursor-pointer'
|
||||
onClick={() => {
|
||||
router.push('/')
|
||||
}}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={siteInfo?.icon} className='rounded-full' width={120} alt={BLOG.AUTHOR}/>
|
||||
</div>
|
||||
<div className='font-medium text-center text-xl pb-4'>{BLOG.AUTHOR}</div>
|
||||
<div className='text-sm text-center'>{BLOG.BIO}</div>
|
||||
<MenuGroupCard {...props}/>
|
||||
<SocialButton />
|
||||
</Card>
|
||||
return (
|
||||
<Card className={className}>
|
||||
<div
|
||||
className='justify-center items-center flex py-6 dark:text-gray-100 transform duration-200 cursor-pointer'
|
||||
onClick={() => {
|
||||
router.push('/')
|
||||
}}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={siteInfo?.icon} className='rounded-full' width={120} alt={BLOG.AUTHOR} />
|
||||
</div>
|
||||
<div className='font-medium text-center text-xl pb-4'>{BLOG.AUTHOR}</div>
|
||||
<div className='text-sm text-center'>{BLOG.BIO}</div>
|
||||
<MenuGroupCard {...props} />
|
||||
<SocialButton />
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ export const MenuItemDrop = ({ link }) => {
|
||||
{/* 子菜单 */}
|
||||
{hasSubMenu && <ul style={{ backdropFilter: 'blur(3px)' }} className={`${show ? 'visible opacity-100 top-12' : 'invisible opacity-0 top-20'} drop-shadow-md overflow-hidden rounded-md bg-white transition-all duration-300 z-20 absolute block `}>
|
||||
{link.subMenus.map((sLink, index) => {
|
||||
return <li key={index} className='cursor-pointer hover:bg-indigo-300 text-gray-900 hover:text-black tracking-widest transition-all duration-200 dark:border-gray-800 py-1 pr-6 pl-2'>
|
||||
return <li key={index} className='cursor-pointer hover:bg-indigo-300 text-gray-900 hover:text-black tracking-widest transition-all duration-200 dark:border-gray-800 py-1 pr-6 pl-3'>
|
||||
<Link href={sLink.to}>
|
||||
<span className='text-sm text-nowrap font-extralight'>{link?.icon && <i className={sLink?.icon} > </i>}{sLink.title}</span>
|
||||
</Link>
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useEffect, useRef } from 'react'
|
||||
import Footer from './components/Footer'
|
||||
import SideRight from './components/SideRight'
|
||||
import TopNav from './components/TopNav'
|
||||
import LoadingCover from './components/LoadingCover'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import BLOG from '@/blog.config'
|
||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||
@@ -32,6 +31,7 @@ import ShareBar from '@/components/ShareBar'
|
||||
import TagItemMini from './components/TagItemMini'
|
||||
import Link from 'next/link'
|
||||
import SlotBar from './components/SlotBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
||||
@@ -57,16 +57,41 @@ const LayoutBase = props => {
|
||||
<TopNav {...props} />
|
||||
|
||||
{/* 顶部嵌入 */}
|
||||
{headerSlot}
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 -translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{headerSlot}
|
||||
</Transition>
|
||||
|
||||
{/* 主区块 */}
|
||||
<main id="wrapper" className={`${CONFIG_HEXO.HOME_BANNER_ENABLE ? '' : 'pt-16'} bg-hexo-background-gray dark:bg-black w-full py-8 md:px-8 lg:px-24 min-h-screen relative`}>
|
||||
<div id="container-inner" className={(BLOG.LAYOUT_SIDEBAR_REVERSE ? 'flex-row-reverse' : '') + ' w-full mx-auto lg:flex lg:space-x-4 justify-center relative z-10'} >
|
||||
<div className={`${className || ''} w-full max-w-4xl h-full `}>
|
||||
{/* 主区上部嵌入 */}
|
||||
{slotTop}
|
||||
|
||||
{onLoading ? <LoadingCover /> : children}
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{/* 主区上部嵌入 */}
|
||||
{slotTop}
|
||||
|
||||
{children}
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
{/* 右侧栏 */}
|
||||
|
||||
@@ -4,23 +4,15 @@ export default function HeaderArticle({ post, siteInfo }) {
|
||||
const headerImage = post?.pageCoverThumbnail ? post?.pageCoverThumbnail : siteInfo?.pageCover
|
||||
const title = post?.title
|
||||
return (
|
||||
<div
|
||||
data-aos="fade-down"
|
||||
data-aos-duration="300"
|
||||
data-aos-once="true"
|
||||
data-aos-anchor-placement="top-center"
|
||||
id='header' className="flex h-96 justify-center align-middle items-center w-full relative bg-black">
|
||||
<div id='header' className="flex h-96 justify-center align-middle items-center w-full relative bg-black">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
{/* <img
|
||||
src={headerImage}
|
||||
alt={title}
|
||||
className="opacity-50 dark:opacity-40 h-full w-full object-cover"
|
||||
/> */}
|
||||
<Image alt={title} src={headerImage} fill
|
||||
style={{ objectFit: 'cover' }}
|
||||
className='opacity-50'
|
||||
placeholder='blur'
|
||||
blurDataURL='/bg_image.jpg' />
|
||||
<Image alt={title} src={headerImage} fill style={{ objectFit: 'cover' }} className='opacity-50'
|
||||
placeholder='blur' blurDataURL='/bg_image.jpg' />
|
||||
<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">
|
||||
{title}
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@ export const MenuItemDrop = ({ link }) => {
|
||||
{/* 子菜单 */}
|
||||
{hasSubMenu && <ul style={{ backdropFilter: 'blur(3px)' }} className={`${show ? 'visible opacity-100 top-12' : 'invisible opacity-0 top-20'} drop-shadow-md overflow-hidden rounded-md bg-white transition-all duration-300 z-20 absolute block `}>
|
||||
{link.subMenus.map(sLink => {
|
||||
return <li key={sLink.id} className='cursor-pointer hover:bg-indigo-300 text-gray-900 hover:text-black tracking-widest transition-all duration-200 dark:border-gray-800 py-1 pr-6 pl-2'>
|
||||
return <li key={sLink.id} className='cursor-pointer hover:bg-indigo-300 text-gray-900 hover:text-black tracking-widest transition-all duration-200 dark:border-gray-800 py-1 pr-6 pl-3'>
|
||||
<Link href={sLink.to}>
|
||||
<span className='text-sm text-nowrap font-extralight'>{link?.icon && <i className={sLink?.icon} > </i>}{sLink.title}</span>
|
||||
</Link>
|
||||
|
||||
@@ -2,7 +2,6 @@ import CONFIG_MATERY from './config_matery'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
import TopNav from './components/TopNav'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import LoadingCover from './components/LoadingCover'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import BLOG from '@/blog.config'
|
||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||
@@ -31,6 +30,7 @@ import BlogPostArchive from './components/BlogPostArchive'
|
||||
import Card from './components/Card'
|
||||
import JumpToCommentButton from './components/JumpToCommentButton'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
/**
|
||||
* 基础布局
|
||||
@@ -56,7 +56,19 @@ const LayoutBase = props => {
|
||||
<TopNav {...props} />
|
||||
|
||||
{/* 顶部嵌入 */}
|
||||
{headerSlot}
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 -translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{headerSlot}
|
||||
</Transition>
|
||||
|
||||
<main id="wrapper" className={`${CONFIG_MATERY.HOME_BANNER_ENABLE ? '' : 'pt-16'} flex-1 w-full py-8 md:px-8 lg:px-24 relative`}>
|
||||
{/* 嵌入区域 */}
|
||||
@@ -64,8 +76,21 @@ const LayoutBase = props => {
|
||||
{containerSlot}
|
||||
</div>
|
||||
|
||||
<div id="container-inner" className="w-full max-w-6xl mx-auto lg:flex lg:space-x-4 justify-center relative z-10">
|
||||
{onLoading ? <LoadingCover /> : children}
|
||||
<div id="container-inner" className="w-full min-h-fit 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 translate-y-0"
|
||||
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>
|
||||
|
||||
@@ -38,7 +38,7 @@ export const MenuItemDrop = ({ link }) => {
|
||||
{/* 子菜单 */}
|
||||
{hasSubMenu && <ul className={`${show ? 'visible opacity-100 top-12 ' : 'invisible opacity-0 top-10 '} border-gray-100 bg-white dark:bg-black dark:border-gray-800 transition-all duration-300 z-20 absolute block drop-shadow-lg `}>
|
||||
{link?.subMenus?.map(sLink => {
|
||||
return <li key={sLink.id} className='not:last-child:border-b-0 border-b text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-2'>
|
||||
return <li key={sLink.id} className='not:last-child:border-b-0 border-b text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-3'>
|
||||
<Link href={sLink.to}>
|
||||
<span className='text-xs font-extralight'>{link?.icon && <i className={sLink?.icon} > </i>}{sLink.title}</span>
|
||||
</Link>
|
||||
|
||||
@@ -15,7 +15,6 @@ import Live2D from '@/components/Live2D'
|
||||
import BLOG from '@/blog.config'
|
||||
import Announcement from './components/Announcement'
|
||||
import JumpToTopButton from './components/JumpToTopButton'
|
||||
import LoadingCover from './components/LoadingCover'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import Catalog from './components/Catalog'
|
||||
@@ -34,6 +33,7 @@ import CategoryItem from './components/CategoryItem'
|
||||
import TagItemMini from './components/TagItemMini'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import Link from 'next/link'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalMedium = createContext()
|
||||
@@ -69,9 +69,20 @@ const LayoutBase = props => {
|
||||
<TopNavBar {...props} />
|
||||
|
||||
<div id='container-inner' className='px-7 max-w-5xl justify-center mx-auto min-h-screen'>
|
||||
{slotTop}
|
||||
|
||||
{onLoading ? <LoadingCover /> : children}
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{slotTop}
|
||||
{children}
|
||||
</Transition>
|
||||
|
||||
<JumpToTopButton />
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,6 @@ import FloatDarkModeButton from './components/FloatDarkModeButton'
|
||||
import Footer from './components/Footer'
|
||||
import JumpToBottomButton from './components/JumpToBottomButton'
|
||||
import JumpToTopButton from './components/JumpToTopButton'
|
||||
import LoadingCover from './components/LoadingCover'
|
||||
import SideAreaLeft from './components/SideAreaLeft'
|
||||
import SideAreaRight from './components/SideAreaRight'
|
||||
import TopNav from './components/TopNav'
|
||||
@@ -27,6 +26,7 @@ import { useRouter } from 'next/router'
|
||||
import ArticleDetail from './components/ArticleDetail'
|
||||
import Link from 'next/link'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左中右三栏布局,移动端使用顶部导航栏
|
||||
@@ -88,7 +88,19 @@ const LayoutBase = (props) => {
|
||||
|
||||
{/* 中央内容 */}
|
||||
<section id='container-inner' className={`${CONFIG_NEXT.NAV_TYPE !== 'normal' ? 'mt-24' : ''} lg:max-w-3xl xl:max-w-4xl flex-grow md:mt-0 min-h-screen w-full relative z-10`} ref={targetRef}>
|
||||
{onLoading ? <LoadingCover /> : <> {children}</>}
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{children}
|
||||
</Transition>
|
||||
</section>
|
||||
|
||||
{/* 右侧栏样式 */}
|
||||
|
||||
@@ -31,7 +31,7 @@ export const MenuItemDrop = ({ link }) => {
|
||||
{/* 子菜单 */}
|
||||
{hasSubMenu && <ul className={`${show ? 'visible opacity-100 top-12 ' : 'invisible opacity-0 top-10 '} border-gray-100 bg-white dark:bg-black dark:border-gray-800 transition-all duration-300 z-20 absolute block drop-shadow-lg `}>
|
||||
{link.subMenus.map(sLink => {
|
||||
return <li key={sLink.id} className='not:last-child:border-b-0 border-b text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-2'>
|
||||
return <li key={sLink.id} className='not:last-child:border-b-0 border-b text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-3'>
|
||||
<Link href={sLink.to}>
|
||||
<span className='text-sm text-nowrap font-extralight'>{link?.icon && <i className={sLink?.icon} > </i>}{sLink.title}</span>
|
||||
</Link>
|
||||
|
||||
@@ -44,7 +44,7 @@ const Nav = props => {
|
||||
<div className="flex items-center">
|
||||
<Link href="/" aria-label={BLOG.title}>
|
||||
|
||||
<div className="h-6">
|
||||
<div className="h-6 w-6">
|
||||
{/* <SvgIcon/> */}
|
||||
{CONFIG_NOBELIUM.NAV_NOTION_ICON
|
||||
/* eslint-disable-next-line @next/next/no-img-element */
|
||||
|
||||
@@ -18,16 +18,15 @@ import Mark from 'mark.js'
|
||||
import { deepClone, isBrowser } from '@/lib/utils'
|
||||
import SearchNavBar from './components/SearchNavBar'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import { ArticleInfo } from './components/ArticleInfo'
|
||||
import Comment from '@/components/Comment'
|
||||
import { ArticleFooter } from './components/ArticleFooter'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
|
||||
import Link from 'next/link'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
||||
@@ -41,11 +40,6 @@ const LayoutBase = props => {
|
||||
const fullWidth = post?.fullWidth ?? false
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
const LoadingCover = <div id='cover-loading' className={`${onLoading ? 'z-50 opacity-50' : '-z-10 opacity-0'} pointer-events-none transition-all duration-300`}>
|
||||
<div className='w-full h-screen flex justify-center items-center'>
|
||||
<i className="fa-solid fa-spinner text-2xl text-black dark:text-white animate-spin"> </i>
|
||||
</div>
|
||||
</div>
|
||||
return (
|
||||
<div id='theme-nobelium' className='nobelium relative dark:text-gray-300 w-full bg-white dark:bg-black min-h-screen'>
|
||||
{/* SEO相关 */}
|
||||
@@ -56,10 +50,22 @@ const LayoutBase = props => {
|
||||
|
||||
{/* 主区 */}
|
||||
<main id='out-wrapper' className={`relative m-auto flex-grow w-full transition-all ${!fullWidth ? 'max-w-2xl px-4' : 'px-4 md:px-24'}`}>
|
||||
{/* 顶部插槽 */}
|
||||
{topSlot}
|
||||
|
||||
{onLoading ? LoadingCover : children}
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{/* 顶部插槽 */}
|
||||
{topSlot}
|
||||
{children}
|
||||
</Transition>
|
||||
|
||||
</main>
|
||||
|
||||
@@ -114,7 +120,7 @@ const LayoutPostList = props => {
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} topSlot={<BlogListBar {...props} setFilterKey={setFilterKey} />}>
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} posts={filteredBlogPosts}/> : <BlogListScroll {...props} posts={filteredBlogPosts}/>}
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} posts={filteredBlogPosts} /> : <BlogListScroll {...props} posts={filteredBlogPosts} />}
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import CONFIG_SIMPLE from './config_simple'
|
||||
|
||||
import { BlogListPage } from './components/BlogListPage'
|
||||
import { BlogListScroll } from './components/BlogListScroll'
|
||||
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
import Mark from 'mark.js'
|
||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import { ArticleInfo } from './components/ArticleInfo'
|
||||
@@ -27,6 +24,7 @@ import JumpToTopButton from './components/JumpToTopButton'
|
||||
import { Footer } from './components/Footer'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import SearchInput from './components/SearchInput'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
/**
|
||||
* 基础布局
|
||||
@@ -38,15 +36,6 @@ const LayoutBase = props => {
|
||||
const { children, meta, slotTop } = props
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
/**
|
||||
* 路由跳转时的遮罩
|
||||
*/
|
||||
const LoadingCover = <div id='cover-loading' className={`${onLoading ? 'z-50 opacity-50' : '-z-10 opacity-0'} pointer-events-none transition-all duration-300`}>
|
||||
<div className='w-full h-96 flex justify-center items-center'>
|
||||
<i className="fa-solid fa-spinner text-2xl text-black dark:text-white animate-spin"> </i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
if (isBrowser()) {
|
||||
loadExternalResource('/css/theme-simple.css', 'css')
|
||||
}
|
||||
@@ -64,9 +53,22 @@ const LayoutBase = props => {
|
||||
|
||||
{/* 主体 */}
|
||||
<div id='container-wrapper' className={(BLOG.LAYOUT_SIDEBAR_REVERSE ? 'flex-row-reverse' : '') + ' w-full flex-1 flex items-start max-w-9/10 mx-auto pt-12'}>
|
||||
<div id='container-inner ' className='w-full flex-grow'>
|
||||
{slotTop}
|
||||
{onLoading ? LoadingCover : children}
|
||||
<div id='container-inner ' className='w-full flex-grow min-h-fit'>
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{slotTop}
|
||||
|
||||
{children}
|
||||
</Transition>
|
||||
<AdSlot type='native' />
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user