Use simple markdown

This commit is contained in:
Nate Butler 2023-06-12 09:00:59 -04:00
parent 48dcacc7ce
commit 57ae64d44a
79 changed files with 32 additions and 15209 deletions

View File

@ -1,3 +0,0 @@
{
"extends": "next/core-web-vitals"
}

32
docs/.gitignore vendored
View File

@ -1,32 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env*.local
# vercel
.vercel

View File

@ -1 +0,0 @@
.next

View File

@ -1,5 +0,0 @@
# Zed Internal Docs
## Template: Protocol
Protocol is a [Tailwind UI](https://tailwindui.com) site template built using [Tailwind CSS](https://tailwindcss.com) and [Next.js](https://nextjs.org).

View File

@ -1,30 +1,30 @@
export const description = 'Get your machine set up for the first time'
# Building Zed
# Setup
How to build Zed from source for the first time.
## Getting Zed to build
## Process
Expect this to take 30min to an hour! Some of these steps will take quite a while based on your connection speed, and how long your first build will be.
1. Install the [GitHub CLI](https://cli.github.com/):
- `brew install gh`
2. Clone the `zed` repo
1. Clone the `zed` repo
- `gh repo clone zed-industries/zed`
3. Install Xcode from the macOS App Store
4. Install [Postgres](https://postgresapp.com)
5. Install rust/rustup
1. Install Xcode from the macOS App Store
1. Install [Postgres](https://postgresapp.com)
1. Install rust/rustup
- `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
6. Install the wasm toolchain
1. Install the wasm toolchain
- `rustup target add wasm32-wasi`
7. Generate an GitHub API Key
1. Generate an GitHub API Key
- Go to https://github.com/settings/tokens and Generate new token
- GitHub currently provides two kinds of tokens:
- Classic Tokens, where only `repo` (Full control of private repositories) OAuth scope has to be selected
Unfortunately, unselecting `repo` scope and selecting every its inner scope instead does not allow the token users to read from private repositories
- (not applicable) Fine-grained Tokens, at the moment of writing, did not allow any kind of access of non-owned private repos
- Keep the token in the browser tab/editor for the next two steps
8. Open Postgres.app
9. From `./path/to/zed/`:
1. Open Postgres.app
1. From `./path/to/zed/`:
- Run:
- `GITHUB_TOKEN={yourGithubAPIToken} script/bootstrap`
- Replace `{yourGithubAPIToken}` with the API token you generated above.
@ -42,7 +42,7 @@ Expect this to take 30min to an hour! Some of these steps will take quite a whil
- Replace `{username}` with your home folder name (usually your login name)
- `echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/{username}/.zprofile`
- `eval "$(/opt/homebrew/bin/brew shellenv)"`
10. To run the Zed app:
1. To run the Zed app:
- If you are working on zed:
- `cargo run`
- If you are just using the latest version, but not working on zed:

View File

@ -1,10 +1,4 @@
export const description = 'Welcome to Zed!'
# Welcome to Zed
Welcome! These internal docs are a work in progress. You can contribute to them by submitting a PR directly!
## Getting Started
# Company & Vision
## Vision

View File

@ -1,6 +1,4 @@
export const description = 'A list of useful design tools.'
# Design Tools
# Design Tools & Links
Generally useful tools and resources for design.

12
docs/index.md Normal file
View File

@ -0,0 +1,12 @@
# Welcome to Zed
Welcome! These internal docs are a work in progress. You can contribute to them by submitting a PR directly!
## Contents
- [The Company](./company-and-vision.md)
- [Tools We Use](./tools.md)
- [Building Zed](./building-zed.md)
- [Reloease Process](./release-process.md)
- [Backend Development](./backend-development.md)
- [Design Tools & Links](design-tools.md)

View File

@ -1,8 +0,0 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}

View File

@ -1,24 +0,0 @@
import nextMDX from '@next/mdx'
import { remarkPlugins } from './src/mdx/remark.mjs'
import { rehypePlugins } from './src/mdx/rehype.mjs'
import { recmaPlugins } from './src/mdx/recma.mjs'
const withMDX = nextMDX({
options: {
remarkPlugins,
rehypePlugins,
recmaPlugins,
providerImportSource: '@mdx-js/react',
},
})
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'mdx'],
experimental: {
scrollRestoration: true,
},
}
export default withMDX(nextConfig)

11975
docs/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,51 +0,0 @@
{
"name": "zed-internal-docs",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"browserslist": "defaults, not ie <= 11",
"dependencies": {
"@algolia/autocomplete-core": "^1.7.3",
"@headlessui/react": "^1.7.13",
"@mdx-js/loader": "^2.1.5",
"@mdx-js/react": "^2.1.5",
"@next/mdx": "^13.0.3",
"@sindresorhus/slugify": "^2.1.1",
"@tailwindcss/typography": "^0.5.8",
"acorn": "^8.8.1",
"autoprefixer": "^10.4.7",
"clsx": "^1.2.0",
"fast-glob": "^3.2.12",
"focus-visible": "^5.2.0",
"framer-motion": "7.8.1",
"mdast-util-to-string": "^3.2.0",
"mdx-annotations": "^0.1.1",
"next": "13.4.2",
"postcss-focus-visible": "^6.0.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-highlight-words": "^0.20.0",
"recma-nextjs-static-props": "^1.0.0",
"rehype-mdx-title": "^2.0.0",
"remark": "^14.0.2",
"remark-gfm": "^3.0.1",
"remark-mdx": "^2.3.0",
"shiki": "^0.11.1",
"simple-functional-loader": "^1.2.1",
"tailwindcss": "^3.3.0",
"unist-util-filter": "^4.0.1",
"unist-util-visit": "^4.1.1",
"zustand": "^4.3.2"
},
"devDependencies": {
"eslint": "8.26.0",
"eslint-config-next": "13.0.2",
"prettier": "^2.8.7",
"prettier-plugin-tailwindcss": "^0.2.6"
}
}

View File

@ -1,9 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
'postcss-focus-visible': {
replaceWith: '[data-focus-visible-added]',
},
autoprefixer: {},
},
}

View File

@ -1,5 +0,0 @@
module.exports = {
singleQuote: true,
semi: false,
plugins: [require('prettier-plugin-tailwindcss')],
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,7 +1,7 @@
export const description = 'The process to create and ship a Zed release'
# Zed's Release Process
The process to create and ship a Zed release
## Overview
### Release Channels
@ -79,9 +79,9 @@ This means that when releasing a new version of Zed that has changes to the RPC
1. Deploying the server is a two-step process that begins with pushing a tag. 1. Check out the commit you'd like to deploy. Often it will be the head of `main`, but could be on any branch.
1. Run the following script, which will bump the version of the `collab` crate and create a new tag. The script takes an argument `minor` or `patch`, to indicate how to increment the version. If you're releasing new features, use `minor`. If it's just a bugfix, use `patch`
```
script/bump-collab-version patch
```
```
script/bump-collab-version patch
```
1. This script will make local changes only, and print out a shell command that you can use to push the branch and tag.
1. Pushing the new tag will trigger a CI build that, when finished will upload a new versioned docker image to the DigitalOcean docker registry.

View File

@ -1,62 +0,0 @@
import Link from 'next/link'
import clsx from 'clsx'
function ArrowIcon(props) {
return (
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" {...props}>
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
d="m11.5 6.5 3 3.5m0 0-3 3.5m3-3.5h-9"
/>
</svg>
)
}
const variantStyles = {
primary:
'rounded-full bg-zinc-900 py-1 px-3 text-white hover:bg-zinc-700 dark:bg-emerald-400/10 dark:text-emerald-400 dark:ring-1 dark:ring-inset dark:ring-emerald-400/20 dark:hover:bg-emerald-400/10 dark:hover:text-emerald-300 dark:hover:ring-emerald-300',
secondary:
'rounded-full bg-zinc-100 py-1 px-3 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-800/40 dark:text-zinc-400 dark:ring-1 dark:ring-inset dark:ring-zinc-800 dark:hover:bg-zinc-800 dark:hover:text-zinc-300',
filled:
'rounded-full bg-zinc-900 py-1 px-3 text-white hover:bg-zinc-700 dark:bg-emerald-500 dark:text-white dark:hover:bg-emerald-400',
outline:
'rounded-full py-1 px-3 text-zinc-700 ring-1 ring-inset ring-zinc-900/10 hover:bg-zinc-900/2.5 hover:text-zinc-900 dark:text-zinc-400 dark:ring-white/10 dark:hover:bg-white/5 dark:hover:text-white',
text: 'text-emerald-500 hover:text-emerald-600 dark:text-emerald-400 dark:hover:text-emerald-500',
}
export function Button({
variant = 'primary',
className,
children,
arrow,
...props
}) {
let Component = props.href ? Link : 'button'
className = clsx(
'inline-flex gap-0.5 justify-center overflow-hidden text-sm font-medium transition',
variantStyles[variant],
className
)
let arrowIcon = (
<ArrowIcon
className={clsx(
'mt-0.5 h-5 w-5',
variant === 'text' && 'relative top-px',
arrow === 'left' && '-ml-1 rotate-180',
arrow === 'right' && '-mr-1'
)}
/>
)
return (
<Component className={className} {...props}>
{arrow === 'left' && arrowIcon}
{children}
{arrow === 'right' && arrowIcon}
</Component>
)
}

View File

@ -1,297 +0,0 @@
import {
Children,
createContext,
useContext,
useEffect,
useRef,
useState,
} from 'react'
import { Tab } from '@headlessui/react'
import clsx from 'clsx'
import { create } from 'zustand'
import { Tag } from '@/components/Tag'
const languageNames = {
js: 'JavaScript',
ts: 'TypeScript',
javascript: 'JavaScript',
typescript: 'TypeScript',
php: 'PHP',
python: 'Python',
ruby: 'Ruby',
go: 'Go',
}
function getPanelTitle({ title, language }) {
return title ?? languageNames[language] ?? 'Code'
}
function ClipboardIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeWidth="0"
d="M5.5 13.5v-5a2 2 0 0 1 2-2l.447-.894A2 2 0 0 1 9.737 4.5h.527a2 2 0 0 1 1.789 1.106l.447.894a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2Z"
/>
<path
fill="none"
strokeLinejoin="round"
d="M12.5 6.5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2m5 0-.447-.894a2 2 0 0 0-1.79-1.106h-.527a2 2 0 0 0-1.789 1.106L7.5 6.5m5 0-1 1h-3l-1-1"
/>
</svg>
)
}
function CopyButton({ code }) {
let [copyCount, setCopyCount] = useState(0)
let copied = copyCount > 0
useEffect(() => {
if (copyCount > 0) {
let timeout = setTimeout(() => setCopyCount(0), 1000)
return () => {
clearTimeout(timeout)
}
}
}, [copyCount])
return (
<button
type="button"
className={clsx(
'group/button absolute right-4 top-3.5 overflow-hidden rounded-full py-1 pl-2 pr-3 text-2xs font-medium opacity-0 backdrop-blur transition focus:opacity-100 group-hover:opacity-100',
copied
? 'bg-emerald-400/10 ring-1 ring-inset ring-emerald-400/20'
: 'bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5'
)}
onClick={() => {
window.navigator.clipboard.writeText(code).then(() => {
setCopyCount((count) => count + 1)
})
}}
>
<span
aria-hidden={copied}
className={clsx(
'pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300',
copied && '-translate-y-1.5 opacity-0'
)}
>
<ClipboardIcon className="h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" />
Copy
</span>
<span
aria-hidden={!copied}
className={clsx(
'pointer-events-none absolute inset-0 flex items-center justify-center text-emerald-400 transition duration-300',
!copied && 'translate-y-1.5 opacity-0'
)}
>
Copied!
</span>
</button>
)
}
function CodePanelHeader({ tag, label }) {
if (!tag && !label) {
return null
}
return (
<div className="flex h-9 items-center gap-2 border-y border-b-white/7.5 border-t-transparent bg-white/2.5 bg-zinc-900 px-4 dark:border-b-white/5 dark:bg-white/1">
{tag && (
<div className="dark flex">
<Tag variant="small">{tag}</Tag>
</div>
)}
{tag && label && (
<span className="h-0.5 w-0.5 rounded-full bg-zinc-500" />
)}
{label && (
<span className="font-mono text-xs text-zinc-400">{label}</span>
)}
</div>
)
}
function CodePanel({ tag, label, code, children }) {
let child = Children.only(children)
return (
<div className="group dark:bg-white/2.5">
<CodePanelHeader
tag={child.props.tag ?? tag}
label={child.props.label ?? label}
/>
<div className="relative">
<pre className="overflow-x-auto p-4 text-xs text-white">{children}</pre>
<CopyButton code={child.props.code ?? code} />
</div>
</div>
)
}
function CodeGroupHeader({ title, children, selectedIndex }) {
let hasTabs = Children.count(children) > 1
if (!title && !hasTabs) {
return null
}
return (
<div className="flex min-h-[calc(theme(spacing.12)+1px)] flex-wrap items-start gap-x-4 border-b border-zinc-700 bg-zinc-800 px-4 dark:border-zinc-800 dark:bg-transparent">
{title && (
<h3 className="mr-auto pt-3 text-xs font-semibold text-white">
{title}
</h3>
)}
{hasTabs && (
<Tab.List className="-mb-px flex gap-4 text-xs font-medium">
{Children.map(children, (child, childIndex) => (
<Tab
className={clsx(
'border-b py-3 transition focus:[&:not(:focus-visible)]:outline-none',
childIndex === selectedIndex
? 'border-emerald-500 text-emerald-400'
: 'border-transparent text-zinc-400 hover:text-zinc-300'
)}
>
{getPanelTitle(child.props)}
</Tab>
))}
</Tab.List>
)}
</div>
)
}
function CodeGroupPanels({ children, ...props }) {
let hasTabs = Children.count(children) > 1
if (hasTabs) {
return (
<Tab.Panels>
{Children.map(children, (child) => (
<Tab.Panel>
<CodePanel {...props}>{child}</CodePanel>
</Tab.Panel>
))}
</Tab.Panels>
)
}
return <CodePanel {...props}>{children}</CodePanel>
}
function usePreventLayoutShift() {
let positionRef = useRef()
let rafRef = useRef()
useEffect(() => {
return () => {
window.cancelAnimationFrame(rafRef.current)
}
}, [])
return {
positionRef,
preventLayoutShift(callback) {
let initialTop = positionRef.current.getBoundingClientRect().top
callback()
rafRef.current = window.requestAnimationFrame(() => {
let newTop = positionRef.current.getBoundingClientRect().top
window.scrollBy(0, newTop - initialTop)
})
},
}
}
const usePreferredLanguageStore = create((set) => ({
preferredLanguages: [],
addPreferredLanguage: (language) =>
set((state) => ({
preferredLanguages: [
...state.preferredLanguages.filter(
(preferredLanguage) => preferredLanguage !== language
),
language,
],
})),
}))
function useTabGroupProps(availableLanguages) {
let { preferredLanguages, addPreferredLanguage } = usePreferredLanguageStore()
let [selectedIndex, setSelectedIndex] = useState(0)
let activeLanguage = [...availableLanguages].sort(
(a, z) => preferredLanguages.indexOf(z) - preferredLanguages.indexOf(a)
)[0]
let languageIndex = availableLanguages.indexOf(activeLanguage)
let newSelectedIndex = languageIndex === -1 ? selectedIndex : languageIndex
if (newSelectedIndex !== selectedIndex) {
setSelectedIndex(newSelectedIndex)
}
let { positionRef, preventLayoutShift } = usePreventLayoutShift()
return {
as: 'div',
ref: positionRef,
selectedIndex,
onChange: (newSelectedIndex) => {
preventLayoutShift(() =>
addPreferredLanguage(availableLanguages[newSelectedIndex])
)
},
}
}
const CodeGroupContext = createContext(false)
export function CodeGroup({ children, title, ...props }) {
let languages = Children.map(children, (child) => getPanelTitle(child.props))
let tabGroupProps = useTabGroupProps(languages)
let hasTabs = Children.count(children) > 1
let Container = hasTabs ? Tab.Group : 'div'
let containerProps = hasTabs ? tabGroupProps : {}
let headerProps = hasTabs
? { selectedIndex: tabGroupProps.selectedIndex }
: {}
return (
<CodeGroupContext.Provider value={true}>
<Container
{...containerProps}
className="not-prose my-6 overflow-hidden rounded-2xl bg-zinc-900 shadow-md dark:ring-1 dark:ring-white/10"
>
<CodeGroupHeader title={title} {...headerProps}>
{children}
</CodeGroupHeader>
<CodeGroupPanels {...props}>{children}</CodeGroupPanels>
</Container>
</CodeGroupContext.Provider>
)
}
export function Code({ children, ...props }) {
let isGrouped = useContext(CodeGroupContext)
if (isGrouped) {
return <code {...props} dangerouslySetInnerHTML={{ __html: children }} />
}
return <code {...props}>{children}</code>
}
export function Pre({ children, ...props }) {
let isGrouped = useContext(CodeGroupContext)
if (isGrouped) {
return children
}
return <CodeGroup {...props}>{children}</CodeGroup>
}

View File

@ -1,228 +0,0 @@
import { forwardRef, Fragment, useState } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { Transition } from '@headlessui/react'
import { Button } from '@/components/Button'
import { navigation } from '@/components/Navigation'
function CheckIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<circle cx="10" cy="10" r="10" strokeWidth="0" />
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
d="m6.75 10.813 2.438 2.437c1.218-4.469 4.062-6.5 4.062-6.5"
/>
</svg>
)
}
function FeedbackButton(props) {
return (
<button
type="submit"
className="px-3 text-sm font-medium text-zinc-600 transition hover:bg-zinc-900/2.5 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-white/5 dark:hover:text-white"
{...props}
/>
)
}
const FeedbackForm = forwardRef(function FeedbackForm({ onSubmit }, ref) {
return (
<form
ref={ref}
onSubmit={onSubmit}
className="absolute inset-0 flex items-center justify-center gap-6 md:justify-start"
>
<p className="text-sm text-zinc-600 dark:text-zinc-400">
(Not hooked up) Was this page helpful?
</p>
<div className="group grid h-8 grid-cols-[1fr,1px,1fr] overflow-hidden rounded-full border border-zinc-900/10 dark:border-white/10">
<FeedbackButton data-response="yes">Yes</FeedbackButton>
<div className="bg-zinc-900/10 dark:bg-white/10" />
<FeedbackButton data-response="no">No</FeedbackButton>
</div>
</form>
)
})
const FeedbackThanks = forwardRef(function FeedbackThanks(_props, ref) {
return (
<div
ref={ref}
className="absolute inset-0 flex justify-center md:justify-start"
>
<div className="flex items-center gap-3 rounded-full bg-emerald-50/50 py-1 pl-1.5 pr-3 text-sm text-emerald-900 ring-1 ring-inset ring-emerald-500/20 dark:bg-emerald-500/5 dark:text-emerald-200 dark:ring-emerald-500/30">
<CheckIcon className="h-5 w-5 flex-none fill-emerald-500 stroke-white dark:fill-emerald-200/20 dark:stroke-emerald-200" />
(Not hooked up) Thanks for your feedback!
</div>
</div>
)
})
function Feedback() {
let [submitted, setSubmitted] = useState(false)
function onSubmit(event) {
event.preventDefault()
// event.nativeEvent.submitter.dataset.response
// => "yes" or "no"
setSubmitted(true)
}
return (
<div className="relative h-8">
<Transition
show={!submitted}
as={Fragment}
leaveFrom="opacity-100"
leaveTo="opacity-0"
leave="pointer-events-none duration-300"
>
<FeedbackForm onSubmit={onSubmit} />
</Transition>
<Transition
show={submitted}
as={Fragment}
enterFrom="opacity-0"
enterTo="opacity-100"
enter="delay-150 duration-300"
>
<FeedbackThanks />
</Transition>
</div>
)
}
function PageLink({ label, page, previous = false }) {
return (
<>
<Button
href={page.href}
aria-label={`${label}: ${page.title}`}
variant="secondary"
arrow={previous ? 'left' : 'right'}
>
{label}
</Button>
<Link
href={page.href}
tabIndex={-1}
aria-hidden="true"
className="text-base font-semibold text-zinc-900 transition hover:text-zinc-600 dark:text-white dark:hover:text-zinc-300"
>
{page.title}
</Link>
</>
)
}
function PageNavigation() {
let router = useRouter()
let allPages = navigation.flatMap((group) => group.links)
let currentPageIndex = allPages.findIndex(
(page) => page.href === router.pathname
)
if (currentPageIndex === -1) {
return null
}
let previousPage = allPages[currentPageIndex - 1]
let nextPage = allPages[currentPageIndex + 1]
if (!previousPage && !nextPage) {
return null
}
return (
<div className="flex">
{previousPage && (
<div className="flex flex-col items-start gap-3">
<PageLink label="Previous" page={previousPage} previous />
</div>
)}
{nextPage && (
<div className="ml-auto flex flex-col items-end gap-3">
<PageLink label="Next" page={nextPage} />
</div>
)}
</div>
)
}
function TwitterIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path d="M16.712 6.652c.01.146.01.29.01.436 0 4.449-3.267 9.579-9.242 9.579v-.003a8.963 8.963 0 0 1-4.98-1.509 6.379 6.379 0 0 0 4.807-1.396c-1.39-.027-2.608-.966-3.035-2.337.487.097.99.077 1.467-.059-1.514-.316-2.606-1.696-2.606-3.3v-.041c.45.26.956.404 1.475.42C3.18 7.454 2.74 5.486 3.602 3.947c1.65 2.104 4.083 3.382 6.695 3.517a3.446 3.446 0 0 1 .94-3.217 3.172 3.172 0 0 1 4.596.148 6.38 6.38 0 0 0 2.063-.817 3.357 3.357 0 0 1-1.428 1.861 6.283 6.283 0 0 0 1.865-.53 6.735 6.735 0 0 1-1.62 1.744Z" />
</svg>
)
}
function GitHubIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10 1.667c-4.605 0-8.334 3.823-8.334 8.544 0 3.78 2.385 6.974 5.698 8.106.417.075.573-.182.573-.406 0-.203-.011-.875-.011-1.592-2.093.397-2.635-.522-2.802-1.002-.094-.246-.5-1.005-.854-1.207-.291-.16-.708-.556-.01-.567.656-.01 1.124.62 1.281.876.75 1.292 1.948.93 2.427.705.073-.555.291-.93.531-1.143-1.854-.213-3.791-.95-3.791-4.218 0-.929.322-1.698.854-2.296-.083-.214-.375-1.09.083-2.265 0 0 .698-.224 2.292.876a7.576 7.576 0 0 1 2.083-.288c.709 0 1.417.096 2.084.288 1.593-1.11 2.291-.875 2.291-.875.459 1.174.167 2.05.084 2.263.53.599.854 1.357.854 2.297 0 3.278-1.948 4.005-3.802 4.219.302.266.563.78.563 1.58 0 1.143-.011 2.061-.011 2.35 0 .224.156.491.573.405a8.365 8.365 0 0 0 4.11-3.116 8.707 8.707 0 0 0 1.567-4.99c0-4.721-3.73-8.545-8.334-8.545Z"
/>
</svg>
)
}
function DiscordIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path d="M16.238 4.515a14.842 14.842 0 0 0-3.664-1.136.055.055 0 0 0-.059.027 10.35 10.35 0 0 0-.456.938 13.702 13.702 0 0 0-4.115 0 9.479 9.479 0 0 0-.464-.938.058.058 0 0 0-.058-.027c-1.266.218-2.497.6-3.664 1.136a.052.052 0 0 0-.024.02C1.4 8.023.76 11.424 1.074 14.782a.062.062 0 0 0 .024.042 14.923 14.923 0 0 0 4.494 2.272.058.058 0 0 0 .064-.02c.346-.473.654-.972.92-1.496a.057.057 0 0 0-.032-.08 9.83 9.83 0 0 1-1.404-.669.058.058 0 0 1-.029-.046.058.058 0 0 1 .023-.05c.094-.07.189-.144.279-.218a.056.056 0 0 1 .058-.008c2.946 1.345 6.135 1.345 9.046 0a.056.056 0 0 1 .059.007c.09.074.184.149.28.22a.058.058 0 0 1 .023.049.059.059 0 0 1-.028.046 9.224 9.224 0 0 1-1.405.669.058.058 0 0 0-.033.033.056.056 0 0 0 .002.047c.27.523.58 1.022.92 1.495a.056.056 0 0 0 .062.021 14.878 14.878 0 0 0 4.502-2.272.055.055 0 0 0 .016-.018.056.056 0 0 0 .008-.023c.375-3.883-.63-7.256-2.662-10.246a.046.046 0 0 0-.023-.021Zm-9.223 8.221c-.887 0-1.618-.814-1.618-1.814s.717-1.814 1.618-1.814c.908 0 1.632.821 1.618 1.814 0 1-.717 1.814-1.618 1.814Zm5.981 0c-.887 0-1.618-.814-1.618-1.814s.717-1.814 1.618-1.814c.908 0 1.632.821 1.618 1.814 0 1-.71 1.814-1.618 1.814Z" />
</svg>
)
}
function SocialLink({ href, icon: Icon, children }) {
return (
<Link href={href} className="group">
<span className="sr-only">{children}</span>
<Icon className="h-5 w-5 fill-zinc-700 transition group-hover:fill-zinc-900 dark:group-hover:fill-zinc-500" />
</Link>
)
}
function SmallPrint() {
return (
<div className="flex flex-col items-center justify-between gap-5 border-t border-zinc-900/5 pt-8 dark:border-white/5 sm:flex-row">
<p className="text-xs text-zinc-600 dark:text-zinc-400">
&copy; Copyright {new Date().getFullYear()}. All rights reserved.
</p>
<div className="flex gap-4">
<SocialLink href="#" icon={TwitterIcon}>
Follow us on Twitter
</SocialLink>
<SocialLink href="#" icon={GitHubIcon}>
Follow us on GitHub
</SocialLink>
<SocialLink href="#" icon={DiscordIcon}>
Join our Discord server
</SocialLink>
</div>
</div>
)
}
export function Footer() {
let router = useRouter()
return (
<footer className="mx-auto max-w-2xl space-y-10 pb-16 lg:max-w-5xl">
<Feedback key={router.pathname} />
<PageNavigation />
<SmallPrint />
</footer>
)
}

View File

@ -1,42 +0,0 @@
import { useId } from 'react'
export function GridPattern({ width, height, x, y, squares, ...props }) {
let patternId = useId()
return (
<svg aria-hidden="true" {...props}>
<defs>
<pattern
id={patternId}
width={width}
height={height}
patternUnits="userSpaceOnUse"
x={x}
y={y}
>
<path d={`M.5 ${height}V.5H${width}`} fill="none" />
</pattern>
</defs>
<rect
width="100%"
height="100%"
strokeWidth={0}
fill={`url(#${patternId})`}
/>
{squares && (
<svg x={x} y={y} className="overflow-visible">
{squares.map(([x, y]) => (
<rect
strokeWidth="0"
key={`${x}-${y}`}
width={width + 1}
height={height + 1}
x={x * width}
y={y * height}
/>
))}
</svg>
)}
</svg>
)
}

View File

@ -1,54 +0,0 @@
import { Button } from '@/components/Button'
import { Heading } from '@/components/Heading'
const guides = [
{
href: '/authentication',
name: 'Authentication',
description: 'Learn how to authenticate your API requests.',
},
{
href: '/pagination',
name: 'Pagination',
description: 'Understand how to work with paginated responses.',
},
{
href: '/errors',
name: 'Errors',
description:
'Read about the different types of errors returned by the API.',
},
{
href: '/webhooks',
name: 'Webhooks',
description:
'Learn how to programmatically configure webhooks for your app.',
},
]
export function Guides() {
return (
<div className="my-16 xl:max-w-none">
<Heading level={2} id="guides">
Guides
</Heading>
<div className="not-prose mt-4 grid grid-cols-1 gap-8 border-t border-zinc-900/5 pt-10 dark:border-white/5 sm:grid-cols-2 xl:grid-cols-4">
{guides.map((guide) => (
<div key={guide.href}>
<h3 className="text-sm font-semibold text-zinc-900 dark:text-white">
{guide.name}
</h3>
<p className="mt-1 text-sm text-zinc-600 dark:text-zinc-400">
{guide.description}
</p>
<p className="mt-4">
<Button href={guide.href} variant="text" arrow="right">
Read more
</Button>
</p>
</div>
))}
</div>
</div>
)
}

View File

@ -1,84 +0,0 @@
import { forwardRef } from 'react'
import Link from 'next/link'
import clsx from 'clsx'
import { motion, useScroll, useTransform } from 'framer-motion'
import { Button } from '@/components/Button'
import { Logo } from '@/components/Logo'
import {
MobileNavigation,
useIsInsideMobileNavigation,
} from '@/components/MobileNavigation'
import { useMobileNavigationStore } from '@/components/MobileNavigation'
import { ModeToggle } from '@/components/ModeToggle'
function TopLevelNavItem({ href, children }) {
return (
<li>
<Link
href={href}
className="text-sm leading-5 text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white"
>
{children}
</Link>
</li>
)
}
export const Header = forwardRef(function Header({ className }, ref) {
let { isOpen: mobileNavIsOpen } = useMobileNavigationStore()
let isInsideMobileNavigation = useIsInsideMobileNavigation()
let { scrollY } = useScroll()
let bgOpacityLight = useTransform(scrollY, [0, 72], [0.5, 0.9])
let bgOpacityDark = useTransform(scrollY, [0, 72], [0.2, 0.8])
return (
<motion.div
ref={ref}
className={clsx(
className,
'fixed inset-x-0 top-0 z-50 flex h-14 items-center justify-between gap-12 px-4 transition sm:px-6 lg:left-72 lg:z-30 lg:px-8 xl:left-80',
!isInsideMobileNavigation &&
'backdrop-blur-sm dark:backdrop-blur lg:left-72 xl:left-80',
isInsideMobileNavigation
? 'bg-white dark:bg-zinc-900'
: 'bg-white/[var(--bg-opacity-light)] dark:bg-zinc-900/[var(--bg-opacity-dark)]'
)}
style={{
'--bg-opacity-light': bgOpacityLight,
'--bg-opacity-dark': bgOpacityDark,
}}
>
<div
className={clsx(
'absolute inset-x-0 top-full h-px transition',
(isInsideMobileNavigation || !mobileNavIsOpen) &&
'bg-zinc-900/7.5 dark:bg-white/7.5'
)}
/>
<div className="flex items-center gap-5 lg:hidden">
<MobileNavigation />
<Link href="/" aria-label="Home">
<Logo className="h-6" />
</Link>
</div>
<div className="flex items-center gap-5">
<nav className="hidden md:block">
<ul role="list" className="flex items-center gap-8">
<TopLevelNavItem href="/">API</TopLevelNavItem>
<TopLevelNavItem href="#">Documentation</TopLevelNavItem>
<TopLevelNavItem href="#">Support</TopLevelNavItem>
</ul>
</nav>
<div className="hidden md:block md:h-5 md:w-px md:bg-zinc-900/10 md:dark:bg-white/15" />
<div className="flex gap-4">
<ModeToggle />
</div>
<div className="hidden min-[416px]:contents">
<Button href="#">Sign in</Button>
</div>
</div>
</motion.div>
)
})

View File

@ -1,102 +0,0 @@
import { useEffect, useRef } from 'react'
import Link from 'next/link'
import { useInView } from 'framer-motion'
import { useSectionStore } from '@/components/SectionProvider'
import { Tag } from '@/components/Tag'
import { remToPx } from '@/lib/remToPx'
function AnchorIcon(props) {
return (
<svg
viewBox="0 0 20 20"
fill="none"
strokeLinecap="round"
aria-hidden="true"
{...props}
>
<path d="m6.5 11.5-.964-.964a3.535 3.535 0 1 1 5-5l.964.964m2 2 .964.964a3.536 3.536 0 0 1-5 5L8.5 13.5m0-5 3 3" />
</svg>
)
}
function Eyebrow({ tag, label }) {
if (!tag && !label) {
return null
}
return (
<div className="flex items-center gap-x-3">
{tag && <Tag>{tag}</Tag>}
{tag && label && (
<span className="h-0.5 w-0.5 rounded-full bg-zinc-300 dark:bg-zinc-600" />
)}
{label && (
<span className="font-mono text-xs text-zinc-400">{label}</span>
)}
</div>
)
}
function Anchor({ id, inView, children }) {
return (
<Link
href={`#${id}`}
className="group text-inherit no-underline hover:text-inherit"
>
{inView && (
<div className="absolute ml-[calc(-1*var(--width))] mt-1 hidden w-[var(--width)] opacity-0 transition [--width:calc(2.625rem+0.5px+50%-min(50%,calc(theme(maxWidth.lg)+theme(spacing.8))))] group-hover:opacity-100 group-focus:opacity-100 md:block lg:z-50 2xl:[--width:theme(spacing.10)]">
<div className="group/anchor block h-5 w-5 rounded-lg bg-zinc-50 ring-1 ring-inset ring-zinc-300 transition hover:ring-zinc-500 dark:bg-zinc-800 dark:ring-zinc-700 dark:hover:bg-zinc-700 dark:hover:ring-zinc-600">
<AnchorIcon className="h-5 w-5 stroke-zinc-500 transition dark:stroke-zinc-400 dark:group-hover/anchor:stroke-white" />
</div>
</div>
)}
{children}
</Link>
)
}
export function Heading({
level = 2,
children,
id,
tag,
label,
anchor = true,
...props
}) {
let Component = `h${level}`
let ref = useRef()
let registerHeading = useSectionStore((s) => s.registerHeading)
let inView = useInView(ref, {
margin: `${remToPx(-3.5)}px 0px 0px 0px`,
amount: 'all',
})
useEffect(() => {
if (level === 2) {
registerHeading({ id, ref, offsetRem: tag || label ? 8 : 6 })
}
})
return (
<>
<Eyebrow tag={tag} label={label} />
<Component
ref={ref}
id={anchor ? id : undefined}
className={tag || label ? 'mt-2 scroll-mt-32' : 'scroll-mt-24'}
{...props}
>
{anchor ? (
<Anchor id={id} inView={inView}>
{children}
</Anchor>
) : (
children
)}
</Component>
</>
)
}

View File

@ -1,32 +0,0 @@
import { GridPattern } from '@/components/GridPattern'
export function HeroPattern() {
return (
<div className="absolute inset-0 -z-10 mx-0 max-w-none overflow-hidden">
<div className="absolute left-1/2 top-0 ml-[-38rem] h-[25rem] w-[81.25rem] dark:[mask-image:linear-gradient(white,transparent)]">
<div className="absolute inset-0 bg-gradient-to-r from-[#36b49f] to-[#DBFF75] opacity-40 [mask-image:radial-gradient(farthest-side_at_top,white,transparent)] dark:from-[#36b49f]/30 dark:to-[#DBFF75]/30 dark:opacity-100">
<GridPattern
width={72}
height={56}
x="-12"
y="4"
squares={[
[4, 3],
[2, 1],
[7, 3],
[10, 6],
]}
className="absolute inset-x-0 inset-y-[-50%] h-[200%] w-full skew-y-[-18deg] fill-black/40 stroke-black/50 mix-blend-overlay dark:fill-white/2.5 dark:stroke-white/5"
/>
</div>
<svg
viewBox="0 0 1113 440"
aria-hidden="true"
className="absolute left-1/2 top-0 ml-[-19rem] w-[69.5625rem] fill-white blur-[26px] dark:hidden"
>
<path d="M.016 439.5s-9.5-300 434-300S882.516 20 882.516 20V0h230.004v439.5H.016Z" />
</svg>
</div>
</div>
)
}

View File

@ -1,38 +0,0 @@
import Link from 'next/link'
import { motion } from 'framer-motion'
import { Footer } from '@/components/Footer'
import { Header } from '@/components/Header'
import { Logo } from '@/components/Logo'
import { Navigation } from '@/components/Navigation'
import { Prose } from '@/components/Prose'
import { SectionProvider } from '@/components/SectionProvider'
export function Layout({ children, sections = [] }) {
return (
<SectionProvider sections={sections}>
<div className="lg:ml-72 xl:ml-80">
<motion.header
layoutScroll
className="contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex"
>
<div className="contents lg:pointer-events-auto lg:block lg:w-72 lg:overflow-y-auto lg:border-r lg:border-zinc-900/10 lg:px-6 lg:pb-8 lg:pt-4 lg:dark:border-white/10 xl:w-80">
<div className="hidden lg:flex">
<Link href="/" aria-label="Home">
<Logo className="h-6" />
</Link>
</div>
<Header />
<Navigation className="hidden lg:mt-10 lg:block" />
</div>
</motion.header>
<div className="relative px-4 pt-14 sm:px-6 lg:px-8">
<main className="py-16">
<Prose as="article">{children}</Prose>
</main>
<Footer />
</div>
</div>
</SectionProvider>
)
}

View File

@ -1,82 +0,0 @@
import Image from 'next/image'
import { Button } from '@/components/Button'
import { Heading } from '@/components/Heading'
import logoGo from '@/images/logos/go.svg'
import logoNode from '@/images/logos/node.svg'
import logoPhp from '@/images/logos/php.svg'
import logoPython from '@/images/logos/python.svg'
import logoRuby from '@/images/logos/ruby.svg'
const libraries = [
{
href: '#',
name: 'PHP',
description:
'A popular general-purpose scripting language that is especially suited to web development.',
logo: logoPhp,
},
{
href: '#',
name: 'Ruby',
description:
'A dynamic, open source programming language with a focus on simplicity and productivity.',
logo: logoRuby,
},
{
href: '#',
name: 'Node.js',
description:
'Node.js® is an open-source, cross-platform JavaScript runtime environment.',
logo: logoNode,
},
{
href: '#',
name: 'Python',
description:
'Python is a programming language that lets you work quickly and integrate systems more effectively.',
logo: logoPython,
},
{
href: '#',
name: 'Go',
description:
'An open-source programming language supported by Google with built-in concurrency.',
logo: logoGo,
},
]
export function Libraries() {
return (
<div className="my-16 xl:max-w-none">
<Heading level={2} id="official-libraries">
Official libraries
</Heading>
<div className="not-prose mt-4 grid grid-cols-1 gap-x-6 gap-y-10 border-t border-zinc-900/5 pt-10 dark:border-white/5 sm:grid-cols-2 xl:max-w-none xl:grid-cols-3">
{libraries.map((library) => (
<div key={library.name} className="flex flex-row-reverse gap-6">
<div className="flex-auto">
<h3 className="text-sm font-semibold text-zinc-900 dark:text-white">
{library.name}
</h3>
<p className="mt-1 text-sm text-zinc-600 dark:text-zinc-400">
{library.description}
</p>
<p className="mt-4">
<Button href={library.href} variant="text" arrow="right">
Read more
</Button>
</p>
</div>
<Image
src={library.logo}
alt=""
className="h-12 w-12"
unoptimized
/>
</div>
))}
</div>
</div>
)
}

View File

@ -1,17 +0,0 @@
export function Logo(props) {
return (
<div className="flex items-center gap-4">
<svg aria-hidden="true" {...props} viewBox="0 0 24 24">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M1.34266 1.34265V18.7972H0V1.20839C0 0.541014 0.541015 0 1.20839 0H23.0045C23.7222 0 24.0817 0.867745 23.5742 1.37523L10.5526 14.3968H14.3496V12.7552H15.6923V14.9339C15.6923 15.3788 15.3316 15.7395 14.8867 15.7395H9.20989L6.44591 18.5035H18.5035V8.979H19.8462V18.9062C19.8462 19.4253 19.4254 19.8461 18.9063 19.8461H5.10325L2.29206 22.6573H22.6573V5.20278H24V22.7916C24 23.4589 23.459 23.9999 22.7916 23.9999H0.995475C0.277776 23.9999 -0.0816697 23.1322 0.425834 22.6247C0.425835 22.6247 0.425836 22.6247 0.425838 22.6247L13.4002 9.65033H9.65035V11.2447H8.30769V9.11326C8.30769 8.66835 8.66837 8.30767 9.11329 8.30767H14.7429L17.5541 5.49649H5.4965V15.0209H4.15385V5.09369C4.15385 4.57462 4.57464 4.15384 5.09371 4.15384H18.8968L21.7079 1.34265H1.34266Z"
className="fill-zinc-900 dark:fill-white"
/>
</svg>
<div className="font-mono text-sm text-zinc-900 dark:text-white">
Zed Internal
</div>
</div>
)
}

View File

@ -1,115 +0,0 @@
import { createContext, Fragment, useContext } from 'react'
import { Dialog, Transition } from '@headlessui/react'
import { motion } from 'framer-motion'
import { create } from 'zustand'
import { Header } from '@/components/Header'
import { Navigation } from '@/components/Navigation'
function MenuIcon(props) {
return (
<svg
viewBox="0 0 10 9"
fill="none"
strokeLinecap="round"
aria-hidden="true"
{...props}
>
<path d="M.5 1h9M.5 8h9M.5 4.5h9" />
</svg>
)
}
function XIcon(props) {
return (
<svg
viewBox="0 0 10 9"
fill="none"
strokeLinecap="round"
aria-hidden="true"
{...props}
>
<path d="m1.5 1 7 7M8.5 1l-7 7" />
</svg>
)
}
const IsInsideMobileNavigationContext = createContext(false)
export function useIsInsideMobileNavigation() {
return useContext(IsInsideMobileNavigationContext)
}
export const useMobileNavigationStore = create((set) => ({
isOpen: false,
open: () => set({ isOpen: true }),
close: () => set({ isOpen: false }),
toggle: () => set((state) => ({ isOpen: !state.isOpen })),
}))
export function MobileNavigation() {
let isInsideMobileNavigation = useIsInsideMobileNavigation()
let { isOpen, toggle, close } = useMobileNavigationStore()
let ToggleIcon = isOpen ? XIcon : MenuIcon
return (
<IsInsideMobileNavigationContext.Provider value={true}>
<button
type="button"
className="flex h-6 w-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5"
aria-label="Toggle navigation"
onClick={toggle}
>
<ToggleIcon className="w-2.5 stroke-zinc-900 dark:stroke-white" />
</button>
{!isInsideMobileNavigation && (
<Transition.Root show={isOpen} as={Fragment}>
<Dialog onClose={close} className="fixed inset-0 z-50 lg:hidden">
<Transition.Child
as={Fragment}
enter="duration-300 ease-out"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="duration-200 ease-in"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 top-14 bg-zinc-400/20 backdrop-blur-sm dark:bg-black/40" />
</Transition.Child>
<Dialog.Panel>
<Transition.Child
as={Fragment}
enter="duration-300 ease-out"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="duration-200 ease-in"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Header />
</Transition.Child>
<Transition.Child
as={Fragment}
enter="duration-500 ease-in-out"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
leave="duration-500 ease-in-out"
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
>
<motion.div
layoutScroll
className="fixed bottom-0 left-0 top-14 w-full overflow-y-auto bg-white px-4 pb-4 pt-6 shadow-lg shadow-zinc-900/10 ring-1 ring-zinc-900/7.5 dark:bg-zinc-900 dark:ring-zinc-800 min-[416px]:max-w-sm sm:px-6 sm:pb-10"
>
<Navigation />
</motion.div>
</Transition.Child>
</Dialog.Panel>
</Dialog>
</Transition.Root>
)}
</IsInsideMobileNavigationContext.Provider>
)
}

View File

@ -1,54 +0,0 @@
function SunIcon(props) {
return (
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" {...props}>
<path d="M12.5 10a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z" />
<path
strokeLinecap="round"
d="M10 5.5v-1M13.182 6.818l.707-.707M14.5 10h1M13.182 13.182l.707.707M10 15.5v-1M6.11 13.889l.708-.707M4.5 10h1M6.11 6.111l.708.707"
/>
</svg>
)
}
function MoonIcon(props) {
return (
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" {...props}>
<path d="M15.224 11.724a5.5 5.5 0 0 1-6.949-6.949 5.5 5.5 0 1 0 6.949 6.949Z" />
</svg>
)
}
export function ModeToggle() {
function disableTransitionsTemporarily() {
document.documentElement.classList.add('[&_*]:!transition-none')
window.setTimeout(() => {
document.documentElement.classList.remove('[&_*]:!transition-none')
}, 0)
}
function toggleMode() {
disableTransitionsTemporarily()
let darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
let isSystemDarkMode = darkModeMediaQuery.matches
let isDarkMode = document.documentElement.classList.toggle('dark')
if (isDarkMode === isSystemDarkMode) {
delete window.localStorage.isDarkMode
} else {
window.localStorage.isDarkMode = isDarkMode
}
}
return (
<button
type="button"
className="flex h-6 w-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5"
aria-label="Toggle dark mode"
onClick={toggleMode}
>
<SunIcon className="h-5 w-5 stroke-zinc-900 dark:hidden" />
<MoonIcon className="hidden h-5 w-5 stroke-white dark:block" />
</button>
)
}

View File

@ -1,230 +0,0 @@
import { useRef } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import clsx from 'clsx'
import { AnimatePresence, motion, useIsPresent } from 'framer-motion'
import { Button } from '@/components/Button'
import { useIsInsideMobileNavigation } from '@/components/MobileNavigation'
import { useSectionStore } from '@/components/SectionProvider'
import { Tag } from '@/components/Tag'
import { remToPx } from '@/lib/remToPx'
function useInitialValue(value, condition = true) {
let initialValue = useRef(value).current
return condition ? initialValue : value
}
function TopLevelNavItem({ href, children }) {
return (
<li className="md:hidden">
<Link
href={href}
className="block py-1 text-sm text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white"
>
{children}
</Link>
</li>
)
}
function NavLink({ href, tag, active, isAnchorLink = false, children }) {
return (
<Link
href={href}
aria-current={active ? 'page' : undefined}
className={clsx(
'flex justify-between gap-2 py-1 pr-3 text-sm transition',
isAnchorLink ? 'pl-7' : 'pl-4',
active
? 'text-zinc-900 dark:text-white'
: 'text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white'
)}
>
<span className="truncate">{children}</span>
{tag && (
<Tag variant="small" color="zinc">
{tag}
</Tag>
)}
</Link>
)
}
function VisibleSectionHighlight({ group, pathname }) {
let [sections, visibleSections] = useInitialValue(
[
useSectionStore((s) => s.sections),
useSectionStore((s) => s.visibleSections),
],
useIsInsideMobileNavigation()
)
let isPresent = useIsPresent()
let firstVisibleSectionIndex = Math.max(
0,
[{ id: '_top' }, ...sections].findIndex(
(section) => section.id === visibleSections[0]
)
)
let itemHeight = remToPx(2)
let height = isPresent
? Math.max(1, visibleSections.length) * itemHeight
: itemHeight
let top =
group.links.findIndex((link) => link.href === pathname) * itemHeight +
firstVisibleSectionIndex * itemHeight
return (
<motion.div
layout
initial={{ opacity: 0 }}
animate={{ opacity: 1, transition: { delay: 0.2 } }}
exit={{ opacity: 0 }}
className="absolute inset-x-0 top-0 bg-zinc-800/2.5 will-change-transform dark:bg-white/2.5"
style={{ borderRadius: 8, height, top }}
/>
)
}
function ActivePageMarker({ group, pathname }) {
let itemHeight = remToPx(2)
let offset = remToPx(0.25)
let activePageIndex = group.links.findIndex((link) => link.href === pathname)
let top = offset + activePageIndex * itemHeight
return (
<motion.div
layout
className="absolute left-2 h-6 w-px bg-emerald-500"
initial={{ opacity: 0 }}
animate={{ opacity: 1, transition: { delay: 0.2 } }}
exit={{ opacity: 0 }}
style={{ top }}
/>
)
}
function NavigationGroup({ group, className }) {
// If this is the mobile navigation then we always render the initial
// state, so that the state does not change during the close animation.
// The state will still update when we re-open (re-render) the navigation.
let isInsideMobileNavigation = useIsInsideMobileNavigation()
let [router, sections] = useInitialValue(
[useRouter(), useSectionStore((s) => s.sections)],
isInsideMobileNavigation
)
let isActiveGroup =
group.links.findIndex((link) => link.href === router.pathname) !== -1
return (
<li className={clsx('relative mt-6', className)}>
<motion.h2
layout="position"
className="text-xs font-semibold text-zinc-900 dark:text-white"
>
{group.title}
</motion.h2>
<div className="relative mt-3 pl-2">
<AnimatePresence initial={!isInsideMobileNavigation}>
{isActiveGroup && (
<VisibleSectionHighlight group={group} pathname={router.pathname} />
)}
</AnimatePresence>
<motion.div
layout
className="absolute inset-y-0 left-2 w-px bg-zinc-900/10 dark:bg-white/5"
/>
<AnimatePresence initial={false}>
{isActiveGroup && (
<ActivePageMarker group={group} pathname={router.pathname} />
)}
</AnimatePresence>
<ul role="list" className="border-l border-transparent">
{group.links.map((link) => (
<motion.li key={link.href} layout="position" className="relative">
<NavLink href={link.href} active={link.href === router.pathname}>
{link.title}
</NavLink>
<AnimatePresence mode="popLayout" initial={false}>
{link.href === router.pathname && sections.length > 0 && (
<motion.ul
role="list"
initial={{ opacity: 0 }}
animate={{
opacity: 1,
transition: { delay: 0.1 },
}}
exit={{
opacity: 0,
transition: { duration: 0.15 },
}}
>
{sections.map((section) => (
<li key={section.id}>
<NavLink
href={`${link.href}#${section.id}`}
tag={section.tag}
isAnchorLink
>
{section.title}
</NavLink>
</li>
))}
</motion.ul>
)}
</AnimatePresence>
</motion.li>
))}
</ul>
</div>
</li>
)
}
export const navigation = [
{
title: 'General',
links: [
{ title: 'Welcome', href: '/' },
{ title: 'Tools', href: '/tools' },
],
},
{
title: 'Zed',
links: [{ title: 'Release Process', href: '/release-process' },
{ title: 'Environment Setup', href: '/setup' },
{ title: 'Backend', href: '/backend' },
],
},
{
title: 'Design',
links: [{ title: 'Tools', href: '/design/tools' }],
},
]
export function Navigation(props) {
return (
<nav {...props}>
<ul role="list">
<TopLevelNavItem href="/">API</TopLevelNavItem>
<TopLevelNavItem href="#">Documentation</TopLevelNavItem>
<TopLevelNavItem href="#">Support</TopLevelNavItem>
{navigation.map((group, groupIndex) => (
<NavigationGroup
key={group.title}
group={group}
className={groupIndex === 0 && 'md:mt-0'}
/>
))}
<li className="sticky bottom-0 z-10 mt-6 min-[416px]:hidden">
<Button href="#" variant="filled" className="w-full">
Sign in
</Button>
</li>
</ul>
</nav>
)
}

View File

@ -1,10 +0,0 @@
import clsx from 'clsx'
export function Prose({ as: Component = 'div', className, ...props }) {
return (
<Component
className={clsx(className, 'prose dark:prose-invert')}
{...props}
/>
)
}

View File

@ -1,157 +0,0 @@
import Link from 'next/link'
import { motion, useMotionTemplate, useMotionValue } from 'framer-motion'
import { GridPattern } from '@/components/GridPattern'
import { Heading } from '@/components/Heading'
import { ChatBubbleIcon } from '@/components/icons/ChatBubbleIcon'
import { EnvelopeIcon } from '@/components/icons/EnvelopeIcon'
import { UserIcon } from '@/components/icons/UserIcon'
import { UsersIcon } from '@/components/icons/UsersIcon'
const resources = [
{
href: '/contacts',
name: 'Contacts',
description:
'Learn about the contact model and how to create, retrieve, update, delete, and list contacts.',
icon: UserIcon,
pattern: {
y: 16,
squares: [
[0, 1],
[1, 3],
],
},
},
{
href: '/conversations',
name: 'Conversations',
description:
'Learn about the conversation model and how to create, retrieve, update, delete, and list conversations.',
icon: ChatBubbleIcon,
pattern: {
y: -6,
squares: [
[-1, 2],
[1, 3],
],
},
},
{
href: '/messages',
name: 'Messages',
description:
'Learn about the message model and how to create, retrieve, update, delete, and list messages.',
icon: EnvelopeIcon,
pattern: {
y: 32,
squares: [
[0, 2],
[1, 4],
],
},
},
{
href: '/groups',
name: 'Groups',
description:
'Learn about the group model and how to create, retrieve, update, delete, and list groups.',
icon: UsersIcon,
pattern: {
y: 22,
squares: [[0, 1]],
},
},
]
function ResourceIcon({ icon: Icon }) {
return (
<div className="flex h-7 w-7 items-center justify-center rounded-full bg-zinc-900/5 ring-1 ring-zinc-900/25 backdrop-blur-[2px] transition duration-300 group-hover:bg-white/50 group-hover:ring-zinc-900/25 dark:bg-white/7.5 dark:ring-white/15 dark:group-hover:bg-emerald-300/10 dark:group-hover:ring-emerald-400">
<Icon className="h-5 w-5 fill-zinc-700/10 stroke-zinc-700 transition-colors duration-300 group-hover:stroke-zinc-900 dark:fill-white/10 dark:stroke-zinc-400 dark:group-hover:fill-emerald-300/10 dark:group-hover:stroke-emerald-400" />
</div>
)
}
function ResourcePattern({ mouseX, mouseY, ...gridProps }) {
let maskImage = useMotionTemplate`radial-gradient(180px at ${mouseX}px ${mouseY}px, white, transparent)`
let style = { maskImage, WebkitMaskImage: maskImage }
return (
<div className="pointer-events-none">
<div className="absolute inset-0 rounded-2xl transition duration-300 [mask-image:linear-gradient(white,transparent)] group-hover:opacity-50">
<GridPattern
width={72}
height={56}
x="50%"
className="absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/[0.02] stroke-black/5 dark:fill-white/1 dark:stroke-white/2.5"
{...gridProps}
/>
</div>
<motion.div
className="absolute inset-0 rounded-2xl bg-gradient-to-r from-[#D7EDEA] to-[#F4FBDF] opacity-0 transition duration-300 group-hover:opacity-100 dark:from-[#202D2E] dark:to-[#303428]"
style={style}
/>
<motion.div
className="absolute inset-0 rounded-2xl opacity-0 mix-blend-overlay transition duration-300 group-hover:opacity-100"
style={style}
>
<GridPattern
width={72}
height={56}
x="50%"
className="absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/50 stroke-black/70 dark:fill-white/2.5 dark:stroke-white/10"
{...gridProps}
/>
</motion.div>
</div>
)
}
function Resource({ resource }) {
let mouseX = useMotionValue(0)
let mouseY = useMotionValue(0)
function onMouseMove({ currentTarget, clientX, clientY }) {
let { left, top } = currentTarget.getBoundingClientRect()
mouseX.set(clientX - left)
mouseY.set(clientY - top)
}
return (
<div
key={resource.href}
onMouseMove={onMouseMove}
className="group relative flex rounded-2xl bg-zinc-50 transition-shadow hover:shadow-md hover:shadow-zinc-900/5 dark:bg-white/2.5 dark:hover:shadow-black/5"
>
<ResourcePattern {...resource.pattern} mouseX={mouseX} mouseY={mouseY} />
<div className="absolute inset-0 rounded-2xl ring-1 ring-inset ring-zinc-900/7.5 group-hover:ring-zinc-900/10 dark:ring-white/10 dark:group-hover:ring-white/20" />
<div className="relative rounded-2xl px-4 pb-4 pt-16">
<ResourceIcon icon={resource.icon} />
<h3 className="mt-4 text-sm font-semibold leading-7 text-zinc-900 dark:text-white">
<Link href={resource.href}>
<span className="absolute inset-0 rounded-2xl" />
{resource.name}
</Link>
</h3>
<p className="mt-1 text-sm text-zinc-600 dark:text-zinc-400">
{resource.description}
</p>
</div>
</div>
)
}
export function Resources() {
return (
<div className="my-16 xl:max-w-none">
<Heading level={2} id="resources">
Resources
</Heading>
<div className="not-prose mt-4 grid grid-cols-1 gap-8 border-t border-zinc-900/5 pt-10 dark:border-white/5 sm:grid-cols-2 xl:grid-cols-4">
{resources.map((resource) => (
<Resource key={resource.href} resource={resource} />
))}
</div>
</div>
)
}

View File

@ -1,117 +0,0 @@
import {
createContext,
useContext,
useEffect,
useLayoutEffect,
useState,
} from 'react'
import { createStore, useStore } from 'zustand'
import { remToPx } from '@/lib/remToPx'
function createSectionStore(sections) {
return createStore((set) => ({
sections,
visibleSections: [],
setVisibleSections: (visibleSections) =>
set((state) =>
state.visibleSections.join() === visibleSections.join()
? {}
: { visibleSections }
),
registerHeading: ({ id, ref, offsetRem }) =>
set((state) => {
return {
sections: state.sections.map((section) => {
if (section.id === id) {
return {
...section,
headingRef: ref,
offsetRem,
}
}
return section
}),
}
}),
}))
}
function useVisibleSections(sectionStore) {
let setVisibleSections = useStore(sectionStore, (s) => s.setVisibleSections)
let sections = useStore(sectionStore, (s) => s.sections)
useEffect(() => {
function checkVisibleSections() {
let { innerHeight, scrollY } = window
let newVisibleSections = []
for (
let sectionIndex = 0;
sectionIndex < sections.length;
sectionIndex++
) {
let { id, headingRef, offsetRem } = sections[sectionIndex]
let offset = remToPx(offsetRem)
let top = headingRef.current.getBoundingClientRect().top + scrollY
if (sectionIndex === 0 && top - offset > scrollY) {
newVisibleSections.push('_top')
}
let nextSection = sections[sectionIndex + 1]
let bottom =
(nextSection?.headingRef.current.getBoundingClientRect().top ??
Infinity) +
scrollY -
remToPx(nextSection?.offsetRem ?? 0)
if (
(top > scrollY && top < scrollY + innerHeight) ||
(bottom > scrollY && bottom < scrollY + innerHeight) ||
(top <= scrollY && bottom >= scrollY + innerHeight)
) {
newVisibleSections.push(id)
}
}
setVisibleSections(newVisibleSections)
}
let raf = window.requestAnimationFrame(() => checkVisibleSections())
window.addEventListener('scroll', checkVisibleSections, { passive: true })
window.addEventListener('resize', checkVisibleSections)
return () => {
window.cancelAnimationFrame(raf)
window.removeEventListener('scroll', checkVisibleSections)
window.removeEventListener('resize', checkVisibleSections)
}
}, [setVisibleSections, sections])
}
const SectionStoreContext = createContext()
const useIsomorphicLayoutEffect =
typeof window === 'undefined' ? useEffect : useLayoutEffect
export function SectionProvider({ sections, children }) {
let [sectionStore] = useState(() => createSectionStore(sections))
useVisibleSections(sectionStore)
useIsomorphicLayoutEffect(() => {
sectionStore.setState({ sections })
}, [sectionStore, sections])
return (
<SectionStoreContext.Provider value={sectionStore}>
{children}
</SectionStoreContext.Provider>
)
}
export function useSectionStore(selector) {
let store = useContext(SectionStoreContext)
return useStore(store, selector)
}

View File

@ -1,58 +0,0 @@
import clsx from 'clsx'
const variantStyles = {
medium: 'rounded-lg px-1.5 ring-1 ring-inset',
}
const colorStyles = {
emerald: {
small: 'text-emerald-500 dark:text-emerald-400',
medium:
'ring-emerald-300 dark:ring-emerald-400/30 bg-emerald-400/10 text-emerald-500 dark:text-emerald-400',
},
sky: {
small: 'text-sky-500',
medium:
'ring-sky-300 bg-sky-400/10 text-sky-500 dark:ring-sky-400/30 dark:bg-sky-400/10 dark:text-sky-400',
},
amber: {
small: 'text-amber-500',
medium:
'ring-amber-300 bg-amber-400/10 text-amber-500 dark:ring-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400',
},
rose: {
small: 'text-red-500 dark:text-rose-500',
medium:
'ring-rose-200 bg-rose-50 text-red-500 dark:ring-rose-500/20 dark:bg-rose-400/10 dark:text-rose-400',
},
zinc: {
small: 'text-zinc-400 dark:text-zinc-500',
medium:
'ring-zinc-200 bg-zinc-50 text-zinc-500 dark:ring-zinc-500/20 dark:bg-zinc-400/10 dark:text-zinc-400',
},
}
const valueColorMap = {
get: 'emerald',
post: 'sky',
put: 'amber',
delete: 'rose',
}
export function Tag({
children,
variant = 'medium',
color = valueColorMap[children.toLowerCase()] ?? 'emerald',
}) {
return (
<span
className={clsx(
'font-mono text-[0.625rem] font-semibold leading-6',
variantStyles[variant],
colorStyles[color][variant]
)}
>
{children}
</span>
)
}

View File

@ -1,17 +0,0 @@
export function BellIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M4.438 8.063a5.563 5.563 0 0 1 11.125 0v2.626c0 1.182.34 2.34.982 3.332L17.5 15.5h-15l.955-1.479c.641-.993.982-2.15.982-3.332V8.062Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M7.5 15.5v0a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v0"
/>
</svg>
)
}

View File

@ -1,11 +0,0 @@
export function BoltIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M4.5 11.5 10 2v5.5a1 1 0 0 0 1 1h4.5L10 18v-5.5a1 1 0 0 0-1-1H4.5Z"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function BookIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="m10 5.5-7.5-3v12l7.5 3m0-12 7.5-3v12l-7.5 3m0-12v12"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="m17.5 2.5-7.5 3v12l7.5-3v-12Z"
/>
</svg>
)
}

