Skip to content

Commit

Permalink
Cursorless enablement group page (#1660)
Browse files Browse the repository at this point in the history
See [deploy
preview](https://deploy-preview-1660--cursorless.netlify.app/enablement-group)

- Also adds support for mdx in our top-level cursorless-org package

## Checklist

- [x] Add meta social tags
- [x] Use latest logo
- [x] Why is logo on social slow? And is it new logo?
- [x] Make prices clickable
- [x] document that sponsorship levels are yearly
- [-] I have added
[tests](https://www.cursorless.org/docs/contributing/test-case-recorder/)
- [-] I have updated the
[docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and
[cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet)
- [-] I have not broken the cheatsheet

---------

Co-authored-by: F-Kunkle <[email protected]>
  • Loading branch information
pokey and F-Kunkle authored Nov 2, 2023
1 parent 1453284 commit 962f64f
Show file tree
Hide file tree
Showing 31 changed files with 721 additions and 44 deletions.
Binary file added images/logo-white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions packages/cursorless-org/mdx-components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { MDXComponents } from "mdx/types";

// This file allows you to provide custom React components
// to be used in MDX files. You can import and use any
// React component you want, including components from
// other libraries.

// This file is required to use MDX in `app` directory.
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
// Allows customizing built-in components, e.g. to add styling.
// h1: ({ children }) => <h1 style={{ fontSize: "100px" }}>{children}</h1>,
...components,
};
}
11 changes: 10 additions & 1 deletion packages/cursorless-org/next.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
const withMDX = require("@next/mdx")({
options: {
providerImportSource: "@mdx-js/react",
},
});

/** @type {import('next').NextConfig} */
const nextConfig = {
webpack(config) {
Expand All @@ -9,7 +15,10 @@ const nextConfig = {

return config;
},
experimental: {
mdxRs: true,
},
reactStrictMode: true,
};

module.exports = nextConfig;
module.exports = withMDX(nextConfig);
5 changes: 5 additions & 0 deletions packages/cursorless-org/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
},
"dependencies": {
"@cursorless/cheatsheet": "workspace:*",
"@mdx-js/loader": "2.3.0",
"@mdx-js/react": "2.3.0",
"@next/mdx": "13.4.10",
"eslint": "^8.38.0",
"eslint-config-next": "13.5.4",
"next": "13.5.4",
Expand All @@ -24,6 +27,8 @@
},
"devDependencies": {
"@svgr/webpack": "6.5.1",
"@types/mdx": "2.0.5",
"@types/mdx-js__react": "1.5.5",
"@types/node": "^16.11.3",
"@types/react": "18.0.28",
"@types/react-dom": "18.0.11",
Expand Down
Binary file added packages/cursorless-org/public/andrew-dant.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/cursorless-org/public/big-hats.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added packages/cursorless-org/public/james-stout.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/cursorless-org/public/sohee-yang.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/cursorless-org/public/video-share-thumbnail.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
import {
DESCRIPTION,
BASE_URL,
VIDEO_SHARE_THUMBNAIL_HEIGHT,
VIDEO_SHARE_THUMBNAIL_URL,
YOUTUBE_SLUG,
TITLE,
VIDEO_SHARE_THUMBNAIL_WIDTH,
VIDEO_SHARE_THUMBNAIL_HEIGHT,
} from "./constants";

export default function Social() {
export interface Props {
title: string;
description: string;
relativeUrl: string;
youtubeSlug?: string;
thumbnailUrl?: string;
thumbnailWidth?: string;
thumbnailHeight?: string;
}

export default function BaseSocial({
title,
description,
relativeUrl,
youtubeSlug,
thumbnailUrl = VIDEO_SHARE_THUMBNAIL_URL,
thumbnailWidth = VIDEO_SHARE_THUMBNAIL_WIDTH,
thumbnailHeight = VIDEO_SHARE_THUMBNAIL_HEIGHT,
}: Props) {
const url = `${BASE_URL}/${relativeUrl}`;

return (
<>
<meta property="og:title" content={TITLE} key="title" />
<meta property="og:title" content={title} key="title" />
<link
rel="apple-touch-icon"
sizes="180x180"
Expand All @@ -31,30 +48,63 @@ export default function Social() {
/>
<link rel="manifest" href="/site.webmanifest" />
<meta property="og:site_name" content="Cursorless" />
<meta property="og:url" content={BASE_URL} />
<meta property="og:image" content={VIDEO_SHARE_THUMBNAIL_URL} />
<meta property="og:image:width" content={VIDEO_SHARE_THUMBNAIL_WIDTH} />
<meta property="og:image:height" content={VIDEO_SHARE_THUMBNAIL_HEIGHT} />
<meta property="og:description" content={DESCRIPTION} />
<meta property="og:url" content={url} />
<meta property="og:image" content={thumbnailUrl} />
<meta property="og:image:width" content={thumbnailWidth} />
<meta property="og:image:height" content={thumbnailHeight} />
<meta property="og:description" content={description} />
<meta property="og:type" content="video" />
{youtubeSlug != null ? (
<VideoSocial youtubeSlug={youtubeSlug} />
) : (
<meta name="twitter:card" content="summary_large_image" />
)}
<meta name="twitter:site" content="@GoCursorless" />
<meta name="twitter:url" content={url} />
<meta name="twitter:title" content="Cursorless" />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={thumbnailUrl} />
<link itemProp="url" href={url} />
<meta itemProp="name" content="Cursorless" />
<meta itemProp="description" content={description} />
<meta name="description" content={description} />
<meta itemProp="paid" content="false" />
<meta itemProp="channelId" content="UCIh61mLlS6Do3R_8KnEScIQ" />
<link itemProp="thumbnailUrl" href={thumbnailUrl} />
<meta itemProp="isFamilyFriendly" content="true" />
<meta
itemProp="regionsAllowed"
content="HK,HT,TC,BW,PA,FK,AW,TN,AU,GE,SL,CC,TF,PN,TZ,CL,ET,BN,AR,PH,VI,EE,MY,LB,BM,UG,LU,NZ,KR,GG,BJ,SO,HM,GT,PR,IT,AZ,ZA,MH,MF,CW,UY,MN,MQ,MW,SE,PT,MK,SR,MA,RS,GQ,NP,BD,FM,GD,KI,IL,CK,YE,ML,BF,AO,SG,CG,GS,BI,CY,LR,UM,GH,BR,GY,KP,PM,IO,EH,SK,LV,AQ,IN,RE,LY,ZW,SZ,HR,LT,KE,TT,CR,KW,ER,NF,TK,BE,JM,SA,BH,RO,BO,MM,TH,IE,TD,QA,CN,FR,SC,VU,MG,SY,JP,PS,JO,MV,MD,TL,BY,GN,TJ,DE,TO,TR,BT,FJ,TW,AE,ES,DO,BS,NO,GU,DK,KH,SD,GB,ZM,VE,SS,IQ,AD,KG,NI,PK,PL,CZ,NA,LC,PY,SV,LA,AI,YT,US,VC,IR,NL,NU,AS,AL,GR,SH,GM,LS,ME,TV,EG,CF,DZ,SX,CA,PF,KM,AF,HN,NE,CD,MX,NC,CM,CX,SJ,GW,GF,VG,TG,BA,GP,CV,BQ,MO,SN,CH,BZ,MP,PE,FI,BB,GI,IS,PG,SM,BL,BG,AX,AM,AT,AG,ID,CI,GA,MC,NG,RW,SI,BV,UA,UZ,SB,LI,CU,VN,KN,WS,LK,IM,TM,OM,KY,VA,MT,MZ,DJ,EC,DM,HU,MU,FO,JE,NR,CO,WF,KZ,MR,GL,RU,MS,PW,ST"
/>
</>
);
}

interface VideoProps {
youtubeSlug: string;
}

function VideoSocial({ youtubeSlug }: VideoProps) {
return (
<>
<meta
property="og:video:url"
content={`https://www.youtube.com/embed/${YOUTUBE_SLUG}`}
content={`https://www.youtube.com/embed/${youtubeSlug}`}
/>
<meta
property="og:video:secure_url"
content={`https://www.youtube.com/embed/${YOUTUBE_SLUG}`}
content={`https://www.youtube.com/embed/${youtubeSlug}`}
/>
<meta property="og:video:type" content="text/html" />
<meta property="og:video:width" content="1280" />
<meta property="og:video:height" content="720" />
<meta
property="og:video:url"
content={`http://www.youtube.com/v/${YOUTUBE_SLUG}?version=3&amp;autohide=1`}
content={`http://www.youtube.com/v/${youtubeSlug}?version=3&amp;autohide=1`}
/>
<meta
property="og:video:secure_url"
content={`https://www.youtube.com/v/${YOUTUBE_SLUG}?version=3&amp;autohide=1`}
content={`https://www.youtube.com/v/${youtubeSlug}?version=3&amp;autohide=1`}
/>
<meta property="og:video:type" content="application/x-shockwave-flash" />
<meta property="og:video:width" content="1280" />
Expand All @@ -67,28 +117,12 @@ export default function Social() {
<meta property="og:video:tag" content="Talon voice" />

<meta name="twitter:card" content="player" />
<meta name="twitter:site" content="@GoCursorless" />
<meta name="twitter:url" content={BASE_URL} />
<meta name="twitter:title" content="Cursorless" />
<meta name="twitter:description" content={DESCRIPTION} />
<meta name="twitter:image" content={VIDEO_SHARE_THUMBNAIL_URL} />
<meta
name="twitter:player"
content={`https://www.youtube.com/embed/${YOUTUBE_SLUG}`}
content={`https://www.youtube.com/embed/${youtubeSlug}`}
/>
<meta name="twitter:player:width" content="1280" />
<meta name="twitter:player:height" content="720" />
<link itemProp="url" href={BASE_URL} />
<meta itemProp="name" content="Cursorless" />
<meta itemProp="description" content={DESCRIPTION} />
<meta itemProp="paid" content="false" />
<meta itemProp="channelId" content="UCIh61mLlS6Do3R_8KnEScIQ" />
<link itemProp="thumbnailUrl" href={VIDEO_SHARE_THUMBNAIL_URL} />
<meta itemProp="isFamilyFriendly" content="true" />
<meta
itemProp="regionsAllowed"
content="HK,HT,TC,BW,PA,FK,AW,TN,AU,GE,SL,CC,TF,PN,TZ,CL,ET,BN,AR,PH,VI,EE,MY,LB,BM,UG,LU,NZ,KR,GG,BJ,SO,HM,GT,PR,IT,AZ,ZA,MH,MF,CW,UY,MN,MQ,MW,SE,PT,MK,SR,MA,RS,GQ,NP,BD,FM,GD,KI,IL,CK,YE,ML,BF,AO,SG,CG,GS,BI,CY,LR,UM,GH,BR,GY,KP,PM,IO,EH,SK,LV,AQ,IN,RE,LY,ZW,SZ,HR,LT,KE,TT,CR,KW,ER,NF,TK,BE,JM,SA,BH,RO,BO,MM,TH,IE,TD,QA,CN,FR,SC,VU,MG,SY,JP,PS,JO,MV,MD,TL,BY,GN,TJ,DE,TO,TR,BT,FJ,TW,AE,ES,DO,BS,NO,GU,DK,KH,SD,GB,ZM,VE,SS,IQ,AD,KG,NI,PK,PL,CZ,NA,LC,PY,SV,LA,AI,YT,US,VC,IR,NL,NU,AS,AL,GR,SH,GM,LS,ME,TV,EG,CF,DZ,SX,CA,PF,KM,AF,HN,NE,CD,MX,NC,CM,CX,SJ,GW,GF,VG,TG,BA,GP,CV,BQ,MO,SN,CH,BZ,MP,PE,FI,BB,GI,IS,PG,SM,BL,BG,AX,AM,AT,AG,ID,CI,GA,MC,NG,RW,SI,BV,UA,UZ,SB,LI,CU,VN,KN,WS,LK,IM,TM,OM,KY,VA,MT,MZ,DJ,EC,DM,HU,MU,FO,JE,NR,CO,WF,KZ,MR,GL,RU,MS,PW,ST"
/>
</>
);
}
13 changes: 13 additions & 0 deletions packages/cursorless-org/src/components/IndexSocial.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import BaseSocial from "./BaseSocial";
import { DESCRIPTION, TITLE, VIDEO_SHARE_THUMBNAIL_URL } from "./constants";

export default function IndexSocial() {
return (
<BaseSocial
title={TITLE}
description={DESCRIPTION}
youtubeSlug={VIDEO_SHARE_THUMBNAIL_URL}
relativeUrl=""
/>
);
}
143 changes: 143 additions & 0 deletions packages/cursorless-org/src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { MDXProvider } from "@mdx-js/react";
import type { MDXComponents } from "mdx/types.js";
import Head from "next/head";
import Logo from "../pages/logo.svg";
import BaseSocial from "./BaseSocial";
import { SpamProofEmailLink } from "./SpamProofEmailLink";
import Link from "next/link";

const components: MDXComponents = {
h1: ({ children }) => (
<h1 className="text-center uppercase text-[1.88em] leading-tight mt-7 tracking-[0.14em] font-semibold">
{children}
</h1>
),
h2: ({ children }) => (
<h2 className="uppercase text-[1.4em] mt-8 mb-4 sm:mb-8 font-semibold tracking-[0.08em]">
{children}
</h2>
),
h3: ({ children }) => (
<h3 className="uppercase text-[1.5rem] mt-6 mb-3 sm:mb-6 font-medium tracking-[0.08em]">
{children}
</h3>
),
h4: ({ children }) => (
<h4 className="uppercase text-[1.5rem] mt-11 mb-3 sm:mb-6 font-medium tracking-[0.08em]">
{children}
</h4>
),
hr: () => <hr className="my-8 border-teal-400" />,
ul: ({ children }) => <ul className="list-disc ml-8">{children}</ul>,
ol: ({ children }) => <ol className="list-decimal ml-8">{children}</ol>,
li: ({ children }) => <li className="my-2">{children}</li>,
img: ({ src, alt }) => (
// FIXME: Figure out how to use next/image with MDX
// eslint-disable-next-line @next/next/no-img-element
<img
className="mx-auto my-12 rounded-[4px] border-teal-400 border-[1.5px]"
src={src}
alt={alt}
style={{ maxWidth: "100%" }}
/>
),
CursorlessScreenshot: ({ src, alt }) => (
// FIXME: Figure out how to use next/image with MDX
// eslint-disable-next-line @next/next/no-img-element
<img
className="mx-auto my-12 border-teal-400 border p-3 sm:p-6 rounded-sm"
src={src}
alt={alt}
style={{ maxWidth: "100%" }}
/>
),
CalloutParent: ({ children }) => (
<div className="border-teal-400 border rounded-sm px-7 my-12">
{children}
</div>
),
CalloutBox: ({ title, children }) => (
<div className="my-6">
<h4 className="uppercase text-[1.5rem] mb-3 sm:mb-6 leading-tight font-medium tracking-[0.08em]">
{title}
</h4>
{children}
</div>
),
Testimonials: ({ children }) => (
<div className="flex flex-col gap-5 mt-8">{children}</div>
),
Testimonial: ({ children, src, name, title, company }) => (
<div className="flex flex-col items-center bg-teal-100 dark:bg-teal-900 border border-teal-400 text-teal-700 dark:text-teal-300 p-3 sm:p-6 rounded-sm">
<blockquote className="mb-5 sm:mb-6 flex flex-col gap-4">
{children}
</blockquote>
<div className="flex items-center gap-4">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
className="rounded-full w-[4.5em] h-[4.5em] border-teal-400 border dark:border-[0.5px]"
src={src}
alt={name}
/>
<div className="flex flex-col gap-[0.375rem]">
<div className="text-teal-800 dark:text-teal-200 font-semibold text-[1.2em] leading-none">
{name}
</div>
<div className="text-[0.9em] leading-none">{title}</div>
<div className="text-[0.9em] leading-none">{company}</div>
</div>
</div>
</div>
),
Tiers: ({ children }) => (
<div className="my-8 font-medium tracking-[0.1em] text-[1.2em]">
{children}
</div>
),
Tier: ({ emoji, type, price, address, subject, body }) => (
<div className="flex gap-3 leading-8">
<span className="">{emoji}</span>
<span className="uppercase">{type}</span>
<span>{"-"}</span>
<SpamProofEmailLink address={address} subject={subject} body={body}>
{price} / year
</SpamProofEmailLink>
</div>
),
};

export const bodyClasses = "bg-salmon-100 dark:bg-salmon-900";

export interface Props extends React.PropsWithChildren {
title: string;
description: string;
relativeUrl: string;
}

export function Layout({ title, description, relativeUrl, children }: Props) {
return (
<>
<Head>
<title>{title}</title>
<BaseSocial
title={title}
description={description}
relativeUrl={relativeUrl}
/>
</Head>
<MDXProvider components={components}>
<main className="text-salmon-900 dark:text-salmon-100 font-mono font-normal sm:dark:font-light px-4 pt-8 sm:pt-16 lg:pt-20 pb-8 tracking-[0.08em] leading-6">
<div className="max-w-prose mx-auto">
<Link href="/">
<Logo
title="Logo"
className="mx-auto align-middle w-[6.284em] h-[6.284em]"
/>
</Link>
{children}
</div>
</main>
</MDXProvider>
</>
);
}
Loading

0 comments on commit 962f64f

Please sign in to comment.