mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-13 23:16:47 +00:00
theme-heo
This commit is contained in:
@@ -1,9 +1,26 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { saveDarkModeToCookies } from '@/themes/theme'
|
||||
import { Moon, Sun } from './HeroIcons'
|
||||
import { useImperativeHandle } from 'react'
|
||||
|
||||
/**
|
||||
* 深色模式按钮
|
||||
*/
|
||||
const DarkModeButton = (props) => {
|
||||
const { cRef, className } = props
|
||||
const { isDarkMode, updateDarkMode } = useGlobal()
|
||||
|
||||
/**
|
||||
* 对外暴露方法
|
||||
*/
|
||||
useImperativeHandle(cRef, () => {
|
||||
return {
|
||||
handleChangeDarkMode: () => {
|
||||
handleChangeDarkMode()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 用户手动设置主题
|
||||
const handleChangeDarkMode = () => {
|
||||
const newStatus = !isDarkMode
|
||||
@@ -14,7 +31,7 @@ const DarkModeButton = (props) => {
|
||||
htmlElement.classList?.add(newStatus ? 'dark' : 'light')
|
||||
}
|
||||
|
||||
return <div onClick={handleChangeDarkMode} className={`${props.className ? props.className : ''} flex justify-center dark:text-gray-200 text-gray-800`}>
|
||||
return <div onClick={handleChangeDarkMode} className={`${className || ''} flex justify-center dark:text-gray-200 text-gray-800`}>
|
||||
<div id='darkModeButton' className=' hover:scale-110 cursor-pointer transform duration-200 w-5 h-5'> {isDarkMode ? <Sun /> : <Moon />}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useGitBookGlobal } from '@/themes/gitbook'
|
||||
|
||||
/**
|
||||
* 移动端悬浮目录按钮
|
||||
*/
|
||||
export default function FloatTocButton () {
|
||||
const { tocVisible, changeTocVisible } = useGitBookGlobal()
|
||||
|
||||
@@ -14,7 +17,7 @@ export default function FloatTocButton () {
|
||||
}
|
||||
>
|
||||
<a
|
||||
id="darkModeButton"
|
||||
id="toc-button"
|
||||
className={'fa-list-ol cursor-pointer fas hover:scale-150 transform duration-200'}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -67,10 +67,10 @@ export default function ArticleAdjacent({ prev, next }) {
|
||||
|
||||
{/* 桌面端 */}
|
||||
|
||||
<div id='pc-next-post' className={`hidden md:block fixed right-4 bottom-4 duration-200 transition-all ${isScrollEnd ? 'mb-0 opacity-100' : '-mb-24 opacity-0'}`}>
|
||||
<div id='pc-next-post' className={`hidden md:block fixed z-20 right-4 bottom-4 duration-200 transition-all ${isScrollEnd ? 'mb-0 opacity-100' : '-mb-24 opacity-0'}`}>
|
||||
<Link
|
||||
href={`/${next.slug}`}
|
||||
className='cursor-pointer duration transition-all w-52 h-24 dark:bg-[#1e1e1e] border dark:border-gray-600 p-3 bg-white hover:text-white hover:bg-gray-400 rounded-lg flex flex-col justify-between'
|
||||
className='cursor-pointer duration transition-all h-24 dark:bg-[#1e1e1e] border dark:border-gray-600 p-3 bg-white dark:text-gray-300 dark:hover:text-yellow-600 hover:text-white hover:bg-gray-400 rounded-lg flex flex-col justify-between'
|
||||
>
|
||||
<div className='text-xs'>下一篇</div>
|
||||
<hr />
|
||||
|
||||
45
themes/heo/components/FloatTocButton.js
Normal file
45
themes/heo/components/FloatTocButton.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import { useState } from 'react'
|
||||
import Catalog from './Catalog'
|
||||
|
||||
/**
|
||||
* 移动端悬浮目录按钮
|
||||
*/
|
||||
export default function FloatTocButton(props) {
|
||||
const [tocVisible, changeTocVisible] = useState(false)
|
||||
|
||||
const { post } = props
|
||||
|
||||
const toggleToc = () => {
|
||||
changeTocVisible(!tocVisible)
|
||||
}
|
||||
|
||||
// 没有目录就隐藏该按钮
|
||||
if (!post || !post.toc || post.toc.length < 1) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (<div className='fixed right-4 bottom-12'>
|
||||
{/* 按钮 */}
|
||||
<div onClick={toggleToc} className={'hover:scale-110 transform duration-200 text-black dark:text-gray-200 w-10 h-10 rounded-full bg-white drop-shadow-lg flex justify-center items-center dark:bg-hexo-black-gray py-2 px-2'}>
|
||||
<button id="toc-button" className={'fa-list-ol cursor-pointer fas'} />
|
||||
</div>
|
||||
|
||||
{/* 目录Modal */}
|
||||
<div className='fixed top-0 right-0 z-40 '>
|
||||
{/* 侧边菜单 */}
|
||||
<div
|
||||
className={`${tocVisible ? 'shadow-card ' : ' -mr-72 opacity-0'}
|
||||
w-60 duration-200 fixed right-4 bottom-12 rounded-xl py-2 bg-white dark:bg-gray-900'`}>
|
||||
{post && <>
|
||||
<div className='dark:text-gray-400 text-gray-600'>
|
||||
<Catalog toc={post.toc} />
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{/* 背景蒙版 */}
|
||||
<div id='right-drawer-background' className={(tocVisible ? 'block' : 'hidden') + ' fixed top-0 left-0 z-30 w-full h-full'}
|
||||
onClick={toggleToc} />
|
||||
</div>)
|
||||
}
|
||||
@@ -180,7 +180,7 @@ function TopGroup(props) {
|
||||
<div className='cursor-pointer h-[164px] group relative flex flex-col w-52 xl:w-full overflow-hidden shadow bg-white dark:bg-black dark:text-white rounded-xl'>
|
||||
{/* eslint-disable-next-line */}
|
||||
<img className='h-24 object-cover' src={p?.pageCoverThumbnail || siteInfo?.pageCover} />
|
||||
<div className='group-hover:text-indigo-600 group-hover:text-yellow-600 line-clamp-2 overflow-hidden m-2 font-semibold'>{p?.title}</div>
|
||||
<div className='group-hover:text-indigo-600 dark:group-hover:text-yellow-600 line-clamp-2 overflow-hidden m-2 font-semibold'>{p?.title}</div>
|
||||
{/* hover 悬浮的 ‘荐’ 字 */}
|
||||
<div className='opacity-0 group-hover:opacity-100 -translate-x-4 group-hover:translate-x-0 duration-200 transition-all absolute -top-2 -left-2 bg-indigo-600 dark:bg-yellow-600 text-white rounded-xl overflow-hidden pr-2 pb-2 pl-4 pt-4 text-xs'>
|
||||
荐
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import { Fragment, useImperativeHandle, useState } from 'react'
|
||||
import { Fragment, useImperativeHandle, useRef, useState } from 'react'
|
||||
import { Dialog, Transition } from '@headlessui/react'
|
||||
import DarkModeButton from '@/components/DarkModeButton'
|
||||
import Link from 'next/link'
|
||||
@@ -13,8 +13,8 @@ export default function SlideOver(props) {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
/**
|
||||
* 函数组件暴露方法useImperativeHandle
|
||||
*/
|
||||
* 函数组件暴露方法useImperativeHandle
|
||||
*/
|
||||
useImperativeHandle(cRef, () => ({
|
||||
toggleSlideOvers: toggleSlideOvers
|
||||
}))
|
||||
@@ -77,25 +77,22 @@ export default function SlideOver(props) {
|
||||
|
||||
<section className='space-y-2 flex flex-col'>
|
||||
<div>功能</div>
|
||||
<div className={'flex justify-between items-center px-2 py-2 border dark:border-gray-600 bg-white dark:bg-[#ff953e] rounded-lg'}> <DarkModeButton /> 显示模式</div>
|
||||
{/* 切换深色模式 */}
|
||||
<DarkModeBlockButton />
|
||||
</section>
|
||||
|
||||
<section className='space-y-2 flex flex-col'>
|
||||
<div>博客</div>
|
||||
|
||||
{/* 导航按钮 */}
|
||||
<div className='gap-2 grid grid-cols-2'>
|
||||
<Link href='/' className={'flex cursor-pointer justify-between items-center px-2 py-2 border dark:border-gray-600 bg-white hover:bg-blue-600 dark:bg-[#1e1e1e] rounded-lg'}>
|
||||
主页
|
||||
</Link>
|
||||
<Link href='/about' className={'flex cursor-pointer justify-between items-center px-2 py-2 border dark:border-gray-600 bg-white hover:bg-blue-600 dark:bg-[#1e1e1e] rounded-lg'}>
|
||||
关于
|
||||
</Link>
|
||||
<Button title={'主页'} url={'/'} />
|
||||
<Button title={'关于'} url={'/about'} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className='space-y-2 flex flex-col'>
|
||||
<div>标签</div>
|
||||
<TagGroups tags={tagOptions}/>
|
||||
<TagGroups tags={tagOptions} />
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@@ -109,3 +106,25 @@ export default function SlideOver(props) {
|
||||
</Transition.Root>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个包含图标的按钮
|
||||
*/
|
||||
function DarkModeBlockButton() {
|
||||
const darkModeRef = useRef()
|
||||
function handleChangeDarkMode() {
|
||||
darkModeRef?.current?.handleChangeDarkMode()
|
||||
}
|
||||
return <button onClick={handleChangeDarkMode} className={'group duration-200 hover:text-white hover:shadow-md hover:bg-blue-600 flex justify-between items-center px-2 py-2 border dark:border-gray-600 bg-white dark:bg-[#ff953e] rounded-lg'}>
|
||||
<DarkModeButton cRef={darkModeRef} className='group-hover:text-white' /> 显示模式
|
||||
</button>
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个简单的按钮
|
||||
*/
|
||||
function Button({ title, url }) {
|
||||
return <Link href={url} className={'duration-200 hover:text-white hover:shadow-md flex cursor-pointer justify-between items-center px-2 py-2 border dark:border-gray-600 bg-white hover:bg-blue-600 dark:bg-[#1e1e1e] rounded-lg'}>
|
||||
{title}
|
||||
</Link>
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import Catalog from './Catalog'
|
||||
import React, { useImperativeHandle, useState } from 'react'
|
||||
|
||||
/**
|
||||
* 目录抽屉栏
|
||||
* @param toc
|
||||
* @param post
|
||||
* @returns {JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
const TocDrawer = ({ post, cRef }) => {
|
||||
// 暴露给父组件 通过cRef.current.handleMenuClick 调用
|
||||
useImperativeHandle(cRef, () => {
|
||||
return {
|
||||
handleSwitchVisible: () => switchVisible()
|
||||
}
|
||||
})
|
||||
const [showDrawer, switchShowDrawer] = useState(false)
|
||||
const switchVisible = () => {
|
||||
switchShowDrawer(!showDrawer)
|
||||
}
|
||||
return <>
|
||||
<div className='fixed top-0 right-0 z-40 '>
|
||||
{/* 侧边菜单 */}
|
||||
<div
|
||||
className={(showDrawer ? 'animate__slideInRight ' : ' -mr-72 animate__slideOutRight') +
|
||||
' shadow-card animate__animated animate__faster' +
|
||||
' w-60 duration-200 fixed right-12 bottom-12 rounded py-2 bg-white dark:bg-gray-900'}>
|
||||
{post && <>
|
||||
<div className='dark:text-gray-400 text-gray-600'>
|
||||
<Catalog toc={post.toc}/>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{/* 背景蒙版 */}
|
||||
<div id='right-drawer-background' className={(showDrawer ? 'block' : 'hidden') + ' fixed top-0 left-0 z-30 w-full h-full'}
|
||||
onClick={switchVisible} />
|
||||
</>
|
||||
}
|
||||
export default TocDrawer
|
||||
@@ -30,6 +30,7 @@ import { Style } from './style'
|
||||
import { NoticeBar } from './components/NoticeBar'
|
||||
import { HashTag } from '@/components/HeroIcons'
|
||||
import LatestPostsGroup from './components/LatestPostsGroup'
|
||||
import FloatTocButton from './components/FloatTocButton'
|
||||
|
||||
/**
|
||||
* 基础布局 采用上中下布局,移动端使用顶部侧边导航栏
|
||||
@@ -56,7 +57,7 @@ const LayoutBase = props => {
|
||||
{headerSlot}
|
||||
|
||||
{/* 主区块 */}
|
||||
<main id="wrapper-outer" className={'flex-grow w-full max-w-[86rem] mx-auto relative px-5'}>
|
||||
<main id="wrapper-outer" className={'flex-grow w-full max-w-[86rem] mx-auto relative md:px-5'}>
|
||||
|
||||
<div id="container-inner" className={'w-full mx-auto lg:flex lg:space-x-4 justify-center relative z-10'} >
|
||||
|
||||
@@ -243,14 +244,14 @@ const LayoutSlug = props => {
|
||||
|
||||
return (
|
||||
<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-[#18171d] dark:border-gray-600 article">
|
||||
<div className="w-full max-w-5xl lg:hover:shadow lg:border rounded-t-2xl lg:px-2 lg:py-4 bg-white dark:bg-[#18171d] dark:border-gray-600 article">
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
{!lock && <div id="article-wrapper" className="overflow-x-auto flex-grow mx-auto md:w-full md:px-5 ">
|
||||
|
||||
<article itemScope itemType="https://schema.org/Movie" className="subpixel-antialiased overflow-y-hidden" >
|
||||
{/* Notion文章主体 */}
|
||||
<section className='px-5 justify-center mx-auto max-w-2xl lg:max-w-full'>
|
||||
<section className='px-5 justify-center mx-auto'>
|
||||
{post && <NotionPage post={post} />}
|
||||
</section>
|
||||
|
||||
@@ -277,6 +278,7 @@ const LayoutSlug = props => {
|
||||
</div>
|
||||
</div>}
|
||||
</div>
|
||||
<FloatTocButton {...props}/>
|
||||
|
||||
</LayoutBase>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user