View File

@ -1,23 +0,0 @@
export function CalendarIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M2.5 6.5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-11a2 2 0 0 1-2-2v-9Z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M2.5 6.5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v2h-15v-2Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M5.5 5.5v-3M14.5 5.5v-3"
/>
</svg>
)
}

View File

@ -1,15 +0,0 @@
export function CartIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeWidth="0"
d="M5.98 11.288 3.5 5.5h14l-2.48 5.788A2 2 0 0 1 13.18 12.5H7.82a2 2 0 0 1-1.838-1.212Z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="m3.5 5.5 2.48 5.788A2 2 0 0 0 7.82 12.5h5.362a2 2 0 0 0 1.839-1.212L17.5 5.5h-14Zm0 0-1-2M6.5 14.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2ZM14.5 14.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function ChatBubbleIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M10 16.5c4.142 0 7.5-3.134 7.5-7s-3.358-7-7.5-7c-4.142 0-7.5 3.134-7.5 7 0 1.941.846 3.698 2.214 4.966L3.5 17.5c2.231 0 3.633-.553 4.513-1.248A8.014 8.014 0 0 0 10 16.5Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M7.5 8.5h5M8.5 11.5h3"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function CheckIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M10 1.5a8.5 8.5 0 1 1 0 17 8.5 8.5 0 0 1 0-17Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="m7.5 10.5 2 2c1-3.5 3-5 3-5"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function ChevronRightLeftIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M1.5 10A6.5 6.5 0 0 1 8 3.5h4a6.5 6.5 0 1 1 0 13H8A6.5 6.5 0 0 1 1.5 10Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="m7.5 7.5-3 2.5 3 2.5M12.5 7.5l3 2.5-3 2.5"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function ClipboardIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M3.5 6v10a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-1l-.447.894A2 2 0 0 1 11.263 6H8.737a2 2 0 0 1-1.789-1.106L6.5 4h-1a2 2 0 0 0-2 2Z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="m13.5 4-.447.894A2 2 0 0 1 11.263 6H8.737a2 2 0 0 1-1.789-1.106L6.5 4l.724-1.447A1 1 0 0 1 8.118 2h3.764a1 1 0 0 1 .894.553L13.5 4Z"
/>
</svg>
)
}

