docs: documentation changes for release (#4300)

* docs: added manage reservations user guide (#4290)

* docs: added manage reservations user guide

* removed feature flag details

* docs: added how-to for custom reservations (#4292)

* docs: added how-to for custom reservations

* eslint fixes

* docs: added product module documentation (#4287)

* docs: added product module documentation

* added details about optional environment variables

* small fixes

* Remove reference link

* added example usages

* added link to sample project

* address PR feedback

* docs: moved product module guide + added product module tabs (#4307)

* added product module tab

* adjust design of badge

* docs: added onboarding features (#4168)

* added marketplace page

* added subscription roadmap

* added rating for onboarding

* added learning path components

* small fixes

* fix build error

* fix eslint errors

* change roadmaps to recipes

* small change in text

* optimize learning path and notifications

* fix tracking usage

* fix eslint errors

* added enter/exit animation

* allow starting a path using a query parameter

* fix gap between notifications

* address vercel comments

* fixed links issue

* changed create-medusa-app docs steps

* move troubleshooting section

* improved tracking across docs

* fix build errors

* remove console

* added a note about `boilerplate` option

* added troubleshooting section for eagain

* added invite option in cli reference

* added track event for finished onboarding

* update boilerplate option name

* redesigned learning path component

* docs: added how to create widget docs (#4318)

* docs: added how to create widget docs

* remove development guide

* added types

* docs: added details about createCustomAdminHooks (#4288)

* docs: added details about createCustomAdminHooks

* small improvement

* added missing import

* small changes

* docs: added onboarding guide (#4320)

* docs: added how to create widget docs

* remove development guide

* docs: added onboarding guide

* added types

* added recipes link

* small adjustments

* fixed eslint errors

* styling fixes

* change to singular product module

* updated the what's new section

* shorten down medusa react card

* updated tailwind configurations

* fix build error

* fix newspaper icon

* style fixes

* change modal shadow

* fix color of line numbers

* fix code fade color

* docs: updated admin documentations

* eslint fixes

* text changes

* added a note about beta version

* remove empty object argument

* remove demo repo url

* fix selection color for code headers

* general fixes

* fix eslint error

* changed code theme

* added preparation step

* changes regarding beta version

* Update docs/content/modules/products/serverless-module.md

Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>

* Update docs/content/modules/products/serverless-module.md

Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>

---------

Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>
Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Shahed Nasser
2023-06-20 13:25:22 +03:00
committed by GitHub
parent 8db03619b5
commit 76c4bf4acb
177 changed files with 8828 additions and 1196 deletions

View File

@@ -13,12 +13,21 @@ const Badge: React.FC<BadgeProps> = ({ className, variant, children }) => {
"tw-text-label-x-small-plus tw-py-px tw-px-0.4 tw-rounded tw-border tw-border-solid tw-text-center",
variant === "purple" &&
"tw-bg-medusa-tag-purple-bg dark:tw-bg-medusa-tag-purple-bg-dark tw-text-medusa-tag-purple-text dark:tw-text-medusa-tag-purple-text-dark tw-border-medusa-tag-purple-border dark:tw-border-medusa-tag-purple-border-dark",
variant === "purple-dark" &&
"tw-bg-medusa-tag-purple-bg-dark tw-text-medusa-tag-purple-text-dark tw-border-medusa-tag-purple-border-dark",
variant === "orange" &&
"tw-bg-medusa-tag-orange-bg dark:tw-bg-medusa-tag-orange-bg-dark tw-text-medusa-tag-orange-text dark:tw-text-medusa-tag-orange-text-dark tw-border-medusa-tag-orange-border dark:tw-border-medusa-tag-orange-border-dark",
variant === "orange-dark" &&
"tw-bg-medusa-tag-orange-bg-dark tw-text-medusa-tag-orange-text-dark tw-border-medusa-tag-orange-border-dark",
variant === "green" &&
"tw-bg-medusa-tag-green-bg dark:tw-bg-medusa-tag-green-bg-dark tw-text-medusa-tag-green-text dark:tw-text-medusa-tag-green-text-dark tw-border-medusa-tag-green-border dark:tw-border-medusa-tag-green-border-dark",
variant === "green-dark" &&
"tw-bg-medusa-tag-green-bg-dark tw-text-medusa-tag-green-text-dark tw-border-medusa-tag-green-border-dark",
variant === "blue" &&
"tw-bg-medusa-tag-blue-bg dark:tw-bg-medusa-tag-blue-bg-dark tw-text-medusa-tag-blue-text dark:tw-text-medusa-tag-blue-text-dark tw-border-medusa-tag-blue-border dark:tw-border-medusa-tag-blue-border-dark",
variant === "blue-dark" &&
"tw-bg-medusa-tag-blue-bg-dark tw-text-medusa-tag-blue-text-dark tw-border-medusa-tag-blue-border-dark",
"badge",
className
)}
>

View File

@@ -2,6 +2,7 @@ import React from "react"
import clsx from "clsx"
type ButtonProps = {
btnTypeClassName?: string
className?: string
onClick?: React.MouseEventHandler<HTMLButtonElement>
disabled?: boolean
@@ -9,13 +10,18 @@ type ButtonProps = {
const Button: React.FC<ButtonProps> = ({
className = "",
btnTypeClassName,
onClick,
children,
...props
}) => {
return (
<button
className={clsx("btn-primary", className)}
className={clsx(
!btnTypeClassName?.length && "btn-primary",
btnTypeClassName,
className
)}
onClick={onClick}
{...props}
>

View File

@@ -1,12 +1,12 @@
import React, { useRef, useState, useEffect } from "react"
import { CSSTransition, SwitchTransition } from "react-transition-group"
// import "./index.css"
import useIsBrowser from "@docusaurus/useIsBrowser"
import { useLocation } from "@docusaurus/router"
import uuid from "react-uuid"
import Solutions from "./Solutions/index"
import Button from "../Button"
import { useUser } from "@site/src/providers/User"
type FeedbackProps = {
event?: string
@@ -50,6 +50,7 @@ const Feedback: React.FC<FeedbackProps> = ({
const isBrowser = useIsBrowser()
const location = useLocation()
const { track } = useUser()
function handleFeedback(e) {
const feedback = e.target.classList.contains("positive")
@@ -60,35 +61,28 @@ const Feedback: React.FC<FeedbackProps> = ({
function submitFeedback(e, feedback = null) {
if (isBrowser) {
if (window.analytics) {
if (showForm) {
setLoading(true)
}
window.analytics.track(
event,
{
url: location.pathname,
label: document.title,
feedback:
(feedback !== null && feedback) ||
(feedback === null && positiveFeedback)
? "yes"
: "no",
message: message?.length ? message : null,
uuid: id,
},
function () {
if (showForm) {
setLoading(false)
resetForm()
}
}
)
} else {
if (showForm) {
resetForm()
}
if (showForm) {
setLoading(true)
}
track(
event,
{
url: location.pathname,
label: document.title,
feedback:
(feedback !== null && feedback) ||
(feedback === null && positiveFeedback)
? "yes"
: "no",
message: message?.length ? message : null,
},
function () {
if (showForm) {
setLoading(false)
resetForm()
}
}
)
}
}
@@ -110,7 +104,13 @@ const Feedback: React.FC<FeedbackProps> = ({
<div className={`tw-py-2 ${className}`}>
<SwitchTransition mode="out-in">
<CSSTransition
key={showForm}
key={
showForm
? "show_form"
: !submittedFeedback
? "feedback"
: "submitted_feedback"
}
nodeRef={nodeRef}
timeout={300}
addEndListener={(done) => {

View File

@@ -12,16 +12,16 @@ type SocialLinksProps = {
const SocialLinks: React.FC<SocialLinksProps> = ({ links = [] }) => {
const socialIcons = {
twitter: (
<IconTwitter iconColorClassName="tw-fill-medusa-icon-placeholder dark:tw-fill-medusa-icon-placeholder-dark group-hover:tw-fill-medusa-icon-secondary dark:group-hover:tw-fill-medusa-icon-secondary-dark" />
<IconTwitter iconColorClassName="tw-fill-medusa-icon-muted dark:tw-fill-medusa-icon-muted-dark group-hover:tw-fill-medusa-icon-subtle dark:group-hover:tw-fill-medusa-icon-subtle-dark" />
),
github: (
<IconGitHub iconColorClassName="tw-fill-medusa-icon-placeholder dark:tw-fill-medusa-icon-placeholder-dark group-hover:tw-fill-medusa-icon-secondary dark:group-hover:tw-fill-medusa-icon-secondary-dark" />
<IconGitHub iconColorClassName="tw-fill-medusa-icon-muted dark:tw-fill-medusa-icon-muted-dark group-hover:tw-fill-medusa-icon-subtle dark:group-hover:tw-fill-medusa-icon-subtle-dark" />
),
discord: (
<IconDiscord iconColorClassName="tw-fill-medusa-icon-placeholder dark:tw-fill-medusa-icon-placeholder-dark group-hover:tw-fill-medusa-icon-secondary dark:group-hover:tw-fill-medusa-icon-secondary-dark" />
<IconDiscord iconColorClassName="tw-fill-medusa-icon-muted dark:tw-fill-medusa-icon-muted-dark group-hover:tw-fill-medusa-icon-subtle dark:group-hover:tw-fill-medusa-icon-subtle-dark" />
),
linkedin: (
<IconLinkedIn iconColorClassName="tw-fill-medusa-icon-placeholder dark:tw-fill-medusa-icon-placeholder-dark group-hover:tw-fill-medusa-icon-secondary dark:group-hover:tw-fill-medusa-icon-secondary-dark" />
<IconLinkedIn iconColorClassName="tw-fill-medusa-icon-muted dark:tw-fill-medusa-icon-muted-dark group-hover:tw-fill-medusa-icon-subtle dark:group-hover:tw-fill-medusa-icon-subtle-dark" />
),
}

View File

@@ -12,8 +12,8 @@ type LargeCardProps = {
dark?: string
}
title: string
action: {
href: string
action?: {
href?: string
}
isSoon?: boolean
className?: string
@@ -23,7 +23,9 @@ const LargeCard: React.FC<LargeCardProps> = ({
Icon,
image,
title,
action: { href },
action: { href } = {
href: "",
},
isSoon = false,
className = "",
children,
@@ -38,6 +40,9 @@ const LargeCard: React.FC<LargeCardProps> = ({
"[&:nth-child(3n+1):before]:tw-bg-[2%_52%] [&:nth-child(3n+2):before]:tw-bg-[19%_16%] [&:nth-child(3n+3):before]:tw-bg-[17%_50%]",
!isSoon &&
"hover:tw-bg-medusa-bg-subtle-hover dark:hover:tw-bg-medusa-bg-base-hover-dark hover:tw-shadow-card-hover dark:hover:tw-shadow-card-hover-dark",
!isSoon &&
"group-hover:tw-bg-medusa-bg-subtle-hover dark:group-hover:tw-bg-medusa-bg-base-hover-dark group-hover:tw-shadow-card-hover dark:group-hover:tw-shadow-card-hover-dark",
"tw-transition-all tw-duration-200 tw-ease-ease",
"large-card",
className
)}
@@ -79,13 +84,15 @@ const LargeCard: React.FC<LargeCardProps> = ({
{children}
</div>
</div>
<Link
href={href}
className={clsx(
"tw-absolute tw-top-0 tw-left-0 tw-w-full tw-h-full tw-z-[4] tw-rounded",
isSoon && "group-hover:tw-pointer-events-none"
)}
></Link>
{href && (
<Link
href={href}
className={clsx(
"tw-absolute tw-top-0 tw-left-0 tw-w-full tw-h-full tw-z-[4] tw-rounded",
isSoon && "group-hover:tw-pointer-events-none"
)}
></Link>
)}
</article>
)
}

View File

@@ -0,0 +1,42 @@
import { LearningPathStepType } from "@site/src/providers/LearningPath"
import React from "react"
import Rating from "../../Rating"
export type LearningPathFinishType =
| {
type: "rating"
step: Omit<LearningPathStepType, "descriptionJSX"> & {
eventName?: string
}
}
| {
type: "custom"
step: LearningPathStepType & {
descriptionJSX: JSX.Element
}
}
type LearningPathFinishProps = LearningPathFinishType & {
onRating?: () => void
}
const LearningPathFinish: React.FC<LearningPathFinishProps> = ({
type,
step,
onRating,
}) => {
return (
<>
{type === "rating" && (
<Rating event={step.eventName} onRating={onRating} />
)}
{type === "custom" && (
<span className="tw-text-label-small tw-text-medusa-text-subtle dark:tw-text-medusa-text-subtle-dark">
{step.descriptionJSX}
</span>
)}
</>
)
}
export default LearningPathFinish

View File

@@ -0,0 +1,33 @@
import useBaseUrl from "@docusaurus/useBaseUrl"
import clsx from "clsx"
import React from "react"
type LearningPathIconProps = {
className?: string
imgClassName?: string
} & React.AllHTMLAttributes<HTMLDivElement>
const LearningPathIcon: React.FC<LearningPathIconProps> = ({
className = "",
imgClassName = "",
}) => {
return (
<div
className={clsx(
"tw-rounded-full tw-shadow-card-rest dark:tw-shadow-card-rest-dark tw-w-3 tw-h-3 tw-bg-button-neutral dark:tw-bg-button-neutral-dark",
"tw-flex tw-justify-center tw-items-center tw-flex-none",
className
)}
>
<img
src={useBaseUrl("/img/learning-path-img.png")}
className={clsx(
"tw-rounded-full tw-w-[40px] tw-h-[40px] no-zoom-img",
imgClassName
)}
/>
</div>
)
}
export default LearningPathIcon

View File

@@ -0,0 +1,41 @@
import Button from "@site/src/components/Button"
import { useLearningPath } from "@site/src/providers/LearningPath"
import React from "react"
type LearningPathStepActionsType = {
onFinish?: () => void
onClose?: () => void
} & React.AllHTMLAttributes<HTMLDivElement>
const LearningPathStepActions: React.FC<LearningPathStepActionsType> = ({
onFinish,
onClose,
}) => {
const { hasNextStep, nextStep, endPath } = useLearningPath()
const handleFinish = () => {
if (onFinish) {
onFinish()
} else {
endPath()
}
}
return (
<div className="tw-flex tw-gap-0.5 tw-p-1 tw-justify-end tw-items-center">
<Button onClick={onClose}>Close</Button>
{hasNextStep() && (
<Button onClick={nextStep} btnTypeClassName="btn-inverted">
Next
</Button>
)}
{!hasNextStep() && (
<Button onClick={handleFinish} btnTypeClassName="btn-inverted">
Finish
</Button>
)}
</div>
)
}
export default LearningPathStepActions

View File

@@ -0,0 +1,84 @@
import { useLearningPath } from "@site/src/providers/LearningPath"
import React from "react"
import LearningPathStepActions from "./Actions"
import clsx from "clsx"
import IconCircleDottedLine from "@site/src/theme/Icon/CircleDottedLine"
import IconCheckCircleSolid from "@site/src/theme/Icon/CheckCircleSolid"
import IconCircleMiniSolid from "@site/src/theme/Icon/CircleMiniSolid"
import Link from "@docusaurus/Link"
type LearningPathStepsProps = {
onFinish?: () => void
onClose?: () => void
}
const LearningPathSteps: React.FC<LearningPathStepsProps> = ({ ...rest }) => {
const { path, currentStep, goToStep } = useLearningPath()
if (!path) {
return <></>
}
return (
<div>
{path.steps.map((step, index) => (
<div
className={clsx(
"tw-border-0 tw-border-b tw-border-solid tw-border-medusa-border-base dark:tw-border-medusa-border-base-dark",
"tw-relative tw-p-1"
)}
key={index}
>
<div className={clsx("tw-flex tw-items-center tw-gap-1")}>
<div className="tw-w-2 tw-flex-none tw-flex tw-items-center tw-justify-center">
{index === currentStep && (
<IconCircleDottedLine
className="tw-shadow-active dark:tw-shadow-active-dark tw-rounded-full"
iconColorClassName="tw-stroke-medusa-icon-interactive dark:tw-stroke-medusa-icon-interactive-dark"
/>
)}
{index < currentStep && (
<IconCheckCircleSolid iconColorClassName="tw-fill-medusa-icon-interactive dark:tw-fill-medusa-icon-interactive-dark" />
)}
{index > currentStep && <IconCircleMiniSolid />}
</div>
<span
className={clsx(
"tw-text-label-regular-plus tw-text-medusa-text-base dark:tw-text-medusa-text-base-dark"
)}
>
{step.title}
</span>
</div>
{index === currentStep && (
<div className={clsx("tw-flex tw-items-center tw-gap-1")}>
<div className="tw-w-2 tw-flex-none"></div>
<div
className={clsx(
"tw-text-body-regular tw-text-medusa-text-subtle dark:tw-text-medusa-text-subtle-dark tw-mt-1"
)}
>
{step.descriptionJSX ?? step.description}
</div>
</div>
)}
{index < currentStep && (
<Link
href={step.path}
className={clsx(
"tw-absolute tw-top-0 tw-left-0 tw-w-full tw-h-full"
)}
onClick={(e) => {
e.preventDefault()
goToStep(index)
}}
/>
)}
</div>
))}
<LearningPathStepActions {...rest} />
</div>
)
}
export default LearningPathSteps

View File

@@ -0,0 +1,96 @@
import { useLearningPath } from "@site/src/providers/LearningPath"
import { useNotifications } from "@site/src/providers/NotificationProvider"
import { getLearningPath } from "@site/src/utils/learning-paths"
import clsx from "clsx"
import React from "react"
import useBaseUrl from "@docusaurus/useBaseUrl"
import Button from "../Button"
import IconCircleMiniSolid from "@site/src/theme/Icon/CircleMiniSolid"
import LearningPathIcon from "./Icon"
type LearningPathProps = {
pathName: string
className?: string
} & React.AllHTMLAttributes<HTMLDivElement>
const LearningPath: React.FC<LearningPathProps> = ({
pathName,
className = "",
}) => {
const path = getLearningPath(pathName)
if (!path) {
throw new Error("Learning path does not exist.")
}
const { startPath, path: currentPath } = useLearningPath()
const notificationContext = useNotifications()
const handleClick = () => {
if (notificationContext && currentPath?.notificationId) {
notificationContext.removeNotification(currentPath.notificationId)
}
startPath(path)
}
return (
<div
className={clsx(
"tw-rounded tw-shadow-card-rest dark:tw-shadow-card-rest-dark tw-bg-docs-bg-surface dark:tw-bg-docs-bg-surface-dark tw-mt-1.5 tw-mb-4",
className
)}
>
<div
className={clsx(
"tw-flex tw-items-center tw-gap-1 tw-p-1 tw-border-0 tw-border-b tw-border-solid tw-border-medusa-border-base dark:tw-border-medusa-border-base-dark"
)}
>
<LearningPathIcon />
<div className={clsx("tw-flex-auto")}>
<span
className={clsx(
"tw-text-medusa-text-base dark:tw-text-medusa-text-base-dark tw-text-label-large-plus tw-block"
)}
>
{path.label}
</span>
{path.description && (
<span
className={clsx(
"tw-text-medusa-text-subtle dark:tw-text-medusa-text-subtle-dark tw-text-label-regular tw-mt-[4px] tw-inline-block"
)}
>
{path.description}
</span>
)}
</div>
<Button onClick={handleClick} className={clsx("tw-flex-initial")}>
Start Path
</Button>
</div>
{path.steps.map((step, index) => (
<div
className={clsx(
"tw-flex tw-items-center tw-p-1 tw-gap-1",
index !== path.steps.length - 1 &&
"tw-border-0 tw-border-b tw-border-solid tw-border-medusa-border-base dark:tw-border-medusa-border-base-dark"
)}
key={index}
>
<div
className={clsx("tw-w-3 tw-flex tw-items-center tw-justify-center")}
>
<IconCircleMiniSolid iconColorClassName="tw-stroke-medusa-icon-muted dark:tw-stroke-medusa-icon-muted-dark" />
</div>
<span
className={clsx(
"tw-text-medusa-text-base dark:tw-text-medusa-text-base-dark tw-text-label-regular-plus"
)}
>
{step.title}
</span>
</div>
))}
</div>
)
}
export default LearningPath

View File

@@ -0,0 +1,61 @@
import {
NotificationItemType,
useNotifications,
} from "@site/src/providers/NotificationProvider"
import React from "react"
import NotificationItem from "../Item"
import { CSSTransition, TransitionGroup } from "react-transition-group"
import clsx from "clsx"
const NotificationContainer = () => {
const { notifications, removeNotification } = useNotifications()
const handleClose = (notification: NotificationItemType) => {
notification.onClose?.()
removeNotification(notification.id)
}
const renderFilteredNotifications = (
condition: (notificaiton: NotificationItemType) => boolean,
className?: string
) => {
return (
<TransitionGroup className={className}>
{notifications.filter(condition).map((notification) => (
<CSSTransition
key={notification.id}
timeout={200}
classNames={{
enter: "animate__animated animate__slideInRight animate__fastest",
exit: "animate__animated animate__slideOutRight animate__fastest",
}}
>
<NotificationItem
{...notification}
onClose={() => handleClose(notification)}
className={clsx(
notification.className,
"!tw-relative !tw-top-0 !tw-bottom-0 !tw-right-0"
)}
/>
</CSSTransition>
))}
</TransitionGroup>
)
}
return (
<>
{renderFilteredNotifications(
(notification) => notification.placement === "top",
"tw-flex tw-fixed tw-flex-col tw-gap-0.5 md:tw-right-1 tw-right-0 md:tw-top-1 tw-top-0 tw-z-[400] md:tw-w-auto tw-w-full"
)}
{renderFilteredNotifications(
(notification) => notification.placement !== "top",
"tw-flex tw-flex-col tw-gap-0.5 tw-fixed md:tw-right-1 tw-right-0 md:tw-bottom-1 tw-bottom-0 tw-z-[400] md:tw-w-auto tw-w-full"
)}
</>
)
}
export default NotificationContainer

View File

@@ -0,0 +1,90 @@
import React from "react"
import { NotificationItemProps } from "../.."
import clsx from "clsx"
import IconInformationCircleSolid from "@site/src/theme/Icon/InformationCircleSolid"
import IconXCircleSolid from "@site/src/theme/Icon/XCircleSolid"
import IconExclamationCircleSolid from "@site/src/theme/Icon/ExclamationCircleSolid"
import IconCheckCircleSolid from "@site/src/theme/Icon/CheckCircleSolid"
import Button from "@site/src/components/Button"
type NotificationItemLayoutDefaultProps = NotificationItemProps & {
handleClose: () => void
}
const NotificationItemLayoutDefault: React.FC<
NotificationItemLayoutDefaultProps
> = ({
type = "info",
title = "",
text = "",
children,
isClosable = true,
handleClose,
CustomIcon,
}) => {
return (
<>
<div className={clsx("tw-flex tw-gap-1 tw-p-1")}>
{type !== "none" && (
<div
className={clsx(
type !== "custom" &&
"tw-w-2 tw-flex tw-justify-center tw-items-center"
)}
>
{type === "info" && (
<IconInformationCircleSolid iconColorClassName="tw-fill-medusa-support-info dark:tw-fill-medusa-support-info-dark" />
)}
{type === "error" && (
<IconXCircleSolid iconColorClassName="tw-fill-medusa-tag-red-icon dark:tw-fill-medusa-tag-red-icon-dark" />
)}
{type === "warning" && (
<IconExclamationCircleSolid iconColorClassName="tw-fill-medusa-tag-orange-icon dark:tw-fill-medusa-tag-orange-icon-dark" />
)}
{type === "success" && (
<IconCheckCircleSolid iconColorClassName="tw-fill-medusa-tag-green-icon dark:tw-fill-medusa-tag-green-icon-dark" />
)}
{type === "custom" && CustomIcon}
</div>
)}
<span
className={clsx(
"tw-text-label-regular-plus",
"tw-text-medusa-text-base dark:tw-text-medusa-text-base-dark"
)}
>
{title}
</span>
</div>
{(text || children) && (
<div
className={clsx(
"tw-flex tw-pt-0 tw-pr-1 tw-pb-1.5 tw-pl-1 tw-gap-1",
"tw-border-0 tw-border-b tw-border-solid tw-border-medusa-border-base dark:tw-border-medusa-border-base-dark"
)}
>
<div className="tw-w-2 tw-flex-none"></div>
<div className={clsx("tw-flex tw-flex-col", children && "tw-gap-1")}>
{text && (
<span
className={clsx(
"tw-text-body-regular tw-text-medusa-text-subtle dark:tw-text-medusa-text-subtle-dark"
)}
>
{text}
</span>
)}
{children}
</div>
</div>
)}
{isClosable && (
<div className={clsx("tw-p-1 tw-flex tw-justify-end tw-items-center")}>
<Button onClick={handleClose}>Close</Button>
</div>
)}
</>
)
}
export default NotificationItemLayoutDefault

View File

@@ -0,0 +1,63 @@
import clsx from "clsx"
import React, { Children, ReactElement, useEffect, useRef } from "react"
import NotificationItemLayoutDefault from "./Layout/Default"
export type NotificationItemProps = {
layout?: "default" | "empty"
type?: "info" | "error" | "warning" | "success" | "custom" | "none"
CustomIcon?: React.ReactNode
title?: string
text?: string
className?: string
children?: ReactElement
isClosable?: boolean
placement?: "top" | "bottom"
show?: boolean
setShow?: (value: boolean) => void
onClose?: () => void
} & React.HTMLAttributes<HTMLDivElement>
const Notification = ({
className = "",
placement = "bottom",
show = true,
layout = "default",
setShow,
onClose,
children,
...rest
}: NotificationItemProps) => {
const handleClose = () => {
setShow?.(false)
onClose?.()
}
return (
<div
className={clsx(
"md:tw-max-w-[320px] md:tw-w-[320px] tw-w-full tw-bg-medusa-bg-base dark:tw-bg-medusa-bg-base-dark tw-rounded",
"tw-shadow-flyout dark:tw-shadow-flyout-dark",
"tw-fixed md:tw-right-1 tw-left-0 tw-block tw-z-[400]",
placement === "bottom" && "md:tw-bottom-1 tw-bottom-0",
placement === "top" && "md:tw-top-1 tw-top-0",
"tw-opacity-100 tw-transition-opacity tw-duration-200 tw-ease-ease",
!show && "!tw-opacity-0",
className
)}
>
{layout === "default" && (
<NotificationItemLayoutDefault {...rest} handleClose={handleClose}>
{children}
</NotificationItemLayoutDefault>
)}
{layout === "empty" &&
Children.map(children, (child) =>
React.cloneElement(child, {
onClose: handleClose,
})
)}
</div>
)
}
export default Notification

View File

@@ -0,0 +1,80 @@
import { useUser } from "@site/src/providers/User"
import IconStar from "@site/src/theme/Icon/Star"
import IconStarSolid from "@site/src/theme/Icon/StarSolid"
import clsx from "clsx"
import React, { useRef, useState } from "react"
type RatingProps = {
event?: string
className?: string
onRating?: () => void
} & React.HTMLAttributes<HTMLDivElement>
const Rating: React.FC<RatingProps> = ({
event = "rating",
className = "",
onRating,
}) => {
const [rating, setRating] = useState(0)
const [hoverRating, setHoverRating] = useState(0)
const starElms = useRef<HTMLElement[]>([])
const starArr = Array.from(Array(5).keys())
const { track } = useUser()
const handleRating = (selectedRating: number) => {
if (rating) {
return
}
setHoverRating(0)
setRating(selectedRating)
for (let i = 0; i < selectedRating; i++) {
starElms.current[i].classList.add("animate__animated", "animate__tada")
}
track(
event,
{
rating: selectedRating,
},
() => onRating?.()
)
}
return (
<div className={clsx("tw-flex tw-gap-0.5", className)}>
{starArr.map((i) => {
const isSelected =
(rating !== 0 && rating - 1 >= i) ||
(hoverRating !== 0 && hoverRating - 1 >= i)
return (
<button
className="transparent-button"
ref={(element) => {
if (starElms.current.length - 1 < i) {
starElms.current.push(element)
}
}}
key={i}
onMouseOver={() => {
if (!rating) {
setHoverRating(i + 1)
}
}}
onMouseLeave={() => {
if (!rating) {
setHoverRating(0)
}
}}
onClick={() => handleRating(i + 1)}
>
{!isSelected && <IconStar />}
{isSelected && (
<IconStarSolid iconColorClassName="tw-fill-medusa-tag-orange-icon dark:tw-fill-medusa-tag-orange-icon-dark" />
)}
</button>
)
})}
</div>
)
}
export default Rating