mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: render all steps at the same time, add thank you; first anims
This commit is contained in:
		
							parent
							
								
									5456b093be
								
							
						
					
					
						commit
						355b516dae
					
				| @ -92,217 +92,260 @@ export const FeedbackWrapper = ({ seedData, open }) => { | ||||
|         console.log('send feedback here '); | ||||
|     }; | ||||
| 
 | ||||
|     const step1ref = React.useRef(null); | ||||
| 
 | ||||
|     const visuallyHidden = (stepNumber) => state.currentStep !== stepNumber; | ||||
|     const isHidden = (stepNumber) => | ||||
|         !feedbackIsOpen || visuallyHidden(stepNumber); | ||||
| 
 | ||||
|     const Step1 = () => { | ||||
|         const hidden = isHidden(1); | ||||
|         const [newValue, setNewValue] = React.useState(undefined); | ||||
|         return ( | ||||
|             <form | ||||
|                 className="step-1" | ||||
|                 className={visuallyHidden(1) ? styles['invisible'] : ''} | ||||
|                 onSubmit={(e) => { | ||||
|                     e.preventDefault(); | ||||
|                     setScore(newValue); | ||||
|                     stepForward(); | ||||
|                 }} | ||||
|                 aria-hidden={hidden} | ||||
|             > | ||||
|                 <p> | ||||
|                     <span className="visually-hidden"> | ||||
|                         On a scale from 1 to 5 where 1 is very unsatisfied and 5 | ||||
|                         is very satisfied, | ||||
|                     </span>{' '} | ||||
|                     How would you rate your overall satisfaction with the | ||||
|                     Unleash documentation? | ||||
|                 </p> | ||||
|                 <fieldset disabled={hidden}> | ||||
|                     <p> | ||||
|                         <span className="visually-hidden"> | ||||
|                             On a scale from 1 to 5 where 1 is very unsatisfied | ||||
|                             and 5 is very satisfied, | ||||
|                         </span>{' '} | ||||
|                         How would you rate your overall satisfaction with the | ||||
|                         Unleash documentation? | ||||
|                     </p> | ||||
| 
 | ||||
|                 <div className={styles['satisfaction-input-container']}> | ||||
|                     <span | ||||
|                         aria-hidden="true" | ||||
|                         className={styles['satisfaction-input-visual-label']} | ||||
|                     > | ||||
|                         Very unsatisfied | ||||
|                     </span> | ||||
|                     <span className={styles['satisfaction-input-inputs']}> | ||||
|                         {[1, 2, 3, 4, 5].map((n) => ( | ||||
|                             <span key={`input-group-${n}`}> | ||||
|                                 <input | ||||
|                                     className={join( | ||||
|                                         'visually-hidden', | ||||
|                                         styles['user-satisfaction-score-input'], | ||||
|                                     )} | ||||
|                                     required | ||||
|                                     id={`user-satisfaction-score-${n}`} | ||||
|                                     name="satisfaction-level" | ||||
|                                     type="radio" | ||||
|                                     value={n} | ||||
|                                     defaultChecked={n === state.data.score} | ||||
|                                     onChange={(e) => { | ||||
|                                         const value = parseInt(e.target.value); | ||||
|                                         console.log('the value is', value); | ||||
|                                         setNewValue(value); | ||||
|                                     }} | ||||
|                                 /> | ||||
|                                 <label | ||||
|                                     className={ | ||||
|                                         styles['user-satisfaction-score-label'] | ||||
|                                     } | ||||
|                                     htmlFor={`user-satisfaction-score-${n}`} | ||||
|                                 > | ||||
|                                     {n} | ||||
|                                 </label> | ||||
|                             </span> | ||||
|                         ))} | ||||
|                     </span> | ||||
|                     <span | ||||
|                         aria-hidden="true" | ||||
|                         className={styles['satisfaction-input-visual-label']} | ||||
|                     > | ||||
|                         Very satisfied | ||||
|                     </span> | ||||
|                 </div> | ||||
|                 <div className={styles['button-container']}> | ||||
|                     <button type="submit">Next</button> | ||||
|                 </div> | ||||
|                     <div className={styles['satisfaction-input-container']}> | ||||
|                         <span | ||||
|                             aria-hidden="true" | ||||
|                             className={ | ||||
|                                 styles['satisfaction-input-visual-label'] | ||||
|                             } | ||||
|                         > | ||||
|                             Very unsatisfied | ||||
|                         </span> | ||||
|                         <span className={styles['satisfaction-input-inputs']}> | ||||
|                             {[1, 2, 3, 4, 5].map((n) => ( | ||||
|                                 <span key={`input-group-${n}`}> | ||||
|                                     <input | ||||
|                                         ref={n === 1 ? step1ref : undefined} | ||||
|                                         className={join( | ||||
|                                             'visually-hidden', | ||||
|                                             styles[ | ||||
|                                                 'user-satisfaction-score-input' | ||||
|                                             ], | ||||
|                                         )} | ||||
|                                         required | ||||
|                                         id={`user-satisfaction-score-${n}`} | ||||
|                                         name="satisfaction-level" | ||||
|                                         type="radio" | ||||
|                                         value={n} | ||||
|                                         defaultChecked={n === state.data.score} | ||||
|                                         onChange={(e) => { | ||||
|                                             const value = parseInt( | ||||
|                                                 e.target.value, | ||||
|                                             ); | ||||
|                                             console.log('the value is', value); | ||||
|                                             setNewValue(value); | ||||
|                                         }} | ||||
|                                     /> | ||||
|                                     <label | ||||
|                                         className={ | ||||
|                                             styles[ | ||||
|                                                 'user-satisfaction-score-label' | ||||
|                                             ] | ||||
|                                         } | ||||
|                                         htmlFor={`user-satisfaction-score-${n}`} | ||||
|                                     > | ||||
|                                         {n} | ||||
|                                     </label> | ||||
|                                 </span> | ||||
|                             ))} | ||||
|                         </span> | ||||
|                         <span | ||||
|                             aria-hidden="true" | ||||
|                             className={ | ||||
|                                 styles['satisfaction-input-visual-label'] | ||||
|                             } | ||||
|                         > | ||||
|                             Very satisfied | ||||
|                         </span> | ||||
|                     </div> | ||||
|                     <div className={styles['button-container']}> | ||||
|                         <button type="submit">Next</button> | ||||
|                     </div> | ||||
|                 </fieldset> | ||||
|             </form> | ||||
|         ); | ||||
|     }; | ||||
| 
 | ||||