View File

@ -1,19 +0,0 @@
export function CogIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeWidth="0"
fillRule="evenodd"
d="M11.063 1.5H8.937l-.14 1.128c-.086.682-.61 1.22-1.246 1.484-.634.264-1.37.247-1.912-.175l-.898-.699-1.503 1.503.699.898c.422.543.44 1.278.175 1.912-.264.635-.802 1.16-1.484 1.245L1.5 8.938v2.124l1.128.142c.682.085 1.22.61 1.484 1.244.264.635.247 1.37-.175 1.913l-.699.898 1.503 1.503.898-.699c.543-.422 1.278-.44 1.912-.175.635.264 1.16.801 1.245 1.484l.142 1.128h2.124l.142-1.128c.085-.683.61-1.22 1.244-1.484.635-.264 1.37-.247 1.913.175l.898.699 1.503-1.503-.699-.898c-.422-.543-.44-1.278-.175-1.913.264-.634.801-1.16 1.484-1.245l1.128-.14V8.937l-1.128-.14c-.683-.086-1.22-.611-1.484-1.246-.264-.634-.247-1.37.175-1.912l.699-.898-1.503-1.503-.898.699c-.543.422-1.278.44-1.913.175-.634-.264-1.16-.802-1.244-1.484L11.062 1.5ZM10 12.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z"
clipRule="evenodd"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M8.938 1.5h2.124l.142 1.128c.085.682.61 1.22 1.244 1.484v0c.635.264 1.37.247 1.913-.175l.898-.699 1.503 1.503-.699.898c-.422.543-.44 1.278-.175 1.912v0c.264.635.801 1.16 1.484 1.245l1.128.142v2.124l-1.128.142c-.683.085-1.22.61-1.484 1.244v0c-.264.635-.247 1.37.175 1.913l.699.898-1.503 1.503-.898-.699c-.543-.422-1.278-.44-1.913-.175v0c-.634.264-1.16.801-1.245 1.484l-.14 1.128H8.937l-.14-1.128c-.086-.683-.611-1.22-1.246-1.484v0c-.634-.264-1.37-.247-1.912.175l-.898.699-1.503-1.503.699-.898c.422-.543.44-1.278.175-1.913v0c-.264-.634-.802-1.16-1.484-1.245l-1.128-.14V8.937l1.128-.14c.682-.086 1.22-.61 1.484-1.246v0c.264-.634.247-1.37-.175-1.912l-.699-.898 1.503-1.503.898.699c.543.422 1.278.44 1.912.175v0c.635-.264 1.16-.802 1.245-1.484L8.938 1.5Z"
/>
<circle cx="10" cy="10" r="2.5" fill="none" />
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function CopyIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M14.5 5.5v-1a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h1"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M5.5 7.5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-8a2 2 0 0 1-2-2v-8Z"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function DocumentIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M3.5 4.5v11a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-8h-5v-5h-6a2 2 0 0 0-2 2Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="m11.5 2.5 5 5"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function EnvelopeIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M2.5 5.5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v8a3 3 0 0 1-3 3h-9a3 3 0 0 1-3-3v-8Z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M10 10 4.526 5.256c-.7-.607-.271-1.756.655-1.756h9.638c.926 0 1.355 1.15.655 1.756L10 10Z"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function FaceSmileIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M10 1.5a8.5 8.5 0 1 1 0 17 8.5 8.5 0 0 1 0-17Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M7.5 6.5v2M12.5 6.5v2M5.5 11.5s1 3 4.5 3 4.5-3 4.5-3"
/>
</svg>
)
}

