1
+ import AliAbdaal from '../../../../assets/images/ali-abdaal.png' ;
2
+ import IsaacSaul from '../../../../assets/images/isaac-saul.png' ;
3
+ import JoelWarner from '../../../../assets/images/joel-warner.png' ;
1
4
import NiceModal , { useModal } from '@ebay/nice-modal-react' ;
2
5
import { Avatar , Button , Form , Modal , Select , TextArea , showToast } from '@tryghost/admin-x-design-system' ;
3
6
import { generateAvatarColor , getInitials } from '../../../../utils/helpers' ;
@@ -76,13 +79,13 @@ const TestimonialsModal = NiceModal.create(() => {
76
79
} ) ;
77
80
78
81
const migratedFromOptions : Array < { value : string ; label : string ; } > = [
79
- { value : 'wordpress ' , label : 'Wordpress ' } ,
82
+ { value : '' , label : 'None - This is a new site ' } ,
80
83
{ value : 'substack' , label : 'Substack' } ,
81
- { value : 'medium' , label : 'Medium' } ,
82
84
{ value : 'beehiiv' , label : 'Beehiiv' } ,
85
+ { value : 'wordpress' , label : 'Wordpress' } ,
83
86
{ value : 'newspack' , label : 'Newspack' } ,
87
+ { value : 'medium' , label : 'Medium' } ,
84
88
{ value : 'squarespace' , label : 'Squarespace' } ,
85
- { value : 'patreon' , label : 'Patreon' } ,
86
89
{ value : 'memberful' , label : 'Memberful' } ,
87
90
{ value : 'other' , label : 'Other' }
88
91
] ;
@@ -94,73 +97,123 @@ const TestimonialsModal = NiceModal.create(() => {
94
97
} }
95
98
cancelLabel = ''
96
99
footer = { false }
97
- // height={645}
98
100
padding = { false }
99
101
testId = 'explore-testimonials-modal'
100
102
title = ''
101
103
topRightContent = 'close'
102
- width = { 520 }
104
+ width = { 920 }
103
105
>
104
- < div className = 'h-[140px] bg-gradient-to-tr from-[rgba(142,66,255,0.07)] to-[rgba(142,66,255,0.02)]' > </ div >
105
- < div className = 'mx-6 mt-[-30px] flex size-[60px] items-center justify-center rounded-full bg-gradient-to-t from-[#CFB0FF] to-[#B27EFF]' >
106
- < svg fill = "none" height = "26" viewBox = "0 0 32 26" width = "32" xmlns = "http://www.w3.org/2000/svg" >
107
- < path d = "M19.9967 26L18.1562 21.4542C23.4268 19.1176 25.7693 16.5261 26.2712 11.7255C25.5183 12.3627 24.5562 12.7026 23.3431 12.7026C20.1641 12.7026 17.4869 10.1536 17.4869 6.41503C17.4869 2.80392 20.3732 9.72736e-07 24.2634 6.32644e-07C28.2791 2.81581e-07 31.5 3.10131 31.5 8.96405C31.5 17.5458 27.4425 23.0261 19.9967 26ZM3.0098 26L1.12745 21.4543C6.43987 19.1176 8.78235 16.5261 9.24248 11.7255C8.53137 12.3627 7.56928 12.7026 6.35621 12.7026C3.17712 12.7026 0.499999 10.1536 0.499998 6.41504C0.499998 2.80393 3.38627 2.45778e-06 7.23464 2.12135e-06C11.2503 1.77028e-06 14.5131 3.10131 14.5131 8.96405C14.5131 17.5458 10.4556 23.0261 3.0098 26Z" fill = "white" />
108
- </ svg >
109
- </ div >
110
- < Form >
111
- < div className = '-mb-1 px-7 pt-3' >
112
- < div >
113
- < div className = 'text-xl font-semibold tracking-tight' > Send a testimonial</ div >
114
- < div className = 'mt-1 text-pretty' >
115
- We're featuring sites that share a testimonial more prominently on Ghost Explore.
106
+ < Form className = '!mb-0' >
107
+ < div className = 'flex items-stretch' >
108
+ < div className = 'hidden w-full flex-col justify-between bg-gradient-to-tl from-grey-100/50 to-grey-100/80 p-8 dark:from-grey-900/40 dark:to-grey-900/60 [@media(min-width:905px)]:!visible [@media(min-width:905px)]:!flex' >
109
+ < div className = 'pr-6' >
110
+ < div className = 'relative rounded-xl bg-white px-3 py-2.5 italic text-grey-700 shadow-lg before:absolute before:-bottom-1.5 before:left-5 before:block before:size-3 before:rotate-45 before:bg-white dark:bg-black dark:text-grey-300 before:dark:bg-black' >
111
+ Moving to Ghost has proven to be one of the best business decisions we’ve made as an independent media outlet.
112
+ </ div >
113
+ < div className = 'ml-2 mt-[14px] flex items-center gap-2 text-sm' >
114
+ < div className = 'size-9 rounded-full bg-white bg-cover bg-center opacity-90 grayscale' style = { {
115
+ backgroundImage : `url(${ JoelWarner } )`
116
+ } } > </ div >
117
+ < div >
118
+ < div className = 'font-medium text-black dark:text-white' > Joel Warner</ div >
119
+ < div className = '-mt-0.5 text-grey-700' > Lever News</ div >
120
+ </ div >
121
+ </ div >
116
122
</ div >
117
- </ div >
118
- < div className = 'mt-5' >
119
- < TextArea
120
- error = { Boolean ( errors . content ) }
121
- hint = { errors . content }
122
- placeholder = 'Share your love for Ghost'
123
- rows = { 5 }
124
- value = { formState . content }
125
- autoFocus
126
- onChange = { e => updateForm ( state => ( { ...state , content : e . target . value } ) ) }
127
- onKeyDown = { ( ) => clearError ( 'content' ) }
128
- />
129
- </ div >
130
- < div className = 'ml-0.5 mt-4' >
131
- < div className = 'flex items-center gap-2' >
132
- < Avatar bgColor = { generateAvatarColor ( ( staffUserName ? staffUserName : staffUserEmail ) ) } image = { staffUserProfileImage ?? undefined } label = { getInitials ( staffUserName ) } labelColor = 'white' size = 'lg' />
133
- < div className = 'flex flex-col' >
134
- < span className = 'text-sm font-medium' > By { staffUserName ? staffUserName : staffUserEmail } </ span >
135
- < span className = 'text-xs text-grey-700' > { staffUserRole } — { siteTitle } </ span >
123
+
124
+ < div className = 'ml-6 mt-8' >
125
+ < div className = 'relative rounded-xl bg-white px-3 py-2.5 italic text-grey-700 shadow-lg before:absolute before:-bottom-1.5 before:right-5 before:block before:size-3 before:rotate-45 before:bg-white dark:bg-black dark:text-grey-300 before:dark:bg-black' >
126
+ It has now been one year since I quit my full-time job to go all in on Tangle. Today, we have 50,000+ paying subscribers. That’s roughly $5M in gross yearly revenue ... it’s the best paying job I’ve ever had.
127
+ </ div >
128
+ < div className = 'mr-2 mt-[14px] flex items-center justify-end gap-2 text-sm' >
129
+ < div className = 'flex flex-col items-end' >
130
+ < div className = 'font-medium text-black dark:text-white' > Isaac Saul</ div >
131
+ < div className = '-mt-0.5 text-grey-700' > Tangle</ div >
132
+ </ div >
133
+ < div className = 'size-9 rounded-full bg-white bg-cover bg-center opacity-90 grayscale' style = { {
134
+ backgroundImage : `url(${ IsaacSaul } )`
135
+ } } > </ div >
136
+ </ div >
137
+ </ div >
138
+
139
+ < div className = 'mt-8 hidden pr-6 [@media(min-width:940px)]:!visible [@media(min-width:940px)]:!block' >
140
+ < div className = 'relative rounded-xl bg-white px-3 py-2.5 italic text-grey-700 shadow-lg before:absolute before:-bottom-1.5 before:left-5 before:block before:size-3 before:rotate-45 before:bg-white dark:bg-black dark:text-grey-300 before:dark:bg-black' >
141
+ You should be using Ghost because it’s absolutely amazing and I love it. It’s what I’ve been using for all my sites since 2016.
142
+ </ div >
143
+ < div className = 'ml-2 mt-[14px] flex items-center gap-2 text-sm' >
144
+ < div className = 'size-9 rounded-full bg-white bg-cover bg-center opacity-90 grayscale' style = { {
145
+ backgroundImage : `url(${ AliAbdaal } )`
146
+ } } > </ div >
147
+ < div >
148
+ < div className = 'font-medium text-black dark:text-white' > Ali Abdaal</ div >
149
+ < div className = '-mt-0.5 text-grey-700' > YouTuber</ div >
150
+ </ div >
136
151
</ div >
137
152
</ div >
138
153
</ div >
139
- < div className = 'mt-10 flex items-center gap-4' >
140
- < div className = 'grow' >
141
- < Select
142
- error = { Boolean ( errors . prev_platform ) }
143
- hint = { errors . prev_platform }
144
- options = { migratedFromOptions }
145
- placeholder = 'Which platform did you switch from?'
146
- selectedOption = { migratedFromOptions . find ( option => option . value === formState . prev_platform ) }
147
- testId = 'migrated-from'
148
- onSelect = { ( option ) => {
149
- updateForm ( state => ( { ...state , prev_platform : option ?. value || '' } ) ) ;
150
- clearError ( 'prev_platform' ) ;
151
- } }
152
- />
154
+ < div className = 'flex grow flex-col justify-between gap-6 p-8 [@media(min-width:905px)]:min-w-[520px] [@media(min-width:940px)]:min-w-[460px]' >
155
+ < div >
156
+ < div className = 'flex size-[60px] items-center justify-center rounded-full bg-gradient-to-t from-[#CFB0FF] to-[#B27EFF]' >
157
+ < svg fill = "none" height = "26" viewBox = "0 0 32 26" width = "32" xmlns = "http://www.w3.org/2000/svg" >
158
+ < path d = "M19.9967 26L18.1562 21.4542C23.4268 19.1176 25.7693 16.5261 26.2712 11.7255C25.5183 12.3627 24.5562 12.7026 23.3431 12.7026C20.1641 12.7026 17.4869 10.1536 17.4869 6.41503C17.4869 2.80392 20.3732 9.72736e-07 24.2634 6.32644e-07C28.2791 2.81581e-07 31.5 3.10131 31.5 8.96405C31.5 17.5458 27.4425 23.0261 19.9967 26ZM3.0098 26L1.12745 21.4543C6.43987 19.1176 8.78235 16.5261 9.24248 11.7255C8.53137 12.3627 7.56928 12.7026 6.35621 12.7026C3.17712 12.7026 0.499999 10.1536 0.499998 6.41504C0.499998 2.80393 3.38627 2.45778e-06 7.23464 2.12135e-06C11.2503 1.77028e-06 14.5131 3.10131 14.5131 8.96405C14.5131 17.5458 10.4556 23.0261 3.0098 26Z" fill = "white" />
159
+ </ svg >
160
+ </ div >
161
+ < div className = 'mt-6' >
162
+ < div className = 'text-2xl font-semibold tracking-tight' > A quote about Ghost</ div >
163
+ < div className = 'mt-2 text-pretty' >
164
+ We feature quotes from publishers to showcase their work, including a logo and a link! If you'd like to be included, share a quote we can use to highlight you.
165
+ </ div >
166
+ </ div >
167
+ < div className = 'mt-8' >
168
+ < TextArea
169
+ error = { Boolean ( errors . content ) }
170
+ hint = { errors . content }
171
+ placeholder = 'What changed for the better since you switched to Ghost?'
172
+ rows = { 7 }
173
+ value = { formState . content }
174
+ autoFocus
175
+ onChange = { e => updateForm ( state => ( { ...state , content : e . target . value } ) ) }
176
+ onKeyDown = { ( ) => clearError ( 'content' ) }
177
+ />
178
+ </ div >
179
+ < div className = 'ml-0.5 mt-4' >
180
+ < div className = 'flex items-center gap-2' >
181
+ < Avatar bgColor = { generateAvatarColor ( ( staffUserName ? staffUserName : staffUserEmail ) ) } image = { staffUserProfileImage ?? undefined } label = { getInitials ( staffUserName ) } labelColor = 'white' size = 'md' />
182
+ < div className = 'flex flex-col' >
183
+ < span className = 'text-sm font-medium' > By { staffUserName ? staffUserName : staffUserEmail } </ span >
184
+ < span className = 'text-xs text-grey-700' > { staffUserRole } — { siteTitle } </ span >
185
+ </ div >
186
+ </ div >
187
+ </ div >
188
+ </ div >
189
+ < div >
190
+ < div className = 'mt-2 flex items-center gap-4' >
191
+ < div className = 'grow' >
192
+ < Select
193
+ error = { Boolean ( errors . prev_platform ) }
194
+ hint = { errors . prev_platform }
195
+ options = { migratedFromOptions }
196
+ placeholder = 'Previous platform'
197
+ selectedOption = { migratedFromOptions . find ( option => option . value === formState . prev_platform ) }
198
+ testId = 'migrated-from'
199
+ onSelect = { ( option ) => {
200
+ updateForm ( state => ( { ...state , prev_platform : option ?. value || '' } ) ) ;
201
+ clearError ( 'prev_platform' ) ;
202
+ } }
203
+ />
204
+ </ div >
205
+ < Button
206
+ className = '!h-[38px] rounded-lg'
207
+ color = "black"
208
+ disabled = { saveState === 'saving' }
209
+ label = "Send testimonial"
210
+ loading = { saveState === 'saving' }
211
+ onClick = { async ( ) => {
212
+ await handleSave ( ) ;
213
+ } }
214
+ />
215
+ </ div >
153
216
</ div >
154
- < Button
155
- className = '!h-[38px] rounded-lg'
156
- color = "black"
157
- disabled = { saveState === 'saving' }
158
- label = "Send testimonial"
159
- loading = { saveState === 'saving' }
160
- onClick = { async ( ) => {
161
- await handleSave ( ) ;
162
- } }
163
- />
164
217
</ div >
165
218
</ div >
166
219
</ Form >
0 commit comments