new-theme-plog

This commit is contained in:
tangly1024.com
2023-07-11 16:48:09 +08:00
parent 563b130e77
commit 2297777bd0
9 changed files with 244 additions and 41 deletions

View File

@@ -32,4 +32,23 @@ const ArrowPath = ({ className }) => {
<path strokeLinecap="round" strokeLinejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>
}
export { Moon, Sun, Home, User, ArrowPath }
const ChevronLeft = ({ className }) => {
return <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className={className}>
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" />
</svg>
}
const ChevronRight = ({ className }) => {
return <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className={className}>
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
</svg>
}
const InformationCircle = ({ className }) => {
return <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className={className}>
<path strokeLinecap="round" strokeLinejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" />
</svg>
}
export { Moon, Sun, Home, User, ArrowPath, ChevronLeft, ChevronRight, InformationCircle }

View File

@@ -5,6 +5,7 @@ import CONFIG from '../config'
import { SvgIcon } from './SvgIcon'
import { MenuItemDrop } from './MenuItemDrop'
import FullScreenButton from '@/components/FullScreenButton'
import InformationButton from './InformationButton'
/**
* 桌面端底部导航
@@ -15,7 +16,7 @@ const BottomNav = props => {
const { navBarTitle, siteInfo } = props
return <>
<div id="bottom-nav" style={{ backgroundColor: '#00000063' }} className={'px-4 hidden glassmorphism md:fixed bottom-0 w-screen py-4 md:flex flex-row justify-between items-center'}>
<div id="bottom-nav" style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }} className={'z-20 px-4 hidden glassmorphism md:fixed bottom-0 w-screen py-4 md:flex flex-row justify-between items-center'}>
<div className="flex items-center">
<Link href="/" aria-label={BLOG.title}>
<div className="h-6 w-6">
@@ -28,17 +29,20 @@ const BottomNav = props => {
</Link>
{navBarTitle
? (
<p className="ml-2 font-medium text-gray-800 dark:text-gray-300 header-name">
{navBarTitle}
</p>
<Link href="/" aria-label={BLOG.title}>
<p className="ml-2 font-medium text-gray-800 dark:text-gray-300 header-name">
{navBarTitle}
</p>
</Link>
)
: (
<p className="ml-2 font-medium text-gray-800 dark:text-gray-300 header-name">
{siteInfo?.title}
<Link href="/" aria-label={BLOG.title}> {siteInfo?.title}</Link>
{' '}<span className="font-normal text-sm text-gray-00 dark:text-gray-400">{siteInfo?.description}</span>
</p>
)}
</div>
{/* 右下角菜单栏 */}
<MenuList {...props} />
</div>
</>
@@ -78,7 +82,10 @@ const MenuList = props => {
<ul className="hidden md:flex flex-row">
{links?.map(link => <MenuItemDrop key={link?.id} link={link} />)}
<li className='my-auto px-2'>
<FullScreenButton/>
<FullScreenButton />
</li>
<li className='my-auto px-2'>
<InformationButton/>
</li>
</ul>
</div>

View File

@@ -1,12 +1,9 @@
import BLOG from '@/blog.config'
import DarkModeButton from '@/components/DarkModeButton'
import Vercel from '@/components/Vercel'
export const Footer = (props) => {
const d = new Date()
const currentYear = d.getFullYear()
const { post } = props
const fullWidth = post?.fullWidth ?? false
const copyrightDate = (function() {
if (Number.isInteger(BLOG.SINCE) && BLOG.SINCE < currentYear) {
@@ -15,18 +12,11 @@ export const Footer = (props) => {
return currentYear
})()
return <footer
className={`z-10 relative mt-6 flex-shrink-0 m-auto w-full text-gray-500 dark:text-gray-400 transition-all ${
!fullWidth ? 'max-w-2xl px-4' : 'px-4 md:px-24'
}`}
>
<DarkModeButton className='text-center pt-4'/>
<hr className="border-gray-200 dark:border-gray-600" />
return <footer className={'z-10 relative mt-6 flex-shrink-0 m-auto w-full text-gray-500 dark:text-gray-400 transition-all' } >
<div className="my-4 text-sm leading-6">
<div className="flex align-baseline justify-between flex-wrap">
<p>
© {BLOG.AUTHOR} {copyrightDate}
</p>
<div className="flex align-baseline justify-start flex-wrap space-x-6">
<div> © {BLOG.AUTHOR} {copyrightDate} </div>
<div>Powered By <a href="https://github.com/tangly1024/NotionNext" className='underline'>NotionNext {BLOG.VERSION}</a></div>
<Vercel />
</div>
</div>

View File

@@ -0,0 +1,23 @@
import { InformationCircle } from '@/components/HeroIcons'
import SlideOvers from './SlideOvers'
import { useRef } from 'react'
/**
* 显示网站用户信息按钮
* @returns
*/
export default function InformationButton() {
const slideOversRef = useRef({})
const toggleCollapsed = () => {
console.log(slideOversRef)
slideOversRef.current.toggleSlideOvers()
}
return <>
<div className='cursor-pointer' onClick={toggleCollapsed}>
<InformationCircle className={'w-5 h-5'} />
</div>
<SlideOvers cRef={slideOversRef} />
</>
}

View File

@@ -28,8 +28,8 @@ export const MenuItemDrop = ({ link }) => {
{/* 子菜单 */}
{hasSubMenu && <ul className={`${show ? 'visible opacity-100 bottom-16 ' : 'invisible opacity-0 top-10 '} border-gray-100 bg-white rounded-lg dark:bg-black dark:border-gray-800 bg-opacity-60 transition-all duration-300 z-20 absolute block drop-shadow-lg `}>
{link.subMenus.map(sLink => {
return <li key={sLink.id} className='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.subMenus.map((sLink, index) => {
return <li key={index} className='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} > &nbsp; </i>}{sLink.title}</span>
</Link>

View File

@@ -1,15 +1,16 @@
import { Fragment, useRef, useState } from 'react'
import { Dialog, Transition } from '@headlessui/react'
import { usePlogGlobal } from '..'
import { ArrowPath } from '@/components/HeroIcons'
import { ArrowPath, ChevronLeft, ChevronRight } from '@/components/HeroIcons'
import Link from 'next/link'
import BLOG from '@/blog.config'
/**
* 弹出框
*/
export default function Modal(props) {
const { showModal, setShowModal, modalContent } = usePlogGlobal()
const { siteInfo } = props
const { showModal, setShowModal, modalContent, setModalContent } = usePlogGlobal()
const { siteInfo, posts } = props
const cancelButtonRef = useRef(null)
const img = modalContent?.pageCover || siteInfo?.pageCover
const imgRef = useRef(null)
@@ -18,7 +19,7 @@ export default function Modal(props) {
const [loading, setLoading] = useState(true)
// 在图片加载完成时设置loading为false
async function handleImageLoad() {
function handleImageLoad() {
setLoading(false)
}
@@ -27,6 +28,28 @@ export default function Modal(props) {
setShowModal(false)
setLoading(true)
}
// 修改当前显示的遮罩内容
function prev() {
const index = posts.findIndex(post => post.slug === modalContent.slug)
if (index === 0) {
setModalContent(posts[posts.length - 1])
} else {
setModalContent(posts[index - 1])
}
setLoading(true)
}
// 下一个
const next = () => {
const index = posts.findIndex(post => post.slug === modalContent.slug)
if (index === posts.length - 1) {
setModalContent(posts[0])
} else {
setModalContent(posts[index + 1])
}
setLoading(true)
}
return (
<Transition.Root show={showModal} as={Fragment}>
<Dialog as="div" className="relative z-10" initialFocus={cancelButtonRef} onClose={handleClose}>
@@ -40,7 +63,7 @@ export default function Modal(props) {
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div style={{ backgroundColor: '#00000063' }} className="fixed inset-0 glassmorphism transition-opacity" />
<div style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }} className="fixed inset-0 glassmorphism transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
@@ -59,20 +82,37 @@ export default function Modal(props) {
<div className={`bg-hexo-black-gray w-32 h-32 flex justify-center items-center ${loading ? '' : 'hidden'}`}>
<ArrowPath className='w-10 h-10 animate-spin text-gray-200' />
</div>
{/* 添加onLoad事件处理函数 */}
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={img} ref={imgRef} className={'w-full max-w-7xl max-h-[90vh] shadow-xl'} onLoad={handleImageLoad} style={{ display: loading ? 'none' : 'block' }} />
{!loading && <div className='absolute bottom-0 left-0 m-4'>
<div className='flex'>
<h2 style={{ textShadow: '0.1em 0.1em 0.2em black' }} className='text-5xl text-white mb-4 px-2 py-1 rounded-lg'>{modalContent?.title}</h2>
</div>
<div style={{ textShadow: '0.1em 0.1em 0.2em black' }} className={'text-gray-50 rounded-lg p-2'}>{modalContent?.summary}</div>
{modalContent?.category && <div className='flex '>
<Link href={`/category/${modalContent?.category}`} className='text-xs rounded-lg mt-3 px-2 py-1 bg-black bg-opacity-20 text-white hover:bg-blue-700 hover:text-white duration-200'>
{modalContent?.category}
<img src={img} ref={imgRef} className={`w-full max-w-7xl max-h-[90vh] shadow-xl ${!loading ? ' animate__animated animate__fadeIn' : ''}`} onLoad={handleImageLoad} style={{ display: loading ? 'none' : 'block' }} />
{!loading && (<>
<div className='absolute bottom-0 left-0 m-4 z-20'>
<div className='flex'>
<h2 style={{ textShadow: '0.1em 0.1em 0.2em black' }} className='text-5xl text-white mb-4 px-2 py-1 rounded-lg'>{modalContent?.title}</h2>
</div>
<Link href={`${BLOG.SUB_PATH}/${modalContent.slug}`}>
<div style={{ textShadow: '0.1em 0.1em 0.2em black' }} className={'cursor-pointer text-gray-50 rounded-lg p-2'}>
{modalContent?.summary}
</div>
</Link>
</div>}
</div>}
{modalContent?.category && (
<div className='flex'>
<Link href={`/category/${modalContent?.category}`} className='text-xs rounded-lg mt-3 px-2 py-1 bg-black bg-opacity-20 text-white hover:bg-blue-700 hover:text-white duration-200'>
{modalContent?.category}
</Link>
</div>
)}
</div>
<div className='z-10 absolute hover:opacity-50 opacity-0 duration-200 transition-opacity w-full top-0 left-0 px-4 h-full items-center flex justify-between'>
<div onClick={prev}><ChevronLeft className='cursor-pointer w-24 h-32 hover:opacity-100 stroke-white stroke-1 scale-y-150' /></div>
<div onClick={next}><ChevronRight className='cursor-pointer w-24 h-32 hover:opacity-100 stroke-white stroke-1 scale-y-150' /></div>
</div>
</>)}
</Dialog.Panel>
</Transition.Child>
</div>

View File

@@ -0,0 +1,79 @@
import { Fragment, useRef, useImperativeHandle, useState } from 'react'
import { Dialog, Transition } from '@headlessui/react'
import { Footer } from './Footer'
import SocialButton from './SocialButton'
import BLOG from '@/blog.config'
/**
* 侧拉抽屉
* @returns
*/
export default function SlideOvers({ children, cRef }) {
const [open, setOpen] = useState(false)
const slideOversRef = useRef({})
/**
* 函数组件暴露方法
*/
useImperativeHandle(cRef, () => ({
toggleSlideOvers: toggleSlideOvers
}))
const toggleSlideOvers = () => {
setOpen(!open)
}
return (
<Transition.Root show={open} as={Fragment}>
<Dialog ref={slideOversRef} as="div" className="relative" onClose={setOpen}>
{/* 遮罩 */}
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }} className="fixed inset-0 z-10 glassmorphism transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 overflow-hidden z-10">
<div className="absolute inset-0 overflow-hidden">
<div className="pointer-events-none fixed inset-x-0 bottom-0 flex max-h-full pb-16">
<Transition.Child
as={Fragment}
enter="transform transition ease-in-out duration-500"
enterFrom="translate-y-full"
enterTo="translate-y-0"
leave="transform transition ease-in-out duration-500"
leaveFrom="translate-y-0"
leaveTo="translate-y-full"
>
<Dialog.Panel style={{ backgroundColor: 'rgba(0, 0, 0, 0.6)' }} className="pointer-events-auto relative y-screen max-h-md glassmorphism w-screen p-4 mb-2">
<Transition.Child
as={Fragment}
enter="ease-in-out duration-500"
enterFrom="opacity-0 transition-y-32"
enterTo="opacity-100 transition-y-0"
leave="ease-in-out duration-500"
leaveFrom="opacity-100 transition-y-0"
leaveTo="opacity-0 transition-y-32"
>
<div className='max-w-7xl mx-auto space-y-6'>
<h2 className='text-4xl text-gray-200'>关于{BLOG.AUTHOR}</h2>
<h2 className='text-2xl text-gray-400'>{BLOG.BIO}</h2>
<h2 className='text-4xl text-gray-200'>联系我</h2>
<SocialButton/>
<Footer/>
</div>
</Transition.Child>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</div>
</Dialog>
</Transition.Root>
)
}

View File

@@ -0,0 +1,45 @@
import BLOG from '@/blog.config'
import React from 'react'
/**
* 社交联系方式按钮组
* @returns {JSX.Element}
* @constructor
*/
const SocialButton = () => {
return <div className='justify-start flex-wrap flex mx-1'>
<div className='space-x-3 text-2xl text-gray-600 dark:text-gray-400 text-center'>
{BLOG.CONTACT_GITHUB && <a target='_blank' rel='noreferrer' title={'github'} href={BLOG.CONTACT_GITHUB} >
<i className='fab fa-github transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_TWITTER && <a target='_blank' rel='noreferrer' title={'twitter'} href={BLOG.CONTACT_TWITTER} >
<i className='fab fa-twitter transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_TELEGRAM && <a target='_blank' rel='noreferrer' href={BLOG.CONTACT_TELEGRAM} title={'telegram'} >
<i className='fab fa-telegram transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_LINKEDIN && <a target='_blank' rel='noreferrer' href={BLOG.CONTACT_LINKEDIN} title={'linkedIn'} >
<i className='transform hover:scale-125 duration-150 fab fa-linkedin dark:hover:text-indigo-400 hover:text-indigo-600'/>
</a>}
{BLOG.CONTACT_WEIBO && <a target='_blank' rel='noreferrer' title={'weibo'} href={BLOG.CONTACT_WEIBO} >
<i className='fab fa-weibo transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_INSTAGRAM && <a target='_blank' rel='noreferrer' title={'instagram'} href={BLOG.CONTACT_INSTAGRAM} >
<i className='fab fa-instagram transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_EMAIL && <a target='_blank' rel='noreferrer' title={'email'} href={`mailto:${BLOG.CONTACT_EMAIL}`} >
<i className='fas fa-envelope transform hover:scale-125 duration-150'/>
</a>}
{BLOG.ENABLE_RSS && <a target='_blank' rel='noreferrer' title={'RSS'} href={'/feed'} >
<i className='fas fa-rss transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_BILIBILI && <a target='_blank' rel='noreferrer' title={'bilibili'} href={BLOG.CONTACT_BILIBILI} >
<i className='fab fa-bilibili transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_YOUTUBE && <a target='_blank' rel='noreferrer' title={'youtube'} href={BLOG.CONTACT_YOUTUBE} >
<i className='fab fa-youtube transform hover:scale-125 duration-150'/>
</a>}
</div>
</div>
}
export default SocialButton

View File

@@ -68,7 +68,7 @@ const LayoutBase = props => {
<Nav {...props} />
{/* 主区 */}
<main id='out-wrapper' className={'relative m-auto flex-grow w-full transition-all pb-12'}>
<main id='out-wrapper' className={'relative m-auto flex-grow w-full transition-all pb-16'}>
<Transition
show={!onLoading}
@@ -179,7 +179,7 @@ const LayoutSlug = props => {
{lock && <ArticleLock validPassword={validPassword} />}
{!lock && <div id="article-wrapper" className="px-2">
{!lock && <div id="article-wrapper" className="px-2 max-w-6xl mx-auto">
<>
<ArticleInfo post={post} />
<NotionPage post={post} />