View File

@ -1,22 +0,0 @@
export function FolderIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M17.5 15.5v-8a2 2 0 0 0-2-2h-2.93a2 2 0 0 1-1.664-.89l-.812-1.22A2 2 0 0 0 8.43 2.5H4.5a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2Z"
/>
<path
strokeWidth="0"
d="M8.43 2.5H4.5a2 2 0 0 0-2 2v1h9l-1.406-2.11A2 2 0 0 0 8.43 2.5Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="m11.5 5.5-1.406-2.11A2 2 0 0 0 8.43 2.5H4.5a2 2 0 0 0-2 2v1h9Zm0 0h2"
/>
</svg>
)
}

View File

@ -1,12 +0,0 @@
export function LinkIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="m5.056 11.5-1.221-1.222a4.556 4.556 0 0 1 6.443-6.443L11.5 5.056M7.5 7.5l5 5m2.444-4 1.222 1.222a4.556 4.556 0 0 1-6.444 6.444L8.5 14.944"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function ListIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M2.5 4.5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2h-11a2 2 0 0 1-2-2v-11Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M6.5 6.5h7M6.5 13.5h7M6.5 10h7"
/>
</svg>
)
}

View File

@ -1,13 +0,0 @@
export function MagnifyingGlassIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path strokeWidth="0" d="M2.5 8.5a6 6 0 1 1 12 0 6 6 0 0 1-12 0Z" />
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="m13 13 4.5 4.5m-9-3a6 6 0 1 1 0-12 6 6 0 0 1 0 12Z"
/>
</svg>
)
}

