1
+ import {
2
+ Box ,
3
+ Button ,
4
+ VStack ,
5
+ Text ,
6
+ extendTheme ,
7
+ useTheme ,
8
+ ChakraProvider ,
9
+ Image ,
10
+ Flex ,
11
+ keyframes ,
12
+ } from "@chakra-ui/react" ;
13
+ import { AnimatePresence , motion } from "framer-motion" ;
14
+ import { useState , useEffect } from "react" ;
15
+
16
+ const moveBackground = keyframes `
17
+ 0% { background-position: 0 0; }
18
+ 100% { background-position: 100% 0; }
19
+ ` ;
20
+ const VerticalSlideFeatures = ( ) => {
21
+ const [ selected , setSelected ] = useState ( 0 ) ;
22
+
23
+ useEffect ( ( ) => {
24
+ const intervalId = setInterval ( ( ) => {
25
+ setSelected ( ( prevSelected ) => ( prevSelected + 1 ) % FEATURES . length ) ;
26
+ } , 20000 ) ;
27
+ return ( ) => clearInterval ( intervalId ) ;
28
+ } , [ ] ) ;
29
+
30
+ return (
31
+ < Flex mx = "auto" px = { { base : 4 , md : 8 } } py = { 12 } bg = "white" gap = { 6 } >
32
+ < VStack maxW = "40%" align = "start" spacing = { 4 } >
33
+ < Text fontSize = "md" color = "blackAlpha.800" >
34
+ { FEATURES [ selected ] . description }
35
+ </ Text >
36
+ < Tabs selected = { selected } setSelected = { setSelected } />
37
+ </ VStack >
38
+ < AnimatePresence mode = "wait" >
39
+ { FEATURES . map ( ( tab , index ) => {
40
+ return selected === index ? (
41
+ < motion . div
42
+ initial = { { opacity : 0 , y : 10 } }
43
+ animate = { { opacity : 1 , y : 0 } }
44
+ exit = { { opacity : 0 , y : 10 } }
45
+ key = { index }
46
+ className = "w-full"
47
+ >
48
+ < tab . Feature />
49
+ </ motion . div >
50
+ ) : undefined ;
51
+ } ) }
52
+ </ AnimatePresence >
53
+ </ Flex >
54
+
55
+ ) ;
56
+ } ;
57
+
58
+ const Tabs = ( { selected, setSelected } ) => {
59
+ return (
60
+ < VStack align = "start" spacing = { 2 } >
61
+ { FEATURES . map ( ( tab , index ) => {
62
+ return (
63
+ < Tab
64
+ key = { index }
65
+ setSelected = { setSelected }
66
+ selected = { selected === index }
67
+ title = { tab . title }
68
+ tabNum = { index }
69
+ />
70
+ ) ;
71
+ } ) }
72
+ </ VStack >
73
+ ) ;
74
+ } ;
75
+
76
+ const Tab = ( { selected, title, setSelected, tabNum } ) => {
77
+ const theme = useTheme ( ) ;
78
+
79
+ return (
80
+ < Button
81
+ onClick = { ( ) => setSelected ( tabNum ) }
82
+ p = { 4 }
83
+ d = "flex"
84
+ alignItems = "center"
85
+ justifyContent = "start"
86
+ position = "relative"
87
+ _hover = { { borderColor : theme . colors . blue [ 500 ] } }
88
+
89
+ >
90
+ < Box
91
+ position = "absolute"
92
+ top = "0"
93
+ left = "0"
94
+ bottom = "0"
95
+ bg = "gray.200"
96
+ transition = "width 10s linear"
97
+ width = { selected ? "100%" : "0" }
98
+ zIndex = "-1"
99
+ />
100
+ < Text
101
+ fontSize = { { base : "xl" , md : "2xl" } }
102
+ fontWeight = "bold"
103
+ color = { selected ? theme . colors . blue [ 500 ] : "black" }
104
+ _hover = { { color : theme . colors . blue [ 500 ] } }
105
+ >
106
+ { title }
107
+ </ Text >
108
+ </ Button >
109
+ ) ;
110
+ } ;
111
+
112
+ export default VerticalSlideFeatures ;
113
+
114
+ const FEATURES = [
115
+ {
116
+ title : "Practical Coding Experience" ,
117
+ description :
118
+ "Master the skills you need from our lessons and apply them to real-world projects." ,
119
+ Feature : ( ) => < Image src = "sneakpeak1.svg" /> ,
120
+ } ,
121
+ {
122
+ title : "AI Assistant" ,
123
+ description :
124
+ "Tech Guru will be there to provide hints and tips within lessons when you need them." ,
125
+ Feature : ( ) => (
126
+ < Image src = "sneakpeak2.svg" />
127
+ ) ,
128
+ } ,
129
+ {
130
+ title : "Progress Checks & Quizzes" ,
131
+ description :
132
+ "Test your knowledge as you are learning with our quizzes and progress checks." ,
133
+ Feature : ( ) => (
134
+ < Image src = "sneakpeak3.svg" />
135
+ ) ,
136
+ } ,
137
+ ] ;
138
+
0 commit comments