diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000000..7768da2ba0 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,2 @@ +beta: +- beta/**/* diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml new file mode 100644 index 0000000000..13a37a88c1 --- /dev/null +++ b/.github/workflows/analyze.yml @@ -0,0 +1,96 @@ +name: Analyze Bundle + +on: + pull_request: + push: + branches: + - main # change this if your default branch is named differently + workflow_dispatch: + +jobs: + analyze: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Set up node + uses: actions/setup-node@v1 + with: + node-version: "14.x" + + - name: Install dependencies + uses: bahmutov/npm-install@v1.6.0 + with: + working-directory: 'beta' + + - name: Restore next build + uses: actions/cache@v2 + id: restore-build-cache + env: + cache-name: cache-next-build + with: + path: beta/.next/cache + # change this if you prefer a more strict cache + key: ${{ runner.os }}-build-${{ env.cache-name }} + + - name: Build next.js app + # change this if your site requires a custom build command + run: ./node_modules/.bin/next build + working-directory: beta + + # Here's the first place where next-bundle-analysis' own script is used + # This step pulls the raw bundle stats for the current bundle + - name: Analyze bundle + run: npx -p nextjs-bundle-analysis report + working-directory: beta + + - name: Upload bundle + uses: actions/upload-artifact@v2 + with: + path: beta/.next/analyze/__bundle_analysis.json + name: bundle_analysis.json + + - name: Download base branch bundle stats + uses: dawidd6/action-download-artifact@v2 + if: success() && github.event.number + with: + workflow: bundle_analysis_upload.yml + branch: ${{ github.event.pull_request.base.ref }} + name: bundle_analysis.json + path: beta/.next/analyze/base/bundle + + # And here's the second place - this runs after we have both the current and + # base branch bundle stats, and will compare them to determine what changed. + # There are two configurable arguments that come from package.json: + # + # - budget: optional, set a budget (bytes) against which size changes are measured + # it's set to 350kb here by default, as informed by the following piece: + # https://infrequently.org/2021/03/the-performance-inequality-gap/ + # + # - red-status-percentage: sets the percent size increase where you get a red + # status indicator, defaults to 20% + # + # Either of these arguments can be changed or removed by editing the `nextBundleAnalysis` + # entry in your package.json file. + - name: Compare with base branch bundle + if: success() && github.event.number + run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare + working-directory: beta + + - name: Upload analysis comment + uses: actions/upload-artifact@v2 + with: + name: analysis_comment.txt + path: beta/.next/analyze/__bundle_analysis_comment.txt + + - name: Save PR number + run: echo ${{ github.event.number }} > ./pr_number + + - name: Upload PR number + uses: actions/upload-artifact@v2 + with: + name: pr_number + path: ./pr_number + + # The actual commenting happens in the other action, matching the guidance in + # https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ diff --git a/.github/workflows/analyze_comment.yml b/.github/workflows/analyze_comment.yml new file mode 100644 index 0000000000..8166089fdc --- /dev/null +++ b/.github/workflows/analyze_comment.yml @@ -0,0 +1,72 @@ +name: Analyze Bundle (Comment) + +on: + workflow_run: + workflows: ["Analyze Bundle"] + types: + - completed + +jobs: + comment: + runs-on: ubuntu-latest + if: > + ${{ github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' }} + steps: + - name: Download base branch bundle stats + uses: dawidd6/action-download-artifact@v2 + with: + workflow: analyze.yml + run_id: ${{ github.event.workflow_run.id }} + name: analysis_comment.txt + path: analysis_comment.txt + + - name: Download PR number + uses: dawidd6/action-download-artifact@v2 + with: + workflow: analyze.yml + run_id: ${{ github.event.workflow_run.id }} + name: pr_number + path: pr_number + + - name: Get comment body + id: get-comment-body + if: success() + run: | + pr_number=$(cat pr_number/pr_number) + body=$(cat analysis_comment.txt/__bundle_analysis_comment.txt) + body="## Size Changes +
+ + ${body} + +
" + body="${body//'%'/'%25'}" + body="${body//$'\n'/'%0A'}" + body="${body//$'\r'/'%0D'}" + echo ::set-output name=body::$body + echo ::set-output name=pr-number::$pr_number + + - name: Find Comment + uses: peter-evans/find-comment@v1 + if: success() + id: fc + with: + issue-number: ${{ steps.get-comment-body.outputs.pr-number }} + body-includes: "" + + - name: Create Comment + uses: peter-evans/create-or-update-comment@v1.4.4 + if: success() && steps.fc.outputs.comment-id == 0 + with: + issue-number: ${{ steps.get-comment-body.outputs.pr-number }} + body: ${{ steps.get-comment-body.outputs.body }} + + - name: Update Comment + uses: peter-evans/create-or-update-comment@v1.4.4 + if: success() && steps.fc.outputs.comment-id != 0 + with: + issue-number: ${{ steps.get-comment-body.outputs.pr-number }} + body: ${{ steps.get-comment-body.outputs.body }} + comment-id: ${{ steps.fc.outputs.comment-id }} + edit-mode: replace \ No newline at end of file diff --git a/.github/workflows/beta_site_lint.yml b/.github/workflows/beta_site_lint.yml new file mode 100644 index 0000000000..40d1c3f853 --- /dev/null +++ b/.github/workflows/beta_site_lint.yml @@ -0,0 +1,27 @@ +name: Beta Site Lint + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + + name: Lint on node 12.x and ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + + - name: Install deps and build (with cache) + uses: bahmutov/npm-install@v1.6.0 + with: + working-directory: 'beta' + + + - name: Lint codebase + run: cd beta && yarn ci-check diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml new file mode 100644 index 0000000000..90a961d4c5 --- /dev/null +++ b/.github/workflows/label.yml @@ -0,0 +1,22 @@ +# This workflow will triage pull requests and apply a label based on the +# paths that are modified in the pull request. +# +# To use this workflow, you will need to set up a .github/labeler.yml +# file with configuration. For more information, see: +# https://github.com/actions/labeler + +name: Labeler +on: [pull_request_target] + +jobs: + label: + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + + steps: + - uses: actions/labeler@v2 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 49d3621c56..eae9820a7c 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -18,7 +18,7 @@ jobs: node-version: 12.x - name: Install deps and build (with cache) - uses: bahmutov/npm-install@v1 + uses: bahmutov/npm-install@v1.6.0 - name: Lint codebase run: yarn ci-check diff --git a/beta/.eslintrc b/beta/.eslintrc index e09462ca8c..9df06b09f0 100644 --- a/beta/.eslintrc +++ b/beta/.eslintrc @@ -1,18 +1,10 @@ { - "extends": ["react-app", "plugin:jsx-a11y/recommended"], - "plugins": ["jsx-a11y"], - "overrides": [ - { - "files": ["**/*.ts?(x)"], - "rules": { - "jsx-a11y/anchor-is-valid": 0 - } - } - ], + "root": true, + "extends": "next", "env": { "node": true, "commonjs": true, "browser": true, "es6": true } -} +} \ No newline at end of file diff --git a/beta/.husky/pre-commit b/beta/.husky/pre-commit new file mode 100755 index 0000000000..c2af848941 --- /dev/null +++ b/beta/.husky/pre-commit @@ -0,0 +1,8 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +cd beta +# yarn generate-ids +# git add -u src/pages/**/*.md +yarn prettier +yarn lint:fix \ No newline at end of file diff --git a/beta/.prettierrc b/beta/.prettierrc index 6ba2b30061..36b8264e31 100644 --- a/beta/.prettierrc +++ b/beta/.prettierrc @@ -1,7 +1,7 @@ { "bracketSpacing": false, "singleQuote": true, - "jsxBracketSameLine": true, + "bracketSameLine": true, "trailingComma": "es5", "printWidth": 80 } diff --git a/beta/README.md b/beta/README.md index e47628e92c..85f6703e95 100644 --- a/beta/README.md +++ b/beta/README.md @@ -16,10 +16,12 @@ This repo contains the source code and documentation powering [reactjs.org](http ### Installation 1. `cd reactjs.org` to go into the project root -1. `yarn` to install the website's npm dependencies +1. `cd beta` to open the beta website +3. `yarn` to install the website's npm dependencies ### Running locally +1. Make sure you're in the `beta` folder 1. `yarn dev` to start the development server (powered by [Next.js](https://nextjs.org/)) 1. `open http://localhost:3000` to open the site in your favorite browser @@ -46,7 +48,7 @@ The documentation is divided into several sections with a different tone and pur ### Test the change 1. If possible, test any visual changes in all latest versions of common browsers, on both desktop and mobile. -1. Run `yarn check-all` from the project root. (This will run Prettier, ESLint, and Flow.) +2. Run `yarn check-all` from the `beta` folder. (This will run Prettier, ESLint and validate types.) ### Push it diff --git a/beta/colors.js b/beta/colors.js index 1c3e26f11b..bac74d41e9 100644 --- a/beta/colors.js +++ b/beta/colors.js @@ -23,6 +23,7 @@ module.exports = { 'secondary-button-dark': '#404756', // gray-70 // Gray + 'gray-95': '#16181D', 'gray-90': '#23272F', 'gray-80': '#343A46', 'gray-70': '#404756', diff --git a/beta/next.config.js b/beta/next.config.js index f0d1216c07..9f925932a4 100644 --- a/beta/next.config.js +++ b/beta/next.config.js @@ -10,7 +10,8 @@ module.exports = { pageExtensions: ['jsx', 'js', 'ts', 'tsx', 'mdx', 'md'], experimental: { plugins: true, - reactMode: 'concurrent', + // TODO: this doesn't work because https://github.com/vercel/next.js/issues/30714 + // concurrentFeatures: true, scrollRestoration: true, }, async redirects() { @@ -30,6 +31,18 @@ module.exports = { ]; }, webpack: (config, {dev, isServer, ...options}) => { + if (process.env.ANALYZE) { + const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer') + config.plugins.push( + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + reportFilename: options.isServer + ? '../analyze/server.html' + : './analyze/client.html', + }) + ); + } + // Add our custom markdown loader in order to support frontmatter // and layout config.module.rules.push({ diff --git a/beta/package.json b/beta/package.json index fde750e3d2..8f27f27074 100644 --- a/beta/package.json +++ b/beta/package.json @@ -4,36 +4,35 @@ "private": true, "license": "CC", "scripts": { + "analyze": "ANALYZE=true next build", "dev": "next", "build": "next build && node ./scripts/generateRSS.js", - "lint": "eslint 'src/**/*.{js,ts,tsx}'", + "lint": "next lint", + "lint:fix": "next lint --fix", "format:source": "prettier --config .prettierrc --write \"{plugins,src}/**/*.{js,ts,jsx,tsx}\"", "nit:source": "prettier --config .prettierrc --list-different \"{plugins,src}/**/*.{js,ts,jsx,tsx}\"", "prettier": "yarn format:source", "prettier:diff": "yarn nit:source", - "generate-ids": "node scripts/generateHeadingIDs.js src/pages/docs && node scripts/generateHeadingIDs.js src/pages/blog", + "generate-ids": "node scripts/generateHeadingIDs.js src/pages/", "ci-check": "npm-run-all prettier:diff --parallel lint tsc", "tsc": "tsc --noEmit", - "start": "next start" + "start": "next start", + "postinstall": "is-ci || (cd .. && husky install beta/.husky)", + "check-all": "npm-run-all prettier lint:fix tsc" }, "dependencies": { - "@codesandbox/sandpack-react": "^0.1.15", - "@docsearch/react": "3.0.0-alpha.41", + "@codesandbox/sandpack-react": "^0.1.20", "@docsearch/css": "3.0.0-alpha.41", + "@docsearch/react": "3.0.0-alpha.41", "@headlessui/react": "^1.3.0", - "@mdx-js/mdx": "^1.6.16", "@mdx-js/react": "^1.6.16", - "@mdx-js/tag": "^0.20.3", "@next/plugin-google-analytics": "^10.0.6", - "add": "^2.0.6", "body-scroll-lock": "^3.1.3", "classnames": "^2.2.6", - "copy-to-clipboard": "^3.3.1", "date-fns": "^2.16.1", "debounce": "^1.2.1", "github-slugger": "^1.3.0", - "hex2rgba": "^0.0.1", - "next": "^11.1.2", + "next": "^12.0.3-canary.2", "parse-numeric-range": "^1.2.0", "react": "18.0.0-alpha-930c9e7ee-20211015", "react-collapsed": "3.1.0", @@ -55,7 +54,8 @@ "asyncro": "^3.0.0", "autoprefixer": "^10.3.1", "babel-eslint": "10.x", - "eslint": "6.x", + "eslint": "7.x", + "eslint-config-next": "12.0.3", "eslint-config-react-app": "^5.2.1", "eslint-plugin-flowtype": "4.x", "eslint-plugin-import": "2.x", @@ -65,6 +65,8 @@ "fs-extra": "^9.0.1", "globby": "^11.0.1", "gray-matter": "^4.0.2", + "husky": "^7.0.4", + "is-ci": "^3.0.1", "mdast-util-to-string": "^1.1.0", "npm-run-all": "^4.1.5", "patch-package": "^6.2.2", @@ -77,15 +79,22 @@ "remark-external-links": "^7.0.0", "remark-html": "^13.0.2", "remark-images": "^2.0.0", + "remark-slug": "^7.0.0", "remark-unwrap-images": "^2.0.0", "retext": "^7.0.1", "retext-smartypants": "^4.0.0", "rss": "^1.2.2", "tailwindcss": "^2.2.7", "typescript": "^4.0.2", - "unist-util-visit": "^2.0.3" + "unist-util-visit": "^2.0.3", + "webpack-bundle-analyzer": "^4.5.0" }, "engines": { "node": ">=12.x" + }, + "nextBundleAnalysis": { + "budget": null, + "budgetPercentIncreaseRed": 10, + "showDetails": true } } diff --git a/beta/plugins/md-layout-loader.js b/beta/plugins/md-layout-loader.js index 7937923bf4..1fee3136d7 100644 --- a/beta/plugins/md-layout-loader.js +++ b/beta/plugins/md-layout-loader.js @@ -1,4 +1,5 @@ const fm = require('gray-matter'); +const path = require('path'); // Makes mdx in next.js suck less by injecting necessary exports so that // the docs are still readable on github. @@ -15,7 +16,16 @@ const fm = require('gray-matter'); module.exports = async function (src) { const callback = this.async(); const {content, data} = fm(src); - const layout = data.layout || 'Learn'; + const pageParentDir = path + .dirname(path.relative('./src/pages', this.resourcePath)) + .split(path.sep) + .shift(); + const layoutMap = { + blog: 'Post', + learn: 'Learn', + reference: 'API', + }; + const layout = layoutMap[pageParentDir] || 'Home'; const code = `import withLayout from 'components/Layout/Layout${layout}'; diff --git a/beta/plugins/remark-header-custom-ids.js b/beta/plugins/remark-header-custom-ids.js index 00d33aef70..bf51e98e09 100644 --- a/beta/plugins/remark-header-custom-ids.js +++ b/beta/plugins/remark-header-custom-ids.js @@ -30,16 +30,34 @@ module.exports = ({ slugs.reset(); return function transformer(tree) { visit(tree, 'heading', (node) => { - // Support custom-id syntax. - const rawHeader = toString(node); - const match = /^.+(\s*\{#([a-z0-9\-_]+?)\}\s*)$/.exec(rawHeader); - const id = match ? match[2] : slugs.slug(rawHeader, maintainCase); - if (match) { - // Remove the custom ID part from the text node. - const lastNode = node.children[node.children.length - 1]; - lastNode.value = lastNode.value.replace(match[1], ''); + const children = node.children; + let tail = children[children.length - 1]; + + // A bit weird: this is to support MDX 2 comments in expressions, + // while we’re still on MDX 1, which doesn’t support them. + if (!tail || tail.type !== 'text' || tail.value !== '/}') { + return; } + tail = children[children.length - 2]; + + if (!tail && tail.type !== 'emphasis') { + return; + } + + const id = toString(tail); + + tail = children[children.length - 3]; + + if (!tail || tail.type !== 'text' || !tail.value.endsWith('{/')) { + return; + } + + // Remove the emphasis and trailing `/}` + children.splice(children.length - 2, 2); + // Remove the `{/` + tail.value = tail.value.replace(/[ \t]*\{\/$/, ''); + const data = patch(node, 'data', {}); patch(data, 'id', id); diff --git a/beta/scripts/generateHeadingIDs.js b/beta/scripts/generateHeadingIDs.js index 9a36c54987..d8690172d9 100644 --- a/beta/scripts/generateHeadingIDs.js +++ b/beta/scripts/generateHeadingIDs.js @@ -2,9 +2,16 @@ * Copyright (c) Facebook, Inc. and its affiliates. */ +// To do: Make this ESM. +// To do: properly check heading numbers (headings with the same text get +// numbered, this script doesn’t check that). + +const assert = require('assert'); const fs = require('fs'); const GithubSlugger = require('github-slugger'); +let modules + function walk(dir) { let results = []; const list = fs.readdirSync(dir); @@ -31,15 +38,25 @@ function addHeaderID(line, slugger) { if (!line.startsWith('#')) { return line; } - // check if it already has an id - if (/\{#[^}]+\}/.test(line)) { - return line; + + const match = /^(#+\s+)(.+?)(\s*\{(?:\/\*|#)([^\}\*\/]+)(?:\*\/)?\}\s*)?$/.exec(line); + const before = match[1] + match[2] + const proc = modules.unified().use(modules.remarkParse).use(modules.remarkSlug) + const tree = proc.runSync(proc.parse(before)) + const head = tree.children[0] + assert(head && head.type === 'heading', 'expected `' + before + '` to be a heading, is it using a normal space after `#`?') + const autoId = head.data.id + const existingId = match[4] + const id = existingId || autoId + // Ignore numbers: + const cleanExisting = existingId ? existingId.replace(/-\d+$/, '') : undefined + const cleanAuto = autoId.replace(/-\d+$/, '') + + if (cleanExisting && cleanExisting !== cleanAuto) { + console.log('Note: heading `%s` has a different ID (`%s`) than what GH generates for it: `%s`:', before, existingId, autoId) } - const headingText = line.slice(line.indexOf(' ')).trim(); - const headingLevel = line.slice(0, line.indexOf(' ')); - return `${headingLevel} ${headingText} {#${slugger.slug( - stripLinks(headingText) - )}}`; + + return match[1] + match[2] + ' {/*' + id + '*/}'; } function addHeaderIDs(lines) { @@ -66,14 +83,26 @@ function addHeaderIDs(lines) { const [path] = process.argv.slice(2); -const files = walk(path); -files.forEach((file) => { - if (!(file.endsWith('.md') || file.endsWith('.mdx'))) { - return; - } +main() + +async function main() { + const [unifiedMod, remarkParseMod, remarkSlugMod] = await Promise.all([import('unified'), import('remark-parse'), import('remark-slug')]) + const unified = unifiedMod.default + const remarkParse = remarkParseMod.default + const remarkSlug = remarkSlugMod.default + modules = {unified, remarkParse, remarkSlug} - const content = fs.readFileSync(file, 'utf8'); - const lines = content.split('\n'); - const updatedLines = addHeaderIDs(lines); - fs.writeFileSync(file, updatedLines.join('\n')); -}); + const files = walk(path); + + files.forEach((file) => { + if (!(file.endsWith('.md') || file.endsWith('.mdx'))) { + return; + } + + const content = fs.readFileSync(file, 'utf8'); + const lines = content.split('\n'); + const updatedLines = addHeaderIDs(lines); + fs.writeFileSync(file, updatedLines.join('\n')); + }); + +} diff --git a/beta/src/components/Button.tsx b/beta/src/components/Button.tsx index 7d318f4b2f..9d4d0cf2b0 100644 --- a/beta/src/components/Button.tsx +++ b/beta/src/components/Button.tsx @@ -32,8 +32,10 @@ export function Button({ className, 'text-base leading-tight font-bold border rounded-lg py-2 px-4 focus:ring-1 focus:ring-offset-2 focus:ring-link active:bg-link active:border-link active:text-white active:ring-0 active:ring-offset-0 outline-none inline-flex items-center my-1', { - 'bg-link border-link text-white hover:bg-link focus:bg-link active:bg-link': active, - 'bg-transparent text-secondary dark:text-secondary-dark bg-secondary-button dark:bg-secondary-button-dark hover:text-link focus:text-link border-transparent': !active, + 'bg-link border-link text-white hover:bg-link focus:bg-link active:bg-link': + active, + 'bg-transparent text-secondary dark:text-secondary-dark bg-secondary-button dark:bg-secondary-button-dark hover:text-link focus:text-link border-transparent': + !active, } )}> {children} diff --git a/beta/src/components/Layout/MarkdownPage.tsx b/beta/src/components/Layout/MarkdownPage.tsx index 630ca7f3e8..78badc8e2f 100644 --- a/beta/src/components/Layout/MarkdownPage.tsx +++ b/beta/src/components/Layout/MarkdownPage.tsx @@ -123,7 +123,7 @@ export function MarkdownPage< flushWrapper('last'); return ( -
+
{!isHomePage && ( diff --git a/beta/src/components/Layout/Nav/MobileNav.tsx b/beta/src/components/Layout/Nav/MobileNav.tsx index a6b6cc919b..2b310b43af 100644 --- a/beta/src/components/Layout/Nav/MobileNav.tsx +++ b/beta/src/components/Layout/Nav/MobileNav.tsx @@ -74,7 +74,8 @@ function TabButton({ const classes = cn( 'inline-flex items-center w-full border-b-2 justify-center text-base leading-9 px-3 py-0.5 hover:text-link hover:gray-5', { - 'text-link dark:text-link-dark dark:border-link-dark border-link font-bold': isActive, + 'text-link dark:text-link-dark dark:border-link-dark border-link font-bold': + isActive, 'border-transparent': !isActive, } ); diff --git a/beta/src/components/Layout/Nav/Nav.tsx b/beta/src/components/Layout/Nav/Nav.tsx index e4c37083d3..bcd76231f5 100644 --- a/beta/src/components/Layout/Nav/Nav.tsx +++ b/beta/src/components/Layout/Nav/Nav.tsx @@ -15,6 +15,13 @@ import {MenuContext} from 'components/useMenu'; import {Logo} from '../../Logo'; import NavLink from './NavLink'; +declare global { + interface Window { + __theme: string; + __setPreferredTheme: (theme: string) => void; + } +} + const feedbackIcon = ( { - if (typeof document === 'undefined') { - return false; - } - return document.documentElement.classList.contains('dark'); - }); const section = inferSection(pathname); function handleFeedback() { @@ -137,21 +136,28 @@ export default function Nav() { Beta
- +
+ +
+
+ +
@@ -172,21 +178,28 @@ export default function Nav() { onClick={handleFeedback}> {feedbackIcon} - +
+ +
+
+ +
); diff --git a/beta/src/components/Layout/Nav/NavButtonLink.tsx b/beta/src/components/Layout/Nav/NavButtonLink.tsx deleted file mode 100644 index 41a08727fc..0000000000 --- a/beta/src/components/Layout/Nav/NavButtonLink.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - */ - -import * as React from 'react'; -import cn from 'classnames'; -import NextLink from 'next/link'; -import {ExternalLink} from 'components/ExternalLink'; - -interface NavButtonLinkProps { - href: string; - children: React.ReactNode; - className?: string; -} - -export default function NavButtonLink({ - href, - children, - className, -}: NavButtonLinkProps) { - const classes = cn( - 'mr-3 text-xs items-center border-b border-link border-opacity-0 hover:text-link hover:border-opacity-100', - className - ); - if (href.startsWith('https://')) { - return ( - - {children} - - ); - } - - return ( - - {/* eslint-disable-next-line jsx-a11y/anchor-has-content */} - {children} - - ); -} diff --git a/beta/src/components/Layout/Nav/NavLink.tsx b/beta/src/components/Layout/Nav/NavLink.tsx index d97d63f555..3fddc6e163 100644 --- a/beta/src/components/Layout/Nav/NavLink.tsx +++ b/beta/src/components/Layout/Nav/NavLink.tsx @@ -16,7 +16,8 @@ interface NavLinkProps { export default function NavLink({href, children, isActive}: NavLinkProps) { const classes = cn( { - 'text-link border-link dark:text-link-dark dark:border-link-dark font-bold': isActive, + 'text-link border-link dark:text-link-dark dark:border-link-dark font-bold': + isActive, }, {'border-transparent': !isActive}, 'inline-flex w-full items-center border-b-2 justify-center text-base leading-9 px-3 py-0.5 hover:text-link dark:hover:text-link-dark whitespace-nowrap' diff --git a/beta/src/components/Layout/Page.tsx b/beta/src/components/Layout/Page.tsx index 7cbf250526..2f8ad2f4d1 100644 --- a/beta/src/components/Layout/Page.tsx +++ b/beta/src/components/Layout/Page.tsx @@ -18,16 +18,14 @@ export function Page({routeTree, children}: PageProps) {
-
+
-
+
-
+
{children}
diff --git a/beta/src/components/Layout/Sidebar/Sidebar.tsx b/beta/src/components/Layout/Sidebar/Sidebar.tsx index bf8f9de2ab..e1a9668024 100644 --- a/beta/src/components/Layout/Sidebar/Sidebar.tsx +++ b/beta/src/components/Layout/Sidebar/Sidebar.tsx @@ -18,7 +18,7 @@ export function Sidebar({isMobileOnly}: {isMobileOnly?: boolean}) { const {menuRef, isOpen} = React.useContext(MenuContext); const isMobileSidebar = useMediaQuery(SIDEBAR_BREAKPOINT); let routeTree = React.useContext(SidebarContext); - const isHidden = isMobileOnly && !isMobileSidebar; + const isHidden = isMobileSidebar ? !isOpen : false; // HACK. Fix up the data structures instead. if ((routeTree as any).routes.length === 1) { @@ -62,14 +62,10 @@ export function Sidebar({isMobileOnly}: {isMobileOnly?: boolean}) { return (