View File

@ -1,19 +0,0 @@
export function MapPinIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeWidth="0"
fillRule="evenodd"
clipRule="evenodd"
d="M10 2.5A5.5 5.5 0 0 0 4.5 8c0 3.038 5.5 9.5 5.5 9.5s5.5-6.462 5.5-9.5A5.5 5.5 0 0 0 10 2.5Zm0 7a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M4.5 8a5.5 5.5 0 1 1 11 0c0 3.038-5.5 9.5-5.5 9.5S4.5 11.038 4.5 8Z"
/>
<circle cx="10" cy="8" r="1.5" fill="none" />
</svg>
)
}

View File

@ -1,16 +0,0 @@
export function PackageIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeWidth="0"
d="m10 9.5-7.5-4v9l7.5 4v-9ZM10 9.5l7.5-4v9l-7.5 4v-9Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="m2.5 5.5 7.5 4m-7.5-4v9l7.5 4m-7.5-13 7.5-4 7.5 4m-7.5 4v9m0-9 7.5-4m-7.5 13 7.5-4v-9m-11 6 .028-3.852L13.5 3.5"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function PaperAirplaneIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M17 3L1 9L8 12M17 3L11 19L8 12M17 3L8 12"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M11 19L8 12L17 3L11 19Z"
/>
</svg>
)
}

