Skip to content

Commit 3460580

Browse files
authored
Merge pull request #32 from hasparus/new-landing--a-proven-solution
new landing — proven solution
2 parents f34c76d + 102bba7 commit 3460580

File tree

8 files changed

+170
-13
lines changed

8 files changed

+170
-13
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { clsx } from "clsx"
2+
import { ChevronRight } from "./pixelarticons/chevron-right"
3+
4+
export function SectionLabel({
5+
children,
6+
className,
7+
...rest
8+
}: {
9+
children: React.ReactNode
10+
className?: string
11+
rest?: React.HTMLAttributes<HTMLSpanElement>
12+
}) {
13+
return (
14+
<span
15+
className={clsx(
16+
"flex shrink-0 items-center gap-1 self-start whitespace-nowrap font-mono text-sm/none font-normal uppercase text-pri-base dark:text-pri-light",
17+
className,
18+
)}
19+
{...rest}
20+
>
21+
<ChevronRight className="shrink-0 translate-y-[-0.5px]" />
22+
{children}
23+
</span>
24+
)
25+
}

src/components/index-page/how-it-works.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ChevronRight } from "@/app/conf/_design-system/pixelarticons/chevron-right"
21
import { Button } from "@/app/conf/_design-system/button"
2+
import { SectionLabel } from "@/app/conf/_design-system/section-label"
33

44
import { CodeA, CodeB, CodeC } from "../code-blocks"
55

