diff --git a/.vscode/settings.json b/.vscode/settings.json
index cb56bf9fab..02d49400e5 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -8,5 +8,6 @@
"typescript.tsdk": "node_modules/typescript/lib",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
- }
+ },
+ "tailwindCSS.classFunctions": ["clsx"]
}
diff --git a/next.config.js b/next.config.js
index bfd990f81e..24baa11c51 100644
--- a/next.config.js
+++ b/next.config.js
@@ -31,12 +31,38 @@ export default withLess(
rule.test?.test?.(".svg"),
)
- fileLoaderRule.exclude = ALLOWED_SVG_REGEX
+ fileLoaderRule.exclude = /\.svg$/i
+
+ config.module.rules.push(
+ // All .svg from /icons/ and with ?svgr are going to be processed by @svgr/webpack
+ {
+ test: ALLOWED_SVG_REGEX,
+ use: ["@svgr/webpack"],
+ },
+ {
+ test: /\.svg$/i,
+ exclude: ALLOWED_SVG_REGEX,
+ resourceQuery: /svgr/,
+ use: [
+ {
+ loader: "@svgr/webpack",
+ options: {
+ dimensions: false, // **adds** viewBox.
+ },
+ },
+ ],
+ },
+ // Otherwise, we use the default file loader
+ {
+ ...fileLoaderRule,
+ test: /\.svg$/i,
+ exclude: ALLOWED_SVG_REGEX,
+ resourceQuery: {
+ not: [...fileLoaderRule.resourceQuery.not, /svgr/],
+ },
+ },
+ )
- config.module.rules.push({
- test: ALLOWED_SVG_REGEX,
- use: ["@svgr/webpack"],
- })
return config
},
output: "export",
diff --git a/package.json b/package.json
index 4b92b8bf88..b7d60df083 100644
--- a/package.json
+++ b/package.json
@@ -23,6 +23,7 @@
"@graphql-tools/schema": "10.0.15",
"@headlessui/react": "^1.7.17",
"@radix-ui/react-radio-group": "^1.1.3",
+ "@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
"@tailwindcss/typography": "^0.5.10",
"autoprefixer": "^10.4.17",
@@ -39,6 +40,7 @@
"lucide-react": "^0.469.0",
"markdown-to-jsx": "^7.4.0",
"marked": "5.1.2",
+ "motion": "^12.11.0",
"next": "^14.2.5",
"next-image-export-optimizer": "^1.12.3",
"next-query-params": "^5.0.0",
@@ -53,6 +55,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-medium-image-zoom": "5.2.13",
+ "react-use-measure": "^2.1.7",
"rss": "1.2.2",
"server-only": "0.0.1",
"string-similarity": "^4.0.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c830a6cbd2..c2cde5d2db 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -22,6 +22,9 @@ importers:
'@radix-ui/react-radio-group':
specifier: ^1.1.3
version: 1.2.2(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@tailwindcss/container-queries':
+ specifier: ^0.1.1
+ version: 0.1.1(tailwindcss@3.4.17)
'@tailwindcss/nesting':
specifier: 0.0.0-insiders.565cd3e
version: 0.0.0-insiders.565cd3e(postcss@8.4.49)
@@ -70,6 +73,9 @@ importers:
marked:
specifier: 5.1.2
version: 5.1.2
+ motion:
+ specifier: ^12.11.0
+ version: 12.11.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
next:
specifier: ^14.2.5
version: 14.2.22(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -112,6 +118,9 @@ importers:
react-medium-image-zoom:
specifier: 5.2.13
version: 5.2.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-use-measure:
+ specifier: ^2.1.7
+ version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
rss:
specifier: 1.2.2
version: 1.2.2
@@ -1703,6 +1712,11 @@ packages:
'@swc/helpers@0.5.5':
resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
+ '@tailwindcss/container-queries@0.1.1':
+ resolution: {integrity: sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==}
+ peerDependencies:
+ tailwindcss: '>=3.2.0'
+
'@tailwindcss/nesting@0.0.0-insiders.565cd3e':
resolution: {integrity: sha512-WhHoFBx19TnH/c+xLwT/sxei6+4RpdfiyG3MYXfmLaMsADmVqBkF7B6lDalgZD9YdM459MF7DtxVbWkOrV7IaQ==}
peerDependencies:
@@ -2731,6 +2745,20 @@ packages:
fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
+ framer-motion@12.11.0:
+ resolution: {integrity: sha512-BaBPmkhaC2l0n619Kt1nQaxSdUdyyz5V1Z7EKJ1CcraOTZitgVx0RTbL8lmg2XesaFi6o8MPBIhkWDIvzDpGaQ==}
+ peerDependencies:
+ '@emotion/is-prop-valid': '*'
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@emotion/is-prop-valid':
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@@ -3596,6 +3624,26 @@ packages:
mj-context-menu@0.6.1:
resolution: {integrity: sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==}
+ motion-dom@12.11.0:
+ resolution: {integrity: sha512-CItkGYJenn5ZsbzTX0D9mE0UWdjdd9r535FrxEXhzR8Kwa9I2dLr1uhEJgQPWbgaIJ6i0sNFnf2T9NvVDWQVBw==}
+
+ motion-utils@12.9.4:
+ resolution: {integrity: sha512-BW3I65zeM76CMsfh3kHid9ansEJk9Qvl+K5cu4DVHKGsI52n76OJ4z2CUJUV+Mn3uEP9k1JJA3tClG0ggSrRcg==}
+
+ motion@12.11.0:
+ resolution: {integrity: sha512-1DIh+uBh2Ledv8VlJfveLuE+6tTAkLqRxhBHQSH6Ct8PxcZpUWY7z9E34L3LvnGbXp8u97hGSjeDsmvmVrjOeQ==}
+ peerDependencies:
+ '@emotion/is-prop-valid': '*'
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@emotion/is-prop-valid':
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
@@ -4054,6 +4102,15 @@ packages:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-use-measure@2.1.7:
+ resolution: {integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==}
+ peerDependencies:
+ react: '>=16.13'
+ react-dom: '>=16.13'
+ peerDependenciesMeta:
+ react-dom:
+ optional: true
+
react@18.3.1:
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
engines: {node: '>=0.10.0'}
@@ -6456,6 +6513,10 @@ snapshots:
'@swc/counter': 0.1.3
tslib: 2.8.1
+ '@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.17)':
+ dependencies:
+ tailwindcss: 3.4.17
+
'@tailwindcss/nesting@0.0.0-insiders.565cd3e(postcss@8.4.49)':
dependencies:
postcss: 8.4.49
@@ -7593,6 +7654,15 @@ snapshots:
fraction.js@4.3.7: {}
+ framer-motion@12.11.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ motion-dom: 12.11.0
+ motion-utils: 12.9.4
+ tslib: 2.8.1
+ optionalDependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
fs.realpath@1.0.0: {}
fsevents@2.3.3:
@@ -8886,6 +8956,20 @@ snapshots:
mj-context-menu@0.6.1: {}
+ motion-dom@12.11.0:
+ dependencies:
+ motion-utils: 12.9.4
+
+ motion-utils@12.9.4: {}
+
+ motion@12.11.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ framer-motion: 12.11.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ tslib: 2.8.1
+ optionalDependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
mri@1.2.0: {}
ms@2.1.2: {}
@@ -9332,6 +9416,12 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
+ react-use-measure@2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ react-dom: 18.3.1(react@18.3.1)
+
react@18.3.1:
dependencies:
loose-envify: 1.4.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
deleted file mode 100644
index cac8a5aaf9..0000000000
--- a/pnpm-workspace.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-packages:
- - "website"
diff --git a/public/img/conf/Sponsors/Tyk.svg b/public/img/conf/Sponsors/Tyk.svg
index 5d9487148a..06fa8b1397 100644
--- a/public/img/conf/Sponsors/Tyk.svg
+++ b/public/img/conf/Sponsors/Tyk.svg
@@ -1,18 +1,7 @@
-
\ No newline at end of file
+
diff --git a/src/app/colors.css b/src/app/colors.css
new file mode 100644
index 0000000000..95ec008b24
--- /dev/null
+++ b/src/app/colors.css
@@ -0,0 +1,40 @@
+:root,
+.light {
+ --color-pri-lighter: 319 100% 90%;
+ --color-pri-light: 318 100% 80%;
+ --color-pri-base: 319 100% 44.1%;
+ --color-pri-dark: 319 100% 30%;
+ --color-pri-darker: 319 100% 20%;
+
+ --color-sec-lighter: 79 80% 90%;
+ --color-sec-light: 79 82% 80%;
+ --color-sec-base: 79 90% 65%;
+ --color-sec-dark: 79 98% 37%;
+ --color-sec-darker: 79 98% 23%;
+
+ --color-neu-0: 0 0% 100%;
+ --color-neu-50: 75 57% 97%;
+ --color-neu-100: 75 15% 95%;
+ --color-neu-200: 77 14% 90%;
+ --color-neu-300: 76 14% 85%;
+ --color-neu-400: 77 14% 80%;
+ --color-neu-500: 74 14% 70%;
+ --color-neu-600: 76 15% 60%;
+ --color-neu-700: 76 15% 40%;
+ --color-neu-800: 77 14% 20%;
+ --color-neu-900: 75 15% 5%;
+}
+
+.dark {
+ --color-neu-900: 0 0% 100%;
+ --color-neu-800: 75 57% 97%;
+ --color-neu-700: 75 15% 95%;
+ --color-neu-600: 77 14% 90%;
+ --color-neu-500: 76 14% 85%;
+ --color-neu-400: 77 14% 80%;
+ --color-neu-300: 74 14% 70%;
+ --color-neu-200: 76 15% 60%;
+ --color-neu-100: 76 15% 40%;
+ --color-neu-50: 77 14% 20%;
+ --color-neu-0: 75 15% 5%;
+}
diff --git a/src/app/conf/2023/layout.tsx b/src/app/conf/2023/layout.tsx
index 4669949d2c..6b3f04a9db 100644
--- a/src/app/conf/2023/layout.tsx
+++ b/src/app/conf/2023/layout.tsx
@@ -4,6 +4,7 @@ import { Header } from "../_components/header"
import { Footer } from "../_components/footer"
import { GraphQLConf, HostedByGraphQLFoundation } from "@/icons"
import NextLink from "next/link"
+import { OldFontsStyleTag } from "../../fonts/old-fonts"
export const metadata = {
description:
@@ -33,6 +34,7 @@ export default function ConfLayout({
const hover = "#c026d3"
return (
<>
+
diff --git a/src/globals.css b/src/globals.css
index 4d74f4b054..efca847c5b 100644
--- a/src/globals.css
+++ b/src/globals.css
@@ -503,3 +503,24 @@ div[id^="headlessui-menu-items"] {
@apply text-xl;
@apply dark:border-neutral-700/80;
}
+
+.gql-focus-visible,
+.gql-all-anchors-focusable a {
+ @apply focus-visible:outline focus-visible:outline-[3px] focus-visible:outline-offset-[5px] focus-visible:outline-neu-900;
+}
+
+.gql-conf-container {
+ @apply mx-auto w-full max-w-[120rem];
+}
+
+.gql-conf-section {
+ @apply px-4 py-8 lg:px-12 xl:gap-x-24 xl:px-24 3xl:px-[240px];
+}
+
+.gql-conf-navbar-strip {
+ @apply relative [contain:paint] before:sticky before:top-0 before:z-[9] before:-mt-[var(--navbar-h)] before:block before:h-[var(--navbar-h)] before:w-full before:content-[''];
+}
+
+:root {
+ --navbar-h: 70px;
+}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 6a71eba9d0..639673a139 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -1,6 +1,8 @@
+import { fontFamily } from "tailwindcss/defaultTheme"
import type { Config } from "tailwindcss"
import typography from "@tailwindcss/typography"
-
+import plugin from "tailwindcss/plugin"
+import containerQueries from "@tailwindcss/container-queries"
const config: Config = {
content: ["./src/**/*.{js,ts,jsx,tsx,mdx}", "./theme.config.tsx"],
theme: {
@@ -9,10 +11,59 @@ const config: Config = {
padding: "1rem",
},
extend: {
+ fontFamily: {
+ sans: [
+ `var(--font-sans, ${fontFamily.sans.slice(0, 3).join(", ")})`,
+ ...fontFamily.sans,
+ ],
+ mono: [
+ `var(--font-mono, ${fontFamily.mono.slice(0, 3).join(", ")})`,
+ ...fontFamily.mono,
+ ],
+ },
+ screens: {
+ "3xl": "1920px",
+ },
colors: {
primary: "#e10098",
"conf-black": "#0e031c",
black: "#1b1b1b",
+
+ // #region new design system colors
+ "pri-lighter": "hsl(var(--color-pri-lighter) / )",
+ "pri-light": "hsl(var(--color-pri-light) / )",
+ "pri-base": "hsl(var(--color-pri-base) / )",
+ "pri-dark": "hsl(var(--color-pri-dark) / )",
+ "pri-darker": "hsl(var(--color-pri-darker) / )",
+
+ "sec-lighter": "hsl(var(--color-sec-lighter) / )",
+ "sec-light": "hsl(var(--color-sec-light) / )",
+ "sec-base": "hsl(var(--color-sec-base) / )",
+ "sec-dark": "hsl(var(--color-sec-dark) / )",
+ "sec-darker": "hsl(var(--color-sec-darker) / )",
+
+ // We're using 3-letter color names to avoid conflicting
+ // with the old `neutral` color.
+ "neu-0": "hsl(var(--color-neu-0) / )",
+ "neu-50": "hsl(var(--color-neu-50) / )",
+ "neu-100": "hsl(var(--color-neu-100) / )",
+ "neu-200": "hsl(var(--color-neu-200) / )",
+ "neu-300": "hsl(var(--color-neu-300) / )",
+ "neu-400": "hsl(var(--color-neu-400) / )",
+ "neu-500": "hsl(var(--color-neu-500) / )",
+ "neu-600": "hsl(var(--color-neu-600) / )",
+ "neu-700": "hsl(var(--color-neu-700) / )",
+ "neu-800": "hsl(var(--color-neu-800) / )",
+ "neu-900": "hsl(var(--color-neu-900) / )",
+
+ blk: "#000",
+
+ /**
+ * GraphQL Rhodamine as per the trademark guidelines
+ * https://www.graphql.org/brand/
+ */
+ rhodamine: "#e10098",
+ // #endregion new design system colors
},
backgroundImage: {
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
@@ -32,7 +83,101 @@ const config: Config = {
},
},
},
- plugins: [typography],
+ plugins: [
+ typography,
+ containerQueries,
+ plugin(({ addUtilities }) => {
+ // heading styles
+ addUtilities({
+ ".typography-d1, .typography-h1, .typography-h2, .typography-h3": {
+ lineHeight: "1.2",
+ },
+ ".typography-d1": {
+ fontSize: "48px",
+ "@screen lg": {
+ fontSize: "96px",
+ },
+ },
+ ".typography-h1": {
+ fontSize: "40px",
+ "@screen lg": {
+ fontSize: "72px",
+ },
+ },
+ ".typography-h2": {
+ fontSize: "32px",
+ "@screen md": {
+ fontSize: "48px",
+ },
+ },
+ ".typography-h3": {
+ fontSize: "24px",
+ "@screen md": {
+ fontSize: "32px",
+ },
+ },
+ })
+
+ // paragraph styles
+ addUtilities({
+ ".typography-body-lg, .typography-body-md, .typography-body-sm, .typography-body-xs":
+ {
+ lineHeight: "1.5",
+ },
+ ".typography-body-lg": {
+ fontSize: "16px",
+ "@screen md": {
+ fontSize: "20px",
+ },
+ },
+ ".typography-body-md": {
+ fontSize: "14px",
+ "@screen md": {
+ fontSize: "16px",
+ },
+ },
+ ".typography-body-sm": {
+ fontSize: "12px",
+ "@screen md": {
+ fontSize: "14px",
+ },
+ },
+ ".typography-body-xs": {
+ fontSize: "10px",
+ "@screen md": {
+ fontSize: "12px",
+ },
+ },
+ })
+
+ // other text styles
+ addUtilities({
+ ".typography-button, .typography-tagline": {
+ fontSize: "16px",
+ lineHeight: "1",
+ },
+ ".typography-tagline": {
+ textTransform: "uppercase",
+ },
+ ".typography-menu": {
+ fontFamily: "var(--font-mono)",
+ fontSize: "14px",
+ lineHeight: "1",
+ textTransform: "uppercase",
+ },
+ })
+
+ addUtilities({
+ ".typography-link": {
+ color: "theme('colors.neu-800')",
+ textDecoration: "underline",
+ "&:hover": {
+ textDecoration: "none",
+ },
+ },
+ })
+ }),
+ ],
darkMode: ["class", 'html[class~="dark"]'],
}
export default config