1- import  React ,  {  ReactNode ,  useState  }  from  "react" 
2- import  styled  from  "@emotion/styled" 
3- import  {  motion  }  from  "framer-motion" 
1+ import  React ,  {  ReactNode  }  from  "react" 
42import  {  GatsbyImage ,  IGatsbyImageData  }  from  "gatsby-plugin-image" 
3+ import  { 
4+   BackgroundProps , 
5+   Box , 
6+   Center , 
7+   ChakraProps , 
8+   Collapse , 
9+   Heading , 
10+   HStack , 
11+   Icon , 
12+   Stack , 
13+   Text , 
14+   useDisclosure , 
15+   VStack , 
16+ }  from  "@chakra-ui/react" 
17+ import  {  motion  }  from  "framer-motion" 
18+ import  {  MdExpandMore  }  from  "react-icons/md" 
519
6- import  Icon  from  "./Icon" 
7- 
8- const  Card  =  styled . div < { 
9-   background : string 
10- } > ` 
11-   border: 1px solid ${ ( {  theme } )  =>  theme . colors . border }  
12-   border-radius: 2px; 
13-   padding: 1.5rem; 
14-   display: flex; 
15-   flex-direction: column; 
16-   margin-bottom: 1rem; 
17-   background: ${ ( {  background,  theme } )  =>  
18-     background  ? theme . colors [ background ]  : theme . colors . background }  ;
19-   &:hover { 
20-     img { 
21-       transform: scale(1.08); 
22-       transition: transform 0.1s; 
23-     } 
24-   } 
25- ` 
26- 
27- const  Content  =  styled . div ` 
28-   display: flex; 
29-   align-items: center; 
30-   justify-content: space-between; 
31-   gap: 3rem; 
32-   @media (max-width: ${ ( {  theme } )  =>  theme . breakpoints . m }  
33-     gap: 2rem; 
34-     flex-direction: column; 
35-   } 
36- ` 
37- 
38- const  TitleContent  =  styled . div ` 
39-   display: flex; 
40-   align-items: center; 
41-   gap: 3rem; 
42-   width: 100%; 
43- ` 
44- 
45- const  Title  =  styled . h2 ` 
46-   margin-top: 0rem; 
47-   margin-bottom: 0.5rem; 
48- ` 
49- 
50- const  TextPreview  =  styled . p ` 
51-   font-weight: 400; 
52-   color: ${ ( props )  =>  props . theme . colors . text200 }  
53-   margin-bottom: 0rem; 
54- ` 
55- 
56- const  Text  =  styled ( motion . div ) ` 
57-   font-size: 16px; 
58-   font-weight: 400; 
59-   color: ${ ( props )  =>  props . theme . colors . text }  
60-   margin-top: 2rem; 
61-   border-top: 1px solid ${ ( props )  =>  props . theme . colors . border }  
62-   padding-top: 1.5rem; 
63- ` 
64- 
65- const  Question  =  styled . div ` 
66-   margin-right: 1rem; 
67- ` 
68- 
69- const  Header  =  styled . div ` 
70-   display: flex; 
71-   width: 100%; 
72-   margin: 1rem 0; 
73-   align-items: center; 
74-   img { 
75-     margin-right: 1.5rem; 
76-   } 
77- ` 
78- 
79- const  ButtonContainer  =  styled ( motion . div ) ` 
80-   display: flex; 
81-   width: 5rem; 
82-   justify-content: center; 
83-   align-items: center; 
84-   min-height: 10rem; 
85-   cursor: pointer; 
86-   @media (max-width: ${ ( {  theme } )  =>  theme . breakpoints . m }  
87-     min-height: 100%; 
88-     height: 100%; 
89-     width: 100%; 
90-     margin: 0; 
91-   } 
92-   &:hover { 
93-     svg { 
94-       transform: scale(1.25); 
95-       transition: transform 0.1s; 
96-     } 
97-   } 
98- ` 
99- 
100- export  interface  IProps  { 
20+ export  interface  IProps  extends  ChakraProps  { 
10121  children ?: React . ReactNode 
10222  image ?: IGatsbyImageData 
10323  title : ReactNode 
10424  contentPreview : ReactNode 
105-   background : string 
106-   forceOpen : boolean 
25+   background : BackgroundProps [ "background" ] 
26+   forceOpen ? : boolean 
10727  className ?: string 
10828} 
10929
@@ -115,22 +35,12 @@ const ExpandableInfo: React.FC<IProps> = ({
11535  background, 
11636  forceOpen, 
11737  className, 
38+   ...rest 
11839} )  =>  { 
119-   const  [ isVisible ,  setIsVisible ]  =  useState ( forceOpen ) 
120-   const  expandCollapse  =  { 
121-     collapsed : { 
122-       height : 0 , 
123-       transition : { 
124-         when : "afterChildren" , 
125-       } , 
126-     } , 
127-     expanded : { 
128-       height : "100%" , 
129-       transition : { 
130-         when : "beforeChildren" , 
131-       } , 
132-     } , 
133-   } 
40+   const  {  isOpen,  getButtonProps,  getDisclosureProps }  =  useDisclosure ( { 
41+     defaultIsOpen : forceOpen , 
42+   } ) 
43+ 
13444  const  chevronFlip  =  { 
13545    collapsed : { 
13646      rotate : 0 , 
@@ -145,71 +55,100 @@ const ExpandableInfo: React.FC<IProps> = ({
14555      } , 
14656    } , 
14757  } 
148-   const  showHide  =  { 
149-     collapsed : { 
150-       display : "none" , 
151-     } , 
152-     expanded : { 
153-       display : "inline-block" , 
154-     } , 
155-   } 
156-   const  fadeInOut  =  { 
157-     collapsed : { 
158-       opacity : 0 , 
159-       transition : { 
160-         duration : 0.1 , 
161-       } , 
162-     } , 
163-     expanded : { 
164-       opacity : 1 , 
165-       transition : { 
166-         duration : 0.4 , 
167-       } , 
168-     } , 
169-   } 
58+ 
59+   const  animateToggle  =  isOpen  ? "expanded"  : "collapsed" 
60+ 
17061  return  ( 
171-     < Card  background = { background }  className = { className } > 
172-       < Content > 
62+     < VStack 
63+       border = "1px solid" 
64+       borderColor = "border" 
65+       borderRadius = "2px" 
66+       p = { 6 } 
67+       mb = { 4 } 
68+       spacing = "0" 
69+       background = { background  ??  "background" } 
70+       position = "relative" 
71+       _hover = { { 
72+         "& img" : { 
73+           transform : "scale(1.08)" , 
74+           transition : "transform 0.1s" , 
75+         } , 
76+       } } 
77+       { ...rest } 
78+     > 
79+       < Stack 
80+         justify = "space-between" 
81+         align = "center" 
82+         gap = { {  base : 8 ,  md : 12  } } 
83+         flexDirection = { {  base : "column" ,  md : "row"  } } 
84+         width = "full" 
85+       > 
17386        { image  &&  < GatsbyImage  image = { image }  alt = ""  /> } 
174-         < TitleContent > 
175-           < Question > 
176-             < Header > 
177-               < Title > { title } </ Title > 
178-             </ Header > 
179-             < TextPreview > { contentPreview } </ TextPreview > 
180-           </ Question > 
181-         </ TitleContent > 
87+         < HStack  gap = { 12 }  width = "full" > 
88+           < Box  mr = { 4 } > 
89+             < HStack 
90+               width = "full" 
91+               my = { 4 } 
92+               sx = { { 
93+                 img : { 
94+                   mr : 6 , 
95+                 } , 
96+               } } 
97+             > 
98+               < Heading 
99+                 mt = "0" 
100+                 mb = { 1 } 
101+                 fontSize = { {  base : "2xl" ,  md : "2rem"  } } 
102+                 fontWeight = "600" 
103+                 lineHeight = "1.4" 
104+               > 
105+                 { title } 
106+               </ Heading > 
107+             </ HStack > 
108+             < Text  color = "text200"  mb = "0" > 
109+               { contentPreview } 
110+             </ Text > 
111+           </ Box > 
112+         </ HStack > 
182113        { ! forceOpen  &&  ( 
183-           < ButtonContainer 
114+           < Center 
115+             as = { motion . div } 
184116            variants = { chevronFlip } 
185-             animate = { isVisible  ?  "expanded"  :  "collapsed" } 
117+             animate = { animateToggle } 
186118            initial = { false } 
187-             onClick = { ( )  =>  setIsVisible ( ! isVisible ) } 
119+             { ...getButtonProps ( ) } 
120+             width = { {  base : "full" ,  md : "5rem"  } } 
121+             minHeight = { {  base : "full" ,  md : "10rem"  } } 
122+             cursor = "pointer" 
123+             _hover = { { 
124+               "& svg" : { 
125+                 transform : "scale(1.25)" , 
126+                 transition : "transform 0.1s" , 
127+               } , 
128+             } } 
188129          > 
189-             < Icon  name = "chevronDown "size = "36"  /> 
190-           </ ButtonContainer > 
130+             < Icon  as = { MdExpandMore }   boxSize = "initial "size = "36"  /> 
131+           </ Center > 
191132        ) } 
192-       </ Content > 
193-       < motion . div 
194-         variants = { expandCollapse } 
195-         animate = { isVisible  ? "expanded"  : "collapsed" } 
133+       </ Stack > 
134+       < Collapse 
135+         { ...getDisclosureProps ( ) } 
136+         in = { isOpen } 
137+         startingHeight = "0" 
138+         endingHeight = "100%" 
196139        initial = { false } 
197140      > 
198-         < motion . div 
199-           variants = { showHide } 
200-           animate = { isVisible  ? "expanded"  : "collapsed" } 
201-           initial = { false } 
141+         < Box 
142+           color = "text" 
143+           mt = { 8 } 
144+           borderTop = "1px solid" 
145+           borderColor = "border" 
146+           paddingTop = { 6 } 
202147        > 
203-           < Text 
204-             variants = { fadeInOut } 
205-             animate = { isVisible  ? "expanded"  : "collapsed" } 
206-             initial = { false } 
207-           > 
208-             { children } 
209-           </ Text > 
210-         </ motion . div > 
211-       </ motion . div > 
212-     </ Card > 
148+           { children } 
149+         </ Box > 
150+       </ Collapse > 
151+     </ VStack > 
213152  ) 
214153} 
215154
0 commit comments