Skip to content

Commit 4dff2a9

Browse files
authored
add <Hero> component (#1998)
1 parent 0883f26 commit 4dff2a9

File tree

4 files changed

+185
-0
lines changed

4 files changed

+185
-0
lines changed

.changeset/six-boats-tell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@theguild/components': patch
3+
---
4+
5+
add `<Hero>` component
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { ComponentProps } from 'react';
2+
import { GitHubIcon } from 'nextra/icons';
3+
import { Meta, StoryObj } from '@storybook/react';
4+
import { hiveThemeDecorator } from '../../../../../.storybook/hive-theme-decorator';
5+
import { ModulesLogo } from '../../logos';
6+
import { CallToAction } from '../call-to-action';
7+
import { Hero } from './index';
8+
9+
export default {
10+
title: 'Hive/Hero',
11+
component: Hero,
12+
decorators: [hiveThemeDecorator],
13+
argTypes: {
14+
className: {
15+
name: 'className',
16+
},
17+
heading: {
18+
name: 'Heading text',
19+
},
20+
checkmarks: {
21+
name: 'Checkmarks text',
22+
},
23+
logo: {
24+
name: 'Logo',
25+
},
26+
text: {
27+
name: 'Hero text',
28+
},
29+
},
30+
} satisfies Meta<ComponentProps<typeof Hero>>;
31+
32+
export const Default: StoryObj<ComponentProps<typeof Hero>> = {
33+
args: {
34+
heading: 'Enterprise Grade Tooling for Your GraphQL Server',
35+
text: 'GraphQL Modules is a toolset of libraries and guidelines dedicated to create reusable, maintainable, testable and extendable modules out of your GraphQL server.',
36+
logo: <ModulesLogo />,
37+
checkmarks: ['Fully open source', 'No vendor lock'],
38+
children: (
39+
<>
40+
<CallToAction variant="primary-inverted" href="/docs">
41+
Get started
42+
</CallToAction>
43+
<CallToAction variant="secondary-inverted" href="/changelog">
44+
Changelog
45+
</CallToAction>
46+
<CallToAction variant="tertiary" href="https://github.com/Urigo/graphql-modules">
47+
<GitHubIcon className="size-6" />
48+
GitHub
49+
</CallToAction>
50+
</>
51+
),
52+
},
53+
};
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { cloneElement, ComponentProps, FC, ReactElement, ReactNode, useId } from 'react';
2+
import { cn } from '../../cn';
3+
import { DecorationIsolation } from '../decorations';
4+
import { Heading } from '../heading';
5+
import { CheckIcon } from '../icons';
6+
7+
export const Hero: FC<{
8+
className?: string;
9+
heading: string;
10+
text: string;
11+
checkmarks: string[];
12+
logo: ReactElement<ComponentProps<'svg'>>;
13+
children?: ReactNode;
14+
}> = props => {
15+
const gradientWhiteId = useId();
16+
const gradientWhiteId2 = useId();
17+
const greenBgId = useId();
18+
19+
return (
20+
<div
21+
className={cn(
22+
'relative isolate mx-4 flex max-w-[90rem] flex-col items-center justify-center gap-6 overflow-hidden rounded-3xl bg-blue-400 px-4 py-6 max-sm:mt-2 sm:py-12 md:mx-6 md:gap-8 lg:py-24',
23+
props.className,
24+
)}
25+
>
26+
<DecorationIsolation className="-z-10">
27+
{cloneElement(props.logo, {
28+
className: cn(
29+
'absolute stroke-white/10 max-lg:hidden',
30+
'-left-1/2 top-1/2 -translate-y-1/2',
31+
),
32+
fill: `url(#${gradientWhiteId2})`,
33+
strokeWidth: '0.1',
34+
width: 'auto',
35+
height: '50%',
36+
})}
37+
{cloneElement(props.logo, {
38+
className: cn(
39+
'absolute top-1/2 -translate-y-1/2 stroke-white/10',
40+
'-right-1/2 lg:-right-1/3',
41+
'h-2/3 lg:h-[calc(100%-5%)]',
42+
),
43+
fill: `url(#${gradientWhiteId2})`,
44+
strokeWidth: '0.1',
45+
width: 'auto',
46+
})}
47+
</DecorationIsolation>
48+
<div className="relative">
49+
{cloneElement(props.logo, {
50+
fill: `url(#${gradientWhiteId})`,
51+
className: 'absolute inset-1/2 -translate-x-1/2 -translate-y-1/2 size-1/2',
52+
})}
53+
<svg
54+
width="96"
55+
height="96"
56+
viewBox="0 0 96 96"
57+
fill="none"
58+
xmlns="http://www.w3.org/2000/svg"
59+
>
60+
<rect width="96" height="96" rx="24" fill={`url(#${greenBgId})`} />
61+
<rect
62+
x="0.5"
63+
y="0.5"
64+
width="95"
65+
height="95"
66+
rx="23.5"
67+
stroke={`url(#${gradientWhiteId})`}
68+
/>
69+
<path d="M57.0264 32.1652H48.9577L53.8032 27.3197L48.4855 22L43.1658 27.3197L48.0114 32.1652H39.9427C38.9042 32.1652 37.9069 32.5786 37.1721 33.3134L23 47.4855L28.3197 52.8052L45.715 35.4099C47.2452 33.8797 49.7258 33.8797 51.2561 35.4099L68.6513 52.8052L73.971 47.4855L59.797 33.3114C59.0622 32.5767 58.0649 32.1632 57.0264 32.1632V32.1652ZM48.4854 63.3623L43.1665 68.6811L48.4854 74L53.8042 68.6811L48.4854 63.3623ZM39.9446 52.8054H48.4855H48.4894H57.0303C58.0688 52.8054 59.0661 53.2188 59.8008 53.9536L63.89 58.0428L58.5704 63.3625L51.258 56.0501C49.7277 54.5198 47.2472 54.5198 45.7169 56.0501L38.4045 63.3625L33.0848 58.0428L37.174 53.9536C37.9088 53.2188 38.9061 52.8054 39.9446 52.8054Z" />
70+
<defs>
71+
<linearGradient
72+
id={greenBgId}
73+
x1="0"
74+
y1="0"
75+
x2="96"
76+
y2="96"
77+
gradientUnits="userSpaceOnUse"
78+
>
79+
<stop stopColor="#3B736A" />
80+
<stop offset="1" stopColor="#15433C" />
81+
</linearGradient>
82+
<linearGradient
83+
id={gradientWhiteId}
84+
x1="0"
85+
y1="0"
86+
x2="96"
87+
y2="96"
88+
gradientUnits="userSpaceOnUse"
89+
>
90+
<stop stopColor="white" stopOpacity="0.8" />
91+
<stop offset="1" stopColor="white" stopOpacity="0.4" />
92+
</linearGradient>
93+
<linearGradient
94+
id={gradientWhiteId2}
95+
x1="1"
96+
y1="2"
97+
x2="161"
98+
y2="171"
99+
gradientUnits="userSpaceOnUse"
100+
>
101+
<stop stopColor="white" stopOpacity="0.1" />
102+
<stop offset="1" stopColor="white" stopOpacity="0.5" />
103+
</linearGradient>
104+
</defs>
105+
</svg>
106+
</div>
107+
<Heading as="h1" size="xl" className="mx-auto max-w-3xl text-balance text-center">
108+
{props.heading}
109+
</Heading>
110+
<p className="mx-auto w-[512px] max-w-[80%] text-center leading-6 text-green-800">
111+
{props.text}
112+
</p>
113+
<ul className="mx-auto flex list-none gap-x-6 gap-y-2 text-sm font-medium max-md:flex-col">
114+
{props.checkmarks.map(text => (
115+
<li key={text} className="flex items-center gap-2">
116+
<CheckIcon className="text-green-800" />
117+
{text}
118+
</li>
119+
))}
120+
</ul>
121+
<div className="flex w-full justify-center gap-2 px-0.5 max-sm:flex-col sm:gap-4">
122+
{props.children}
123+
</div>
124+
</div>
125+
);
126+
};

packages/components/src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export { HiveNavigation, GraphQLConfCard } from './hive-navigation';
1818
export type { HiveNavigationProps, GraphQLConfCardProps } from './hive-navigation';
1919
export { HiveFooter } from './hive-footer';
2020
export { ToolsAndLibrariesCards } from './tools-and-libraries-cards';
21+
export { Hero } from './hero';
2122
export * from './product-card';
2223
export * from './decorations';
2324
export * from './call-to-action';

0 commit comments

Comments
 (0)