From 987dd8f5681697a443b9281c8e01c39ea83424b8 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Tue, 26 Sep 2023 20:26:09 +0300 Subject: [PATCH] docs: expanded rating form + UI docs improvement (#5211) * docs: expanded rating form + UI docs improvement * added props table + changed example --- www/apps/docs/src/hooks/use-onboarding.tsx | 7 +- www/apps/ui/src/components/feedback.tsx | 2 +- www/apps/ui/src/components/mdx-components.tsx | 14 ++ .../content/docs/components/focus-modal.mdx | 27 ++++ www/apps/ui/src/props/focus-modal.tsx | 26 ++++ www/apps/ui/src/registries/prop-registry.tsx | 3 + .../Item/Layout/Default/index.tsx | 4 +- .../components/Notification/Item/index.tsx | 1 + .../src/components/Notification/index.tsx | 13 +- .../docs-ui/src/components/Rating/index.tsx | 142 ++++++++++++------ www/packages/docs-ui/src/constants.ts | 1 + .../docs-ui/src/providers/Analytics/index.tsx | 85 ++++++++--- .../src/providers/Notification/index.tsx | 6 +- .../docs-ui/src/utils/format-report-link.ts | 20 ++- www/packages/tailwind/base.tailwind.config.js | 20 +++ 15 files changed, 285 insertions(+), 86 deletions(-) create mode 100644 www/apps/ui/src/props/focus-modal.tsx diff --git a/www/apps/docs/src/hooks/use-onboarding.tsx b/www/apps/docs/src/hooks/use-onboarding.tsx index a7bf5d496a..ef7f8a6a6f 100644 --- a/www/apps/docs/src/hooks/use-onboarding.tsx +++ b/www/apps/docs/src/hooks/use-onboarding.tsx @@ -22,9 +22,12 @@ const useOnboarding = () => { children: ( { - setTimeout(() => removeNotification(id), 1500) + onRating={(rating?: number) => { + if (rating >= 4) { + setTimeout(() => removeNotification(id), 1500) + } }} + parentNotificationId={id} /> ), }) diff --git a/www/apps/ui/src/components/feedback.tsx b/www/apps/ui/src/components/feedback.tsx index 0972a25108..b337e4874c 100644 --- a/www/apps/ui/src/components/feedback.tsx +++ b/www/apps/ui/src/components/feedback.tsx @@ -20,7 +20,7 @@ export const Feedback = ({ title, ...props }: FeedbackProps) => { ) }, + ol: ({ + className, + children, + ...props + }: React.HTMLAttributes) => { + return ( +
    + {children} +
+ ) + }, li: ({ className, children, diff --git a/www/apps/ui/src/content/docs/components/focus-modal.mdx b/www/apps/ui/src/content/docs/components/focus-modal.mdx index f1a6e8fb1d..c13966d535 100644 --- a/www/apps/ui/src/content/docs/components/focus-modal.mdx +++ b/www/apps/ui/src/content/docs/components/focus-modal.mdx @@ -30,6 +30,8 @@ import { FocusModal } from "@medusajs/ui" This component is based on the [Radix UI Dialog](https://www.radix-ui.com/primitives/docs/components/dialog) primitives. + + ### FocusModal.Header This component is based on the `div` element and supports all props of this element. @@ -37,3 +39,28 @@ This component is based on the `div` element and supports all props of this elem ### FocusModal.Body This component is based on the `div` element and supports all props of this element. + +## Example: Control Open State + +--- + +```tsx +import { useState } from "react" + +const MyModal = () => { + const [open, setOpen] = useState(false) + + return ( + + Trigger + + Title + Content + + + ) +} +``` \ No newline at end of file diff --git a/www/apps/ui/src/props/focus-modal.tsx b/www/apps/ui/src/props/focus-modal.tsx new file mode 100644 index 0000000000..144564cf3e --- /dev/null +++ b/www/apps/ui/src/props/focus-modal.tsx @@ -0,0 +1,26 @@ +import { PropTable } from "@/components/props-table" +import { PropDataMap } from "@/types/props" + +const focusModalProps: PropDataMap = [ + { + prop: "defaultOpen", + type: "boolean", + }, + { + prop: "open", + type: "boolean", + }, + { + prop: "onOpenChange", + type: { + type: "function", + signature: `(open: boolean) => void`, + }, + }, +] + +const Props = () => { + return +} + +export default Props diff --git a/www/apps/ui/src/registries/prop-registry.tsx b/www/apps/ui/src/registries/prop-registry.tsx index ccefb663ac..1ee9ebba0f 100644 --- a/www/apps/ui/src/registries/prop-registry.tsx +++ b/www/apps/ui/src/registries/prop-registry.tsx @@ -29,6 +29,9 @@ export const PropRegistry: Record = { "date-picker": { table: React.lazy(async () => import("../props/date-picker")), }, + "focus-modal": { + table: React.lazy(async () => import("../props/focus-modal")), + }, heading: { table: React.lazy(async () => import("../props/heading")), }, diff --git a/www/packages/docs-ui/src/components/Notification/Item/Layout/Default/index.tsx b/www/packages/docs-ui/src/components/Notification/Item/Layout/Default/index.tsx index 7a91577e89..5824975acc 100644 --- a/www/packages/docs-ui/src/components/Notification/Item/Layout/Default/index.tsx +++ b/www/packages/docs-ui/src/components/Notification/Item/Layout/Default/index.tsx @@ -11,6 +11,7 @@ import { Button } from "@/components" export type NotificationItemLayoutDefaultProps = NotificationItemProps & { handleClose: () => void + closeButtonText?: string } export const NotificationItemLayoutDefault: React.FC< @@ -23,6 +24,7 @@ export const NotificationItemLayoutDefault: React.FC< isClosable = true, handleClose, CustomIcon, + closeButtonText = "Close", }) => { return ( <> @@ -74,7 +76,7 @@ export const NotificationItemLayoutDefault: React.FC< )} {isClosable && (
- +
)} diff --git a/www/packages/docs-ui/src/components/Notification/Item/index.tsx b/www/packages/docs-ui/src/components/Notification/Item/index.tsx index ccb1cf6fbe..d4598d25e9 100644 --- a/www/packages/docs-ui/src/components/Notification/Item/index.tsx +++ b/www/packages/docs-ui/src/components/Notification/Item/index.tsx @@ -15,6 +15,7 @@ export type NotificationItemProps = { show?: boolean setShow?: (value: boolean) => void onClose?: () => void + closeButtonText?: string } & React.HTMLAttributes export const NotificationItem = ({ diff --git a/www/packages/docs-ui/src/components/Notification/index.tsx b/www/packages/docs-ui/src/components/Notification/index.tsx index 6fd439a80e..1e0bec8dfe 100644 --- a/www/packages/docs-ui/src/components/Notification/index.tsx +++ b/www/packages/docs-ui/src/components/Notification/index.tsx @@ -1,11 +1,16 @@ -import { NotificationItemType, useNotifications } from "@/providers" +import { + NotificationContextType, + NotificationItemType, + useNotifications, +} from "@/providers" import React from "react" import { NotificationItem } from "./Item" import { CSSTransition, TransitionGroup } from "react-transition-group" import clsx from "clsx" export const NotificationContainer = () => { - const { notifications, removeNotification } = useNotifications() + const { notifications, removeNotification } = + useNotifications() as NotificationContextType const handleClose = (notification: NotificationItemType) => { notification.onClose?.() @@ -25,8 +30,8 @@ export const NotificationContainer = () => { key={notification.id} timeout={200} classNames={{ - enter: "animate__animated animate__slideInRight animate__fastest", - exit: "animate__animated animate__slideOutRight animate__fastest", + enter: "animate-slideInRight animate-fast", + exit: "animate-slideOutRight animate-fast", }} > void + onRating?: (rating?: number) => void + additionalQuestion?: string + parentNotificationId?: string } & React.HTMLAttributes export const Rating: React.FC = ({ event = "rating", className = "", onRating, + additionalQuestion = "What should we improve?", + parentNotificationId, }) => { const [rating, setRating] = useState(0) + const [additionalFeedback, setAdditionalFeedback] = useState("") const [hoverRating, setHoverRating] = useState(0) const starElms = useRef([]) const starArr = Array.from(Array(5).keys()) const { track } = useAnalytics() + const { updateNotification } = useNotifications(true) || {} + + const submitTracking = useCallback( + (selectedRating?: number, feedback?: string) => { + track( + event, + { + rating: selectedRating || rating, + additionalFeedback: feedback || additionalFeedback, + }, + () => onRating?.(selectedRating || rating) + ) + }, + [rating, additionalFeedback] + ) const handleRating = (selectedRating: number) => { if (rating) { @@ -29,52 +49,82 @@ export const Rating: React.FC = ({ } setHoverRating(0) setRating(selectedRating) - for (let i = 0; i < selectedRating; i++) { - starElms.current[i].classList.add("animate-tada") + if (selectedRating >= 4) { + for (let i = 0; i < selectedRating; i++) { + starElms.current[i].classList.add("animate-tada") + } + submitTracking(selectedRating) } - track( - event, - { - rating: selectedRating, - }, - () => onRating?.() - ) } + useEffect(() => { + if ( + rating > 0 && + rating < 4 && + parentNotificationId && + updateNotification + ) { + // update parent notification ID + updateNotification(parentNotificationId, { + closeButtonText: "Submit", + onClose: () => submitTracking(rating, additionalFeedback), + }) + } + }, [additionalFeedback, rating]) + return ( -
- {starArr.map((i) => { - const isSelected = - (rating !== 0 && rating - 1 >= i) || - (hoverRating !== 0 && hoverRating - 1 >= i) - return ( - - ) - })} +
+
+ {starArr.map((i) => { + const isSelected = + (rating !== 0 && rating - 1 >= i) || + (hoverRating !== 0 && hoverRating - 1 >= i) + return ( + + ) + })} +
+ {rating !== 0 && rating < 4 && ( +
+ +