Skip to content

Commit 8338eab

Browse files
committed
Tweak mobile UI
1 parent 89ce26f commit 8338eab

File tree

6 files changed

+91
-39
lines changed

6 files changed

+91
-39
lines changed

src/components/index-page/graphql-advantages/consistency.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function ConsistencyFigure() {
4949
return (
5050
<section
5151
id="type-system"
52-
className="nextra-codeblocks flex w-full bg-gradient-to-b from-transparent to-sec-lighter px-[14px] py-[30px] dark:to-sec-darker/25 max-[360px]:px-0 xl:px-[46px] max-[360px]:[&_:is(.rounded-t-md,pre)]:rounded-none [&_pre]:!h-[370px] md:[&_pre]:!h-[420px]"
52+
className="nextra-codeblocks flex w-full bg-gradient-to-b from-transparent to-sec-lighter px-[14px] py-[30px] dark:to-sec-darker/25 max-[380px]:px-0 xl:px-[46px] max-[380px]:[&_:is(.rounded-t-md,pre)]:rounded-none [&_pre]:!h-[370px] md:[&_pre]:!h-[420px]"
5353
>
5454
<div
5555
className="nextra-codeblocks grid w-full grid-cols-2 [&_.highlighted]:!bg-pri-lighter/50 dark:[&_.highlighted]:!bg-neu-200/10"

src/components/index-page/graphql-advantages/precision.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export function PrecisionFigure() {
9393
<div
9494
ref={ref}
9595
id="predictable-results"
96-
className="nextra-codeblocks flex w-full max-w-[100vw] bg-gradient-to-b from-transparent to-sec-lighter px-[14px] py-[30px] *:w-1/2 dark:to-sec-darker/25 max-[360px]:px-0 sm:max-w-[calc(100vw-32px)] xl:px-[46px] max-[360px]:[&_:is(.rounded-t-md,pre)]:rounded-none [&_pre]:!h-48"
96+
className="nextra-codeblocks flex w-full max-w-[100vw] bg-gradient-to-b from-transparent to-sec-lighter px-[14px] py-[30px] *:w-1/2 dark:to-sec-darker/25 max-[380px]:px-0 sm:max-w-[calc(100vw-32px)] xl:px-[46px] max-[380px]:[&_:is(.rounded-t-md,pre)]:rounded-none [&_pre]:!h-48"
9797
aria-hidden
9898
>
9999
<Pre data-filename="Query" className="p-4">

src/components/index-page/join-the-community.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { DiscordIcon } from "@/icons"
55

66
export function JoinTheCommunity() {
77
return (
8-
<section className="gql-section max-sm:px-0 lg:pb-16 xl:pb-24">
8+
<section className="gql-section max-sm:px-0 lg:pb-16 lg:max-xl:px-0 xl:pb-24">
99
<div className="gql-container typography-body-lg flex bg-pri-dark text-white dark:bg-pri-darker max-lg:flex-col">
1010
<div className="border-pri-light p-6 max-lg:border-b lg:border-r lg:p-16">
1111
<h2 className="typography-h2 text-balance">Join the community</h2>

src/components/index-page/powered-by-community.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ArrowDownIcon from "@/app/conf/_design-system/pixelarticons/arrow-down.sv
44

55
export function PoweredByCommunity() {
66
return (
7-
<section className="gql-section max-sm:px-0 lg:pb-16 xl:pb-24">
7+
<section className="gql-section max-sm:px-0 lg:pb-16 lg:max-xl:px-0 xl:pb-24">
88
<div className="gql-container dark typography-body-lg flex bg-pri-darker text-neu-900 max-lg:flex-col">
99
<div className="border-pri-light p-6 max-lg:border-b lg:border-r lg:p-16">
1010
<h2 className="typography-h2 text-balance">

src/components/index-page/use-cases/arrow-right.svg

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/components/index-page/use-cases/index.tsx

Lines changed: 87 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"use client"
22

33
import clsx from "clsx"
4-
import { useState } from "react"
4+
import { useState, Fragment } from "react"
55

66
import { Button } from "@/app/conf/_design-system/button"
7-
import ArrowRightIcon from "./arrow-right.svg?svgr"
87
import { StripesDecoration } from "@/app/conf/_design-system/stripes-decoration"
8+
import ArrowDownIcon from "@/app/conf/_design-system/pixelarticons/arrow-down.svg?svgr"
99

1010
import blurBean from "./blur-bean.webp"
1111

@@ -29,28 +29,35 @@ const USE_CASES: UseCase[] = [
2929
description:
3030
"Fetch only the data you need to minimize payload size and round-trips. Build resilient UIs that work well on variable networks.",
3131
cta: "Mobile Patterns",
32-
href: "/learn/best-practices#mobile",
32+
href: "TODO",
3333
},
3434
{
3535
label: "A frontend-heavy app with advanced UI needs",
3636
description:
3737
"Co-locate queries with components and keep state consistent. Compose data from many backends without bespoke endpoints.",
3838
cta: "Frontend Integration Guide",
39-
href: "/learn/queries#components",
39+
href: "TODO",
4040
},
4141
{
4242
label: "An app with real-time updates",
4343
description:
4444
"Use subscriptions for low-latency updates while keeping the schema as the single contract for clients and servers.",
4545
cta: "Real-time with Subscriptions",
46-
href: "/learn/subscriptions",
46+
href: "TODO",
4747
},
4848
{
4949
label: "A simple full stack TypeScript app",
5050
description:
5151
"Strong types end-to-end with code generation and great DX. Ship faster without compromising correctness.",
5252
cta: "Full Stack TS Starter",
53-
href: "/learn#typescript",
53+
href: "TODO",
54+
},
55+
{
56+
label: "An AI-powered app",
57+
description:
58+
"Build apps with soft core with GraphQL MCP, using GraphQL schema introspection to give access and teach an LLM about your data.",
59+
cta: "MCP GraphQL",
60+
href: "https://github.com/graphql/graphql-mcp",
5461
},
5562
]
5663

@@ -75,39 +82,71 @@ export function UseCases({
7582
</p>
7683

7784
<div className="3xl:flex-1" />
78-
<ul className="mt-8 divide-y divide-sec-dark border border-sec-dark lg:mt-16">
85+
<div
86+
role="tablist"
87+
className="mt-8 divide-y divide-sec-dark border border-sec-dark max-lg:sr-only lg:mt-16"
88+
>
7989
{USE_CASES.map((useCase, i) => (
80-
<li key={useCase.label}>
90+
<button
91+
role="tab"
92+
type="button"
93+
key={useCase.label}
94+
tabIndex={i === 0 ? 0 : -1}
95+
onKeyDown={arrowsMoveSideways}
96+
onPointerDown={() => setSelectedIndex(i)}
97+
onFocus={() => setSelectedIndex(i)}
98+
aria-selected={i === selectedIndex ? "true" : undefined}
99+
className="gql-focus-visible group flex w-full items-center justify-between gap-6 border-b border-sec-dark px-3 py-4 text-left transition-colors hover:bg-sec-lighter aria-selected:bg-sec-base aria-selected:hover:bg-sec-lighter hover:dark:bg-neu-100/25 dark:aria-selected:bg-sec-darker"
100+
>
101+
<span className="typography-body-lg">{useCase.label}</span>
102+
<ArrowDownIcon className="size-10 shrink-0 -rotate-90 text-sec-dark opacity-0 transition-opacity group-hover:opacity-100 group-focus-visible:opacity-100 group-aria-selected:opacity-100 dark:text-neu-900" />
103+
</button>
104+
))}
105+
</div>
106+
<div className="3xl:flex-1" />
107+
</div>
108+
109+
<article className="relative flex h-auto flex-col bg-sec-base dark:bg-sec-darker">
110+
<Stripes />
111+
<div className="flex flex-1 justify-center overflow-hidden max-lg:flex-col lg:items-center">
112+
{USE_CASES.map((useCase, i) => (
113+
<Fragment key={useCase.label}>
81114
<button
82115
type="button"
83-
onClick={() => setSelectedIndex(i)}
116+
onPointerDown={() => setSelectedIndex(i)}
117+
onFocus={() => setSelectedIndex(i)}
84118
aria-selected={i === selectedIndex ? "true" : undefined}
85-
className="group flex w-full items-center justify-between gap-6 px-3 py-4 text-left transition-colors hover:bg-sec-lighter aria-selected:bg-sec-base aria-selected:hover:bg-sec-lighter hover:dark:bg-neu-100/25 dark:aria-selected:bg-sec-darker"
119+
className="z-[1] flex w-full items-center justify-between gap-6 border-b border-sec-dark px-3 py-4 text-left first:border-t hover:bg-sec-light aria-selected:bg-sec-light dark:bg-sec-darker dark:hover:bg-neu-100/25 dark:aria-selected:bg-sec-darker max-lg:dark:bg-neu-50 lg:hidden"
86120
>
87-
<span className="typography-body-lg">{useCase.label}</span>
88-
<ArrowRightIcon className="size-10 shrink-0 text-sec-dark opacity-0 transition-opacity group-hover:opacity-100 group-aria-selected:opacity-100 dark:text-neu-900" />
121+
<span className="typography-body-lg text-neu-900">
122+
{useCase.label}
123+
</span>
124+
<ArrowDownIcon className="size-6 shrink-0 text-sec-dark transition-transform [[aria-selected=false]>&]:rotate-180" />
89125
</button>
90-
</li>
126+
<div
127+
role="tabpanel"
128+
className={clsx(
129+
"relative h-full flex-1 p-8 lg:p-12 xl:p-16",
130+
selectedIndex === i ? "border-b border-sec-dark" : "hidden",
131+
)}
132+
>
133+
<div className="relative z-10 my-auto max-h-[528px] max-w-2xl">
134+
<h3 className="typography-body-lg text-sec-darker dark:text-sec-lighter max-lg:hidden">
135+
{useCase.label}
136+
</h3>
137+
<p className="typography-h3 text-neu-800 lg:mt-10 lg:max-xl:text-xl">
138+
{useCase.description}
139+
</p>
140+
<div className="mt-8 flex xl:mt-[120px]">
141+
<Button href={useCase.href} variant="primary">
142+
{useCase.cta}
143+
<ArrowDownIcon className="size-6 shrink-0 -rotate-90 text-neu-0" />
144+
</Button>
145+
</div>
146+
</div>
147+
</div>
148+
</Fragment>
91149
))}
92-
</ul>
93-
<div className="3xl:flex-1" />
94-
</div>
95-
96-
<article className="relative flex h-auto flex-col bg-sec-base p-8 dark:bg-sec-darker md:p-12 lg:p-16">
97-
<Stripes />
98-
<div className="z-10 my-auto max-h-[528px] max-w-2xl">
99-
<h3 className="typography-body-lg text-sec-darker dark:text-sec-lighter">
100-
{selected.label}
101-
</h3>
102-
<p className="typography-h3 mt-10 text-neu-800">
103-
{selected.description}
104-
</p>
105-
<div className="mt-8 flex xl:mt-[120px]">
106-
<Button href={selected.href} variant="primary">
107-
{selected.cta}
108-
<ArrowRightIcon className="size-6 shrink-0 text-neu-0" />
109-
</Button>
110-
</div>
111150
</div>
112151
</article>
113152
</div>
@@ -137,3 +176,19 @@ function Stripes() {
137176
</div>
138177
)
139178
}
179+
180+
function arrowsMoveSideways(event: React.KeyboardEvent<HTMLButtonElement>) {
181+
if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
182+
const previousElement = event.currentTarget.previousElementSibling
183+
if (previousElement) {
184+
event.preventDefault()
185+
;(previousElement as HTMLElement).focus()
186+
}
187+
} else if (event.key === "ArrowRight" || event.key === "ArrowDown") {
188+
const nextElement = event.currentTarget.nextElementSibling
189+
if (nextElement) {
190+
event.preventDefault()
191+
;(nextElement as HTMLElement).focus()
192+
}
193+
}
194+
}

0 commit comments

Comments
 (0)