11import React , { useState , useEffect } from "react" ;
2- import styled from "styled-components" ;
2+ import styled , { css } from "styled-components" ;
33import { useInView } from "react-intersection-observer" ;
44
55const QuotesWrapper = styled . div `
@@ -9,196 +9,154 @@ const QuotesWrapper = styled.div`
99
1010 .quote-box {
1111 display: flex;
12- flex-direction: row;
13- flex: 1 1 0;
14- text-align: center;
1512 align-items: center;
1613 padding: 2rem;
14+ gap: 1.5rem;
1715 border: 2px solid transparent;
18- border-image: ${ props => props . theme . DarkTheme
19- ? "linear-gradient(to right bottom, #00b39f, #121212 80%)"
20- : "linear-gradient(to right bottom, #00b39f, #fff 80%)" } ;
16+ border-image: linear-gradient(
17+ to right bottom,
18+ #00b39f,
19+ ${ props => props . theme . DarkTheme ? "#121212" : "#fff" } 80%
20+ );
2121 border-image-slice: 1 0 1 1;
22- transition: border 0.2s ease-in-out;
23- gap: 1.5rem;
22+ transition: border-image 0.6s ease-in-out;
2423
25- @media screen and (max-width: 768px) {
24+ @media (max-width: 768px) {
2625 flex-direction: column;
2726 padding: 1.5rem 1rem;
2827 gap: 1rem;
2928 }
3029
31- @media screen and (max-width: 500px) {
30+ @media (max-width: 500px) {
3231 padding: 1rem 0.75rem;
3332 }
34-
35- h4 {
36- text-align: ${ props => props . $onlyQuoteIsPresent ? "center" : "right" } ;
37- flex: ${ props => props . $onlyQuoteIsPresent ? "0 0 100%" : "0 0 65%" } ;
38- color: ${ props => props . theme . primaryColor } ;
39- font-weight: 100;
40- font-style: italic;
41- font-size: 1.25rem;
42- line-height: 1.6;
43- margin: 0;
44-
45- @media screen and (max-width: 768px) {
46- text-align: center;
47- flex: 0 0 100%;
48- font-size: 1.1rem;
49- }
50-
51- @media screen and (max-width: 500px) {
52- font-size: 1rem;
53- line-height: 1.5;
54- }
55- }
5633 }
5734
5835 .border {
59- border-image: ${ props => props . theme . DarkTheme
60- ? "linear-gradient(to left top, #00b39f, #121212 80%)"
61- : "linear-gradient(to left top, #00b39f, #fff 80%)" } ;
36+ border-image: linear-gradient(
37+ to left top,
38+ #00b39f,
39+ ${ props => props . theme . DarkTheme ? "#121212" : "#fff" } 80%
40+ );
6241 border-image-slice: 1 1 1 0;
63- transition: 0.6s ease-in-out;
42+ }
43+
44+ h4 {
45+ flex: ${ props => props . $onlyQuoteIsPresent ? "0 0 100%" : "0 0 65%" } ;
46+ margin: 0;
47+ color: ${ props => props . theme . primaryColor } ;
48+ font-size: clamp(1rem, 2.5vw, 1.25rem);
49+ font-weight: 100;
50+ font-style: italic;
51+ line-height: 1.6;
52+ text-align: ${ props => props . $onlyQuoteIsPresent ? "center" : "right" } ;
53+
54+ @media (max-width: 768px) {
55+ flex: 0 0 100%;
56+ text-align: center;
57+ line-height: 1.5;
58+ }
6459 }
6560
6661 img {
62+ flex-shrink: 0;
63+ width: clamp(72px, 10vw, 96px);
64+ height: clamp(72px, 10vw, 96px);
6765 border-radius: 50%;
68- width: 96px;
69- height: 96px;
70- min-width: 96px;
71- min-height: 96px;
7266 object-fit: cover;
73- flex-shrink: 0;
74-
75- @media screen and (max-width: 768px) {
76- width: 80px;
77- height: 80px;
78- min-width: 80px;
79- min-height: 80px;
80- }
81-
82- @media screen and (max-width: 500px) {
83- width: 72px;
84- height: 72px;
85- min-width: 72px;
86- min-height: 72px;
87- }
8867 }
8968
9069 .quote-source {
9170 display: flex;
9271 flex: 2 1 0;
93- padding: 0 1rem;
9472 flex-direction: column;
9573 justify-content: center;
74+ padding: 0 1rem;
9675 text-align: left;
9776
98- @media screen and (max-width: 768px) {
99- text-align: center;
77+ @media (max-width: 768px) {
10078 padding: 0;
79+ text-align: center;
10180 }
10281
10382 h5 {
104- font-weight: bold;
105- padding: 0.1rem;
10683 margin: 0 0 0.5rem 0;
84+ padding: 0.1rem;
85+ font-size: clamp(0.875rem, 2vw, 1rem);
86+ font-weight: bold;
10787 text-transform: uppercase;
108- font-size: 1rem;
109-
110- @media screen and (max-width: 768px) {
111- font-size: 0.95rem;
112- }
113-
114- @media screen and (max-width: 500px) {
115- font-size: 0.875rem;
116- }
11788 }
11889
11990 p {
12091 margin: 0;
121- font-size: 0. 9rem;
92+ font-size: clamp(0.8rem, 1.8vw, 0. 9rem) ;
12293 line-height: 1.4;
12394
124- @media screen and (max-width: 768px) {
125- font-size: 0.85rem;
126- }
127-
128- @media screen and (max-width: 500px) {
129- font-size: 0.8rem;
95+ @media (max-width: 500px) {
13096 line-height: 1.3;
13197 }
13298 }
13399 }
134100
135101 hr {
102+ align-self: stretch;
136103 height: 5rem;
137104 margin: 0;
138105 border: none;
139106 border-left: 1px solid ${ props => props . theme . DarkTheme ? "#444" : "#ddd" } ;
140- align-self: stretch;
141107
142- @media screen and (max-width: 768px) {
108+ @media (max-width: 768px) {
109+ width: clamp(150px, 60%, 200px);
143110 height: 0;
144- width: 60%;
145- max-width: 200px;
146111 margin: 0.5rem auto;
147112 border-left: none;
148113 border-top: 1px solid ${ props => props . theme . DarkTheme ? "#444" : "#ddd" } ;
149114 }
150-
151- @media screen and (max-width: 500px) {
152- width: 50%;
153- max-width: 150px;
154- }
155115 }
156116
157117 .author-section {
158118 display: flex;
159- flex-direction: row;
160119 align-items: center;
161120 gap: 1rem;
162121
163- @media screen and (max-width: 768px) {
122+ @media (max-width: 768px) {
164123 flex-direction: column;
165124 gap: 0.75rem;
166125 }
167126 }
168127` ;
169128
170129const InlineQuotes = ( { person, title, quote, image } ) => {
171- const [ quoteRef , inView ] = useInView ( { threshold : 0.5 } ) ;
130+ const [ quoteRef , inView ] = useInView ( { threshold : 0.5 , triggerOnce : false } ) ;
172131 const [ quoteInView , setquoteInView ] = useState ( false ) ;
173132
174133 useEffect ( ( ) => {
175- if ( inView && ! quoteInView ) {
176- setquoteInView ( true ) ;
177- } else if ( quoteInView && ! inView ) {
178- setquoteInView ( false ) ;
179- }
180- } , [ inView , quoteInView ] ) ;
134+ setquoteInView ( inView ) ;
135+ } , [ inView ] ) ;
136+
137+ const showAuthorSection = image || person || title ;
181138
182139 return (
183- < QuotesWrapper $onlyQuoteIsPresent = { ! ( image || person || title ) } >
140+ < QuotesWrapper $onlyQuoteIsPresent = { ! showAuthorSection } >
184141 < div className = { quoteInView ? "quote-box border" : "quote-box" } ref = { quoteRef } >
185142 < h4 > ❝ { quote } ❞</ h4 >
186- { ( image || person || title ) && < hr /> }
187- { ( image || person || title ) && (
188- < div className = "author-section" >
189- { image && (
190- < img
191- src = { image }
192- alt = { `${ person || "Quote author" } ` }
193- width = "96"
194- height = "96"
195- />
196- ) }
197- < div className = "quote-source" >
198- { person && < h5 > { person } </ h5 > }
199- { title && < p > { title } </ p > }
143+ { showAuthorSection && (
144+ < >
145+ < hr />
146+ < div className = "author-section" >
147+ { image && (
148+ < img
149+ src = { image }
150+ alt = { person || "Quote author" }
151+ loading = "lazy"
152+ />
153+ ) }
154+ < div className = "quote-source" >
155+ { person && < h5 > { person } </ h5 > }
156+ { title && < p > { title } </ p > }
157+ </ div >
200158 </ div >
201- </ div >
159+ </ >
202160 ) }
203161 </ div >
204162 </ QuotesWrapper >
0 commit comments