nextjs-notion-starter-kit移动端支持展示目录
😏

nextjs-notion-starter-kit移动端支持展示目录

最后更新时间
2024-11-18 04:25

1 背景

看到 Github 上有个 Issue:How to add TOC in the mobile phone · Issue #586 · transitive-bullshit/nextjs-notion-starter-kit,刚好我解决了这个问题。虽然代码写得不怎么样(那一定都是 GPT 的问题哈哈哈)…但如果能帮助到有需要的人那就最好啦!当然,如果你有更好的建议,请一定随时反馈!
不过还是要提一嘴,基于这个项目的设计方式,我的改造方式只能算是个 workaround,我认为更彻底的方式还是需要 react-notion-x 进行优化,在作者优化之前可以考虑先用这个方法处理~

2 效果展示

2.1 日间模式

notion image

2.2 夜间模式

notion image

3 Show you the code

代码还是比较简单的,只需要更改两个文件即可实现。
注意,代码块中的 ... 代表原有的代码,只不过被我省略了,按照 ... 所示的对应位置插入下方对应代码即可。

3.1 components/NotionPage.tsx

其中 max-width: 1300px 可以你自己期望的大小调整,代表是宽度小于等于多少就隐藏原 PC 端目录,按移动端展示目录按钮。
import { FaListUl } from "@react-icons/all-files/fa/FaListUl"; ... function AsideVisibleToggle() { const [targetExists, setTargetExists] = React.useState(false); const [isTargetVisible, setIsTargetVisible] = React.useState(false); const [isOverlayVisible, setIsOverlayVisible] = React.useState(false); const [isSmallScreen, setIsSmallScreen] = React.useState(false); React.useEffect(() => { const targetElement = document.querySelector('.notion-aside-table-of-contents'); setTargetExists(!!targetElement); }, []); React.useEffect(() => { const mediaQuery = window.matchMedia('(max-width: 1300px)'); const handleScreenChange = (e) => { setIsSmallScreen(e.matches); const targetElement = document.querySelector('.notion-aside') as HTMLElement; if (targetElement) { if (e.matches) { setIsTargetVisible(false); } else { targetElement.style.display = 'flex'; targetElement.style.opacity = '1'; targetElement.style.transform = 'translateX(0)'; setIsOverlayVisible(false); } } } mediaQuery.addEventListener('change', handleScreenChange); setIsSmallScreen(mediaQuery.matches); return () => mediaQuery.removeEventListener('change', handleScreenChange); }, []); React.useEffect(() => { const handleClickOutside = (event) => { const targetElement = document.querySelector('.notion-aside'); if (targetElement && !targetElement.contains(event.target) && !event.target.closest('.aside-toggle-button')) { setIsTargetVisible(false); setIsOverlayVisible(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); React.useEffect(() => { const targetElement = document.querySelector('.notion-aside') as HTMLElement; if (!isSmallScreen) { return } if (targetElement) { if (isTargetVisible) { targetElement.style.display = 'flex'; requestAnimationFrame(() => { targetElement.style.opacity = '1'; targetElement.style.transform = 'translateX(0)'; }); } else { targetElement.style.opacity = '0'; targetElement.style.transform = 'translateX(100%)'; setTimeout(() => { if (!isTargetVisible) targetElement.style.display = 'none'; }, 300); } } }, [isSmallScreen, isTargetVisible]); const handleToggleVisibility = () => { setIsTargetVisible(true); setIsOverlayVisible(true); }; return ( <div> {isSmallScreen && targetExists && (<div className="aside-toggle-button" onClick={handleToggleVisibility} > <FaListUl /> </div>)} {isOverlayVisible && (<div className="aside-overlay"></div>)} </div> ); } export function NotionPage({ ... return ( <> ... {isBlogPost && <AsideVisibleToggle key={router.asPath} />} </> ) }

3.2 styles/notion.css

其中 max-width: 1300px 保持与 3.1 的设置值一致。
... .aside-toggle-button { display: none; } .notion-table-of-contents-item { white-space: inherit; } @media (max-width:1300px) and (min-height:300px) { .notion-aside { display: none; position: fixed; top: 0; right: 0; height: 100%; max-width: 80vw; overflow: hidden; z-index: 9999; background: hsla(0, 0%, 100%, 0.8); -webkit-backdrop-filter: saturate(180%) blur(16px); backdrop-filter: saturate(180%) blur(16px); transition: transform 0.3s ease, opacity 0.3s ease; transform: translateX(100%); opacity: 0; } .dark-mode .notion-aside { background: var(--bg-color); } .notion-aside-table-of-contents { background: transparent; margin: calc(var(--notion-header-height) + 16px) 16px 0 16px; } .aside-toggle-button { display: flex; position: fixed; right: 0; top: calc(var(--notion-header-height) + 16px); padding: 12px; border-radius: 16px 0 0 16px; box-shadow: 2px 2px 8px 4px var(--bg-color-0); background: var(--bg-color); color: var(--fg-color); border: 1px solid var(--bg-color-0); border-right: 0; z-index: 9998; } .dark-mode .aside-toggle-button { box-shadow: none; border: 1px solid var(--bg-color-0); border-right: 0; } .aside-overlay { z-index: 9997; position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: all; background: rgba(0, 0, 0, 0.1); } }
代码有不少优化空间,请大佬们轻喷…
我测试了好一些场景,理论上是没有 BUG 的(仅仅是理论上哈哈哈),如果大家发现了请反馈给我,我会及时更新代码,也欢迎 订阅 我的博客获取最新信息。

4 修改之后

如果你不知道修改后应该怎么操作,并且你是根据 如何使用 Notion+Vercel 免费搭建自己的博客 系列中介绍的方法进行搭建的,可以看这里的提示。
只需要保存修改的文件后,在代码根目录执行下方命令进行提交即可。
git add . git commit -m "feat: improve mobile aside" git push
 
 

📌 相关文章

📃

博客的坎坷一生共 1 篇文章
去查看

当前文章已是最新文章

欢迎点击此处订阅最新内容
打赏@R同学救救孩子吧
去打赏