mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
nav-bar
This commit is contained in:
@@ -1,73 +0,0 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import Logo from './Logo'
|
||||
|
||||
import { MenuListTop } from './MenuListTop'
|
||||
import throttle from 'lodash.throttle'
|
||||
/**
|
||||
* 顶部导航
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const Header = props => {
|
||||
const [isOpen, changeShow] = useState(false)
|
||||
const [fixedNav, setHeaderBgShow] = useState(false)
|
||||
const [whiteTitle, setWhiteTitle] = useState(false)
|
||||
|
||||
const toggleMenuOpen = () => {
|
||||
changeShow(!isOpen)
|
||||
}
|
||||
|
||||
// 监听滚动
|
||||
useEffect(() => {
|
||||
scrollTrigger()
|
||||
window.addEventListener('scroll', scrollTrigger)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', scrollTrigger)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const throttleMs = 200
|
||||
|
||||
/**
|
||||
* 根据滚动条,切换导航栏样式
|
||||
*/
|
||||
const scrollTrigger = useCallback(throttle(() => {
|
||||
const scrollS = window.scrollY
|
||||
const header = document.querySelector('#header')
|
||||
const postHeader = document.querySelector('#post-bg')
|
||||
|
||||
// 导航栏设置 白色背景
|
||||
if (header && scrollS > 0) {
|
||||
setHeaderBgShow(true)
|
||||
setWhiteTitle(false)
|
||||
} else {
|
||||
if (postHeader) {
|
||||
setWhiteTitle(true)
|
||||
}
|
||||
setHeaderBgShow(false)
|
||||
}
|
||||
}, throttleMs))
|
||||
|
||||
return (<>
|
||||
{/* 头条 */}
|
||||
<header id='header' className={' h-16 w-full z-20 '}>
|
||||
<nav className={`${fixedNav ? 'fixed bg-white' : 'relative bg-none'} ${whiteTitle ? 'text-white' : 'text-black'} h-16 top-0 w-full`}>
|
||||
<div className='flex h-full mx-auto justify-between items-center max-w-[86rem] px-8'>
|
||||
<div className='flex'>
|
||||
<Logo {...props} />
|
||||
</div>
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 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>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
</>)
|
||||
}
|
||||
|
||||
export default Header
|
||||
@@ -6,6 +6,8 @@ import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useImperativeHandle, useRef, useState } from 'react'
|
||||
import CONFIG from '../config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
/**
|
||||
* 顶部英雄区
|
||||
@@ -15,15 +17,28 @@ import CONFIG from '../config'
|
||||
* @returns
|
||||
*/
|
||||
const Hero = props => {
|
||||
const { onLoading } = useGlobal()
|
||||
return (
|
||||
<div id="hero-wrapper" className='recent-top-post-group w-full overflow-hidden select-none px-5 mb-4'>
|
||||
<hero id="hero" style={{ zIndex: 1 }} className="recent-post-top rounded-[12px] 2xl:px-5 recent-top-post-group max-w-[86rem] overflow-x-scroll w-full mx-auto flex-row flex-nowrap flex relative space-x-3" >
|
||||
{/* 左侧banner组 */}
|
||||
<BannerGroup {...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 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}
|
||||
>
|
||||
<hero id="hero" style={{ zIndex: 1 }} className="recent-post-top rounded-[12px] 2xl:px-5 recent-top-post-group max-w-[86rem] overflow-x-scroll w-full mx-auto flex-row flex-nowrap flex relative space-x-3" >
|
||||
{/* 左侧banner组 */}
|
||||
<BannerGroup {...props} />
|
||||
|
||||
{/* 右侧置顶文章组 */}
|
||||
<TopGroup {...props} />
|
||||
</hero>
|
||||
{/* 右侧置顶文章组 */}
|
||||
<TopGroup {...props} />
|
||||
</hero>
|
||||
</Transition>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -186,8 +201,8 @@ function TodayCard({ cRef }) {
|
||||
const [isCoverUp, setIsCoverUp] = useState(true)
|
||||
|
||||
/**
|
||||
* 外部可以调用此方法
|
||||
*/
|
||||
* 外部可以调用此方法
|
||||
*/
|
||||
useImperativeHandle(cRef, () => {
|
||||
return {
|
||||
coverUp: () => {
|
||||
@@ -197,18 +212,18 @@ function TodayCard({ cRef }) {
|
||||
})
|
||||
|
||||
/**
|
||||
* 点击更多
|
||||
* @param {*} e
|
||||
*/
|
||||
* 点击更多
|
||||
* @param {*} e
|
||||
*/
|
||||
function handleClickMore(e) {
|
||||
e.stopPropagation()
|
||||
setIsCoverUp(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击卡片跳转的链接
|
||||
* @param {*} e
|
||||
*/
|
||||
* 点击卡片跳转的链接
|
||||
* @param {*} e
|
||||
*/
|
||||
function handleCardClick(e) {
|
||||
router.push('https://tangly1024.com')
|
||||
}
|
||||
|
||||
79
themes/heo/components/NavBar.js
Normal file
79
themes/heo/components/NavBar.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import Logo from './Logo'
|
||||
|
||||
import { MenuListTop } from './MenuListTop'
|
||||
import throttle from 'lodash.throttle'
|
||||
/**
|
||||
* 顶部导航
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const NavBar = props => {
|
||||
const [isOpen, changeShow] = useState(false)
|
||||
const [fixedNav, setFixedNav] = useState(false)
|
||||
const [textWhite, setTextWhite] = useState(false)
|
||||
const [navBgWhite, setBgWhite] = useState(false)
|
||||
|
||||
const toggleMenuOpen = () => {
|
||||
changeShow(!isOpen)
|
||||
}
|
||||
|
||||
// 监听滚动
|
||||
useEffect(() => {
|
||||
scrollTrigger()
|
||||
window.addEventListener('scroll', scrollTrigger)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', scrollTrigger)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const throttleMs = 200
|
||||
|
||||
/**
|
||||
* 根据滚动条,切换导航栏样式
|
||||
*/
|
||||
const scrollTrigger = useCallback(throttle(() => {
|
||||
const scrollS = window.scrollY
|
||||
|
||||
// 导航栏设置 白色背景
|
||||
if (scrollS <= 0) {
|
||||
setFixedNav(false)
|
||||
setBgWhite(false)
|
||||
|
||||
// 文章详情页特殊处理
|
||||
const postHeader = document.querySelector('#post-bg')
|
||||
if (postHeader) {
|
||||
setFixedNav(true)
|
||||
setTextWhite(true)
|
||||
setBgWhite(false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 向下滚动后的导航样式
|
||||
setFixedNav(true)
|
||||
setTextWhite(false)
|
||||
setBgWhite(true)
|
||||
}, throttleMs))
|
||||
|
||||
return (<>
|
||||
{/* 头条 */}
|
||||
<nav id='nav' className={`${fixedNav ? 'fixed' : 'relative bg-none'} ${textWhite ? 'text-white ' : 'text-black'} ${navBgWhite ? 'bg-white' : 'bg-none'} z-20 h-16 top-0 w-full`}>
|
||||
<div className='flex h-full mx-auto justify-between items-center max-w-[86rem] px-8'>
|
||||
<div className='flex'>
|
||||
<Logo {...props} />
|
||||
</div>
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 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>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</>)
|
||||
}
|
||||
|
||||
export default NavBar
|
||||
@@ -17,15 +17,15 @@ export default function PostHeader({ post, siteInfo }) {
|
||||
return (
|
||||
<div id="post-bg" className="w-full h-[30rem] relative md:flex-shrink-0 overflow-hidden bg-cover bg-center bg-no-repeat z-10">
|
||||
|
||||
<header id='article-header-cover' style={{ backdropFilter: 'blur(15px)' }} className="bg-[#0060e0] absolute top-0 w-full h-full py-10 flex justify-center items-center ">
|
||||
<div id='article-header-cover' style={{ backdropFilter: 'blur(15px)' }} className="bg-[#0060e0] absolute top-0 w-full h-full py-10 flex justify-center items-center ">
|
||||
|
||||
<div id='post-cover-wrapper' style={{ filter: 'blur(15px)' }} className='opacity-50 rotate-12 translate-x-12 -mr-60'>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img id='post-cover' style={{ boxShadow: 'box-shadow:110px -130px 300px 60px #4d240c inset' }} className='w-full h-full object-cover opacity-80 min-w-[50vw] min-h-[20rem]' src={headerImage}/>
|
||||
</div>
|
||||
|
||||
<div id='post-info' className='absolute z-10 flex flex-col'>
|
||||
<div className='mb-3 flex justify-center'>
|
||||
<div id='post-info' className='absolute z-10 flex flex-col w-full max-w-[86rem] px-5'>
|
||||
<div className='mb-3 flex justify-start'>
|
||||
{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">
|
||||
@@ -36,11 +36,11 @@ export default function PostHeader({ post, siteInfo }) {
|
||||
</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">
|
||||
<NotionIcon icon={post.pageIcon} className='text-4xl mx-1' />{post.title}
|
||||
<div className="max-w-5xl font-bold xs:text-4xl sm:text-4xl md:text-4xl md:leading-snug shadow-text-md flex justify-start text-white">
|
||||
<span><NotionIcon icon={post.pageIcon} className='text-4xl mx-1' /></span>{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">
|
||||
<section className="flex-wrap shadow-text-md flex text-sm justify-start 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' && (
|
||||
@@ -79,7 +79,7 @@ export default function PostHeader({ post, siteInfo }) {
|
||||
|
||||
<WavesArea />
|
||||
|
||||
</header>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import CommonHead from '@/components/CommonHead'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import Footer from './components/Footer'
|
||||
import SideRight from './components/SideRight'
|
||||
import Header from './components/Header'
|
||||
import NavBar from './components/NavBar'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import BLOG from '@/blog.config'
|
||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||
@@ -53,23 +53,8 @@ const LayoutBase = props => {
|
||||
<CommonHead meta={meta} siteInfo={siteInfo} />
|
||||
<Style />
|
||||
|
||||
{/* 顶部导航 */}
|
||||
<Header {...props} />
|
||||
|
||||
{/* 顶部嵌入 首页放hero,文章页放大图 */}
|
||||
<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>
|
||||
{/* 顶部嵌入 导航栏,首页放hero,文章页放文章详情 */}
|
||||
{headerSlot}
|
||||
|
||||
{/* 主区块 */}
|
||||
<main id="wrapper-outer" className={'flex-grow w-full max-w-[86rem] mx-auto relative px-5'}>
|
||||
@@ -124,12 +109,13 @@ const LayoutBase = props => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
// 博客列表上方嵌入一个 通知横幅和英雄块
|
||||
const headerSlot = <>
|
||||
{/* 通知横幅 */}
|
||||
<NoticeBar />
|
||||
<Hero {...props} />
|
||||
</>
|
||||
const headerSlot = <header>
|
||||
{/* 顶部导航 */}
|
||||
<div id='nav-bar-wrapper' className='h-16'><NavBar {...props} /></div>
|
||||
{/* 通知横幅 */}
|
||||
<NoticeBar />
|
||||
<Hero {...props} />
|
||||
</header>
|
||||
|
||||
return <LayoutPostList {...props} headerSlot={headerSlot} />
|
||||
}
|
||||
@@ -144,7 +130,7 @@ const LayoutPostList = (props) => {
|
||||
const slotRight = <SideRight {...props} />
|
||||
|
||||
return <LayoutBase {...props} slotRight={slotRight}>
|
||||
{/* 文章分类条 */}
|
||||
{/* 文章分类条 */}
|
||||
<CategoryBar {...props} />
|
||||
|
||||
{BLOG.POST_LIST_STYLE === 'page'
|
||||
@@ -224,8 +210,14 @@ const LayoutSlug = props => {
|
||||
const targetRef = isBrowser() ? document.getElementById('article-wrapper') : null
|
||||
// 右侧栏
|
||||
const slotRight = <SideRight {...props} />
|
||||
const headerSlot = <header>
|
||||
{/* 顶部导航 */}
|
||||
<div id='nav-bar-wrapper'><NavBar {...props} /></div>
|
||||
<PostHeader {...props} />
|
||||
</header>
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} headerSlot={<PostHeader {...props} />} showCategory={false} showTag={false} slotRight={slotRight}>
|
||||
<LayoutBase {...props} headerSlot={headerSlot} showCategory={false} showTag={false} slotRight={slotRight}>
|
||||
<div className="w-full lg:hover:shadow lg:border rounded-t-xl lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black article">
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
@@ -308,8 +300,13 @@ const Layout404 = props => {
|
||||
const LayoutCategoryIndex = props => {
|
||||
const { categoryOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
const headerSlot = <header>
|
||||
{/* 顶部导航 */}
|
||||
<div id='nav-bar-wrapper' className='h-16'><NavBar {...props} /></div>
|
||||
</header>
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} className='mt-8'>
|
||||
<LayoutBase {...props} className='mt-8' headerSlot={headerSlot}>
|
||||
<div className="text-4xl font-extrabold dark:text-gray-200 mb-5">
|
||||
{locale.COMMON.CATEGORY}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user