|     const Step2 = () => { | ||||
|         const hidden = isHidden(2); | ||||
|         const textareaId = 'feedback-comment-input'; | ||||
|         const saveComment = () => | ||||
|             setComment(document.getElementById(textareaId).value); | ||||
| 
 | ||||
|         return ( | ||||
|             <form | ||||
|                 className="step-2" | ||||
|                 className={visuallyHidden(2) ? styles['invisible'] : ''} | ||||
|                 aria-hidden={hidden} | ||||
|                 onSubmit={(e) => { | ||||
|                     e.preventDefault(); | ||||
|                     saveComment(); | ||||
|                     stepForward(); | ||||
|                 }} | ||||
|             > | ||||
|                 <label htmlFor={textareaId}> | ||||
|                     What would you like to see improved in the Unleash | ||||
|                     documentation? | ||||
|                 </label> | ||||
|                 <textarea | ||||
|                     id={textareaId} | ||||
|                     /* cols="30" */ | ||||
|                     name="" | ||||
|                     rows="5" | ||||
|                 > | ||||
|                     {state.data.comment} | ||||
|                 </textarea> | ||||
|                 <fieldset disabled={hidden}> | ||||
|                     <label htmlFor={textareaId}> | ||||
|                         What would you like to see improved in the Unleash | ||||
|                         documentation? | ||||
|                     </label> | ||||
|                     <textarea | ||||
|                         id={textareaId} | ||||
|                         /* cols="30" */ | ||||
|                         name="" | ||||
|                         rows="5" | ||||
|                     > | ||||
|                         {state.data.comment} | ||||
|                     </textarea> | ||||
| 
 | ||||
|                 <div className={styles['button-container']}> | ||||
|                     <button type="submit">Next</button> | ||||
|                     <button | ||||
|                         className={styles['button-secondary']} | ||||
|                         type="button" | ||||
|                         onClick={() => { | ||||
|                             saveComment(); | ||||
|                             stepForward(); | ||||
|                         }} | ||||
|                     > | ||||
|                         Skip | ||||
|                     </button> | ||||
|                     <button | ||||
|                         className={styles['button-secondary']} | ||||
|                         type="button" | ||||
|                         onClick={() => { | ||||
|                             saveComment(); | ||||
|                             stepBack(); | ||||
|                         }} | ||||
|                     > | ||||
|                         Back | ||||
|                     </button> | ||||
|                 </div> | ||||
|                     <div className={styles['button-container']}> | ||||
|                         <button type="submit">Next</button> | ||||
|                         <button | ||||
|                             className={styles['button-secondary']} | ||||
|                             type="button" | ||||
|                             onClick={() => { | ||||
|                                 saveComment(); | ||||
|                                 stepForward(); | ||||
|                             }} | ||||
|                         > | ||||
|                             Skip | ||||
|                         </button> | ||||
|                         <button | ||||
|                             className={styles['button-secondary']} | ||||
|                             type="button" | ||||
|                             onClick={() => { | ||||
|                                 saveComment(); | ||||
|                                 stepBack(); | ||||
|                             }} | ||||
|                         > | ||||
|                             Back | ||||
|                         </button> | ||||
|                     </div> | ||||
|                 </fieldset> | ||||
|             </form> | ||||
|         ); | ||||
|     }; | ||||
| 
 | ||||
