feature: 样式调整,加入Tabs组件

This commit is contained in:
tangly1024
2022-01-01 22:22:52 +08:00
parent f6168e8dc1
commit 8e8b6c1f73
18 changed files with 167 additions and 80 deletions

View File

@@ -20,7 +20,12 @@ const BLOG = {
showAbout: true, // WIP 是否显示关于
showArchive: true, // WIP 是否显示归档
autoCollapsedNavBar: false, // the automatically collapsed navigation bar
socialLink: 'https://weibo.com/u/2245301913',
socialLink: {
weibo: 'https://weibo.com/u/2245301913',
twitter: '',
github: 'https://github.com/tangly1024',
telegram: ''
},
seo: {
keywords: ['Notion', '写作', '博客'],
googleSiteVerification: '' // Remove the value or replace it with your own google site verification code

View File

@@ -1,6 +1,4 @@
import { useGlobal } from '@/lib/global'
import { faChartBar } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
/**
* 统计网站信息
@@ -11,7 +9,7 @@ export default function Analytics ({ postCount }) {
const { locale } = useGlobal()
return <>
<div className='px-5 text-sm font-light pb-1 text-gray-600 dark:text-gray-200'><FontAwesomeIcon icon={faChartBar} className='mr-2' />{locale.COMMON.ANALYTICS}</div>
{/* <div className='px-5 text-sm font-light pb-1 text-gray-600 dark:text-gray-200'><FontAwesomeIcon icon={faChartBar} className='mr-2' />{locale.COMMON.ANALYTICS}</div> */}
<div className='mt-2 text-center dark:text-gray-300 font-light text-xs'>
<span className='px-1 '>
<strong className='font-medium'>{postCount}</strong>{locale.COMMON.POSTS}</span>

View File

@@ -96,7 +96,7 @@ export default function Header () {
return (
<header
id="header"
className="duration-500 md:bg-fixed w-full bg-cover bg-center lg:-mt-14 h-screen bg-black"
className="duration-500 md:bg-fixed w-full bg-cover bg-center h-screen bg-black"
style={{
backgroundImage:
`linear-gradient(rgba(0, 0, 0, 0.8), rgba(0,0,0,0.2), rgba(0, 0, 0, 0.8) ),url("${BLOG.bannerImage}")`

View File

@@ -2,11 +2,12 @@ import BLOG from '@/blog.config'
import Image from 'next/image'
import Router from 'next/router'
import React from 'react'
import SocialButton from './SocialButton'
const InfoCard = ({ postCount }) => {
return <>
<div className='flex flex-col items-center justify-center cursor-pointer' onClick={ () => { Router.push('/') }}>
<div className='hover:rotate-45 hover:scale-125 transform duration-200'>
<div className='flex flex-col items-center justify-center '>
<div className='hover:rotate-45 hover:scale-125 transform duration-200 cursor-pointer' onClick={ () => { Router.push('/about') }}>
<Image
alt={BLOG.title}
width={120}
@@ -17,6 +18,8 @@ const InfoCard = ({ postCount }) => {
/>
</div>
<div className='text-3xl font-serif dark:text-white py-2 hover:scale-105 transform duration-200'>{BLOG.title}</div>
<div className='font-light dark:text-white py-2 hover:scale-105 transform duration-200'>{BLOG.description}</div>
<SocialButton/>
</div>
</>
}

View File

@@ -9,7 +9,7 @@ export default function Live2D () {
hasLoad = true
}
})
return <div className='fixed left-0 bottom-0 hidden md:block lg:ml-24 2xl:ml-36'>
return <div className='fixed right-0 bottom-0 hidden md:block lg:mr-24 2xl:mr-48 z-20'>
<canvas id="live2d"className='animate__slideInLeft animate__animated' width="280" height="250"></canvas>
</div>
}

View File

@@ -3,7 +3,7 @@ import Link from 'next/link'
import { useRouter } from 'next/router'
import { useGlobal } from '@/lib/global'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faArchive, faHome, faInfoCircle } from '@fortawesome/free-solid-svg-icons'
import { faArchive, faHome, faTag, faThList } from '@fortawesome/free-solid-svg-icons'
import BLOG from 'blog.config'
const MenuButtonGroup = ({ allowCollapse = false }) => {
@@ -12,7 +12,9 @@ const MenuButtonGroup = ({ allowCollapse = false }) => {
const links = [
{ id: 0, icon: faHome, name: locale.NAV.INDEX, to: '/' || '/', show: true },
{ id: 1, icon: faArchive, name: locale.NAV.ARCHIVE, to: '/archive', show: BLOG.showArchive },
{ id: 2, icon: faInfoCircle, name: locale.NAV.ABOUT, to: '/about', show: BLOG.showAbout }
{ id: 2, icon: faThList, name: locale.COMMON.CATEGORY, to: '/category', show: BLOG.showArchive },
{ id: 3, icon: faTag, name: locale.COMMON.TAGS, to: '/tag', show: BLOG.showArchive }
// { id: 2, icon: faInfoCircle, name: locale.NAV.ABOUT, to: '/about', show: BLOG.showAbout }
// { id: 7, icon: 'faGithub', name: 'Github', to: 'https://github.com/tangly1024', show: true },
// { id: 5, icon: 'faWeibo', name: '微博', to: 'https://weibo.com/tangly1024', show: true },
// { id: 4, icon: 'faEnvelope', name: locale.NAV.MAIL, to: 'mailto:tlyong1992@hotmail.com', show: true }

View File

@@ -5,7 +5,7 @@ import React, { useEffect, useState } from 'react'
* @returns {JSX.Element}
* @constructor
*/
const Progress = ({ targetRef }) => {
const Progress = ({ targetRef, showPercent = true }) => {
const [percent, changePercent] = useState(0)
const scrollListener = () => {
if (targetRef?.current) {
@@ -24,9 +24,10 @@ const Progress = ({ targetRef }) => {
}, [percent])
return (<div className='h-4 w-full shadow-2xl bg-gray-400'>
<div className='h-4 bg-gray-600 duration-200' style={{ width: `${percent}%` }}><div className='text-right text-white text-xs'>{percent}%</div></div>
</div>)
<div className='h-4 bg-gray-600 duration-200' style={{ width: `${percent}%` }}>
{showPercent && <div className='text-right text-white text-xs'>{percent}%</div>}
</div>
</div>)
}
export default Progress

View File

@@ -0,0 +1,35 @@
import { Router } from 'next/router'
import { useImperativeHandle, useRef } from 'react'
import SearchInput from './SearchInput'
const SearchDrawer = ({ cRef }) => {
const searchDrawer = useRef()
const searchInputRef = useRef()
useImperativeHandle(cRef, () => {
return {
show: () => {
searchDrawer?.current?.classList?.remove('hidden')
searchInputRef?.current?.focus()
}
}
})
const hidden = () => {
searchDrawer?.current?.classList?.add('hidden')
}
Router.events.on('routeChangeComplete', (...args) => {
hidden()
})
return (
<div id='search-drawer-wrapper' ref={searchDrawer} className='hidden'>
<div className='flex absolute px-5 w-full h-full left-0 top-14 z-50 justify-center'>
<div className='md:max-w-3xl w-full mx-auto'>
<SearchInput cRef={searchInputRef} />
</div>
</div>
{/* 背景蒙版 */}
<div id='search-drawer-background' onClick={hidden} className='animate__animated animate__faster animate__fadeIn fixed glassmorphism top-0 left-0 z-30 w-full h-full' />
</div>
)
}
export default SearchDrawer

View File

@@ -5,6 +5,7 @@ import Toc from '@/components/Toc'
import { useGlobal } from '@/lib/global'
import React from 'react'
import Analytics from './Analytics'
import Tabs from '@/components/Tabs'
/**
* 侧边平铺
@@ -24,35 +25,31 @@ const SideAreaLeft = ({ title, tags, currentTag, post, posts, categories, curren
const postCount = posts?.length || 0
return <>
<section className={(!post ? 'sticky top-8 ' : ' ') + ' w-60'}>
<section className='shadow hidden lg:block mb-5 bg-white dark:bg-gray-800 hover:shadow-xl duration-200 py-6'>
<InfoCard postCount={postCount} />
</section>
<section className='sticky top-16 w-60'>
{/* 菜单 */}
<section className='shadow hidden lg:block mb-5 py-4 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
<section className='shadow hidden lg:block mb-5 py-4 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
<MenuButtonGroup allowCollapse={true} />
<div className='px-5 pt-2'>
<SearchInput currentTag={currentTag} currentSearch={currentSearch} />
</div>
</section>
{/* 统计 */}
<section className='shadow hidden lg:block mb-5 bg-white dark:bg-gray-800 hover:shadow-xl duration-200 py-4'>
<Analytics postCount={postCount}/>
</section>
<Tabs>
{showToc && (
<div key={locale.COMMON.TABLE_OF_CONTENTS} className='dark:text-gray-400 text-gray-600 bg-white dark:bg-gray-800 duration-200'>
<Toc toc={post.toc} targetRef={targetRef} />
</div>
)}
<div key={locale.NAV.ABOUT} className='mb-5 bg-white dark:bg-gray-800 duration-200 py-6'>
<InfoCard postCount={postCount} />
<Analytics postCount={postCount}/>
</div>
</Tabs>
</section>
{showToc && (
<section className='shadow sticky top-8 pb-20 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
<div className='border-b text-center text-2xl bg-white text-black dark:border-gray-700 dark:bg-gray-700 dark:text-white py-6 px-6'>
{locale.COMMON.TABLE_OF_CONTENTS}
</div>
<Toc toc={post.toc} targetRef={targetRef} />
</section>
)}
</>
}
export default SideAreaLeft

View File

@@ -1,11 +1,8 @@
import LatestPostsGroup from '@/components/LatestPostsGroup'
import TagGroups from '@/components/TagGroups'
import { useGlobal } from '@/lib/global'
import { faAngleDoubleRight, faArchive, faTags, faThList } from '@fortawesome/free-solid-svg-icons'
import { faArchive } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
import CategoryGroup from '@/components/CategoryGroup'
/**
* 侧边平铺
@@ -64,7 +61,7 @@ const SideAreaRight = ({
{/* <Analytics postCount={postCount}/> */}
<div className="sticky top-8">
<div className="sticky top-16">
{/* {showToc && (
<section className='pb-10 mb-5 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
<div className='border-b text-center text-2xl bg-white text-black dark:border-gray-700 dark:bg-gray-700 dark:text-white py-6 px-6'>
@@ -75,7 +72,7 @@ const SideAreaRight = ({
)} */}
{/* 分类 */}
{categories && (
{/* {categories && (
<section className='shadow py-4 mb-5 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
<div className='text-sm px-5 mb-2 flex flex-nowrap justify-between font-light'>
<div className='pb-1 text-gray-600 dark:text-gray-300'><FontAwesomeIcon icon={faThList} className='mr-2' />{locale.COMMON.CATEGORY}</div>
@@ -87,7 +84,7 @@ const SideAreaRight = ({
</div>
<CategoryGroup currentCategory={currentCategory} categories={categories} />
</section>
)}
)} */}
{/* 最新文章 */}
{posts && (
@@ -108,7 +105,7 @@ const SideAreaRight = ({
</section> */}
{/* 标签云 */}
{tags && (
{/* {tags && (
<section className="shadow py-4 mb-5 bg-white dark:bg-gray-800 hover:shadow-xl duration-200">
<div className="text-sm pb-1 px-5 flex flex-nowrap justify-between font-light dark:text-gray-200">
<div className="text-gray-600 dark:text-gray-200">
@@ -126,7 +123,7 @@ const SideAreaRight = ({
<TagGroups tags={tags} currentTag={currentTag} />
</div>
</section>
)}
)} */}
</div>
</>

View File

@@ -1,4 +1,6 @@
import BLOG from '@/blog.config'
import { faGithub, faTelegram, faTwitter, faWeibo } from '@fortawesome/free-brands-svg-icons'
import { faEnvelope, faRss } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
@@ -8,19 +10,25 @@ import React from 'react'
* @constructor
*/
const SocialButton = () => {
return <div className='w-52'>
return <div className='w-52 justify-center flex'>
<div className='space-x-3 text-xl text-gray-600 dark:text-gray-400 px-6'>
<a target='_blank' rel='noreferrer' title={'github'} href={'https://github.com/tangly1024'} >
{BLOG.socialLink.github && <a target='_blank' rel='noreferrer' title={'github'} href={BLOG.socialLink.github} >
<FontAwesomeIcon icon={faGithub} className='transform hover:scale-125 duration-150'/>
</a>
<a target='_blank' rel='noreferrer' title={'twitter'} href={'https://twitter.com/troy1024_1'} >
</a>}
{BLOG.socialLink.twitter && <a target='_blank' rel='noreferrer' title={'twitter'} href={BLOG.socialLink.twitter} >
<FontAwesomeIcon icon={faTwitter} className='transform hover:scale-125 duration-150'/>
</a>
<a target='_blank' rel='noreferrer' href={'https://t.me/tangly_1024'} title={'telegram'} >
</a>}
{BLOG.socialLink.telegram && <a target='_blank' rel='noreferrer' href={BLOG.socialLink.telegram} title={'telegram'} >
<FontAwesomeIcon icon={faTelegram} className='transform hover:scale-125 duration-150'/>
</a>
<a target='_blank' rel='noreferrer' title={'weibo'} href={'https://weibo.com/tangly1024'} >
</a>}
{BLOG.socialLink.weibo && <a target='_blank' rel='noreferrer' title={'weibo'} href={BLOG.socialLink.weibo} >
<FontAwesomeIcon icon={faWeibo} className='transform hover:scale-125 duration-150'/>
</a>}
{BLOG.email && <a target='_blank' rel='noreferrer' title={'weibo'} href={`mailto:${BLOG.email}`} >
<FontAwesomeIcon icon={faEnvelope} className='transform hover:scale-125 duration-150'/>
</a>}
<a target='_blank' rel='noreferrer' title={'weibo'} href={'/feed'} >
<FontAwesomeIcon icon={faRss} className='transform hover:scale-125 duration-150'/>
</a>
</div>
</div>

51
components/Tabs.js Normal file
View File

@@ -0,0 +1,51 @@
import React, { useState } from 'react'
/**
* Tabs切换标签
* @param {*} param0
* @returns
*/
const Tabs = ({ children }) => {
if (!children) {
return <></>
}
let count = children.length
children.forEach(e => {
if (!e) {
count--
}
})
if (count === 1) {
return <section>
{children}
</section>
}
const [currentTab, setCurrentTab] = useState(0)
function tabClickHandle (i) {
setCurrentTab(i)
}
return (
<section >
{<div className='shadow hidden lg:block mb-5 py-4 px-5 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
<ul className='flex justify-center space-x-5 pb-4 cursor-pointer dark:text-gray-400 text-gray-600'>
{children.map((item, index) => {
return <li key={index} className={currentTab === index ? 'font-black border-b' : 'font-extralight'} onClick={() => { tabClickHandle(index) }}>
{item?.key}
</li>
})}
</ul>
{children.map((item, index) => {
return <section key={index} className={`tabContent ${currentTab === index ? 'block' : 'hidden'}`}>
{item}
</section>
})}
</div>}
</section>)
}
export default Tabs

View File

@@ -55,7 +55,7 @@ const Toc = ({ toc, targetRef }) => {
<div className='w-full'>
<Progress targetRef={targetRef}/>
</div>
<nav className=' dark:text-gray-400 text-gray-600 bg-white dark:bg-gray-800 overflow-y-auto scroll-hidden p-6'>
<nav className=' overflow-y-auto scroll-hidden'>
{toc.map((tocItem) => {
const id = uuidToId(tocItem.id)
return (

View File

@@ -32,7 +32,9 @@ const TocDrawer = ({ post, cRef, targetRef }) => {
<div className='text-xl font-bold text-center text-black dark:text-white bg-white dark:bg-gray-600 py-2 px-6'>
{locale.COMMON.TABLE_OF_CONTENTS}
</div>
<Toc toc={post.toc} targetRef={targetRef}/>
<div className='p-6 dark:text-gray-400 text-gray-600 bg-white dark:bg-gray-800'>
<Toc toc={post.toc} targetRef={targetRef}/>
</div>
</>
}
</div>

View File

@@ -1,11 +1,11 @@
import BLOG from '@/blog.config'
import SideBarDrawer from '@/components/SideBarDrawer'
import { useGlobal } from '@/lib/global'
import { faBars, faSearch } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import { useCallback, useEffect, useRef } from 'react'
import Image from 'next/image'
import { faBars } from '@fortawesome/free-solid-svg-icons'
import SearchDrawer from './SearchDrawer'
import throttle from 'lodash.throttle'
let windowTop = 0
@@ -18,6 +18,7 @@ let windowTop = 0
const TopNav = ({ tags, currentTag, post, posts, categories, currentCategory, autoHide = true }) => {
const drawer = useRef()
const { locale } = useGlobal()
const searchDrawer = useRef()
const scrollTrigger = useCallback(throttle(() => {
const scrollS = window.scrollY
@@ -30,7 +31,7 @@ const TopNav = ({ tags, currentTag, post, posts, categories, currentCategory, au
nav && nav.classList.replace('-top-16', 'top-0')
windowTop = scrollS
}
}, 200))
}, 200), [])
// 监听滚动
useEffect(() => {
@@ -42,10 +43,10 @@ const TopNav = ({ tags, currentTag, post, posts, categories, currentCategory, au
autoHide && window.removeEventListener('scroll', scrollTrigger)
}
}, [])
return (<div id='top-nav'>
return (<div id='top-nav' className='sticky top-0 z-40 block lg:hidden'>
{/* 侧面抽屉 */}
<SideBarDrawer post={post} currentTag={currentTag} cRef={drawer} tags={tags} posts={posts} categories={categories} currentCategory={currentCategory}/>
<SearchDrawer cRef={searchDrawer}/>
{/* 导航栏 */}
<div id='sticky-nav' className='flex animate__animated animate__fadeIn fixed lg:relative w-full top-0 z-20 transform duration-500'>
@@ -53,16 +54,10 @@ const TopNav = ({ tags, currentTag, post, posts, categories, currentCategory, au
{/* 左侧LOGO 标题 */}
<div className='flex flex-none flex-grow-0'>
<div onClick={() => { drawer.current.handleSwitchSideDrawerVisible() }}
className='w-8 cursor-pointer dark:text-gray-300 block lg:hidden'>
className='w-8 cursor-pointer dark:text-gray-300'>
<FontAwesomeIcon icon={faBars} size={'lg'}/>
</div>
<div className='relative w-10 hidden lg:block' ><Image
alt={BLOG.title}
layout='fill'
loading='lazy'
src='/favicon.svg'
className='border-black'
/></div>
<Link href='/' passHref>
<a>
<h1 className='cursor-pointer ml-2 w-full hover:scale-105 duration-200 transform font-serif dark:text-gray-200 whitespace-nowrap overflow-x-hidden'>{ BLOG.title }</h1>
@@ -72,15 +67,9 @@ const TopNav = ({ tags, currentTag, post, posts, categories, currentCategory, au
{/* 右侧功能 */}
<div className='mr-1 flex flex-nowrap flex-grow justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
<Link href='/'>
<a>{locale.NAV.INDEX}</a>
</Link>
<Link href='/archive'>
<a>{locale.NAV.ARCHIVE}</a>
</Link>
<Link href='/about'>
<a>{locale.NAV.ABOUT}</a>
</Link>
<div className="cursor-pointer block lg:hidden" onClick={() => { searchDrawer?.current?.show() }}>
<FontAwesomeIcon icon={faSearch} className="mr-2" />{locale.NAV.SEARCH}
</div>
</div>
</div>
</div>

View File

@@ -24,6 +24,7 @@ const About = ({ post, blockMap, tags, prev, next, allPosts, categories }) => {
return <Custom404 />
}
const { locale } = useGlobal()
post.title = locale.NAV.ABOUT
const meta = {
title: `${locale.NAV.ABOUT} | ${BLOG.title} `,
description: post.summary,

View File

@@ -46,14 +46,12 @@ const Search = ({ allPosts, tags, categories }) => {
}
return (
<BaseLayout meta={meta} tags={tags} totalPosts={allPosts} currentSearch={searchKey} categories={categories}>
<div className=''>
<StickyBar>
<div className='p-4 dark:text-gray-200'><FontAwesomeIcon icon={faSearch} className='mr-1'/> 搜索词 {searchKey}</div>
<div className='p-4 dark:text-gray-200'><FontAwesomeIcon icon={faSearch} className='mr-1'/> {locale.NAV.SEARCH} {searchKey}</div>
</StickyBar>
<div className='md:mt-5'>
<BlogPostListScroll posts={filteredPosts} tags={tags} currentSearch={searchKey} />
</div>
</div>
</BaseLayout>
)
}

View File

@@ -151,12 +151,12 @@ nav {
.glassmorphism{
background: hsla(0, 0%, 100%, .75);
-webkit-backdrop-filter: blur(5px);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
}
.dark .glassmorphism{
background: rgba(31, 41, 55, .75);
-webkit-backdrop-filter: blur(3px);
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
}