Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/app/colors.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
:root,
.light {
--color-pri-lightest: 319 100% 96%;
--color-pri-lighter: 319 100% 90%;
--color-pri-light: 318 100% 80%;
--color-pri-base: 319 100% 44.1%;
Expand Down
97 changes: 70 additions & 27 deletions src/components/cards.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,88 @@
import { ReactElement } from "react"
import { Card } from "./card"
import { clsx } from "clsx"
import NextLink from "next/link"
import ArrowDownIcon from "@/app/conf/_design-system/pixelarticons/arrow-down.svg?svgr"
import { learnPages } from "./learn-aggregator/learn-pages"

export function Cards({
items,
numbered,
}: {
items: {
icon: ReactElement
icon?:
| (({ className }: { className?: string }) => React.ReactNode)
| React.ReactNode
title: string
description?: string
link: string
}[]
numbered?: string
}) {
return (
<div className="mt-6 grid grid-cols-2 gap-4">
{items.map(({ icon: Icon, title, link, description }) => {
const isExternal = link.startsWith("https://")
<ul className="grid grid-cols-1 justify-stretch gap-2 pt-6 sm:grid-cols-2 lg:gap-4">
{items.map((item, index) => {
// Try to get section from learn-pages
let section: "getting-started" | "best-practices" | undefined

const path = item.link.replace(/^\/learn\//, "").replace(/\/$/, "")
const learnPage = learnPages[path as keyof typeof learnPages]
if (learnPage) {
section = learnPage.section
}

return (
<Card
key={title}
as={isExternal ? "a" : NextLink}
// @ts-expect-error
href={link}
className={clsx(
"flex flex-col items-center",
isExternal &&
"relative after:absolute after:right-4 after:top-4 after:font-sans after:content-['_↗']",
)}
>
{/* @ts-expect-error */}
{typeof Icon === "function" ? <Icon className="h-12" /> : Icon}
<b className="mb-2 mt-4 text-center text-lg">{title}</b>
<span
className={`text-xs md:text-sm text-center${description ? "" : "break-all"}`}
<li key={item.title} className="flex text-neu-900">
<a
href={item.link}
className={clsx(
"gql-focus-visible grid w-full border border-neu-200 bg-neu-0 transition-colors [grid-template-areas:'header''desc'] [grid-template-rows:auto_1fr] hover:ring hover:ring-neu-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 dark:border-neu-100 dark:hover:ring-neu-50 lg:[grid-template-areas:'header_header''desc_arrow'] lg:[grid-template-columns:1fr_64px]",
section === "getting-started" &&
"bg-pri-lighter/10 dark:bg-pri-lighter/5",
section === "best-practices" &&
"bg-sec-lighter/10 dark:bg-sec-lighter/5",
)}
>
{description ? description : link.replace(/^https?:\/\//, "")}
</span>
</Card>
<span className="flex flex-col gap-1 [grid-area:header]">
{numbered && (
<span className="typography-body-sm px-2 pt-2 text-neu-700 max-lg:typography-body-md lg:px-4 lg:pt-4">
{numbered} {index + 1}
</span>
)}
<span
className={clsx(
"typography-h3 flex items-center gap-2 border-neu-200 text-neu-900 dark:border-neu-100",
item.icon ? "border-b" : "pl-2 lg:pl-4",
)}
>
{item.icon && (
<span className="flex items-center justify-center border-r border-neu-200 p-2 lg:p-4">
{typeof item.icon === "function" ? (
<item.icon className="size-8 shrink-0" />
) : (
item.icon
)}
</span>
)}
{item.title}
</span>
</span>

<p className="typography-body-sm text-pretty p-4 text-neu-900 [grid-area:desc] max-lg:typography-body-md max-lg:border-t max-lg:border-neu-200 dark:max-lg:border-neu-100">
{item.description
? item.description
: item.link.replace(/^https?:\/\//, "")}
</p>

<span
className={clsx(
"hidden items-center justify-center place-self-end border-l border-neu-200 p-4 [grid-area:arrow] dark:border-neu-100 lg:flex",
item.icon ? "h-full" : "border-t",
)}
>
<ArrowDownIcon className="size-8 shrink-0 -rotate-90" />
</span>
</a>
</li>
)
})}
</div>
</ul>
)
}
2 changes: 1 addition & 1 deletion src/components/footer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export function Footer() {
<footer className="relative isolate !bg-neu-100 text-neu-900 dark:!bg-neu-0 max-md:px-0 max-md:pt-0">
<Stripes />

<div className="mx-auto max-w-[120rem] border-neu-400 dark:border-neu-100 3xl:border-x 3xl:dark:border-t">
<div className="mx-auto max-w-[120rem] border-neu-400 dark:border-neu-100 xl:border-t 3xl:border-x">
<div className="flex flex-wrap justify-between gap-4 p-4 max-md:w-full md:p-6 2xl:px-10">
<NextLink href="/" className="nextra-logo flex items-center">
<GraphQLWordmarkLogo className="h-6" title="GraphQL" />
Expand Down
16 changes: 16 additions & 0 deletions src/components/learn-aggregator/assets/keyboard.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions src/components/learn-aggregator/learn-hero-stripes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { StripesDecoration } from "@/app/conf/_design-system/stripes-decoration"

import blurBean from "./learn-blur-bean.webp"

export function LearnHeroStripes() {
return (
<div
role="presentation"
// eslint-disable-next-line tailwindcss/no-contradicting-classname
className="pointer-events-none absolute inset-0 bg-neu-50 [--end-1:#FFF] [--end-2:rgb(255_204_239/.2)] [--start-1:#FFEAF8] [--start-2:hsl(var(--color-sec-lighter))] dark:[--end-1:hsl(75,15%,5%)] dark:[--end-2:hsl(319,100%,10%)] dark:[--start-1:hsl(319,100%,14%)] dark:[--start-2:hsl(319,100%,30%)] sm:h-[360px] lg:h-[calc(100%-163px)]"
style={{
maskImage: `url(${blurBean.src})`,
WebkitMaskImage: `url(${blurBean.src})`,
maskSize: "2200px",
WebkitMaskSize: "2200px",
maskPosition: "50% 60%",
WebkitMaskPosition: "50% 60%",
maskRepeat: "no-repeat",
WebkitMaskRepeat: "no-repeat",
}}
>
<StripesDecoration
evenClassName="bg-[linear-gradient(180deg,var(--start-1)_-80%,var(--end-1)_102%)]"
oddClassName="bg-[linear-gradient(180deg,var(--start-2)_-80%,var(--end-2)_102%)]"
/>
</div>
)
}
7 changes: 6 additions & 1 deletion src/components/learn-aggregator/learn-pages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,12 @@ const _items: Record<
section: "getting-started",
},
// ---
"best-practices": null,
"best-practices": {
description:
"Understand the context behind the GraphQL Best Practices lessons.",
icon: new URL("./assets/keyboard.svg", import.meta.url).href,
section: "best-practices",
},
"thinking-in-graphs": {
description:
"Learn how to shift your mindset from RESTful endpoints to graph-based thinking, aligning your schema with business logic and legacy systems.",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { ReactNode, useState } from "react"
import { clsx } from "clsx"

import { StripesDecoration } from "@/app/conf/_design-system/stripes-decoration"
import ArrowDownIcon from "@/app/conf/_design-system/pixelarticons/arrow-down.svg?svgr"

import { Eyebrow } from "@/_design-system/eyebrow"

import blurBean from "./learn-blur-bean.webp"
import { Button } from "@/app/conf/_design-system/button"

export interface TeaserSectionProps
Expand Down Expand Up @@ -121,7 +119,7 @@ function TeaserSectionListItem({
<li className={clsx("flex text-neu-900", className)} {...rest}>
<a
href={href}
className="gql-focus-visible grid border border-neu-200 bg-neu-0 transition-colors [grid-template-areas:'icon_header''desc_desc'] [grid-template-columns:72px_1fr] [grid-template-rows:auto_1fr] hover:ring hover:ring-neu-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 dark:border-neu-100 dark:hover:ring-neu-50 lg:[grid-template-areas:'icon_header_header''icon_desc_arrow'] lg:[grid-template-columns:190px_1fr_64px]"
className="gql-focus-visible grid w-full border border-neu-200 bg-neu-0 transition-colors [grid-template-areas:'icon_header''desc_desc'] [grid-template-columns:72px_1fr] [grid-template-rows:auto_1fr] hover:ring hover:ring-neu-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 dark:border-neu-100 dark:hover:ring-neu-50 lg:[grid-template-areas:'icon_header_header''icon_desc_arrow'] lg:[grid-template-columns:190px_1fr_64px]"
>
<span
className={clsx(
Expand Down Expand Up @@ -156,28 +154,3 @@ function TeaserSectionListItem({
</li>
)
}

export function LearnHeroStripes() {
return (
<div
role="presentation"
// eslint-disable-next-line tailwindcss/no-contradicting-classname
className="pointer-events-none absolute inset-0 h-[300px] bg-neu-50 [--end-1:#FFF] [--end-2:rgb(255_204_239/.2)] [--start-1:#FFEAF8] [--start-2:hsl(var(--color-sec-lighter))] dark:[--end-1:hsl(var(--color-neu-0))] dark:[--end-2:hsl(var(--color-pri-base)/.1)] dark:[--start-1:hsl(var(--color-neu-100)/.2)] dark:[--start-2:hsl(var(--color-sec-light)/.1)] sm:h-[360px] lg:h-[480px]"
style={{
maskImage: `url(${blurBean.src})`,
WebkitMaskImage: `url(${blurBean.src})`,
maskSize: "2200px",
WebkitMaskSize: "2200px",
maskPosition: "50% 60%",
WebkitMaskPosition: "50% 60%",
maskRepeat: "no-repeat",
WebkitMaskRepeat: "no-repeat",
}}
>
<StripesDecoration
evenClassName="bg-[linear-gradient(180deg,var(--start-1)_-80%,var(--end-1)_102%)]"
oddClassName="bg-[linear-gradient(180deg,var(--start-2)_-80%,var(--end-2)_102%)]"
/>
</div>
)
}
59 changes: 59 additions & 0 deletions src/components/nav-links/arrow-nav-links.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// eslint-disable-next-line no-restricted-imports -- since we don't need newWindow prop
import NextLink from "next/link"
import type { Item } from "nextra/normalize-pages"
import type { ReactElement } from "react"
import { useThemeConfig } from "nextra-theme-docs"
import type { DocsThemeConfig } from "nextra-theme-docs"

import ArrowDown from "@/app/conf/_design-system/pixelarticons/arrow-down.svg?svgr"

interface NavLinkProps {
currentIndex: number
flatDocsDirectories: Item[]
}

export function ArrowNavLinks({
flatDocsDirectories,
currentIndex,
}: NavLinkProps): ReactElement | null {
const themeConfig = useThemeConfig()
const nav = themeConfig.navigation
const navigation: Exclude<DocsThemeConfig["navigation"], boolean> =
typeof nav === "boolean" ? { prev: nav, next: nav } : nav
let prev = navigation.prev && flatDocsDirectories[currentIndex - 1]
let next = navigation.next && flatDocsDirectories[currentIndex + 1]

if (prev && !prev.isUnderCurrentDocsTree) prev = false
if (next && !next.isUnderCurrentDocsTree) next = false

if (!prev && !next) return null

return (
<div className="mb-8 flex items-center gap-4 border-t border-neu-200 pt-8 print:hidden">
{prev && (
<NextLink
href={prev.route}
title={prev.title}
className="gql-focus-visible typography-link flex max-w-[50%] items-center gap-2 border border-neu-200 pr-2 text-left text-base no-underline hover:bg-neu-50 hover:ring hover:ring-neu-100 dark:border-neu-100 dark:hover:bg-neu-50/50 dark:hover:ring-neu-50"
>
<span className="border-r p-2">
<ArrowDown className="size-8 shrink-0 rotate-90" />
</span>
<span className="[word-break:break-word]">{prev.title}</span>
</NextLink>
)}
{next && (
<NextLink
href={next.route}
title={next.title}
className="gql-focus-visible typography-link ml-auto flex max-w-[50%] items-center gap-2 border border-neu-200 pl-2 text-left text-base no-underline hover:bg-neu-50 hover:ring hover:ring-neu-100 dark:border-neu-100 dark:hover:bg-neu-50/50 dark:hover:ring-neu-50"
>
<span className="[word-break:break-word]">{next.title}</span>
<span className="border-l border-neu-200 p-2 dark:border-neu-100">
<ArrowDown className="size-8 shrink-0 -rotate-90" />
</span>
</NextLink>
)}
</div>
)
}
Binary file added src/components/nav-links/blur-corner.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/components/nav-links/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { LearnNavLinkCard } from "./learn-nav-link-card"
export { ArrowNavLinks } from "./arrow-nav-links"
Loading
Loading