|     const Step3 = () => { | ||||
|         const hidden = isHidden(3); | ||||
|         const [value, setValue] = React.useState(); | ||||
| 
 | ||||
|         return ( | ||||
|             <form | ||||
|                 className="step-3" | ||||
|                 className={visuallyHidden(3) ? styles['invisible'] : ''} | ||||
|                 aria-hidden={hidden} | ||||
|                 onSubmit={(e) => { | ||||
|                     e.preventDefault(); | ||||
|                     setCustomerType(value); | ||||
|                     submitFeedback(); | ||||
|                 }} | ||||
|             > | ||||
|                 <span> | ||||
|                     Finally, would you mind telling us a little about yourself? | ||||
|                     What kind of customer are you? | ||||
|                 </span> | ||||
|                 <div className={styles['customer-type-inputs']}> | ||||
|                     {[ | ||||
|                         ['a', 'paying', 'paying'], | ||||
|                         ['an', 'open source', 'opensource'], | ||||
|                     ].map(([article, customerType, key]) => ( | ||||
|                         <span key={`input-group-${key}`}> | ||||
|                             <input | ||||
|                                 id={`customer-type-${key}`} | ||||
|                                 className={styles['customer-type-input']} | ||||
|                                 name="customer-type" | ||||
|                                 type="radio" | ||||
|                                 value={key} | ||||
|                                 defaultChecked={key === state.data.customerType} | ||||
|                                 onChange={(e) => { | ||||
|                                     const value = e.target.value; | ||||
|                                     setValue(value); | ||||
|                                 }} | ||||
|                             /> | ||||
|                             <label | ||||
|                                 className={styles['customer-type-label']} | ||||
|                                 htmlFor={`customer-type-${key}`} | ||||
|                             > | ||||
|                                 I'm {article} {customerType} customer | ||||
|                             </label> | ||||
|                         </span> | ||||
|                     ))} | ||||
|                 </div> | ||||
|                 <fieldset disabled={hidden}> | ||||
|                     <span> | ||||
|                         Finally, would you mind telling us a little about | ||||
|                         yourself? What kind of customer are you? | ||||
|                     </span> | ||||
|                     <div className={styles['customer-type-inputs']}> | ||||
|                         {[ | ||||
|                             ['a', 'paying', 'paying'], | ||||
|                             ['an', 'open source', 'opensource'], | ||||
|                         ].map(([article, customerType, key]) => ( | ||||
|                             <span key={`input-group-${key}`}> | ||||
|                                 <input | ||||
|                                     id={`customer-type-${key}`} | ||||
|                                     className={styles['customer-type-input']} | ||||
|                                     name="customer-type" | ||||
|                                     type="radio" | ||||
|                                     value={key} | ||||
|                                     defaultChecked={ | ||||
|                                         key === state.data.customerType | ||||
|                                     } | ||||
|                                     onChange={(e) => { | ||||
|                                         const value = e.target.value; | ||||
|                                         setValue(value); | ||||
|                                     }} | ||||
|                                 /> | ||||
|                                 <label | ||||
|                                     className={styles['customer-type-label']} | ||||
|                                     htmlFor={`customer-type-${key}`} | ||||
|                                 > | ||||
|                                     I'm {article} {customerType} customer | ||||
|                                 </label> | ||||
|                             </span> | ||||
|                         ))} | ||||
|                     </div> | ||||
| 
 | ||||
|                 <div className={styles['button-container']}> | ||||
|                     <button type="submit">Submit feedback</button> | ||||
|                     <button | ||||
|                         className={styles['button-secondary']} | ||||
|                         type="button" | ||||
|                         onClick={() => { | ||||
|                             setCustomerType(value); | ||||
|                             stepBack(); | ||||
|                         }} | ||||
|                     > | ||||
|                         Back | ||||
|                     </button> | ||||
|                 </div> | ||||
|                     <div className={styles['button-container']}> | ||||
|                         <button type="submit">Submit feedback</button> | ||||
|                         <button | ||||
|                             className={styles['button-secondary']} | ||||
|                             type="button" | ||||
|                             onClick={() => { | ||||
|                                 setCustomerType(value); | ||||
|                                 stepBack(); | ||||
|                             }} | ||||
|                         > | ||||
|                             Back | ||||
|                         </button> | ||||
|                     </div> | ||||
|                 </fieldset> | ||||
|             </form> | ||||
|         ); | ||||
|     }; | ||||
| 
 | ||||
