docs: added Feedback component (#2274)

This commit is contained in:
Shahed Nasser
2022-09-30 12:02:13 +03:00
committed by GitHub
parent 8e21246047
commit 7a721e6447
15 changed files with 261 additions and 144 deletions
+123
View File
@@ -0,0 +1,123 @@
.inline-feedback {
display: flex;
flex-direction: row;
align-items: center;
}
.inline-question,
.feedback-message {
display: flex;
flex-direction: column;
}
.inline-feedback span,
.inline-question span {
font-weight: bold;
}
.inline-feedback span {
margin-right: 13px;
}
.inline-question span {
margin-bottom: 13px;
}
.feedback-btn {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 13px;
padding: 12px 16px;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
background-color: transparent;
border: 1px solid #E5E7EB;
color: var(--ifm-font-color-base);
}
.feedback-btn:focus {
box-shadow: 0px 0px 0px 4px rgba(124, 58, 237, 0.1);
}
html:not([data-theme="dark"]) .feedback-btn:hover {
background: #F3F4F6;
}
html:not([data-theme="dark"]) .feedback-btn:active,
html:not([data-theme="dark"]) .feedback-btn:disabled {
background: #E5E7EB;
}
[data-theme="dark"] .feedback-btn,
[data-theme="dark"] .inline-question textarea {
border-color: rgba(255, 255, 255, 0.15);
}
.feedback-btn:not(:last-child) {
margin-right: 13px;
}
.inline-question .feedback-btn {
margin-top: 13px;
width: fit-content;
}
.inline-question textarea {
border-radius: 4px;
background-color: transparent;
border: 1px solid #E5E7EB;
padding: 8px;
font-family: var(--ifm-font-family-base);
}
.feedback-message {
text-align: center;
font-size: 18px;
}
.fade-in {
-webkit-animation: fade-in .3s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
animation: fade-in .3s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
}
@-webkit-keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.fade-out {
-webkit-animation: fade-out .3s ease-out both;
animation: fade-out .3s ease-out both;
}
@-webkit-keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
+88
View File
@@ -0,0 +1,88 @@
import React, { useRef, useState } from 'react';
import { CSSTransition, SwitchTransition } from 'react-transition-group';
import './index.css';
import useIsBrowser from '@docusaurus/useIsBrowser';
import {useLocation} from '@docusaurus/router';
export default function Feedback () {
const [showForm, setShowForm] = useState(false);
const [submittedFeedback, setSubmittedFeedback] = useState(false);
const [loading, setLoading] = useState(false);
const inlineFeedbackRef = useRef(null);
const inlineQuestionRef = useRef(null);
const inlineMessageRef = useRef(null)
const [positiveFeedback, setPositiveFeedbac] = useState(false);
const [message, setMessage] = useState("");
const nodeRef = submittedFeedback ? inlineMessageRef : (showForm ? inlineQuestionRef : inlineFeedbackRef);
const isBrowser = useIsBrowser();
const location = useLocation();
function handleFeedback (e) {
setPositiveFeedbac(e.target.classList.contains('positive'));
setShowForm(true);
}
function submitFeedback (e) {
if (isBrowser) {
if (window.analytics) {
setLoading(true);
window.analytics.track('survey', {
url: location.pathname,
label: document.title,
feedback: positiveFeedback ? 'yes' : 'no',
message
}, function () {
setLoading(false);
setShowForm(false);
setSubmittedFeedback(true);
})
} else {
setShowForm(false);
setSubmittedFeedback(true);
}
}
}
return (
<div className='feedback-container'>
<SwitchTransition mode="out-in">
<CSSTransition
key={showForm}
nodeRef={nodeRef}
timeout={300}
addEndListener={(done) => {
nodeRef.current.addEventListener("transitionend", done, false);
}}
classNames={{
enter: 'fade-in',
exit: 'fade-out'
}}
>
<>
{(!showForm && !submittedFeedback) && (
<div className='inline-feedback' ref={inlineFeedbackRef}>
<span>Was this page helpful?</span>
<button className='positive feedback-btn' onClick={handleFeedback}>Yes</button>
<button className='negative feedback-btn' onClick={handleFeedback}>No</button>
</div>
)}
{(showForm && !submittedFeedback) && (
<div className='inline-question' ref={inlineQuestionRef}>
<span>{positiveFeedback ? 'What was most helpful?' : 'What can we improve?'}</span>
<textarea rows={4} value={message} onChange={(e) => setMessage(e.target.value)}></textarea>
<button className='feedback-btn' onClick={submitFeedback} disabled={loading}>Submit</button>
</div>
)}
{submittedFeedback && (
<div className='feedback-message' ref={inlineMessageRef}>
Thank you for helping improve our documentation!
</div>
)}
</>
</CSSTransition>
</SwitchTransition>
</div>
)
}
-13
View File
@@ -1,13 +0,0 @@
import React, { useEffect } from "react"
import RootLayout from "@theme/Layout"
const Layout = ({ children, ...props }) => {
return (
<RootLayout {...props}>
<div className="container">{children}</div>
</RootLayout>
)
}
export default Layout
-1
View File
@@ -1 +0,0 @@
export { default as Layout } from "./Layout"
@@ -1,19 +0,0 @@
import React from "react"
import styles from "./tab.module.css"
const TabItem = ({ title, isOverviewCard, items }) => {
const overviewModeList = () =>
items.map((item) => <p className="margin-bottom--xs">{item.title}</p>)
return (
<div className="col col--4 padding-right--md padding-bottom--md">
<div className={styles.card}>
<div className={styles.cardContent}>
<h3>{title}</h3>
<div>{isOverviewCard && overviewModeList()}</div>
</div>
</div>
</div>
)
}
export default TabItem
@@ -1 +0,0 @@
export { default as TabItem } from "./TabItem"
@@ -1,18 +0,0 @@
.card {
background-color: var(--ifm-medusa-gray);
min-height: 257px;
border-radius: 5px;
padding: 20px 13px;
height: 100%;
}
.cardContent {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.cardContent p {
font-size: 18px;
}
-77
View File
@@ -1,77 +0,0 @@
import clsx from "clsx"
import React, { useState } from "react"
import { TabItem } from "./TabItem/"
const BUTTONS_DATA = [
{ buttonTitle: "Overview", value: "overview" },
{ buttonTitle: "Tutorial", value: "tutorial" },
{ buttonTitle: "Guides", value: "guide" },
{ buttonTitle: "Reference", value: "reference" },
]
const OVERVIEW_DATA = ["Tutorial", "Guides", "Reference"]
const TabsPanel = ({ items }) => {
const [sort, setSort] = useState("overview")
const buttons = BUTTONS_DATA.map((item) => (
// <button
// className={clsx(
// { [styles.buttonActive]: sort === item.value },
// styles.button
// )}
// onClick={() => setSort(item.value)}
// >
// {item.buttonTitle}
// </button>
<li
className={clsx("tabs__item", {
"tabs__item--active": sort === item.value,
})}
onClick={() => setSort(item.value)}
>
{item.buttonTitle}
</li>
))
const getOverviewCardItemsSet = (currentCard) =>
items.filter((item) => item.key === currentCard.toLowerCase())
const overviewCardsSet = () =>
OVERVIEW_DATA.map((item) => (
<TabItem
isOverviewCard
title={item}
items={getOverviewCardItemsSet(item)}
/>
))
const getSortedArray = () => {
return items.filter((entry) => entry.type === sort)
}
const renderTabItems = () => {
if (sort === "overview") return overviewCardsSet()
return getSortedArray().length > 0 ? (
getSortedArray().map((item) => {
return <TabItem title={item.title} />
})
) : (
<p>hold tight! we are building these things</p>
)
}
return (
<div className="padding-bottom--xl">
{/* <Box sx={{ borderBottom: "1px solid black", marginBottom: "50px" }}>
{buttons}
</Box> */}
<ul class="tabs margin-bottom--lg">{buttons}</ul>
<div className="container padding--none">
<div className="row row--no-gutters">{renderTabItems()}</div>
</div>
</div>
)
}
export default TabsPanel
-1
View File
@@ -1 +0,0 @@
export { default as TabsPanel } from "./TabsPanel"
@@ -1,14 +0,0 @@
.button {
background-color: transparent;
border: none;
cursor: pointer;
height: 30px;
font-size: 16px;
margin-right: 10px;
}
.buttonActive {
color: var(--ifm-color-primary);
border-bottom: 3px solid var(--ifm-color-primary) !important;
font-weight: 500;
}