From a1c1e4e4e0a94456ac30c4e6e032a463d76d831e Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 1 Dec 2022 02:23:26 +0100 Subject: [PATCH] More docs work (#839) * wip * add changeset * add more * more content * fix props * fix lint errors * simplify ci * fix lint error --- .changeset/six-pugs-grow.md | 5 + .eslintrc.cjs | 11 +- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 +- docs/components/card/index.tsx | 42 +- docs/components/card/style.module.css | 3 +- docs/components/file-tree/index.tsx | 143 +++++++ docs/components/screenshot/index.jsx | 22 ++ docs/components/video/index.jsx | 14 + docs/pages/docs/_meta.json | 2 +- docs/pages/docs/custom-theme.mdx | 1 + docs/pages/docs/docs-theme.mdx | 6 +- docs/pages/docs/docs-theme/_meta.json | 6 +- .../docs-theme/{components.mdx => api.mdx} | 2 +- .../docs-theme/{components => api}/bleed.mdx | 0 .../{components => api}/callout.mdx | 0 .../docs-theme/{components => api}/tabs.mdx | 0 .../docs/docs-theme/page-configuration.mdx | 372 +++++++++++++++++- docs/pages/docs/docs-theme/start.mdx | 60 +-- .../docs/docs-theme/theme-configuration.mdx | 135 +++++-- docs/pages/docs/guide.mdx | 29 +- docs/pages/docs/guide/cms.mdx | 1 - docs/pages/docs/index.mdx | 55 +-- docs/pages/docs/your-own-theme.mdx | 1 - docs/pages/index.mdx | 6 +- docs/public/assets/docs/logo.png | Bin 0 -> 20042 bytes docs/public/assets/docs/menu.png | Bin 0 -> 45058 bytes .../public/assets/docs/sidebar-customized.png | Bin 0 -> 113051 bytes docs/public/assets/docs/sub-docs.mp4 | Bin 0 -> 694653 bytes docs/style.css | 39 ++ docs/theme.config.tsx | 24 +- .../src/components/callout.tsx | 2 +- packages/nextra/src/components/pre.tsx | 2 +- 33 files changed, 832 insertions(+), 157 deletions(-) create mode 100644 .changeset/six-pugs-grow.md create mode 100644 docs/components/file-tree/index.tsx create mode 100644 docs/components/screenshot/index.jsx create mode 100644 docs/components/video/index.jsx create mode 100644 docs/pages/docs/custom-theme.mdx rename docs/pages/docs/docs-theme/{components.mdx => api.mdx} (98%) rename docs/pages/docs/docs-theme/{components => api}/bleed.mdx (100%) rename docs/pages/docs/docs-theme/{components => api}/callout.mdx (100%) rename docs/pages/docs/docs-theme/{components => api}/tabs.mdx (100%) delete mode 100644 docs/pages/docs/guide/cms.mdx delete mode 100644 docs/pages/docs/your-own-theme.mdx create mode 100644 docs/public/assets/docs/logo.png create mode 100644 docs/public/assets/docs/menu.png create mode 100644 docs/public/assets/docs/sidebar-customized.png create mode 100644 docs/public/assets/docs/sub-docs.mp4 diff --git a/.changeset/six-pugs-grow.md b/.changeset/six-pugs-grow.md new file mode 100644 index 0000000000..15287622ff --- /dev/null +++ b/.changeset/six-pugs-grow.md @@ -0,0 +1,5 @@ +--- +'nextra': patch +--- + +Update docs diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 4d65fabc38..1559318477 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -5,7 +5,7 @@ const TAILWIND_CONFIG = { 'tailwindcss/enforces-negative-arbitrary-values': 'error', 'tailwindcss/enforces-shorthand': 'error', 'tailwindcss/migration-from-tailwind-2': 'error', - 'tailwindcss/no-custom-classname': 'error' + 'tailwindcss/no-custom-classname': 'warn' } } @@ -94,7 +94,14 @@ module.exports = { tailwindcss: { config: 'docs/tailwind.config.js', callees: ['cn'], - whitelist: ['dash-ring', 'theme-1', 'theme-2', 'theme-3', 'theme-4', 'border-primary-100/10$'] + whitelist: [ + 'dash-ring', + 'theme-1', + 'theme-2', + 'theme-3', + 'theme-4', + 'border-primary-100/10$' + ] } } } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbed838e41..4fc2bc787b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16, 18] + node-version: [18] os: [ubuntu-latest, windows-latest] steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 06a7afe821..fd516204fb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,8 +22,8 @@ jobs: - name: Install Node.js uses: actions/setup-node@v3 with: - node-version: 16 - cache: "pnpm" + node-version: 18 + cache: 'pnpm' - name: Install Dependencies run: pnpm i diff --git a/docs/components/card/index.tsx b/docs/components/card/index.tsx index 3f215580ac..31d068817d 100644 --- a/docs/components/card/index.tsx +++ b/docs/components/card/index.tsx @@ -3,7 +3,16 @@ import Link from 'next/link' import styles from './style.module.css' -export function Card({ children, title, icon, image, arrow, href, ...props }) { +export function Card({ + children, + title, + icon, + image, + arrow, + demo, + href, + ...props +}) { const animatedArrow = arrow ? ( @@ -30,13 +39,15 @@ export function Card({ children, title, icon, image, arrow, href, ...props }) { {icon} - {title} - {animatedArrow} + + {title} + {animatedArrow} + ) @@ -47,15 +58,15 @@ export function Card({ children, title, icon, image, arrow, href, ...props }) { href={href} className={cn( styles.card, - 'group flex flex-col justify-start overflow-hidden rounded-lg border border-transparent bg-gray-100 text-current no-underline shadow shadow-transparent transition-all duration-200', - 'hover:border-gray-200 hover:shadow-md hover:shadow-gray-100' + 'group flex flex-col justify-start overflow-hidden rounded-lg border border-gray-200 text-current no-underline shadow-sm shadow-gray-100 transition-all duration-200', + 'hover:border-gray-300 hover:bg-slate-50 hover:shadow-md hover:shadow-gray-100' )} {...props} > @@ -67,9 +78,18 @@ export function Card({ children, title, icon, image, arrow, href, ...props }) { ) } -export function Cards({ children, ...props }) { +export function Cards({ children, num, ...props }) { return ( -
+
{children}
) diff --git a/docs/components/card/style.module.css b/docs/components/card/style.module.css index b0a86f9a35..10eca5719e 100644 --- a/docs/components/card/style.module.css +++ b/docs/components/card/style.module.css @@ -1,8 +1,9 @@ .cards { display: grid; + --rows: 3; grid-template-columns: repeat( auto-fill, - minmax(max(250px, calc((100% - 1rem * 2) / 3)), 1fr) + minmax(max(250px, calc((100% - 1rem * 2) / var(--rows))), 1fr) ); } diff --git a/docs/components/file-tree/index.tsx b/docs/components/file-tree/index.tsx new file mode 100644 index 0000000000..b7a580e799 --- /dev/null +++ b/docs/components/file-tree/index.tsx @@ -0,0 +1,143 @@ +import React, { useState, useCallback, createContext, useContext } from 'react' +import cn from 'clsx' +import type { ReactElement } from 'react' + +const ctx = createContext(0) + +export const { Provider, Consumer } = ctx +export function useIndent() { + return useContext(ctx) || 0 +} +export default ctx + +interface FolderProps { + name: string + label?: ReactElement + open?: boolean + defaultOpen?: boolean + onToggle?: (open: boolean) => void + children: ReactElement | ReactElement[] +} + +interface FileProps { + name: string + label?: ReactElement + active?: boolean + children: ReactElement | ReactElement[] +} + +const Tree: React.FC<{ + children: ReactElement | ReactElement[] +}> = ({ children }) => ( +
+
+ {children} +
+
+) + +function Ident() { + const indent = useIndent() + + return ( + <> + {[...Array(indent)].map((_, i) => ( + + ))} + + ) +} + +const Folder: React.FC = React.memo( + ({ label, name, open, children, defaultOpen, onToggle }) => { + const indent = useIndent() + + const [isOpen, setIsOpen] = useState(defaultOpen || false) + + const toggle = useCallback(() => { + onToggle && onToggle(!isOpen) + setIsOpen(!isOpen) + }, [isOpen, onToggle]) + + const isFolderOpen = typeof open === 'undefined' ? isOpen : open + + return ( +
  • + + + + {isFolderOpen ? ( + + + + ) : ( + + + + )} + + {label ?? name} + + {isFolderOpen ? ( +
      + {children} +
    + ) : null} +
  • + ) + } +) + +Folder.displayName = 'Folder' + +const File: React.FC = React.memo( + ({ label, name, active, ...props }) => { + return ( +
  • + + + + + + + + {label ?? name} + +
  • + ) + } +) + +File.displayName = 'File' + +export { Tree, Folder, File } diff --git a/docs/components/screenshot/index.jsx b/docs/components/screenshot/index.jsx new file mode 100644 index 0000000000..8e2f8a0d7c --- /dev/null +++ b/docs/components/screenshot/index.jsx @@ -0,0 +1,22 @@ +import cn from 'clsx' +import Image from 'next/image' + +export function Screenshot({ src, alt, full }) { + return ( +
    + {alt} +
    + ) +} diff --git a/docs/components/video/index.jsx b/docs/components/video/index.jsx new file mode 100644 index 0000000000..d7c0df9d27 --- /dev/null +++ b/docs/components/video/index.jsx @@ -0,0 +1,14 @@ +export default function Video({ src }) { + return ( + + ) +} diff --git a/docs/pages/docs/_meta.json b/docs/pages/docs/_meta.json index e0208da1bc..941f902aec 100644 --- a/docs/pages/docs/_meta.json +++ b/docs/pages/docs/_meta.json @@ -7,7 +7,7 @@ }, "docs-theme": "Docs Theme", "blog-theme": "Blog Theme", - "your-own-theme": "Your Own Theme", + "custom-theme": "Custom Theme", "-- About --": { "type": "separator", "title": "About" diff --git a/docs/pages/docs/custom-theme.mdx b/docs/pages/docs/custom-theme.mdx new file mode 100644 index 0000000000..483c6d2cdd --- /dev/null +++ b/docs/pages/docs/custom-theme.mdx @@ -0,0 +1 @@ +# Custom Theme diff --git a/docs/pages/docs/docs-theme.mdx b/docs/pages/docs/docs-theme.mdx index af469220b9..d6e41ec4d4 100644 --- a/docs/pages/docs/docs-theme.mdx +++ b/docs/pages/docs/docs-theme.mdx @@ -10,9 +10,9 @@ import { Card, Cards } from '@components/card' } title="Get Started" href="/docs/docs-theme/start"> - - + + + } title="Page Configuration" href="/docs/docs-theme/page-configuration"> + Read more about Nextra's `_meta.json` files [here](/docs/guide/organize-files). + + +## Pages + +The title and order of a page shown in the sidebar should be configured in the `_meta.json` file as key-value pairs. For example, if you have the following file structure: + + + + + + + + + + +You can define how the pages are shown in the sidebar via the `_meta.json` file: + +```json filename="_meta.json" +{ + "index": "My Homepage", + "contact": "Contact Us", + "about": "About Us" +} +``` + + + If any routes are not listed in the `_meta.json` file, they will be appended to the end of the sidebar and sorted alphabetically, and the title will be formatted with [Title](https://title.sh). + + +## Folders + +Folders can be configured in the same way as pages. For example: + + + + + + + + + + + + + + + +The top-level `_meta.json` file contains the meta information for the top-level pages and folders: + +```json filename="pages/_meta.json" +{ + "index": "My Homepage", + "contact": "Contact Us", + "fruits": "Delicious Fruits", + "about": "About Us" +} +``` + +And the nested `_meta.json` file contains the meta information for pages in the same folder: + +```json filename="pages/fruits/_meta.json" +{ + "apple": "Apple", + "banana": "Banana" +} +``` + +This way, information for pages are grouped together in directories. You can move directories around without having to change the `_meta.json` file. + +### Folders with Index Page + +What if I want to have a folder with an index page? We can add a MDX page with the same name and in the same directory as the folder. Let's say we want to add `/fruits` route in the example above, we can create a `fruits.mdx` file in pages: + + + + + + + + + + + + + + + + +Then Nextra knows that the `fruits` key in `_meta.json` defines a folder with an index page. If you click that folder in the sidebar, it will open the folder and show you the `fruits.mdx` page at the same time. + +## External Links + +You can add external links to the sidebar by adding an item with `href` in `_meta.json`: + +```json filename="pages/_meta.json" {6-9} +{ + "index": "My Homepage", + "contact": "Contact Us", + "fruits": "Delicious Fruits", + "about": "About Us", + "github_link": { + "title": "Nextra", + "href": "https://github.com/shuding/nextra" + } +} +``` + +To always open the link in a new tab, enable the `"newWindow": true` option: + +```json filename="pages/_meta.json" {9} +{ + "index": "My Homepage", + "contact": "Contact Us", + "fruits": "Delicious Fruits", + "about": "About Us", + "github_link": { + "title": "Nextra", + "href": "https://github.com/shuding/nextra", + "newWindow": true + } +} +``` + +You can use this option to link to relative internal links too. + +## Hidden Routes + +By default, all MDX routes in the filesystem will be shown on the sidebar. But you can hide a specific pages or folders by using the `"display": "hidden"` configuration: + +```json filename="pages/_meta.json" {4} +{ + "index": "My Homepage", + "contact": { + "display": "hidden" + }, + "about": "About Us" +} +``` + +The page will still be accessible via the `/contact` URL, but it will not be shown in the sidebar. + +## Navbar Items + +### Sub Docs + +By defining a top-level page or folder as `"type": "page"`, it will be shown as a special page on the navigation bar, instead of the sidebar. With this feature, you can have multiple "sub docs", and special pages or links such as "Contact Us" that are always visible. + +For example, you can have 2 docs folders `frameworks` and `fruits` in your project: + + + + + + + + + + + + + + + + + + +In your top-level `_meta.json` file, you can set everything as a page, instead of a normal sidebar item: + +```json filename="pages/_meta.json" +{ + "index": { + "title": "Home", + "type": "page" + }, + "frameworks": { + "title": "Frameworks", + "type": "page" + }, + "fruits": { + "title": "Fruits", + "type": "page" + }, + "about": { + "title": "About", + "type": "page" + } +} +``` + +And it will look like this: + +
    -
    {children}
    +
    {children}
    ) } diff --git a/packages/nextra/src/components/pre.tsx b/packages/nextra/src/components/pre.tsx index 0595b6eafd..eea0b90d86 100644 --- a/packages/nextra/src/components/pre.tsx +++ b/packages/nextra/src/components/pre.tsx @@ -32,7 +32,7 @@ export const Pre = ({ )}