View File

@ -1,12 +0,0 @@
export function PaperClipIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="m15.56 7.375-3.678-3.447c-2.032-1.904-5.326-1.904-7.358 0s-2.032 4.99 0 6.895l6.017 5.639c1.477 1.384 3.873 1.384 5.35 0 1.478-1.385 1.478-3.63 0-5.015L10.21 6.122a1.983 1.983 0 0 0-2.676 0 1.695 1.695 0 0 0 0 2.507l4.013 3.76"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function ShapesIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M2.5 7.5v-4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1ZM11.5 16.5v-4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1Z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="m2.5 17.5 3-6 3 6h-6ZM14.5 2.5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z"
/>
</svg>
)
}

View File

@ -1,11 +0,0 @@
export function ShirtIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M12.5 1.5s0 2-2.5 2-2.5-2-2.5-2h-2L2.207 4.793a1 1 0 0 0 0 1.414L4.5 8.5v10h11v-10l2.293-2.293a1 1 0 0 0 0-1.414L14.5 1.5h-2Z"
/>
</svg>
)
}

View File

@ -1,17 +0,0 @@
export function SquaresPlusIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8.5 4.5v2a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2ZM8.5 13.5v2a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2ZM17.5 4.5v2a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M14.5 11.5v6M17.5 14.5h-6"
/>
</svg>
)
}

View File

@ -1,19 +0,0 @@
export function TagIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeWidth="0"
fillRule="evenodd"
clipRule="evenodd"
d="M3 8.69499V3H8.69499C9.18447 3 9.65389 3.19444 10 3.54055L16.4594 10C17.1802 10.7207 17.1802 11.8893 16.4594 12.61L12.61 16.4594C11.8893 17.1802 10.7207 17.1802 10 16.4594L3.54055 10C3.19444 9.65389 3 9.18447 3 8.69499ZM7 8.5C7.82843 8.5 8.5 7.82843 8.5 7C8.5 6.17157 7.82843 5.5 7 5.5C6.17157 5.5 5.5 6.17157 5.5 7C5.5 7.82843 6.17157 8.5 7 8.5Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M3 3V8.69499C3 9.18447 3.19444 9.65389 3.54055 10L10 16.4594C10.7207 17.1802 11.8893 17.1802 12.61 16.4594L16.4594 12.61C17.1802 11.8893 17.1802 10.7207 16.4594 10L10 3.54055C9.65389 3.19444 9.18447 3 8.69499 3H3Z"
/>
<circle cx="7" cy="7" r="1.5" fill="none" />
</svg>
)
}

View File

@ -1,24 +0,0 @@
export function UserIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
strokeWidth="0"
fillRule="evenodd"
clipRule="evenodd"
d="M10 .5a9.5 9.5 0 0 1 5.598 17.177C14.466 15.177 12.383 13.5 10 13.5s-4.466 1.677-5.598 4.177A9.5 9.5 0 0 1 10 .5ZM12.5 8a2.5 2.5 0 1 0-5 0 2.5 2.5 0 0 0 5 0Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M10 .5a9.5 9.5 0 0 1 5.598 17.177A9.458 9.458 0 0 1 10 19.5a9.458 9.458 0 0 1-5.598-1.823A9.5 9.5 0 0 1 10 .5Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M4.402 17.677C5.534 15.177 7.617 13.5 10 13.5s4.466 1.677 5.598 4.177M10 5.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z"
/>
</svg>
)
}

View File

@ -1,28 +0,0 @@
export function UsersIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M10.046 16H1.955a.458.458 0 0 1-.455-.459C1.5 13.056 3.515 11 6 11h.5"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M7.5 15.454C7.5 12.442 9.988 10 13 10s5.5 2.442 5.5 5.454a.545.545 0 0 1-.546.546H8.045a.545.545 0 0 1-.545-.546Z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M6.5 4a2 2 0 1 1 0 4 2 2 0 0 1 0-4Z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M13 2a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z"
/>
</svg>
)
}

View File

@ -1,94 +0,0 @@
import Link from 'next/link'
import clsx from 'clsx'
import { Heading } from '@/components/Heading'
export const a = Link
export { Button } from '@/components/Button'
export { CodeGroup, Code as code, Pre as pre } from '@/components/Code'
export const h2 = function H2(props) {
return <Heading level={2} {...props} />
}
function InfoIcon(props) {
return (
<svg viewBox="0 0 16 16" aria-hidden="true" {...props}>
<circle cx="8" cy="8" r="8" strokeWidth="0" />
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
d="M6.75 7.75h1.5v3.5"
/>
<circle cx="8" cy="4" r=".5" fill="none" />
</svg>
)
}
export function Note({ children }) {
return (
<div className="my-6 flex gap-2.5 rounded-2xl border border-emerald-500/20 bg-emerald-50/50 p-4 leading-6 text-emerald-900 dark:border-emerald-500/30 dark:bg-emerald-500/5 dark:text-emerald-200 dark:[--tw-prose-links-hover:theme(colors.emerald.300)] dark:[--tw-prose-links:theme(colors.white)]">
<InfoIcon className="mt-1 h-4 w-4 flex-none fill-emerald-500 stroke-white dark:fill-emerald-200/20 dark:stroke-emerald-200" />
<div className="[&>:first-child]:mt-0 [&>:last-child]:mb-0">
{children}
</div>
</div>
)
}
export function Row({ children }) {
return (
<div className="grid grid-cols-1 items-start gap-x-16 gap-y-10 xl:max-w-none xl:grid-cols-2">
{children}
</div>
)
}
export function Col({ children, sticky = false }) {
return (
<div
className={clsx(
'[&>:first-child]:mt-0 [&>:last-child]:mb-0',
sticky && 'xl:sticky xl:top-24'
)}
>
{children}
</div>
)
}
export function Properties({ children }) {
return (
<div className="my-6">
<ul
role="list"
className="m-0 max-w-[calc(theme(maxWidth.lg)-theme(spacing.8))] list-none divide-y divide-zinc-900/5 p-0 dark:divide-white/5"
>
{children}
</ul>
</div>
)
}
export function Property({ name, type, children }) {
return (
<li className="m-0 px-0 py-4 first:pt-0 last:pb-0">
<dl className="m-0 flex flex-wrap items-center gap-x-3 gap-y-2">
<dt className="sr-only">Name</dt>
<dd>
<code>{name}</code>
</dd>
<dt className="sr-only">Type</dt>
<dd className="font-mono text-xs text-zinc-400 dark:text-zinc-500">
{type}
</dd>
<dt className="sr-only">Description</dt>
<dd className="w-full flex-none [&>:first-child]:mt-0 [&>:last-child]:mb-0">
{children}
</dd>
</dl>
</li>
)
}

View File