@@ -8,10 +8,7 @@ const TRY_IT_OUT_URL = "https://graphql.org/swapi-graphql"
88
export function HowItWorks() {
99
return (
1010
<section className="gql-container gql-section xl:py-20">
11-
<span className="mb-6 flex w-[80px] shrink-0 items-center gap-1 self-start whitespace-nowrap font-mono text-sm/none font-normal uppercase text-pri-base">
12-
<ChevronRight className="shrink-0 translate-y-[-0.5px]" />
13-
How it works
14-
</span>
11+
<SectionLabel className="mb-6">How it works</SectionLabel>
1512
<h2 className="typography-h2 mb-6 lg:mb-16">A GraphQL Query</h2>
1613
<ol className="gql-radial-gradient list-none gap-px max-md:bg-gradient-to-r max-md:from-transparent max-md:via-neu-400 max-md:to-transparent lg:grid lg:grid-cols-3">
1714
<ListItem text="Describe your data" code={<CodeA />} />
@@ -35,7 +32,7 @@ function ListItem({
3532
}) {
3633
return (
3734
<li className="[counter-increment:list-item]">
38-
<div className="typography-body-md bg-neu-0 py-4 before:typography-body-sm before:mr-2 before:inline-flex before:size-5 before:translate-y-[-0.5px] before:items-center before:justify-center before:bg-neu-200 before:p-1 before:text-neu-800 before:content-[counter(list-item)] md:py-6 md:before:ml-6">
35+
<div className="typography-body-md bg-neu-0 py-4 before:typography-body-sm before:mr-2 before:inline-flex before:size-5 before:translate-y-[-0.5px] before:items-center before:justify-center before:bg-neu-200 before:p-1 before:text-neu-800 before:content-[counter(list-item)] dark:before:bg-neu-50 md:py-6 md:before:ml-6">
3936
{text}
4037
</div>
4138
<div className="mt-px bg-neu-0 md:pl-2 md:pt-2 max-md:[&_code>span]:!pl-0 [&_pre]:ring-0">

src/components/index-page/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import { WithoutVersion } from "./without-version"
88
import { BringYourOwnCode } from "./bring-your-own-code"
99
import { WhoIsUsing } from "./who-is-using"
1010
import { HowItWorks } from "./how-it-works"
11+
import { ProvenSolution } from "./proven-solution"
1112

1213
export function IndexPage() {
1314
return (
1415
<div className="bg-neu-0">
1516
<Hero />
1617
<TrustedBy />
1718
<HowItWorks />
19+
<ProvenSolution />
1820
<section className="conf-block container flex max-w-3xl flex-col items-center text-center">
1921
<h2>A query language for your API</h2>
2022
<p>
Binary file not shown.
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { ImageLoaded } from "@/app/conf/2025/components/image-loaded"
2+
import { Button } from "@/app/conf/_design-system/button"
3+
import { SectionLabel } from "@/app/conf/_design-system/section-label"
4+
import CheckIcon from "@/app/conf/_design-system/pixelarticons/check.svg?svgr"
5+
6+
import blurBean from "./blur-bean.webp"
7+
import { StripesDecoration } from "@/app/conf/_design-system/stripes-decoration"
8+
9+
export function ProvenSolution() {
10+
return (
11+
<section className="dark relative overflow-hidden bg-pri-dark text-white dark:bg-pri-darker">
12+
<Stripes />
13+
<div className="gql-container py-8 xl:py-16">
14+
<div className="gql-section relative">
15+
<SectionLabel className="mb-6 !text-sec-light">
16+
Business perspective
17+
</SectionLabel>
18+
<h2 className="typography-h2 mb-6 lg:mb-16">
19+
A proven solution for startups and enterprises
20+
</h2>
21+
<div className="mb-12 grid gap-y-6 lg:grid-cols-3 lg:backdrop-blur-[6.4px] lg:[&>*:not(:first-child)]:border-l-0">
22+
<ProvenSolutionCard
23+
title={
24+
<>
25+
The best user{" "}
26+
<br className="@[530px]/card:hidden max-lg:hidden" />
27+
experience
28+
</>
29+
}
30+
description="Deliver high-performing user experiences at scale. The world’s leading apps use GraphQL to create faster, more responsive digital experiences."
31+
bullets={[
32+
"Faster data retrieval and load times",
33+
"Improved bandwith efficiency",
34+
]}
35+
/>
36+
<ProvenSolutionCard
37+
title={
38+
<>
39+
Stability &{" "}
40+
<br className="@[530px]/card:hidden max-lg:hidden" />
41+
Security
42+
</>
43+
}
44+
description="Protect your APIs while maintaining full visibility into data consumption. GraphQL allows you to monitor, secure, and optimize API usage while ensuring compliance."
45+
bullets={[
46+
"Stronger access control",
47+
"Improved business intelligence & cost analysis",
48+
]}
49+
/>
50+
<ProvenSolutionCard
51+
title={
52+
<>
53+
Efficient distributed{" "}
54+
<br className="@[530px]/card:hidden max-lg:hidden" />
55+
development
56+
</>
57+
}
58+
description="Let your teams ship faster with GraphQL’s flexible, decoupled architecture. GraphQL allows frontend and backend teams to work independently and efficiently."
59+
bullets={[
60+
"More rapid iterations",
61+
"Improved cross-team collaboration",
62+
]}
63+
/>
64+
</div>
65+
<Button
66+
className="mx-auto mt-8 w-fit lg:mt-16"
67+
// todo: this should link to the Business Agregator page
68+
href="/learn"
69+
>
70+
Learn more
71+
</Button>
72+
</div>
73+
</div>
74+
</section>
75+
)
76+
}
77+
78+
function ProvenSolutionCard({
79+
title,
80+
description,
81+
bullets,
82+
}: {
83+
title: React.ReactNode
84+
description: React.ReactNode
85+
bullets: string[]
86+
}) {
87+
return (
88+
<div className="flex flex-col border border-pri-light bg-pri-lighter/20 @container/card dark:bg-pri-base/20 max-lg:backdrop-blur-[6.4px]">
89+
<h3 className="border-b border-pri-light p-6 text-2xl @[331px]/card:typography-h3">
90+
{title}
91+
</h3>
92+
<p className="typography-body-lg p-6">{description}</p>
93+
<ul className="typography-body-md mt-auto flex flex-col gap-2 p-6 pt-0">
94+
{bullets.map(bullet => (
95+
<li key={bullet} className="flex items-center gap-2">
96+
<CheckIcon className="size-4 shrink-0 text-sec-base" aria-hidden />
97+
<span>{bullet}</span>
98+
</li>
99+
))}
100+
</ul>
101+
</div>
102+
)
103+
}
104+
105+
function Stripes() {
106+
// todo: rotate to top right corner on mobile
107+
return (
108+
<ImageLoaded
109+
role="presentation"
110+
image={blurBean}
111+
// eslint-disable-next-line tailwindcss/no-unnecessary-arbitrary-value
112+
className="pointer-events-none absolute inset-0 opacity-0 transition-[translate] duration-[400ms] ease-linear [mask-position:center_calc(100%+65vw)] [mask-size:200%] data-[loaded=true]:opacity-100 max-lg:rotate-[180deg] max-lg:scale-x-[-1] lg:[mask-position:center_500px] lg:[mask-size:150%] xl:translate-y-1/2 xl:[mask-position:center_top] xl:max-3xl:translate-y-[50%]"
113+
style={{
114+
maskImage: `url(${blurBean.src})`,
115+
WebkitMaskImage: `url(${blurBean.src})`,
116+
maskRepeat: "no-repeat",
117+
WebkitMaskRepeat: "no-repeat",
118+
}}
119+
>
120+
{/* todo: ensure colors in dark mode are correct */}
121+
<StripesDecoration
122+
evenClassName="bg-[linear-gradient(180deg,hsl(var(--color-pri-light)/0.2)_20%,hsl(var(--color-pri-base))_150%)] dark:bg-[linear-gradient(180deg,hsl(var(--color-pri-base)/.9)_20%,hsl(var(--color-pri-darker))_150%)]"
123+
oddClassName="bg-[linear-gradient(180deg,hsl(var(--color-pri-light))_20%,hsl(var(--color-pri-lighter)/.9)_150%)] dark:bg-[linear-gradient(180deg,hsl(var(--color-pri-darker)/.9)_20%,hsl(var(--color-pri-base)/.8)_150%)]"
124+
/>
125+
</ImageLoaded>
126+
)
127+
}

src/components/navbar/navbar.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,7 @@ function BackdropBlur() {
228228
return (
229229
<>
230230
<div
231-
// note: we can't use the background trick to reduce flickering, because we have many section
232-
// background colors and big images, so we'd have to change the --bg var with javascript
233-
className="pointer-events-none absolute inset-0 -z-10 h-[200%] backdrop-blur-[12.8px]"
231+
className="pointer-events-none absolute inset-0 -z-10 h-[200%] backdrop-blur-[6.4px]"
234232
style={{
235233
maskImage: mask,
236234
WebkitMaskImage: mask,

src/globals.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ div[id^="headlessui-menu-items"] {
150150
}
151151

152152
::selection {
153-
@apply bg-primary/50 dark:bg-primary/50;
153+
@apply bg-pri-base/25 dark:bg-pri-light/50;
154154
}
155155

156156
@media (prefers-color-scheme: dark) {

src/pages/_meta.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export default {
3535
},
3636
spec: {
3737
type: "page",
38-
title: <span className="after:font-sans after:content-['_↗']">Spec</span>,
38+
title: "Spec",
3939
href: "https://spec.graphql.org",
4040
newWindow: true,
4141
},
@@ -81,10 +81,10 @@ export default {
8181
conf: {
8282
type: "page",
8383
title: (
84-
<span className="[a:has(>&)]:[a:has(>&)]:border [a:has(>&)]:border [a:has(>&)]:border-current [a:has(>&)]:text-pri-base dark:[a:has(>&)]:text-pri-light [a:hover:has(>&)]:border-transparent">
84+
<Emphasis>
8585
GraphQLConf
8686
<span className="max-xl:hidden"> 2025</span>
87-
</span>
87+
</Emphasis>
8888
),
8989
route: "/conf/2025",
9090
},
@@ -93,3 +93,11 @@ export default {
9393
title: "GraphQL.JS Tutorial",
9494
},
9595
}
96+
97+
function Emphasis({ children }: { children: React.ReactNode }) {
98+
return (
99+
<span className="[a:has(>&)]:[a:has(>&)]:border [a:has(>&)]:border [a:has(>&)]:border-current [a:has(>&)]:text-pri-base dark:[a:has(>&)]:text-pri-light [a:hover:has(>&)]:border-transparent">
100+
{children}
101+
</span>
102+
)
103+
}

0 commit comments

Comments
 (0)