1
1
import Link from 'next/link'
2
- import { useContext } from 'react'
2
+ import { useContext , ReactNode } from 'react'
3
3
import { motion } from 'framer-motion'
4
4
import { useInView } from 'react-intersection-observer'
5
5
6
6
import { ModalContext } from 'src/contexts'
7
7
import { PlayType } from 'src/types'
8
8
import { StarIcon , TuringIcon } from 'src/components/Icons/icons'
9
9
10
+ const animationVariants = {
11
+ container : {
12
+ hidden : { opacity : 0 } ,
13
+ visible : {
14
+ opacity : 1 ,
15
+ transition : {
16
+ staggerChildren : 0.1 ,
17
+ } ,
18
+ } ,
19
+ } ,
20
+ item : {
21
+ hidden : { y : 30 , opacity : 0 } ,
22
+ visible : {
23
+ y : 0 ,
24
+ opacity : 1 ,
25
+ transition : { duration : 0.3 , ease : 'easeOut' } ,
26
+ } ,
27
+ } ,
28
+ fadeIn : ( delay = 0 ) => ( {
29
+ initial : { opacity : 0 , y : - 10 } ,
30
+ animate : ( inView : boolean ) =>
31
+ inView ? { opacity : 1 , y : 0 } : { opacity : 0 , y : - 10 } ,
32
+ transition : { duration : 0.3 , delay, ease : 'easeOut' } ,
33
+ } ) ,
34
+ }
35
+
10
36
interface AdditionalFeaturesSectionProps {
11
37
id : string
12
38
}
13
39
40
+ type FeatureActionType =
41
+ | { type : 'link' ; href : string ; label : string }
42
+ | { type : 'button' ; onClick : ( ) => void ; label : string }
43
+
44
+ interface Feature {
45
+ icon : ReactNode
46
+ title : string
47
+ description : string
48
+ action : FeatureActionType
49
+ iconBgColor : string
50
+ iconTextColor : string
51
+ }
52
+
53
+ // Feature Card Component
54
+ const FeatureCard = ( {
55
+ feature,
56
+ variants,
57
+ } : {
58
+ feature : Feature
59
+ variants : any
60
+ } ) => {
61
+ const { icon, title, description, action, iconBgColor, iconTextColor } =
62
+ feature
63
+
64
+ return (
65
+ < motion . div
66
+ className = "hover:scale-102 flex flex-col rounded-lg bg-background-2 p-5 shadow-lg transition-transform duration-200"
67
+ variants = { variants }
68
+ >
69
+ < div
70
+ className = { `mb-4 flex h-12 w-12 items-center justify-center rounded-full ${ iconBgColor } p-2` }
71
+ >
72
+ < div className = { `h-7 w-7 ${ iconTextColor } ` } > { icon } </ div >
73
+ </ div >
74
+ < h3 className = "mb-3 text-xl font-bold" > { title } </ h3 >
75
+ < p className = "mb-5 flex-grow text-primary/80" > { description } </ p >
76
+
77
+ { action . type === 'link' ? (
78
+ < motion . div
79
+ whileHover = { { scale : 1.05 } }
80
+ whileTap = { { scale : 0.95 } }
81
+ transition = { { duration : 0.2 } }
82
+ >
83
+ < Link
84
+ href = { action . href }
85
+ className = "mt-auto inline-flex items-center justify-center rounded-md bg-background-3 px-5 py-3 font-medium"
86
+ >
87
+ { action . label }
88
+ </ Link >
89
+ </ motion . div >
90
+ ) : (
91
+ < motion . button
92
+ onClick = { action . onClick }
93
+ className = "mt-auto inline-flex items-center justify-center rounded-md bg-background-3 px-5 py-3 font-medium"
94
+ whileHover = { { scale : 1.05 } }
95
+ whileTap = { { scale : 0.95 } }
96
+ transition = { { duration : 0.2 } }
97
+ >
98
+ { action . label }
99
+ </ motion . button >
100
+ ) }
101
+ </ motion . div >
102
+ )
103
+ }
104
+
105
+ const SectionHeader = ( { inView } : { inView : boolean } ) => {
106
+ const fadeInVariants = animationVariants . fadeIn
107
+
108
+ return (
109
+ < div className = "max-w-3xl text-left" >
110
+ < motion . div
111
+ { ...fadeInVariants ( 0 ) }
112
+ animate = { fadeInVariants ( 0 ) . animate ( inView ) }
113
+ className = "mb-2 inline-block rounded-full bg-human-3/10 px-4 py-1 text-sm font-medium text-human-3"
114
+ >
115
+ More Features
116
+ </ motion . div >
117
+ < motion . h2
118
+ className = "mb-4 text-3xl font-bold md:text-4xl lg:text-5xl"
119
+ { ...fadeInVariants ( 0.1 ) }
120
+ animate = { fadeInVariants ( 0.1 ) . animate ( inView ) }
121
+ >
122
+ Explore other ways to use Maia
123
+ </ motion . h2 >
124
+ < motion . p
125
+ className = "max-w-2xl text-lg text-primary/80"
126
+ { ...fadeInVariants ( 0.2 ) }
127
+ animate = { fadeInVariants ( 0.2 ) . animate ( inView ) }
128
+ >
129
+ Maia offers a range of innovative tools to help you understand human
130
+ chess and improve your skills
131
+ </ motion . p >
132
+ </ div >
133
+ )
134
+ }
135
+
14
136
export const AdditionalFeaturesSection = ( {
15
137
id,
16
138
} : AdditionalFeaturesSectionProps ) => {
@@ -24,138 +146,61 @@ export const AdditionalFeaturesSection = ({
24
146
setPlaySetupModalProps ( { playType : 'handAndBrain' as PlayType } )
25
147
}
26
148
27
- // Animation variants for staggered animations
28
- const containerVariants = {
29
- hidden : { opacity : 0 } ,
30
- visible : {
31
- opacity : 1 ,
32
- transition : {
33
- staggerChildren : 0.1 ,
149
+ const features : Feature [ ] = [
150
+ {
151
+ icon : < StarIcon /> ,
152
+ title : 'Openings Practice' ,
153
+ description :
154
+ "Drill chess openings against Maia models calibrated to specific rating levels, allowing you to practice against opponents similar to those you'll face." ,
155
+ action : { type : 'link' , href : '/openings' , label : 'Practice Openings' } ,
156
+ iconBgColor : 'bg-human-3/10' ,
157
+ iconTextColor : 'text-human-3' ,
158
+ } ,
159
+ {
160
+ icon : < TuringIcon /> ,
161
+ title : 'Hand & Brain' ,
162
+ description :
163
+ 'Team up with Maia in this collaborative chess variant. You can be the "Hand" making moves while Maia is the "Brain" selecting pieces, or vice versa.' ,
164
+ action : {
165
+ type : 'button' ,
166
+ onClick : startHandBrainGame ,
167
+ label : 'Play Hand & Brain' ,
34
168
} ,
169
+ iconBgColor : 'bg-engine-3/10' ,
170
+ iconTextColor : 'text-engine-3' ,
35
171
} ,
36
- }
37
-
38
- const itemVariants = {
39
- hidden : { y : 30 , opacity : 0 } ,
40
- visible : {
41
- y : 0 ,
42
- opacity : 1 ,
43
- transition : { duration : 0.3 , ease : 'easeOut' } ,
172
+ {
173
+ icon : < TuringIcon /> ,
174
+ title : 'Bot or Not' ,
175
+ description :
176
+ 'Test your ability to distinguish between human and AI chess play. This Turing test for chess helps you understand the differences between human and engine moves.' ,
177
+ action : { type : 'link' , href : '/turing' , label : 'Try Bot or Not' } ,
178
+ iconBgColor : 'bg-human-4/10' ,
179
+ iconTextColor : 'text-human-4' ,
44
180
} ,
45
- }
181
+ ]
46
182
47
183
return (
48
184
< section
49
185
id = { id }
50
186
className = "relative w-full flex-col items-center overflow-hidden bg-background-1 py-16"
51
187
ref = { ref }
52
188
>
53
- < div className = "container mx-auto px-4" >
54
- < div className = "mb-14 max-w-3xl text-left" >
55
- < motion . div
56
- initial = { { opacity : 0 , y : - 10 } }
57
- animate = { inView ? { opacity : 1 , y : 0 } : { opacity : 0 , y : - 10 } }
58
- transition = { { duration : 0.3 } }
59
- className = "mb-2 inline-block rounded-full bg-human-3/10 px-4 py-1 text-sm font-medium text-human-3"
60
- >
61
- More Features
62
- </ motion . div >
63
- < motion . h2
64
- className = "mb-4 text-3xl font-bold md:text-4xl lg:text-5xl"
65
- initial = { { opacity : 0 , y : - 10 } }
66
- animate = { inView ? { opacity : 1 , y : 0 } : { opacity : 0 , y : - 10 } }
67
- transition = { { duration : 0.3 , delay : 0.1 } }
68
- >
69
- Explore other ways to use Maia
70
- </ motion . h2 >
71
- < motion . p
72
- className = "max-w-2xl text-lg text-primary/80"
73
- initial = { { opacity : 0 , y : - 10 } }
74
- animate = { inView ? { opacity : 1 , y : 0 } : { opacity : 0 , y : - 10 } }
75
- transition = { { duration : 0.3 , delay : 0.2 } }
76
- >
77
- Maia offers a range of innovative tools to help you understand human
78
- chess and improve your skills
79
- </ motion . p >
80
- </ div >
81
-
189
+ < div className = "mx-auto flex w-full max-w-[90%] flex-col px-4" >
190
+ < SectionHeader inView = { inView } />
82
191
< motion . div
83
192
className = "grid gap-6 md:grid-cols-3"
84
- variants = { containerVariants }
193
+ variants = { animationVariants . container }
85
194
initial = "hidden"
86
195
animate = { inView ? 'visible' : 'hidden' }
87
196
>
88
- { /* Openings Feature */ }
89
- < motion . div
90
- className = "hover:scale-102 flex flex-col rounded-lg bg-background-2 p-5 shadow-lg transition-transform duration-200"
91
- variants = { itemVariants }
92
- >
93
- < div className = "mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-human-3/10 p-2" >
94
- < div className = "h-7 w-7 text-human-3" >
95
- < StarIcon />
96
- </ div >
97
- </ div >
98
- < h3 className = "mb-3 text-xl font-bold" > Openings Practice</ h3 >
99
- < p className = "mb-5 flex-grow text-primary/80" >
100
- Drill chess openings against Maia models calibrated to specific
101
- rating levels, allowing you to practice against opponents similar
102
- to those you'll face.
103
- </ p >
104
- < Link
105
- href = "/openings"
106
- className = "mt-auto inline-flex items-center justify-center rounded-md bg-background-3 px-5 py-3 font-medium transition duration-200 hover:bg-background-4"
107
- >
108
- Practice Openings
109
- </ Link >
110
- </ motion . div >
111
-
112
- { /* Hand & Brain Feature */ }
113
- < motion . div
114
- className = "hover:scale-102 flex flex-col rounded-lg bg-background-2 p-5 shadow-lg transition-transform duration-200"
115
- variants = { itemVariants }
116
- >
117
- < div className = "mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-engine-3/10 p-2" >
118
- < div className = "h-7 w-7 text-engine-3" >
119
- < TuringIcon />
120
- </ div >
121
- </ div >
122
- < h3 className = "mb-3 text-xl font-bold" > Hand & Brain </ h3 >
123
- < p className = "mb-5 flex-grow text-primary/80" >
124
- Team up with Maia in this collaborative chess variant. You can be
125
- the "Hand" making moves while Maia is the
126
- "Brain" selecting pieces, or vice versa.
127
- </ p >
128
- < button
129
- onClick = { startHandBrainGame }
130
- className = "mt-auto inline-flex items-center justify-center rounded-md bg-background-3 px-5 py-3 font-medium transition duration-200 hover:bg-background-4"
131
- >
132
- Play Hand & Brain
133
- </ button >
134
- </ motion . div >
135
-
136
- { /* Bot or Not Feature */ }
137
- < motion . div
138
- className = "hover:scale-102 flex flex-col rounded-lg bg-background-2 p-5 shadow-lg transition-transform duration-200"
139
- variants = { itemVariants }
140
- >
141
- < div className = "mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-human-4/10 p-2" >
142
- < div className = "h-7 w-7 text-human-4" >
143
- < TuringIcon />
144
- </ div >
145
- </ div >
146
- < h3 className = "mb-3 text-xl font-bold" > Bot or Not</ h3 >
147
- < p className = "mb-5 flex-grow text-primary/80" >
148
- Test your ability to distinguish between human and AI chess play.
149
- This Turing test for chess helps you understand the differences
150
- between human and engine moves.
151
- </ p >
152
- < Link
153
- href = "/turing"
154
- className = "mt-auto inline-flex items-center justify-center rounded-md bg-background-3 px-5 py-3 font-medium transition duration-200 hover:bg-background-4"
155
- >
156
- Try Bot or Not
157
- </ Link >
158
- </ motion . div >
197
+ { features . map ( ( feature , index ) => (
198
+ < FeatureCard
199
+ key = { index }
200
+ feature = { feature }
201
+ variants = { animationVariants . item }
202
+ />
203
+ ) ) }
159
204
</ motion . div >
160
205
</ div >
161
206
</ section >
0 commit comments