@ -1,14 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
<g fill="#00ACD7" clip-path="url(#a)">
<path fill-rule="evenodd"
d="M5.8 19.334c-.08 0-.093-.054-.067-.107l.4-.533a.421.421 0 0 1 .227-.08h6.893c.08 0 .094.053.067.106l-.334.507c-.04.053-.133.12-.2.12L5.8 19.32v.014Zm-2.92 1.773c-.08 0-.093-.04-.053-.107l.4-.52c.04-.053.133-.093.213-.093h8.8c.093 0 .133.053.107.12l-.16.453c-.014.08-.094.134-.174.134H2.88v.013Zm4.68 1.773c-.08 0-.107-.053-.067-.12l.267-.48c.053-.053.133-.12.2-.12h3.866c.08 0 .12.067.12.134l-.04.466c0 .08-.08.134-.133.134L7.56 22.88Zm20.053-3.906-3.24.853c-.293.08-.32.093-.56-.2-.293-.32-.506-.533-.92-.733a3.36 3.36 0 0 0-3.493.293 4.107 4.107 0 0 0-1.973 3.667 3.027 3.027 0 0 0 2.613 3.04c1.306.173 2.413-.294 3.28-1.28l.533-.707H20.12c-.4 0-.507-.267-.373-.587.253-.6.72-1.6.986-2.106a.533.533 0 0 1 .48-.307h7.04c-.04.533-.04 1.04-.12 1.573-.213 1.387-.733 2.667-1.586 3.787a8.053 8.053 0 0 1-5.507 3.28 6.839 6.839 0 0 1-5.2-1.28A6.065 6.065 0 0 1 13.386 24c-.24-2.106.374-4 1.654-5.666A8.573 8.573 0 0 1 20.44 15a6.667 6.667 0 0 1 5.12.934c1.027.666 1.76 1.6 2.253 2.733.107.173.027.267-.2.32v-.013Z"
clip-rule="evenodd" />
<path
d="M34 29.667a7.253 7.253 0 0 1-4.707-1.707 6.066 6.066 0 0 1-2.08-3.733 7.373 7.373 0 0 1 1.56-5.827 8.107 8.107 0 0 1 5.413-3.226 7.173 7.173 0 0 1 5.507.986 6.015 6.015 0 0 1 2.72 4.307 7.467 7.467 0 0 1-2.227 6.547 8.854 8.854 0 0 1-4.626 2.48c-.534.093-1.054.106-1.547.173H34Zm4.613-7.813c-.027-.254-.027-.44-.067-.64a3.186 3.186 0 0 0-3.933-2.547 4.227 4.227 0 0 0-3.387 3.36A3.187 3.187 0 0 0 33 25.68c1.066.454 2.133.4 3.16-.133a4.227 4.227 0 0 0 2.453-3.68v-.013Z" />
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M4 4h40v40H4z" />
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
<path fill="#89D42C"
d="M23.675 39.82a2.48 2.48 0 0 1-1.19-.313l-3.764-2.236c-.568-.31-.285-.425-.114-.48.765-.256.906-.313 1.698-.765.086-.057.198-.029.284.028l2.888 1.727c.113.057.254.057.34 0l11.296-6.54c.113-.057.17-.17.17-.312v-13.05c0-.143-.057-.256-.17-.313l-11.296-6.51c-.114-.057-.256-.057-.34 0L12.18 17.567c-.114.057-.17.198-.17.311V30.93c0 .114.056.255.17.312l3.087 1.784c1.67.849 2.717-.143 2.717-1.133V19.01a.344.344 0 0 1 .34-.34h1.443a.344.344 0 0 1 .341.34v12.882c0 2.237-1.218 3.539-3.342 3.539-.65 0-1.16 0-2.604-.708l-2.975-1.698A2.39 2.39 0 0 1 10 30.959V17.904c0-.849.452-1.642 1.189-2.066l11.296-6.54a2.527 2.527 0 0 1 2.379 0l11.297 6.54a2.39 2.39 0 0 1 1.188 2.066V30.96c0 .85-.452 1.642-1.188 2.066l-11.297 6.54a2.896 2.896 0 0 1-1.189.256v-.001Zm3.482-8.976c-4.954 0-5.973-2.264-5.973-4.19a.344.344 0 0 1 .34-.34h1.472c.169 0 .311.114.311.284.226 1.5.878 2.236 3.879 2.236 2.378 0 3.397-.538 3.397-1.812 0-.736-.283-1.274-3.992-1.642-3.086-.311-5.012-.99-5.012-3.454 0-2.293 1.926-3.652 5.154-3.652 3.623 0 5.407 1.246 5.634 3.963a.459.459 0 0 1-.086.256c-.056.056-.141.113-.226.113h-1.472a.332.332 0 0 1-.311-.256c-.34-1.555-1.217-2.066-3.539-2.066-2.605 0-2.916.906-2.916 1.585 0 .821.368 1.076 3.878 1.53 3.483.452 5.124 1.104 5.124 3.539-.027 2.491-2.066 3.907-5.662 3.907Z" />
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,10 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
<path fill="#6181B6" fill-rule="evenodd"
d="M14.643 21.762h-1.77l-.964 4.965h1.57c1.043 0 1.82-.198 2.33-.59.51-.393.853-1.047 1.03-1.966.173-.882.095-1.503-.232-1.866-.328-.362-.98-.543-1.962-.543h-.002Z"
clip-rule="evenodd" />
<path fill="#6181B6"
d="M24 13.29c-12.426 0-22.5 5.3-22.5 11.835 0 6.535 10.074 11.837 22.5 11.837s22.5-5.3 22.5-11.837S36.426 13.29 24 13.29Zm-6.113 13.971a4.55 4.55 0 0 1-1.718 1.032c-.63.203-1.434.308-2.41.308h-2.215l-.612 3.152H8.346l2.307-11.861h4.968c1.494 0 2.585.391 3.27 1.177.687.785.893 1.88.618 3.285a5.34 5.34 0 0 1-.57 1.588c-.28.493-.634.938-1.053 1.319h.002Zm7.546 1.34 1.018-5.247c.119-.598.073-1.005-.128-1.221-.2-.218-.63-.328-1.288-.328h-2.047l-1.32 6.799h-2.566L21.41 16.74h2.561l-.611 3.155h2.282c1.439 0 2.429.25 2.975.75.546.499.708 1.314.492 2.437l-1.073 5.52h-2.604V28.6Zm14.243-4.245a5.215 5.215 0 0 1-.571 1.586 5.356 5.356 0 0 1-1.051 1.319c-.49.467-1.078.82-1.721 1.032-.63.203-1.434.308-2.41.308H31.71l-.614 3.154h-2.581l2.305-11.862h4.968c1.495 0 2.584.393 3.27 1.177.686.784.895 1.878.62 3.285h-.002Z" />
<path fill="#6181B6" fill-rule="evenodd"
d="M34.81 21.762h-1.765l-.968 4.965h1.571c1.044 0 1.821-.198 2.33-.59.51-.393.852-1.047 1.032-1.966.172-.882.093-1.503-.234-1.866-.326-.362-.983-.543-1.964-.543h-.002Z"
clip-rule="evenodd" />
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,13 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
<g clip-path="url(#a)">
<path fill="#3372A7"
d="M23.429 9.008c-7.882 0-7.39 3.418-7.39 3.418l.01 3.541h7.52v1.063H13.062s-5.043-.572-5.043 7.38c0 7.954 4.402 7.671 4.402 7.671h2.627v-3.69s-.142-4.402 4.331-4.402h7.46s4.191.068 4.191-4.05v-6.81s.637-4.12-7.6-4.12Zm-4.147 2.382a1.353 1.353 0 1 1 .001 2.706 1.353 1.353 0 0 1-.001-2.706Z" />
<path fill="#FFD235"
d="M23.653 39.894c7.881 0 7.39-3.418 7.39-3.418l-.01-3.541h-7.52v-1.063H34.02s5.043.572 5.043-7.381-4.402-7.67-4.402-7.67h-2.627v3.69s.142 4.402-4.332 4.402h-7.46s-4.19-.068-4.19 4.05v6.81s-.637 4.12 7.6 4.12Zm4.147-2.381a1.353 1.353 0 1 1-.002-2.707 1.353 1.353 0 0 1 .002 2.706Z" />
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M8 9h31.122v31H8z" />
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 864 B

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
<path fill="#D91505"
d="M33.735 10.41c3.376.585 4.334 2.893 4.262 5.311l.017-.035-1.519 19.912-19.752 1.352h.017c-1.639-.069-5.294-.218-5.46-5.328l1.83-3.34 3.139 7.331.56 1.306L19.95 26.74l-.032.007.017-.034 10.302 3.29-1.555-6.044-1.101-4.341 9.817-.634-.684-.567-7.048-5.746 4.073-2.272-.004.012v-.001ZM17.01 15.966c3.963-3.932 9.079-6.256 11.044-4.274 1.96 1.98-.118 6.796-4.089 10.726-3.966 3.931-9.02 6.382-10.98 4.405-1.967-1.98.05-6.921 4.02-10.853l.005-.004Z" />
</svg>

Before

Width:  |  Height:  |  Size: 561 B

View File

@ -1,8 +0,0 @@
export function remToPx(remValue) {
let rootFontSize =
typeof window === 'undefined'
? 16
: parseFloat(window.getComputedStyle(document.documentElement).fontSize)
return parseFloat(remValue) * rootFontSize
}

View File

@ -1,19 +0,0 @@
import { mdxAnnotations } from 'mdx-annotations'
import recmaNextjsStaticProps from 'recma-nextjs-static-props'
function recmaRemoveNamedExports() {
return (tree) => {
tree.body = tree.body.map((node) => {
if (node.type === 'ExportNamedDeclaration') {
return node.declaration
}
return node
})
}
}
export const recmaPlugins = [
mdxAnnotations.recma,
recmaRemoveNamedExports,
recmaNextjsStaticProps,
]

View File

@ -1,126 +0,0 @@
import { mdxAnnotations } from 'mdx-annotations'
import { visit } from 'unist-util-visit'
import rehypeMdxTitle from 'rehype-mdx-title'
import shiki from 'shiki'
import { toString } from 'mdast-util-to-string'
import * as acorn from 'acorn'
import { slugifyWithCounter } from '@sindresorhus/slugify'
function rehypeParseCodeBlocks() {
return (tree) => {
visit(tree, 'element', (node, _nodeIndex, parentNode) => {
if (node.tagName === 'code' && node.properties.className) {
parentNode.properties.language = node.properties.className[0]?.replace(
/^language-/,
''
)
}
})
}
}
let highlighter
function rehypeShiki() {
return async (tree) => {
highlighter =
highlighter ?? (await shiki.getHighlighter({ theme: 'css-variables' }))
visit(tree, 'element', (node) => {
if (node.tagName === 'pre' && node.children[0]?.tagName === 'code') {
let codeNode = node.children[0]
let textNode = codeNode.children[0]
node.properties.code = textNode.value
if (node.properties.language) {
let tokens = highlighter.codeToThemedTokens(
textNode.value,
node.properties.language
)
textNode.value = shiki.renderToHtml(tokens, {
elements: {
pre: ({ children }) => children,
code: ({ children }) => children,
line: ({ children }) => `<span>${children}</span>`,
},
})
}
}
})
}
}
function rehypeSlugify() {
return (tree) => {
let slugify = slugifyWithCounter()
visit(tree, 'element', (node) => {
if (node.tagName === 'h2' && !node.properties.id) {
node.properties.id = slugify(toString(node))
}
})
}
}
function rehypeAddMDXExports(getExports) {
return (tree) => {
let exports = Object.entries(getExports(tree))
for (let [name, value] of exports) {
for (let node of tree.children) {
if (
node.type === 'mdxjsEsm' &&
new RegExp(`export\\s+const\\s+${name}\\s*=`).test(node.value)
) {
return
}
}
let exportStr = `export const ${name} = ${value}`
tree.children.push({
type: 'mdxjsEsm',
value: exportStr,
data: {
estree: acorn.parse(exportStr, {
sourceType: 'module',
ecmaVersion: 'latest',
}),
},
})
}
}
}
function getSections(node) {
let sections = []
for (let child of node.children ?? []) {
if (child.type === 'element' && child.tagName === 'h2') {
sections.push(`{
title: ${JSON.stringify(toString(child))},
id: ${JSON.stringify(child.properties.id)},
...${child.properties.annotation}
}`)
} else if (child.children) {
sections.push(...getSections(child))
}
}
return sections
}
export const rehypePlugins = [
mdxAnnotations.rehype,
rehypeParseCodeBlocks,
rehypeShiki,
rehypeSlugify,
rehypeMdxTitle,
[
rehypeAddMDXExports,
(tree) => ({
sections: `[${getSections(tree).join()}]`,
}),
],
]

View File

@ -1,4 +0,0 @@
import { mdxAnnotations } from 'mdx-annotations'
import remarkGfm from 'remark-gfm'
export const remarkPlugins = [mdxAnnotations.remark, remarkGfm]

View File

@ -1,39 +0,0 @@
import Head from 'next/head'
import { Router, useRouter } from 'next/router'
import { MDXProvider } from '@mdx-js/react'
import { Layout } from '@/components/Layout'
import * as mdxComponents from '@/components/mdx'
import { useMobileNavigationStore } from '@/components/MobileNavigation'
import '@/styles/tailwind.css'
import 'focus-visible'
function onRouteChange() {
useMobileNavigationStore.getState().close()
}
Router.events.on('routeChangeStart', onRouteChange)
Router.events.on('hashChangeStart', onRouteChange)
export default function App({ Component, pageProps }) {
let router = useRouter()
return (
<>
<Head>
{router.pathname === '/' ? (
<title>Zed Internal Docs</title>
) : (
<title>{`${pageProps.title} - Zed Internal Docs`}</title>
)}
<meta name="description" content={pageProps.description} />
</Head>
<MDXProvider components={mdxComponents}>
<Layout {...pageProps}>
<Component {...pageProps} />
</Layout>
</MDXProvider>
</>
)
}

View File

@ -1,50 +0,0 @@
import { Head, Html, Main, NextScript } from 'next/document'
const modeScript = `
let darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
updateMode()
darkModeMediaQuery.addEventListener('change', updateModeWithoutTransitions)
window.addEventListener('storage', updateModeWithoutTransitions)
function updateMode() {
let isSystemDarkMode = darkModeMediaQuery.matches
let isDarkMode = window.localStorage.isDarkMode === 'true' || (!('isDarkMode' in window.localStorage) && isSystemDarkMode)
if (isDarkMode) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
if (isDarkMode === isSystemDarkMode) {
delete window.localStorage.isDarkMode
}
}
function disableTransitionsTemporarily() {
document.documentElement.classList.add('[&_*]:!transition-none')
window.setTimeout(() => {
document.documentElement.classList.remove('[&_*]:!transition-none')
}, 0)
}
function updateModeWithoutTransitions() {
disableTransitionsTemporarily()
updateMode()
}
`
export default function Document() {
return (
<Html lang="en">
<Head>
<script dangerouslySetInnerHTML={{ __html: modeScript }} />
</Head>
<body className="bg-white antialiased dark:bg-zinc-900">
<Main />
<NextScript />
</body>
</Html>
)
}

View File

