diff --git a/.nvmrc b/.nvmrc index 0828ab794..209e3ef4b 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v18 \ No newline at end of file +20 diff --git a/Dockerfile b/Dockerfile index f715addb1..c73bacf1c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18-alpine +FROM node:20-alpine COPY . /app diff --git a/package.json b/package.json index f6fba8f59..c7603525d 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "typescript": "^5.2.2" }, "engines": { - "node": ">=18.0.0", + "node": ">=20.0.0", "pnpm": ">=8.0.0" } } diff --git a/packages/blog-starter-kit/themes/enterprise/components/post-toc.tsx b/packages/blog-starter-kit/themes/enterprise/components/post-toc.tsx index 6bc23b40d..d4fd21422 100644 --- a/packages/blog-starter-kit/themes/enterprise/components/post-toc.tsx +++ b/packages/blog-starter-kit/themes/enterprise/components/post-toc.tsx @@ -1,6 +1,12 @@ +import { useState } from 'react'; import Link from 'next/link'; +import { List } from 'react-feather'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; import { PostFullFragment } from '../generated/graphql'; import { useAppContext } from './contexts/appContext'; +import { Button } from './button'; +import CloseSVG from './icons/svgs/CloseSVG'; +import CustomScrollArea from './scroll-area'; type TableOfContentsItem = PostFullFragment['features']['tableOfContents']['items'][number]; @@ -29,9 +35,11 @@ const mapTableOfContentItems = (toc: TableOfContentsItem[]) => { const Toc = ({ data, parentId, + onNavigate, }: { data: TableOfContentsItem[]; parentId: TableOfContentsItem['parentId']; + onNavigate?: () => void; }) => { const children = data.filter((item) => item.parentId === parentId); if (children.length === 0) return null; @@ -41,21 +49,21 @@ const Toc = ({
  • {item.title} - +
  • ))} ); }; -export const PostTOC = () => { +const TagsList = () => { const { post } = useAppContext(); - if (!post) return null; const tagsList = post.tags?.map((tag) => ( @@ -69,15 +77,81 @@ export const PostTOC = () => { )); + return ( +
    + +
    + ); +}; + +export const PostTOC = () => { + const { post } = useAppContext(); + + if (!post) return null; + return (
    -
    -
      {tagsList}
    -
    +

    On this page

    ); }; + +export const PostTOCMobile = () => { + const { post } = useAppContext(); + const [isOpen, setIsOpen] = useState(false); + + if (!post) return null; + + const closeModal = () => setIsOpen(false); + + return ( +
    +
    + ); +}; diff --git a/packages/blog-starter-kit/themes/enterprise/pages/[slug].tsx b/packages/blog-starter-kit/themes/enterprise/pages/[slug].tsx index 39b68da84..7133d245d 100644 --- a/packages/blog-starter-kit/themes/enterprise/pages/[slug].tsx +++ b/packages/blog-starter-kit/themes/enterprise/pages/[slug].tsx @@ -29,7 +29,7 @@ import { useEffect, useState } from 'react'; import { resizeImage } from '@starter-kit/utils/image'; import { triggerCustomWidgetEmbed } from '@starter-kit/utils/trigger-custom-widget-embed'; import { CoverImage } from '../components/cover-image'; -import { PostTOC } from '../components/post-toc'; +import { PostTOC, PostTOCMobile } from '../components/post-toc'; const AboutAuthor = dynamic(() => import('../components/about-author'), { ssr: false }); const Subscribe = dynamic(() => import('../components/subscribe').then((mod) => mod.Subscribe)); @@ -136,6 +136,12 @@ const Post = ({ publication, post }: PostProps) => { author={post.author} readTimeInMinutes={post.readTimeInMinutes} /> + {post.features.tableOfContents.isEnabled && + post.features?.tableOfContents?.items?.length > 0 && ( +
    + +
    + )}
    {post.subtitle && (