|     const Step4 = () => { | ||||
|         return <p className={styles['thank-you']}>Thank you! 🙌</p>; | ||||
|     }; | ||||
| 
 | ||||
|     return ( | ||||
|         <div className={styles['user-feedback-container']}> | ||||
|             <p>feedback is {feedbackIsOpen ? 'open' : 'closed'}</p> | ||||
| 
 | ||||
|             <button | ||||
|                 aria-hidden={feedbackIsOpen} | ||||
|                 className={join( | ||||
|                     feedbackIsOpen ? styles['hidden'] : undefined, | ||||
|                     styles['open-feedback-button'], | ||||
|                     styles['primary-button'], | ||||
|                 )} | ||||
|                 disabled={feedbackIsOpen} | ||||
|                 onClick={() => setFeedbackIsOpen(true)} | ||||
|                 onClick={() => { | ||||
|                     setFeedbackIsOpen(true); | ||||
|                     step1ref.current.focus(); | ||||
|                 }} | ||||
|             > | ||||
|                 Feedback | ||||
|                 <span>Feedback</span> | ||||
|             </button> | ||||
| 
 | ||||
|             <article | ||||
|                 aria-hidden={!feedbackIsOpen} | ||||
|                 /* hidden={!feedbackIsOpen} */ | ||||
|                 className={join( | ||||
|                     styles['user-feedback'], | ||||
|                     feedbackIsOpen ? '' : styles['hidden'], | ||||
|                     feedbackIsOpen ? '' : styles['invisible'], | ||||
|                 )} | ||||
|             > | ||||
|                 <div className={styles['close-button-row']}> | ||||
|                     <button | ||||
|                         onClick={() => setFeedbackIsOpen(false)} | ||||
|                         className={styles['close-button']} | ||||
|                         disabled={!feedbackIsOpen} | ||||
|                     > | ||||
|                         <span className="visually-hidden"> | ||||
|                             close feedback popup | ||||
| @ -310,13 +353,10 @@ export const FeedbackWrapper = ({ seedData, open }) => { | ||||
|                         <CloseIcon /> | ||||
|                     </button> | ||||
|                 </div> | ||||
|                 {state.currentStep === 1 ? ( | ||||
|                     <Step1 /> | ||||
|                 ) : state.currentStep === 2 ? ( | ||||
|                     <Step2 /> | ||||
|                 ) : ( | ||||
|                     <Step3 /> | ||||
|                 )} | ||||
|                 <Step1 /> | ||||
|                 <Step2 /> | ||||
|                 <Step3 /> | ||||
|                 <Step4 /> | ||||
|             </article> | ||||
|         </div> | ||||
|     ); | ||||
|  | ||||
| @ -2,6 +2,17 @@ | ||||
|     --outline-style: 2px solid var(--ifm-color-primary); | ||||
|     --row-gap: 1rem; | ||||
|     --element-horizontal-gap: 1rem; | ||||
| 
 | ||||
|     --animation-duration: 0.25s; | ||||
|     --fade-out-transition: opacity var(--animation-duration); | ||||
|     --fade-in-transition: opacity var(--animation-duration) | ||||
|         calc(var(--animation-duration) / 2); | ||||
| } | ||||
| 
 | ||||
