docs: add options to feedback component (#12698)
This commit is contained in:
@@ -66,9 +66,9 @@ export const CodeBlockActions = ({
|
||||
)}
|
||||
<div
|
||||
className={clsx(
|
||||
"md:flex md:justify-end md:gap-docs_0.25 z-[11] relative",
|
||||
"md:flex md:justify-end md:gap-docs_0.25 relative",
|
||||
!inHeader && [
|
||||
"md:pr-docs_0.5",
|
||||
"md:pr-docs_0.5 z-[11]",
|
||||
isCollapsed && "md:pt-docs_2.5",
|
||||
!isCollapsed && [
|
||||
isSingleLine && "md:pt-docs_0.25",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import React, { useMemo, useRef, useState } from "react"
|
||||
import React, { useEffect, useMemo, useRef, useState } from "react"
|
||||
// @ts-expect-error can't install the types package because it doesn't support React v19
|
||||
import { CSSTransition, SwitchTransition } from "react-transition-group"
|
||||
import { Solutions } from "./Solutions"
|
||||
@@ -10,13 +10,13 @@ import {
|
||||
Button,
|
||||
TextArea,
|
||||
Label,
|
||||
Details,
|
||||
InputText,
|
||||
DottedSeparator,
|
||||
RadioItem,
|
||||
} from "@/components"
|
||||
import { ChatBubbleLeftRight, ThumbDown, ThumbUp } from "@medusajs/icons"
|
||||
import Link from "next/link"
|
||||
import { useSiteConfig } from "../../providers"
|
||||
import { RadioGroup } from "@medusajs/ui"
|
||||
|
||||
export type FeedbackProps = {
|
||||
event: string
|
||||
@@ -33,10 +33,26 @@ export type FeedbackProps = {
|
||||
className?: string
|
||||
extraData?: ExtraData
|
||||
vertical?: boolean
|
||||
showLongForm?: boolean
|
||||
showDottedSeparator?: boolean
|
||||
} & React.HTMLAttributes<HTMLDivElement>
|
||||
|
||||
const feedbackOptions = {
|
||||
positive: [
|
||||
"Easy to understand",
|
||||
"Accurate code and text",
|
||||
"Exactly what I was looking for",
|
||||
"Ease of use",
|
||||
"Other",
|
||||
],
|
||||
negative: [
|
||||
"Difficult to understand",
|
||||
"Inaccurate code or text",
|
||||
"Didn't find what I was looking for",
|
||||
"Trouble using the documentation",
|
||||
"Other",
|
||||
],
|
||||
}
|
||||
|
||||
export const Feedback = ({
|
||||
event,
|
||||
pathName,
|
||||
@@ -44,15 +60,14 @@ export const Feedback = ({
|
||||
question = "Was this page helpful?",
|
||||
positiveBtn = "It was helpful",
|
||||
negativeBtn = "It wasn't helpful",
|
||||
positiveQuestion = "What was most helpful?",
|
||||
negativeQuestion = "What can we improve?",
|
||||
positiveQuestion = "What did you like?",
|
||||
negativeQuestion = "What was the problem?",
|
||||
submitBtn = "Submit",
|
||||
submitMessage = "Thank you for helping improve our documentation!",
|
||||
showPossibleSolutions = true,
|
||||
className = "",
|
||||
extraData = {},
|
||||
vertical = false,
|
||||
showLongForm = false,
|
||||
showDottedSeparator = true,
|
||||
}: FeedbackProps) => {
|
||||
const {
|
||||
@@ -69,10 +84,7 @@ export const Feedback = ({
|
||||
const inlineMessageRef = useRef<HTMLDivElement>(null)
|
||||
const [positiveFeedback, setPositiveFeedback] = useState(false)
|
||||
const [message, setMessage] = useState("")
|
||||
const [steps, setSteps] = useState("")
|
||||
const [medusaVersion, setMedusaVersion] = useState("")
|
||||
const [errorFix, setErrorFix] = useState("")
|
||||
const [contactInfo, setContactInfo] = useState("")
|
||||
const [feedbackOption, setFeedbackOption] = useState("")
|
||||
const nodeRef = submittedFeedback
|
||||
? inlineMessageRef
|
||||
: showForm
|
||||
@@ -80,20 +92,16 @@ export const Feedback = ({
|
||||
: inlineFeedbackRef
|
||||
const { loaded, track } = useAnalytics()
|
||||
|
||||
function handleFeedback(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
|
||||
function handleFeedback(feedback: boolean) {
|
||||
if (!loaded) {
|
||||
return
|
||||
}
|
||||
const feedback = (e.target as Element).classList.contains("positive")
|
||||
setPositiveFeedback(feedback)
|
||||
setShowForm(true)
|
||||
submitFeedback(e, feedback)
|
||||
submitFeedback(feedback)
|
||||
}
|
||||
|
||||
function submitFeedback(
|
||||
e: React.MouseEvent<HTMLButtonElement, MouseEvent>,
|
||||
feedback = false
|
||||
) {
|
||||
function submitFeedback(feedback = false) {
|
||||
if (showForm) {
|
||||
setLoading(true)
|
||||
}
|
||||
@@ -109,10 +117,7 @@ export const Feedback = ({
|
||||
: "no",
|
||||
message: message?.length ? message : null,
|
||||
os: window.navigator.userAgent,
|
||||
steps,
|
||||
medusaVersion,
|
||||
errorFix,
|
||||
contactInfo,
|
||||
feedbackOption,
|
||||
...extraData,
|
||||
},
|
||||
function () {
|
||||
@@ -129,6 +134,10 @@ export const Feedback = ({
|
||||
setSubmittedFeedback(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setFeedbackOption("Other")
|
||||
}, [positiveFeedback])
|
||||
|
||||
return (
|
||||
<div className={clsx(className)}>
|
||||
{showDottedSeparator && (
|
||||
@@ -173,7 +182,7 @@ export const Feedback = ({
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
onClick={handleFeedback}
|
||||
onClick={() => handleFeedback(true)}
|
||||
className={clsx(
|
||||
"positive gap-[6px] !justify-start md:!justify-center",
|
||||
"!px-docs_0.5 !py-docs_0.25 text-left md:text-center"
|
||||
@@ -186,7 +195,7 @@ export const Feedback = ({
|
||||
</span>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleFeedback}
|
||||
onClick={() => handleFeedback(false)}
|
||||
className={clsx(
|
||||
"gap-[6px] !justify-start md:!justify-center",
|
||||
"!px-docs_0.5 !py-docs_0.25 text-left md:text-center"
|
||||
@@ -226,69 +235,39 @@ export const Feedback = ({
|
||||
<Label>
|
||||
{positiveFeedback ? positiveQuestion : negativeQuestion}
|
||||
</Label>
|
||||
<RadioGroup className="gap-docs_0.5">
|
||||
{feedbackOptions[
|
||||
positiveFeedback ? "positive" : "negative"
|
||||
].map((option) => (
|
||||
<div
|
||||
className="flex items-center gap-x-docs_0.5 cursor-pointer group"
|
||||
key={option}
|
||||
tabIndex={-1}
|
||||
onClick={() => setFeedbackOption(option)}
|
||||
>
|
||||
<RadioItem
|
||||
checked={feedbackOption === option}
|
||||
value={option}
|
||||
onChange={() => setFeedbackOption(option)}
|
||||
className={clsx(
|
||||
feedbackOption !== option &&
|
||||
"group-hover:bg-medusa-bg-component-hover"
|
||||
)}
|
||||
/>
|
||||
<Label className="text-medusa-fg-base text-compact-small-plus">
|
||||
{option}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</RadioGroup>
|
||||
<TextArea
|
||||
rows={4}
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
placeholder="Please provide as many details as possible to help us improve the documentation."
|
||||
/>
|
||||
{showLongForm && !positiveFeedback && (
|
||||
<Details summaryContent="More Details" className="mt-docs_1">
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<Label>
|
||||
Can you provide the exact steps you took before
|
||||
receiving the error? For example, the commands you
|
||||
ran.
|
||||
</Label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
value={steps}
|
||||
onChange={(e) => setSteps(e.target.value)}
|
||||
placeholder="1. I ran npm dev..."
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<Label>
|
||||
If applicable, what version of Medusa are you using?
|
||||
If a plugin is related to the error, please provide a
|
||||
version of that as well.
|
||||
</Label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
value={medusaVersion}
|
||||
onChange={(e) => setMedusaVersion(e.target.value)}
|
||||
placeholder="@medusajs/medusa: vX"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<Label>
|
||||
Were you able to fix the error? If so, what steps did
|
||||
you follow?
|
||||
</Label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
value={errorFix}
|
||||
onChange={(e) => setErrorFix(e.target.value)}
|
||||
placeholder="@medusajs/medusa: vX"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<Label>
|
||||
Can you provide your email or discord username? This
|
||||
would allow us to contact you for further info or
|
||||
assist you with your issue.
|
||||
</Label>
|
||||
<InputText
|
||||
value={contactInfo}
|
||||
onChange={(e) => setContactInfo(e.target.value)}
|
||||
placeholder="user@example.com"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Details>
|
||||
)}
|
||||
<Button
|
||||
onClick={submitFeedback}
|
||||
onClick={() => submitFeedback(positiveFeedback)}
|
||||
disabled={loading}
|
||||
className="w-fit"
|
||||
variant="secondary"
|
||||
|
||||
37
www/packages/docs-ui/src/components/RadioItem/index.tsx
Normal file
37
www/packages/docs-ui/src/components/RadioItem/index.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
|
||||
type RadioItemProps = React.DetailedHTMLProps<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
HTMLInputElement
|
||||
> & {
|
||||
checked?: boolean
|
||||
}
|
||||
|
||||
export const RadioItem = ({ className, checked, ...props }: RadioItemProps) => {
|
||||
return (
|
||||
<div className="p-[3px] flex justify-center items-center relative">
|
||||
<input
|
||||
type="radio"
|
||||
className={clsx(
|
||||
"appearance-none bg-medusa-bg-component shadow-borders-base dark:shadow-border-base-dark",
|
||||
"w-[14px] h-[14px] rounded-full",
|
||||
"focus:shadow-borders-interactive-with-focus disabled:opacity-50",
|
||||
"checked:!bg-medusa-bg-interactive checked:!shadow-borders-interactive-with-shadow",
|
||||
!checked && "hover:bg-medusa-bg-component-hover",
|
||||
className
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
/>
|
||||
{checked && (
|
||||
<span
|
||||
className={clsx(
|
||||
"w-[6px] h-[6px] bg-medusa-bg-base dark:bg-medusa-fg-on-color absolute top-1/2 left-1/2 rounded-full",
|
||||
"-translate-x-1/2 -translate-y-1/2 shadow-details-contrast-on-bg-interactive"
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -14,13 +14,13 @@ export const TextArea = (props: TextAreaProps) => {
|
||||
{...props}
|
||||
className={clsx(
|
||||
"bg-medusa-bg-field shadow-border-base dark:shadow-border-base-dark",
|
||||
"border-medusa-border-base rounded-docs_sm border border-solid",
|
||||
"pt-docs_0.4 px-docs_0.75 text-medium font-base pb-[9px]",
|
||||
"rounded-docs_sm",
|
||||
"py-[6px] px-docs_0.5 text-medium font-base",
|
||||
"hover:bg-medusa-bg-field-hover",
|
||||
"focus:border-medusa-border-interactive",
|
||||
"active:border-medusa-border-interactive",
|
||||
"focus:shadow-medusa-border-interactive-with-focus",
|
||||
"active:shadow-medusa-border-interactive-with-focus",
|
||||
"disabled:bg-medusa-bg-disabled",
|
||||
"disabled:border-medusa-border-base",
|
||||
"disabled:border-medusa-border-base disabled:border disabled:shadow-none",
|
||||
"placeholder:text-medusa-fg-muted",
|
||||
"disabled:placeholder:text-medusa-fg-disabled",
|
||||
props.className
|
||||
|
||||
@@ -59,6 +59,7 @@ export * from "./Notification/Item"
|
||||
export * from "./Notification/Item/Layout/Default"
|
||||
export * from "./Pagination"
|
||||
export * from "./Prerequisites"
|
||||
export * from "./RadioItem"
|
||||
export * from "./Rating"
|
||||
export * from "./RootProviders"
|
||||
export * from "./Search"
|
||||
|
||||
Reference in New Issue
Block a user