@ -1,21 +0,0 @@
@layer base {
:root {
--shiki-color-text: theme('colors.white');
--shiki-token-constant: theme('colors.emerald.300');
--shiki-token-string: theme('colors.emerald.300');
--shiki-token-comment: theme('colors.zinc.500');
--shiki-token-keyword: theme('colors.sky.300');
--shiki-token-parameter: theme('colors.pink.300');
--shiki-token-function: theme('colors.violet.300');
--shiki-token-string-expression: theme('colors.emerald.300');
--shiki-token-punctuation: theme('colors.zinc.200');
}
[inert] ::-webkit-scrollbar {
display: none;
}
}
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -1,42 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{js,mjs,jsx,mdx}'],
darkMode: 'class',
theme: {
fontSize: {
'2xs': ['0.75rem', { lineHeight: '1.25rem' }],
xs: ['0.8125rem', { lineHeight: '1.5rem' }],
sm: ['0.875rem', { lineHeight: '1.5rem' }],
base: ['1rem', { lineHeight: '1.75rem' }],
lg: ['1.125rem', { lineHeight: '1.75rem' }],
xl: ['1.25rem', { lineHeight: '1.75rem' }],
'2xl': ['1.5rem', { lineHeight: '2rem' }],
'3xl': ['1.875rem', { lineHeight: '2.25rem' }],
'4xl': ['2.25rem', { lineHeight: '2.5rem' }],
'5xl': ['3rem', { lineHeight: '1' }],
'6xl': ['3.75rem', { lineHeight: '1' }],
'7xl': ['4.5rem', { lineHeight: '1' }],
'8xl': ['6rem', { lineHeight: '1' }],
'9xl': ['8rem', { lineHeight: '1' }],
},
typography: require('./typography'),
extend: {
boxShadow: {
glow: '0 0 4px rgb(0 0 0 / 0.1)',
},
maxWidth: {
lg: '33rem',
'2xl': '40rem',
'3xl': '50rem',
'5xl': '66rem',
},
opacity: {
1: '0.01',
2.5: '0.025',
7.5: '0.075',
15: '0.15',
},
},
},
plugins: [require('@tailwindcss/typography')],
}

View File

@ -1,8 +1,6 @@
export const description = 'Tools to get started at Zed'
# Tools
---
Tools to get started at Zed
## Calendar

View File

@ -1,357 +0,0 @@
module.exports = ({ theme }) => ({
DEFAULT: {
css: {
'--tw-prose-body': theme('colors.zinc.700'),
'--tw-prose-headings': theme('colors.zinc.900'),
'--tw-prose-links': theme('colors.emerald.500'),
'--tw-prose-links-hover': theme('colors.emerald.600'),
'--tw-prose-links-underline': theme('colors.emerald.500 / 0.3'),
'--tw-prose-bold': theme('colors.zinc.900'),
'--tw-prose-counters': theme('colors.zinc.500'),
'--tw-prose-bullets': theme('colors.zinc.300'),
'--tw-prose-hr': theme('colors.zinc.900 / 0.05'),
'--tw-prose-quotes': theme('colors.zinc.900'),
'--tw-prose-quote-borders': theme('colors.zinc.200'),
'--tw-prose-captions': theme('colors.zinc.500'),
'--tw-prose-code': theme('colors.zinc.900'),
'--tw-prose-code-bg': theme('colors.zinc.100'),
'--tw-prose-code-ring': theme('colors.zinc.300'),
'--tw-prose-th-borders': theme('colors.zinc.300'),
'--tw-prose-td-borders': theme('colors.zinc.200'),
'--tw-prose-invert-body': theme('colors.zinc.400'),
'--tw-prose-invert-headings': theme('colors.white'),
'--tw-prose-invert-links': theme('colors.emerald.400'),
'--tw-prose-invert-links-hover': theme('colors.emerald.500'),
'--tw-prose-invert-links-underline': theme('colors.emerald.500 / 0.3'),
'--tw-prose-invert-bold': theme('colors.white'),
'--tw-prose-invert-counters': theme('colors.zinc.400'),
'--tw-prose-invert-bullets': theme('colors.zinc.600'),
'--tw-prose-invert-hr': theme('colors.white / 0.05'),
'--tw-prose-invert-quotes': theme('colors.zinc.100'),
'--tw-prose-invert-quote-borders': theme('colors.zinc.700'),
'--tw-prose-invert-captions': theme('colors.zinc.400'),
'--tw-prose-invert-code': theme('colors.white'),
'--tw-prose-invert-code-bg': theme('colors.zinc.700 / 0.15'),
'--tw-prose-invert-code-ring': theme('colors.white / 0.1'),
'--tw-prose-invert-th-borders': theme('colors.zinc.600'),
'--tw-prose-invert-td-borders': theme('colors.zinc.700'),
// Base
color: 'var(--tw-prose-body)',
fontSize: theme('fontSize.sm')[0],
lineHeight: theme('lineHeight.7'),
// Layout
'> *': {
maxWidth: theme('maxWidth.2xl'),
marginLeft: 'auto',
marginRight: 'auto',
'@screen lg': {
maxWidth: theme('maxWidth.3xl'),
marginLeft: `calc(50% - min(50%, ${theme('maxWidth.lg')}))`,
marginRight: `calc(50% - min(50%, ${theme('maxWidth.lg')}))`,
},
},
// Text
p: {
marginTop: theme('spacing.6'),
marginBottom: theme('spacing.6'),
},
'[class~="lead"]': {
fontSize: theme('fontSize.base')[0],
...theme('fontSize.base')[1],
},
// Lists
ol: {
listStyleType: 'decimal',
marginTop: theme('spacing.5'),
marginBottom: theme('spacing.5'),
paddingLeft: '1.625rem',
},
'ol[type="A"]': {
listStyleType: 'upper-alpha',
},
'ol[type="a"]': {
listStyleType: 'lower-alpha',
},
'ol[type="A" s]': {
listStyleType: 'upper-alpha',
},
'ol[type="a" s]': {
listStyleType: 'lower-alpha',
},
'ol[type="I"]': {
listStyleType: 'upper-roman',
},
'ol[type="i"]': {
listStyleType: 'lower-roman',
},
'ol[type="I" s]': {
listStyleType: 'upper-roman',
},
'ol[type="i" s]': {
listStyleType: 'lower-roman',
},
'ol[type="1"]': {
listStyleType: 'decimal',
},
ul: {
listStyleType: 'disc',
marginTop: theme('spacing.5'),
marginBottom: theme('spacing.5'),
paddingLeft: '1.625rem',
},
li: {
marginTop: theme('spacing.2'),
marginBottom: theme('spacing.2'),
},
':is(ol, ul) > li': {
paddingLeft: theme('spacing[1.5]'),
},
'ol > li::marker': {
fontWeight: '400',
color: 'var(--tw-prose-counters)',
},
'ul > li::marker': {
color: 'var(--tw-prose-bullets)',
},
'> ul > li p': {
marginTop: theme('spacing.3'),
marginBottom: theme('spacing.3'),
},
'> ul > li > *:first-child': {
marginTop: theme('spacing.5'),
},
'> ul > li > *:last-child': {
marginBottom: theme('spacing.5'),
},
'> ol > li > *:first-child': {
marginTop: theme('spacing.5'),
},
'> ol > li > *:last-child': {
marginBottom: theme('spacing.5'),
},
'ul ul, ul ol, ol ul, ol ol': {
marginTop: theme('spacing.3'),
marginBottom: theme('spacing.3'),
},
// Horizontal rules
hr: {
borderColor: 'var(--tw-prose-hr)',
borderTopWidth: 1,
marginTop: theme('spacing.16'),
marginBottom: theme('spacing.16'),
maxWidth: 'none',
marginLeft: `calc(-1 * ${theme('spacing.4')})`,
marginRight: `calc(-1 * ${theme('spacing.4')})`,
'@screen sm': {
marginLeft: `calc(-1 * ${theme('spacing.6')})`,
marginRight: `calc(-1 * ${theme('spacing.6')})`,
},
'@screen lg': {
marginLeft: `calc(-1 * ${theme('spacing.8')})`,
marginRight: `calc(-1 * ${theme('spacing.8')})`,
},
},
// Quotes
blockquote: {
fontWeight: '500',
fontStyle: 'italic',
color: 'var(--tw-prose-quotes)',
borderLeftWidth: '0.25rem',
borderLeftColor: 'var(--tw-prose-quote-borders)',
quotes: '"\\201C""\\201D""\\2018""\\2019"',
marginTop: theme('spacing.8'),
marginBottom: theme('spacing.8'),
paddingLeft: theme('spacing.5'),
},
'blockquote p:first-of-type::before': {
content: 'open-quote',
},
'blockquote p:last-of-type::after': {
content: 'close-quote',
},
// Headings
h1: {
color: 'var(--tw-prose-headings)',
fontWeight: '700',
fontSize: theme('fontSize.2xl')[0],
...theme('fontSize.2xl')[1],
marginBottom: theme('spacing.2'),
},
h2: {
color: 'var(--tw-prose-headings)',
fontWeight: '600',
fontSize: theme('fontSize.lg')[0],
...theme('fontSize.lg')[1],
marginTop: theme('spacing.16'),
marginBottom: theme('spacing.2'),
},
h3: {
color: 'var(--tw-prose-headings)',
fontSize: theme('fontSize.base')[0],
...theme('fontSize.base')[1],
fontWeight: '600',
marginTop: theme('spacing.10'),
marginBottom: theme('spacing.2'),
},
// Media
'img, video, figure': {
marginTop: theme('spacing.8'),
marginBottom: theme('spacing.8'),
},
'figure > *': {
marginTop: '0',
marginBottom: '0',
},
figcaption: {
color: 'var(--tw-prose-captions)',
fontSize: theme('fontSize.xs')[0],
...theme('fontSize.xs')[1],
marginTop: theme('spacing.2'),
},
// Tables
table: {
width: '100%',
tableLayout: 'auto',
textAlign: 'left',
marginTop: theme('spacing.8'),
marginBottom: theme('spacing.8'),
lineHeight: theme('lineHeight.6'),
},
thead: {
borderBottomWidth: '1px',
borderBottomColor: 'var(--tw-prose-th-borders)',
},
'thead th': {
color: 'var(--tw-prose-headings)',
fontWeight: '600',
verticalAlign: 'bottom',
paddingRight: theme('spacing.2'),
paddingBottom: theme('spacing.2'),
paddingLeft: theme('spacing.2'),
},
'thead th:first-child': {
paddingLeft: '0',
},
'thead th:last-child': {
paddingRight: '0',
},
'tbody tr': {
borderBottomWidth: '1px',
borderBottomColor: 'var(--tw-prose-td-borders)',
},
'tbody tr:last-child': {
borderBottomWidth: '0',
},
'tbody td': {
verticalAlign: 'baseline',
},
tfoot: {
borderTopWidth: '1px',
borderTopColor: 'var(--tw-prose-th-borders)',
},
'tfoot td': {
verticalAlign: 'top',
},
':is(tbody, tfoot) td': {
paddingTop: theme('spacing.2'),
paddingRight: theme('spacing.2'),
paddingBottom: theme('spacing.2'),
paddingLeft: theme('spacing.2'),
},
':is(tbody, tfoot) td:first-child': {
paddingLeft: '0',
},
':is(tbody, tfoot) td:last-child': {
paddingRight: '0',
},
// Inline elements
a: {
color: 'var(--tw-prose-links)',
textDecoration: 'underline transparent',
fontWeight: '500',
transitionProperty: 'color, text-decoration-color',
transitionDuration: theme('transitionDuration.DEFAULT'),
transitionTimingFunction: theme('transitionTimingFunction.DEFAULT'),
'&:hover': {
color: 'var(--tw-prose-links-hover)',
textDecorationColor: 'var(--tw-prose-links-underline)',
},
},
':is(h1, h2, h3) a': {
fontWeight: 'inherit',
},
strong: {
color: 'var(--tw-prose-bold)',
fontWeight: '600',
},
':is(a, blockquote, thead th) strong': {
color: 'inherit',
},
code: {
color: 'var(--tw-prose-code)',
borderRadius: theme('borderRadius.lg'),
paddingTop: theme('padding.1'),
paddingRight: theme('padding[1.5]'),
paddingBottom: theme('padding.1'),
paddingLeft: theme('padding[1.5]'),
boxShadow: 'inset 0 0 0 1px var(--tw-prose-code-ring)',
backgroundColor: 'var(--tw-prose-code-bg)',
fontSize: theme('fontSize.2xs'),
},
':is(a, h1, h2, h3, blockquote, thead th) code': {
color: 'inherit',
},
'h2 code': {
fontSize: theme('fontSize.base')[0],
fontWeight: 'inherit',
},
'h3 code': {
fontSize: theme('fontSize.sm')[0],
fontWeight: 'inherit',
},
// Overrides
':is(h1, h2, h3) + *': {
marginTop: '0',
},
'> :first-child': {
marginTop: '0 !important',
},
'> :last-child': {
marginBottom: '0 !important',
},
},
},
invert: {
css: {
'--tw-prose-body': 'var(--tw-prose-invert-body)',
'--tw-prose-headings': 'var(--tw-prose-invert-headings)',
'--tw-prose-links': 'var(--tw-prose-invert-links)',
'--tw-prose-links-hover': 'var(--tw-prose-invert-links-hover)',
'--tw-prose-links-underline': 'var(--tw-prose-invert-links-underline)',
'--tw-prose-bold': 'var(--tw-prose-invert-bold)',
'--tw-prose-counters': 'var(--tw-prose-invert-counters)',
'--tw-prose-bullets': 'var(--tw-prose-invert-bullets)',
'--tw-prose-hr': 'var(--tw-prose-invert-hr)',
'--tw-prose-quotes': 'var(--tw-prose-invert-quotes)',
'--tw-prose-quote-borders': 'var(--tw-prose-invert-quote-borders)',
'--tw-prose-captions': 'var(--tw-prose-invert-captions)',
'--tw-prose-code': 'var(--tw-prose-invert-code)',
'--tw-prose-code-bg': 'var(--tw-prose-invert-code-bg)',
'--tw-prose-code-ring': 'var(--tw-prose-invert-code-ring)',
'--tw-prose-th-borders': 'var(--tw-prose-invert-th-borders)',
'--tw-prose-td-borders': 'var(--tw-prose-invert-td-borders)',
},
},
})