foundry-component-library 0.2.5 → 0.2.7

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.
@@ -44,7 +44,7 @@
44
44
  box-sizing: border-box;
45
45
 
46
46
  @media screen and (max-width: $screen-sm) {
47
- max-width: 90%;
47
+ max-width: 80vw;
48
48
  height: 500px;
49
49
  padding: 40px 33px;
50
50
  }
@@ -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
- <div className={`${styles.contactTeaser} ${styles[theme]}`}>
27
- <Container>
28
- <div className={styles.wrapper}>
29
- {heading && (
30
- <WavyText
31
- className={`${styles.heading} ${!text ? styles.margin : ""}`}
32
- text={heading}
33
- alternate={alternate}
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
- </Container>
42
- </div>
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
  }
@@ -17,7 +17,7 @@
17
17
 
18
18
  @media #{$QUERY-sm} {
19
19
  width: 100%;
20
- padding: 0 20px;
20
+ padding: 0 40px;
21
21
  }
22
22
 
23
23
  &.noMobilePadding {
@@ -45,7 +45,7 @@
45
45
  max-width: 100%;
46
46
 
47
47
  @media screen and (max-width: $screen-sm) {
48
- margin-bottom: 2rem;
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: space-between;
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: 10px;
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 src="/logo.mp4" autoPlay muted />
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: -50px;
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 {
@@ -33,8 +33,6 @@ const Hero = ({
33
33
  const sectionRef = useRef(null);
34
34
  const onScreen = useOnScreen(sectionRef, "-50%");
35
35
 
36
- console.log("pop", video);
37
-
38
36
  if (!image && !video) return;
39
37
 
40
38
  if (isFullWidth) {
@@ -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 20px;
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: 20px;
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 className={styles.name}>{item.name}</div>
31
- <div className={styles.position}>{item.position}</div>
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: center;
90
+ justify-content: flex-start;
88
91
  gap: 16px;
89
- padding-top: 64px;
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}
@@ -87,7 +87,8 @@
87
87
  }
88
88
 
89
89
  img {
90
- object-fit: contain;
90
+ object-fit: cover;
91
+ object-position: center;
91
92
  pointer-events: none;
92
93
  }
93
94
 
@@ -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 && <PopInText className={styles.caption} text={caption} />}
28
+ {caption && <div className={styles.caption}>{caption}</div>}
32
29
  {heading && (
33
- <WavyText
34
- className={`${styles.heading} ${isSmall ? styles.small : ""}`}
35
- text={heading}
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 && <FadeInText className={styles.text} text={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
- <motion.div
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
- </motion.div>
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;
@@ -83,6 +83,21 @@ export default async function getHubBySlug({
83
83
  quoteName
84
84
  quotePosition
85
85
  quoteText
86
+ caseStudies {
87
+ ... on Case {
88
+ title
89
+ uri
90
+ id
91
+ case {
92
+ thumbnailImage {
93
+ sourceUrl
94
+ }
95
+ mainImage {
96
+ sourceUrl
97
+ }
98
+ }
99
+ }
100
+ }
86
101
  }
87
102
  }
88
103
  contactPage: page(id: "${contactPage}", idType: URI) {
@@ -338,6 +338,7 @@ export type Hub = {
338
338
  quoteName?: string;
339
339
  quotePosition?: string;
340
340
  quoteText?: string;
341
+ caseStudies: Case[];
341
342
  };
342
343
  };
343
344
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foundry-component-library",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",