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