Skip to content

Commit 6221327

Browse files
RBorauritonephlin7
andcommitted
[HTD-36] Feat: Add Integration cta / hero component (#54)
* feat(HTD-36): add integration cta / hero * fix(HTD-36): change icons for new ones * fix(HTD-36): add missing keys * fix(HTD-36): make appear icons --------- Co-authored-by: Gerald Martinez <[email protected]>
1 parent feb204a commit 6221327

File tree

14 files changed

+326
-19
lines changed

14 files changed

+326
-19
lines changed

src/app/blog/page.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ export default async function Blog() {
1111
<Container>
1212
<Heading color="textGradient">Blog</Heading>
1313
{posts?.map((post, i) => (
14-
<Link href={`/blog/${post.slug}`} style={{ marginBottom: 10, display: 'block', textDecoration: 'none' }}>
14+
<Link
15+
key={i}
16+
href={`/blog/${post.slug}`}
17+
style={{ marginBottom: 10, display: 'block', textDecoration: 'none' }}
18+
>
1519
<Heading as="h3" fontSize="xs" key={post.slug}>
1620
{/* TODO: Remove ban-ts-comment once work on blog post tasks */}
1721
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}

src/app/page.tsx

+27-11
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import { NavigationSidebarLinks } from '@/components/modules/navigation-sidebar-
4444
import { TableContent } from '@/components/modules/table-content';
4545
import { CTA } from '@/components/sections/cta';
4646
import { FeatureLine } from '@/components/sections/feature-line';
47+
import { IntegrationCTA } from '@/components/sections/integration/cta';
4748
import { IntegrationGrid } from '@/components/sections/integration/grid';
4849
import { IntegrationSinglePageHero } from '@/components/sections/integration/single-page/hero';
4950
import { IntegrationSteps } from '@/components/sections/integration/single-page/steps';
@@ -109,19 +110,19 @@ export default async function Home() {
109110
const nonCollapsibleTableContent = [
110111
{
111112
text: 'Terms Of Service',
112-
href: '#example',
113+
href: '#example-1',
113114
},
114115
{
115116
text: 'Terms Of Service (“Terms”)',
116-
href: '#example',
117+
href: '#example-2',
117118
},
118119
{
119120
text: 'What information do we collect?',
120-
href: '#example',
121+
href: '#example-3',
121122
subItems: [
122123
{
123124
text: 'Information automatically collected',
124-
href: '#example',
125+
href: '#example-5',
125126
},
126127
],
127128
},
@@ -134,7 +135,7 @@ export default async function Home() {
134135
title: 'Android',
135136
text: 'Android integration for apps and mobile browsers, including automated setup, per-app interception, and system-level certificate injection for complete visibility into emulators and rooted devices.',
136137
link: {
137-
href: '/example',
138+
href: '/example-1',
138139
target: '_blank',
139140
},
140141
},
@@ -143,7 +144,7 @@ export default async function Home() {
143144
title: 'Javascript',
144145
text: 'Android integration for apps and mobile browsers, including automated setup, per-app interception, and system-level certificate injection for complete visibility into emulators and rooted devices.',
145146
link: {
146-
href: '/example',
147+
href: '/example-2',
147148
target: '_blank',
148149
},
149150
},
@@ -155,28 +156,28 @@ export default async function Home() {
155156
subitems: [
156157
{
157158
text: 'Standard checkout',
158-
href: '#example',
159+
href: '#example-1',
159160
},
160161
{
161162
text: 'Internet transfer',
162-
href: '#example',
163+
href: '#example-2',
163164
},
164165
],
165166
},
166167
{
167168
text: 'How to pay?',
168-
href: '#example',
169+
href: '#example-3',
169170
},
170171
{
171172
text: 'Troubles with payment',
172173
subitems: [
173174
{
174175
text: 'How to find your money',
175-
href: '#example',
176+
href: '#example-4',
176177
},
177178
{
178179
text: 'My money has gone',
179-
href: '#example',
180+
href: '#example-5',
180181
},
181182
],
182183
},
@@ -595,6 +596,21 @@ export default async function Home() {
595596
/>
596597
<IntegrationGrid integrations={[...integrationsCard, ...integrationsCard, ...integrationsCard]} />
597598
<Statistics title="Why `*HTTP Toolkit*`?" text="Numbers that speak for themselves:" />
599+
<IntegrationCTA
600+
$variant="hero"
601+
title="Automatic setup and powerful integration for all your tools"
602+
text="With deep integrations into a huge range of popular components & tools, HTTP Toolkit lets you intercept mobile apps, whole devices, bash scripts, entire Docker containers and more, so you can see & modify anything in just one click."
603+
/>
604+
<IntegrationCTA
605+
$variant="cta"
606+
title="Integrations"
607+
text="Explore a vast array of integrations and applications designed to streamline your work, consolidate information, and enhance collaboration effortlessly. "
608+
button={{
609+
$small: true,
610+
$variant: 'secondary',
611+
children: 'See all integrations',
612+
}}
613+
/>
598614
<IntegrationTextImage
599615
title="HTTP Toolkit is a beautiful & open-source toolfor debugging, testing and building with HTTP(S)on Windows, Linux & Mac."
600616
subtitle="what is http toolkit?"
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
export const HighlightedText = ({ title }: { title: string }) =>
2-
title.split('`').map(segment => {
2+
title.split('`').map((segment, index) => {
33
const isHighlighted = segment.includes('*');
44
if (!isHighlighted) {
55
return segment;
66
}
7-
return <span>{segment.replaceAll('*', '')}</span>;
7+
return <span key={index}>{segment.replaceAll('*', '')}</span>;
88
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use client';
2+
3+
import { styled } from '@/styles';
4+
5+
export const ShowOnMobileOrDesktop = styled.div<{ $mobile?: boolean }>`
6+
display: ${({ $mobile }) => ($mobile ? 'block' : 'none')};
7+
8+
@media (min-width: ${({ theme }) => theme.screens.lg}) {
9+
display: ${({ $mobile }) => (!$mobile ? 'block' : 'none')};
10+
}
11+
`;

src/components/layout/footer/components/footer-column-block.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const FooterColumnBlock = ({ column }: { column: FooterColumn }) => {
1818
}
1919

2020
return (
21-
<li role="listitem">
21+
<li role="listitem" key={link.label}>
2222
<Link key={link.href} href={link.href}>
2323
{link.label}
2424
</Link>

src/components/modules/growing-numbers/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const GrowingNumbers = ({ stats }: GrowingNumbersProps) => {
1717
stats.map(stat => {
1818
const [number, suffix] = convertToMax3DigitsWithSuffix(stat.number);
1919
return (
20-
<StyledGrowingNumbersStat>
20+
<StyledGrowingNumbersStat key={stat.number}>
2121
<StyledGrowingNumberStatNumber>
2222
{<NumberIncreaser maxValue={number} suffix={suffix} />}
2323
{stat.isOver && '+'}

src/components/modules/navigation-sidebar-links/index.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ export const NavigationSidebarLinks = ({ title, links }: NavigationSidebarLinksP
2727
<StyledNavigationSidebarLinksContentWrapper>
2828
{Array.isArray(links) &&
2929
links?.length > 0 &&
30-
links.map(link => (
31-
<StyledNavigationSidebarLinksContentItem>
30+
links.map((link, index) => (
31+
<StyledNavigationSidebarLinksContentItem key={index}>
3232
<StyledNavigationSidebarLinksContentTitle fontSize="m" fontWeight="bold" color="white">
3333
<ItemTitleComponent {...link} />
3434
</StyledNavigationSidebarLinksContentTitle>
3535
{Array.isArray(link.subitems) &&
3636
link.subitems?.length > 0 &&
3737
link.subitems.map(link => (
38-
<StyledNavigationSidebarLinksContentLink href={link.href}>
38+
<StyledNavigationSidebarLinksContentLink key={link.href} href={link.href}>
3939
{link.text}
4040
</StyledNavigationSidebarLinksContentLink>
4141
))}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use client';
2+
3+
import type { StyledIconRowItem } from './icon-rows.types';
4+
5+
import { styled } from '@/styles';
6+
7+
const iconsSize = 72;
8+
9+
export const StyledIconRowsWrapper = styled.div<StyledIconRowItem>`
10+
display: flex;
11+
gap: 12px;
12+
13+
@media (min-width: ${({ theme }) => theme.screens.lg}) {
14+
flex-direction: column;
15+
${({ $orientation, $offset }) =>
16+
$orientation === 'right'
17+
? `
18+
margin-right: calc(-${iconsSize}px * ${$offset});
19+
`
20+
: `
21+
margin-left: calc(-${iconsSize}px * ${$offset});
22+
`}
23+
}
24+
`;
25+
26+
export const StyledIconRow = styled.div<StyledIconRowItem>`
27+
display: flex;
28+
gap: 12px;
29+
flex-direction: column;
30+
padding-top: calc(${iconsSize}px * ${({ $offset }) => $offset});
31+
32+
@media (min-width: ${({ theme }) => theme.screens.lg}) {
33+
flex-direction: row;
34+
padding-top: 0;
35+
${({ $orientation, $offset }) =>
36+
$orientation === 'right'
37+
? `
38+
justify-content: start;
39+
padding-left: calc(${iconsSize}px * ${$offset});
40+
`
41+
: `
42+
justify-content: end;
43+
padding-right: calc(${iconsSize}px * ${$offset});
44+
`}
45+
}
46+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { Icon } from '@phosphor-icons/react';
2+
3+
import type { CustomIcon } from '@/components/elements/icon/custom/types';
4+
5+
export interface IconRowItem {
6+
icons: (Icon | CustomIcon)[];
7+
offset: number;
8+
}
9+
10+
export interface StyledIconRowItem {
11+
$orientation: IconRowsProps['$orientation'];
12+
$offset: IconRowItem['offset'];
13+
}
14+
15+
export interface IconRowsProps {
16+
rows: IconRowItem[];
17+
$offset: IconRowItem['offset'];
18+
$orientation: 'right' | 'left';
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { StyledIconRow, StyledIconRowsWrapper } from './icon-rows.styles';
2+
import type { IconRowsProps } from './icon-rows.types';
3+
4+
import { SquareIcon } from '@/components/elements/square-icon';
5+
6+
const parserOffset = (offset: number) => {
7+
const additionalOffset = Math.floor(offset) * 0.16; // .16 is the sixth part of the icon size (72)
8+
return offset + additionalOffset;
9+
};
10+
11+
export const IconRows = ({ rows, $orientation, $offset }: IconRowsProps) => {
12+
return (
13+
<StyledIconRowsWrapper $offset={$offset} $orientation={$orientation}>
14+
{Array.isArray(rows) &&
15+
rows?.length > 0 &&
16+
rows.map((row, rowIndex) => (
17+
<StyledIconRow key={rowIndex} $offset={parserOffset(row.offset)} $orientation={$orientation}>
18+
{Array.isArray(row.icons) &&
19+
row.icons?.length > 0 &&
20+
row.icons.map((icon, iconIndex) => <SquareIcon key={iconIndex} icon={icon} $size="xLarge" />)}
21+
</StyledIconRow>
22+
))}
23+
</StyledIconRowsWrapper>
24+
);
25+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
'use client';
2+
3+
import { styled } from 'styled-components';
4+
5+
import type { StyledIntegrationCTAProps } from './cta.types';
6+
7+
export const StyledIntegrationCTAWrapper = styled.section<StyledIntegrationCTAProps>`
8+
display: flex;
9+
flex-direction: column;
10+
justify-content: space-between;
11+
align-items: center;
12+
width: 100%;
13+
position: relative;
14+
overflow: hidden;
15+
16+
${({ $variant, theme }) =>
17+
$variant === 'cta'
18+
? `
19+
background-color: ${theme.colors.inkBlack};
20+
box-shadow: ${theme.colors.borderGradient};
21+
padding: 32px 16px 0;
22+
gap: 42px;
23+
`
24+
: `
25+
padding: 32px 16px 0;
26+
gap: 32px;
27+
`}
28+
29+
&::before {
30+
content: '';
31+
background: linear-gradient(0deg, ${({ theme }) => theme.colors.darkGrey} 13%, rgba(30, 32, 40, 0) 93.25%);
32+
position: absolute;
33+
right: 0;
34+
left: 0;
35+
bottom: 0;
36+
width: 100%;
37+
height: 130px;
38+
}
39+
40+
@media (min-width: ${({ theme }) => theme.screens.lg}) {
41+
flex-direction: row;
42+
43+
${({ $variant }) =>
44+
$variant === 'cta'
45+
? `
46+
padding: 128px 0;
47+
gap: 99px;
48+
`
49+
: `
50+
padding: 96px 0;
51+
gap: 35px;
52+
`}
53+
54+
&::before, &::after {
55+
content: '';
56+
position: absolute;
57+
background: linear-gradient(90deg, ${({ theme }) => theme.colors.darkGrey} 13%, rgba(30, 32, 40, 0) 93.25%);
58+
width: 200px;
59+
height: 100%;
60+
top: 0;
61+
bottom: unset;
62+
}
63+
64+
&::before {
65+
left: 0;
66+
right: unset;
67+
transform: unset;
68+
}
69+
70+
&::after {
71+
right: 0;
72+
left: unset;
73+
transform: rotate(180deg);
74+
}
75+
}
76+
`;
77+
78+
export const StyledIntegrationCTAContent = styled.div<StyledIntegrationCTAProps>`
79+
display: flex;
80+
flex-direction: column;
81+
align-items: center;
82+
gap: 24px;
83+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { ButtonProps } from '@/components/elements/button/button.types';
2+
3+
export interface StyledIntegrationCTAProps {
4+
$variant: 'hero' | 'cta';
5+
}
6+
7+
export interface IntegrationCTAProps extends StyledIntegrationCTAProps {
8+
title: string;
9+
text: string;
10+
button?: ButtonProps;
11+
}

0 commit comments

Comments
 (0)