foundry-component-library 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/CaseStudyTeaser/styles.module.scss +1 -1
- package/lib/components/ContactTeaser/index.tsx +52 -15
- package/lib/components/ContactTeaser/styles.module.scss +23 -0
- package/lib/components/Container/styles.module.scss +1 -1
- package/lib/components/Footer/styles.module.scss +6 -3
- package/lib/components/Header/index.tsx +8 -3
- package/lib/components/Header/styles.module.scss +5 -4
- package/lib/components/HubsAccordion/styles.module.scss +6 -2
- package/lib/components/QuoteSection/index.tsx +27 -7
- package/lib/components/QuoteSection/styles.module.scss +13 -2
- package/lib/components/ServiceHubsTeaser/styles.module.scss +5 -0
- package/lib/components/TeamPhotos/Item.tsx +2 -2
- package/lib/components/TeamPhotos/styles.module.scss +2 -1
- package/lib/components/TextSection/index.tsx +5 -9
- package/lib/components/Tiles/Tile.tsx +2 -19
- package/lib/components/case/Content/styles.module.scss +7 -7
- package/package.json +1 -1
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState } from "react";
|
|
1
3
|
import styles from "./styles.module.scss";
|
|
2
4
|
import Container from "../Container";
|
|
3
5
|
import { translate } from "../../utils";
|
|
4
6
|
import { NextLink } from "../../types";
|
|
5
7
|
import WavyText from "../TextAnimations/WavyText";
|
|
6
8
|
import FadeInText from "../TextAnimations/FadeInText";
|
|
9
|
+
import useClickOutside from "../../hooks/useClickOutside";
|
|
10
|
+
import Script from "next/script";
|
|
7
11
|
|
|
8
12
|
const ContactTeaser = ({
|
|
9
13
|
heading,
|
|
@@ -22,24 +26,57 @@ const ContactTeaser = ({
|
|
|
22
26
|
alternate?: boolean;
|
|
23
27
|
Link: NextLink;
|
|
24
28
|
}) => {
|
|
29
|
+
const [isTypeformOpen, setIsTypeformOpen] = useState(false);
|
|
30
|
+
const ref = useClickOutside<HTMLDivElement>(() => {
|
|
31
|
+
setIsTypeformOpen(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
25
34
|
return (
|
|
26
|
-
|
|
27
|
-
<
|
|
28
|
-
<
|
|
29
|
-
{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
<>
|
|
36
|
+
<div className={`${styles.contactTeaser} ${styles[theme]}`}>
|
|
37
|
+
<Container>
|
|
38
|
+
<div className={styles.wrapper}>
|
|
39
|
+
{heading && (
|
|
40
|
+
<WavyText
|
|
41
|
+
className={`${styles.heading} ${!text ? styles.margin : ""}`}
|
|
42
|
+
text={heading}
|
|
43
|
+
alternate={alternate}
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
{text && <FadeInText className={styles.text} text={text} />}
|
|
47
|
+
{buttonHref !== "typeform" && (
|
|
48
|
+
<Link href={buttonHref} className={styles.button}>
|
|
49
|
+
{translate(buttonText)}
|
|
50
|
+
</Link>
|
|
51
|
+
)}
|
|
52
|
+
{buttonHref == "typeform" && (
|
|
53
|
+
<button
|
|
54
|
+
className={styles.button}
|
|
55
|
+
onClick={() => {
|
|
56
|
+
setIsTypeformOpen(true);
|
|
57
|
+
}}>
|
|
58
|
+
{translate(buttonText)}
|
|
59
|
+
</button>
|
|
60
|
+
)}
|
|
61
|
+
</div>
|
|
62
|
+
</Container>
|
|
63
|
+
</div>
|
|
64
|
+
{buttonHref === "typeform" && (
|
|
65
|
+
<div
|
|
66
|
+
className={styles.typeform}
|
|
67
|
+
style={{ display: isTypeformOpen ? "flex" : "none" }}>
|
|
68
|
+
<Script src="//embed.typeform.com/next/embed.js" />
|
|
69
|
+
<div ref={ref} className={styles.typeformWrapper}>
|
|
70
|
+
<div
|
|
71
|
+
data-tf-widget="qmv6Yk"
|
|
72
|
+
data-tf-iframe-props="title=Foundry Website Contact Form"
|
|
73
|
+
data-tf-medium="snippet"
|
|
74
|
+
style={{ width: "100%", height: "400px" }}
|
|
34
75
|
/>
|
|
35
|
-
|
|
36
|
-
{text && <FadeInText className={styles.text} text={text} />}
|
|
37
|
-
<Link href={buttonHref} className={styles.button}>
|
|
38
|
-
{translate(buttonText)}
|
|
39
|
-
</Link>
|
|
76
|
+
</div>
|
|
40
77
|
</div>
|
|
41
|
-
|
|
42
|
-
|
|
78
|
+
)}
|
|
79
|
+
</>
|
|
43
80
|
);
|
|
44
81
|
};
|
|
45
82
|
|
|
@@ -54,4 +54,27 @@
|
|
|
54
54
|
.button {
|
|
55
55
|
@extend .button--brown;
|
|
56
56
|
display: inline-block;
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.typeform {
|
|
61
|
+
position: fixed;
|
|
62
|
+
top: 0;
|
|
63
|
+
left: 0;
|
|
64
|
+
width: 100%;
|
|
65
|
+
height: 100%;
|
|
66
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
z-index: 9;
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.typeformWrapper {
|
|
75
|
+
background-color: $color-white;
|
|
76
|
+
width: 800px;
|
|
77
|
+
max-width: 100%;
|
|
78
|
+
border-radius: 8px;
|
|
79
|
+
overflow: hidden;
|
|
57
80
|
}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
max-width: 100%;
|
|
46
46
|
|
|
47
47
|
@media screen and (max-width: $screen-sm) {
|
|
48
|
-
margin-bottom:
|
|
48
|
+
margin-bottom: 40px;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -118,6 +118,7 @@
|
|
|
118
118
|
.menu {
|
|
119
119
|
font-size: 18px;
|
|
120
120
|
font-weight: 500;
|
|
121
|
+
font-family: $font-secondary;
|
|
121
122
|
|
|
122
123
|
@media #{$QUERY-sm} {
|
|
123
124
|
width: 100%;
|
|
@@ -147,7 +148,7 @@
|
|
|
147
148
|
@media #{$QUERY-sm} {
|
|
148
149
|
width: 100%;
|
|
149
150
|
display: flex;
|
|
150
|
-
justify-content:
|
|
151
|
+
justify-content: flex-start;
|
|
151
152
|
gap: 24px;
|
|
152
153
|
}
|
|
153
154
|
|
|
@@ -196,8 +197,10 @@
|
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
@media #{$QUERY-sm} {
|
|
199
|
-
margin-top:
|
|
200
|
+
margin-top: 20px;
|
|
200
201
|
width: 100%;
|
|
202
|
+
justify-content: flex-start;
|
|
203
|
+
gap: 40px;
|
|
201
204
|
}
|
|
202
205
|
|
|
203
206
|
a {
|
|
@@ -16,7 +16,13 @@ function Header({ Link }: { Link: NextLink }) {
|
|
|
16
16
|
<div className={styles.wrapper}>
|
|
17
17
|
<div className={styles.left}>
|
|
18
18
|
<Link href="/">
|
|
19
|
-
<video
|
|
19
|
+
<video
|
|
20
|
+
src="/logo.mp4"
|
|
21
|
+
autoPlay
|
|
22
|
+
muted
|
|
23
|
+
playsInline
|
|
24
|
+
{...{ "webkit-playsinline": "true" }}
|
|
25
|
+
/>
|
|
20
26
|
Foundry
|
|
21
27
|
</Link>
|
|
22
28
|
</div>
|
|
@@ -28,8 +34,7 @@ function Header({ Link }: { Link: NextLink }) {
|
|
|
28
34
|
onClick={() => {
|
|
29
35
|
setMenuOpen(!isMenuOpen);
|
|
30
36
|
}}
|
|
31
|
-
aria-label="Toggle menu"
|
|
32
|
-
>
|
|
37
|
+
aria-label="Toggle menu">
|
|
33
38
|
Menu
|
|
34
39
|
<div className={styles.hamburger}>
|
|
35
40
|
<span className={styles.line}></span>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
.left {
|
|
21
21
|
font-size: 0;
|
|
22
|
-
margin-left: -
|
|
22
|
+
margin-left: -65px;
|
|
23
23
|
|
|
24
24
|
@media #{$QUERY-sm} {
|
|
25
25
|
margin-left: -68px;
|
|
@@ -98,9 +98,6 @@
|
|
|
98
98
|
display: flex;
|
|
99
99
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
100
100
|
|
|
101
|
-
@media #{$QUERY-sm} {
|
|
102
|
-
}
|
|
103
|
-
|
|
104
101
|
&.isMenuOpen {
|
|
105
102
|
// display: flex;
|
|
106
103
|
transform: translateX(0);
|
|
@@ -132,6 +129,10 @@
|
|
|
132
129
|
max-height: 600px;
|
|
133
130
|
margin: auto 0;
|
|
134
131
|
padding: 0 40px;
|
|
132
|
+
|
|
133
|
+
@media #{$QUERY-sm} {
|
|
134
|
+
padding-bottom: 60px;
|
|
135
|
+
}
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
.menuList {
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
color: $color-brown;
|
|
13
13
|
position: relative;
|
|
14
14
|
|
|
15
|
+
@media #{$QUERY-sm} {
|
|
16
|
+
padding-bottom: 32px;
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
&:before {
|
|
16
20
|
content: "";
|
|
17
21
|
position: absolute;
|
|
@@ -42,7 +46,7 @@
|
|
|
42
46
|
|
|
43
47
|
@media #{$QUERY-sm} {
|
|
44
48
|
flex-wrap: wrap;
|
|
45
|
-
padding: 16px
|
|
49
|
+
padding: 16px 40px;
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
52
|
|
|
@@ -121,7 +125,7 @@
|
|
|
121
125
|
|
|
122
126
|
@media #{$QUERY-sm} {
|
|
123
127
|
padding-bottom: 0;
|
|
124
|
-
padding-left:
|
|
128
|
+
padding-left: 40px;
|
|
125
129
|
padding-right: 20px;
|
|
126
130
|
}
|
|
127
131
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useState } from "react";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
3
|
import styles from "./styles.module.scss";
|
|
4
4
|
import Container from "../Container";
|
|
5
5
|
|
|
@@ -13,6 +13,20 @@ const QuoteSection = ({
|
|
|
13
13
|
}[];
|
|
14
14
|
}) => {
|
|
15
15
|
const [active, setActive] = useState(0);
|
|
16
|
+
const [paused, setPaused] = useState(false);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!items || items.length <= 1) return;
|
|
20
|
+
|
|
21
|
+
const interval = setInterval(() => {
|
|
22
|
+
if (!paused) {
|
|
23
|
+
setActive((prev) => (prev + 1) % items.length);
|
|
24
|
+
}
|
|
25
|
+
}, 3000);
|
|
26
|
+
|
|
27
|
+
return () => clearInterval(interval);
|
|
28
|
+
}, [items, paused]);
|
|
29
|
+
|
|
16
30
|
if (!items || (items.length === 1 && !items[0].text)) return;
|
|
17
31
|
|
|
18
32
|
return (
|
|
@@ -24,18 +38,24 @@ const QuoteSection = ({
|
|
|
24
38
|
key={item?.name || i}
|
|
25
39
|
className={`${styles.content} ${
|
|
26
40
|
active === i ? styles.active : ""
|
|
27
|
-
}`}
|
|
28
|
-
>
|
|
41
|
+
}`}>
|
|
29
42
|
<div className={styles.person}>
|
|
30
|
-
<div
|
|
31
|
-
|
|
43
|
+
<div>
|
|
44
|
+
<div className={styles.name}>{item.name}</div>
|
|
45
|
+
<div className={styles.position}>{item.position}</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
<div
|
|
49
|
+
className={styles.text}
|
|
50
|
+
onMouseEnter={() => setPaused(true)}
|
|
51
|
+
onMouseLeave={() => setPaused(false)}>
|
|
52
|
+
{item.text}
|
|
32
53
|
</div>
|
|
33
|
-
<div className={styles.text}>{item.text}</div>
|
|
34
54
|
</div>
|
|
35
55
|
);
|
|
36
56
|
})}
|
|
37
57
|
{items.length > 1 && (
|
|
38
|
-
<div className={styles.indicators}>
|
|
58
|
+
<div className={`${styles.indicators} ${styles.desktop}}`}>
|
|
39
59
|
{items.map((el, i) => {
|
|
40
60
|
return (
|
|
41
61
|
<div
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
|
|
64
64
|
@media #{$QUERY-sm} {
|
|
65
65
|
font-size: 14px;
|
|
66
|
+
min-height: 40px;
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -71,6 +72,7 @@
|
|
|
71
72
|
width: 800px;
|
|
72
73
|
max-width: 100%;
|
|
73
74
|
font-family: $font-secondary;
|
|
75
|
+
min-height: 300px;
|
|
74
76
|
|
|
75
77
|
@media screen and (max-width: $screen-md) {
|
|
76
78
|
font-size: 25px;
|
|
@@ -78,15 +80,19 @@
|
|
|
78
80
|
|
|
79
81
|
@media #{$QUERY-sm} {
|
|
80
82
|
font-size: 16px;
|
|
83
|
+
min-height: 200px;
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
.indicators {
|
|
85
88
|
display: flex;
|
|
86
89
|
align-items: center;
|
|
87
|
-
justify-content:
|
|
90
|
+
justify-content: flex-start;
|
|
88
91
|
gap: 16px;
|
|
89
|
-
|
|
92
|
+
|
|
93
|
+
@media #{$QUERY-sm} {
|
|
94
|
+
padding-top: 30px;
|
|
95
|
+
}
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
.indicator {
|
|
@@ -96,6 +102,11 @@
|
|
|
96
102
|
border-radius: 50%;
|
|
97
103
|
cursor: pointer;
|
|
98
104
|
|
|
105
|
+
@media #{$QUERY-sm} {
|
|
106
|
+
width: 11px;
|
|
107
|
+
height: 11px;
|
|
108
|
+
}
|
|
109
|
+
|
|
99
110
|
&.active {
|
|
100
111
|
background-color: $color-pink;
|
|
101
112
|
}
|
|
@@ -66,6 +66,10 @@
|
|
|
66
66
|
height: 100%;
|
|
67
67
|
font-family: $font-secondary;
|
|
68
68
|
|
|
69
|
+
path {
|
|
70
|
+
stroke: $color-brown;
|
|
71
|
+
}
|
|
72
|
+
|
|
69
73
|
&.yellow {
|
|
70
74
|
background-color: $color-yellow;
|
|
71
75
|
color: $color-blue;
|
|
@@ -114,6 +118,7 @@
|
|
|
114
118
|
|
|
115
119
|
.face {
|
|
116
120
|
display: block;
|
|
121
|
+
font-size: 42px;
|
|
117
122
|
}
|
|
118
123
|
|
|
119
124
|
.tails {
|
|
@@ -11,9 +11,9 @@ const Item = ({ person, Image }: { person: Person; Image: NextImage }) => {
|
|
|
11
11
|
<div
|
|
12
12
|
className={styles.person}
|
|
13
13
|
onMouseEnter={() => setIsHovered(true)}
|
|
14
|
-
onMouseLeave={() => setIsHovered(false)}
|
|
15
|
-
>
|
|
14
|
+
onMouseLeave={() => setIsHovered(false)}>
|
|
16
15
|
<div className={styles.image}>
|
|
16
|
+
{video && <div>{video.sourceUrl}</div>}
|
|
17
17
|
{image && (
|
|
18
18
|
<Image
|
|
19
19
|
src={isHovered && video ? video.sourceUrl : image.sourceUrl}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import styles from "./styles.module.scss";
|
|
3
3
|
import Container from "../Container";
|
|
4
|
-
import PopInText from "../TextAnimations/PopInText";
|
|
5
|
-
import WavyText from "../TextAnimations/WavyText";
|
|
6
|
-
import FadeInText from "../TextAnimations/FadeInText";
|
|
7
4
|
|
|
8
5
|
const TextSection = ({
|
|
9
6
|
caption,
|
|
@@ -28,15 +25,14 @@ const TextSection = ({
|
|
|
28
25
|
return (
|
|
29
26
|
<Container>
|
|
30
27
|
<div className={`${styles.section} ${alignStyle} ${themeStyle}`}>
|
|
31
|
-
{caption && <
|
|
28
|
+
{caption && <div className={styles.caption}>{caption}</div>}
|
|
32
29
|
{heading && (
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
/>
|
|
30
|
+
<div className={`${styles.heading} ${isSmall ? styles.small : ""}`}>
|
|
31
|
+
{heading}
|
|
32
|
+
</div>
|
|
37
33
|
)}
|
|
38
34
|
{subheading && <div className={styles.subheading}>{subheading}</div>}
|
|
39
|
-
{text && <
|
|
35
|
+
{text && <div className={styles.text}>{text}</div>}
|
|
40
36
|
</div>
|
|
41
37
|
</Container>
|
|
42
38
|
);
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import styles from "./styles.module.scss";
|
|
2
2
|
import Plus from "../../assets/svg/plus.svg";
|
|
3
|
-
import { motion } from "framer-motion";
|
|
4
3
|
|
|
5
4
|
const Tile = ({
|
|
6
5
|
text,
|
|
7
6
|
background,
|
|
8
7
|
hoverText,
|
|
9
|
-
i,
|
|
10
8
|
}: {
|
|
11
9
|
text: string;
|
|
12
10
|
hoverText: string;
|
|
@@ -14,22 +12,7 @@ const Tile = ({
|
|
|
14
12
|
i: number;
|
|
15
13
|
}) => {
|
|
16
14
|
return (
|
|
17
|
-
<
|
|
18
|
-
className={`${styles.tile} ${styles[background]}`}
|
|
19
|
-
whileHover={{
|
|
20
|
-
scale: 1.08,
|
|
21
|
-
rotate: i % 2 === 0 ? -3 : 3,
|
|
22
|
-
boxShadow: "0px 10px 20px rgba(0,0,0,0.2)",
|
|
23
|
-
y: [0, Math.random() * 12 - 6, 0],
|
|
24
|
-
transition: {
|
|
25
|
-
y: {
|
|
26
|
-
duration: 2,
|
|
27
|
-
repeat: Infinity,
|
|
28
|
-
ease: "easeInOut",
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
}}
|
|
32
|
-
>
|
|
15
|
+
<div className={`${styles.tile} ${styles[background]}`}>
|
|
33
16
|
<div className={styles.face}>
|
|
34
17
|
<div className={styles.text}>{text}</div>
|
|
35
18
|
<div>
|
|
@@ -39,7 +22,7 @@ const Tile = ({
|
|
|
39
22
|
<div className={styles.tails}>
|
|
40
23
|
<div className={styles.tailsText}>{hoverText}</div>
|
|
41
24
|
</div>
|
|
42
|
-
</
|
|
25
|
+
</div>
|
|
43
26
|
);
|
|
44
27
|
};
|
|
45
28
|
|
|
@@ -33,13 +33,6 @@
|
|
|
33
33
|
width: 620px;
|
|
34
34
|
max-width: 100%;
|
|
35
35
|
margin: 0 auto;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.text {
|
|
39
|
-
max-width: 100%;
|
|
40
|
-
min-height: 350px;
|
|
41
|
-
font-size: 18px;
|
|
42
|
-
line-height: 1.4;
|
|
43
36
|
|
|
44
37
|
h1,
|
|
45
38
|
h2,
|
|
@@ -58,6 +51,13 @@
|
|
|
58
51
|
}
|
|
59
52
|
}
|
|
60
53
|
|
|
54
|
+
.text {
|
|
55
|
+
max-width: 100%;
|
|
56
|
+
min-height: 350px;
|
|
57
|
+
font-size: 18px;
|
|
58
|
+
line-height: 1.4;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
61
|
.twoColumns {
|
|
62
62
|
display: flex;
|
|
63
63
|
justify-content: space-between;
|