mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +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