| @media screen and (prefers-reduced-motion: reduced) { | ||||
|     .user-feedback-container { | ||||
|         --animation-duration: 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| .user-feedback { | ||||
| @ -14,6 +25,12 @@ | ||||
|     box-shadow: var(--ifm-global-shadow-lw); | ||||
|     padding: var(--ifm-spacing-vertical) var(--ifm-spacing-horizontal); | ||||
|     text-align: center; | ||||
|     transition: var(--fade-in-transition); | ||||
| } | ||||
| 
 | ||||
| .user-feedback fieldset { | ||||
|     border: none; | ||||
|     padding: 0; | ||||
| } | ||||
| 
 | ||||
| .user-feedback > * + * { | ||||
| @ -30,13 +47,14 @@ | ||||
|     max-width: 850px; | ||||
|     margin-left: auto; | ||||
|     margin-right: auto; | ||||
|     transition: var(--fade-in-transition); | ||||
|     opacity: 1; | ||||
| } | ||||
| 
 | ||||
| .user-feedback > form > * + * { | ||||
|     margin-top: var(--row-gap); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .hidden { | ||||
|     display: none; | ||||
| } | ||||
| @ -147,11 +165,13 @@ button.close-button { | ||||
|     padding-inline: calc(var(--ifm-spacing-horizontal) * 4); | ||||
| } | ||||
| 
 | ||||
| .primary-button:hover, .user-feedback button[type='submit']:hover { | ||||
| .primary-button:hover, | ||||
| .user-feedback button[type='submit']:hover { | ||||
|     background-color: var(--ifm-color-primary-lighter); | ||||
| } | ||||
| 
 | ||||
| .primary-button:hover, .user-feedback button[type='submit']:active { | ||||
| .primary-button:hover, | ||||
| .user-feedback button[type='submit']:active { | ||||
|     background-color: var(--ifm-color-primary-dark); | ||||
| } | ||||
| 
 | ||||
| @ -174,14 +194,12 @@ button.close-button { | ||||
|     background-color: var(--ifm-background-color); | ||||
|     color: currentColor; | ||||
|     border-radius: var(--ifm-global-radius); | ||||
|     border: var(--ifm-global-border-width) solid | ||||
|         var(--ifm-color-emphasis-400); | ||||
|     border: var(--ifm-global-border-width) solid var(--ifm-color-emphasis-400); | ||||
|     font-style: normal; | ||||
|     font-family: inherit; | ||||
|     padding: var(--ifm-spacing-vertical) var(--ifm-spacing-horizontal); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .customer-type-inputs { | ||||
|     display: flex; | ||||
|     justify-content: center; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user