Files
medusa-store/www/api-reference/components/Modal/index.tsx
Shahed Nasser f07dc0384f docs,api-ref: added search filters (#4830)
* initial implementation of search modal

* added hit and search suggestions

* added support for multiple indices

* updated sample env

* added close when click outside dropdown

* test for mobile

* added mobile design

* added shortcut

* dark mode fixes

* added search to docs

* added plugins filter

* added React import

* moved filters to configurations

* handled error on page load

* change suggestion text

* removed hits limit

* handle select all

* open link in current tab

* change highlight colors

* added support for shortcuts + auto focus

* change header and footer

* redesigned search ui
2023-08-24 18:36:06 +03:00

118 lines
3.1 KiB
TypeScript

import clsx from "clsx"
import React, { forwardRef, useCallback, useEffect, useRef } from "react"
import { ButtonProps } from "../Button"
import { useModal } from "../../providers/modal"
import ModalHeader from "./Header"
import ModalFooter from "./Footer"
import useKeyboardShortcut from "../../hooks/use-keyboard-shortcut"
export type ModalProps = {
className?: string
title?: string
actions?: ButtonProps[]
modalContainerClassName?: string
contentClassName?: string
onClose?: React.ReactEventHandler<HTMLDialogElement>
open?: boolean
footerContent?: React.ReactNode
} & Omit<React.ComponentProps<"dialog">, "ref">
const Modal = forwardRef<HTMLDialogElement, ModalProps>(function Modal(
{
className,
title,
actions,
children,
contentClassName,
modalContainerClassName,
onClose,
open = true,
footerContent,
...props
},
passedRef
) {
const { closeModal } = useModal()
const ref = useRef<HTMLDialogElement | null>(null)
const setRefs = useCallback(
(node: HTMLDialogElement) => {
// Ref's from useRef needs to have the node assigned to `current`
ref.current = node
if (typeof passedRef === "function") {
passedRef(node)
} else if (passedRef && "current" in passedRef) {
passedRef.current = node
}
},
[passedRef]
)
useKeyboardShortcut({
metakey: false,
checkEditing: false,
shortcutKeys: ["escape"],
action: () => {
if (open) {
ref.current?.close()
}
},
})
const handleClick = (e: React.MouseEvent<HTMLDialogElement, MouseEvent>) => {
// close modal when the user clicks outside the content
if (e.target === ref.current) {
closeModal()
onClose?.(e)
}
}
const handleClose = (e: React.SyntheticEvent<HTMLDialogElement, Event>) => {
onClose?.(e)
closeModal()
}
useEffect(() => {
if (open) {
document.body.setAttribute("data-modal", "opened")
} else {
document.body.removeAttribute("data-modal")
}
}, [open])
return (
<dialog
{...props}
className={clsx(
"fixed top-0 left-0 flex h-screen w-screen items-center justify-center",
"bg-medusa-bg-overlay dark:bg-medusa-bg-overlay-dark z-[500]",
"hidden open:flex",
className
)}
onClick={handleClick}
ref={setRefs}
onClose={handleClose}
open={open}
>
<div
className={clsx(
"bg-medusa-bg-base dark:bg-medusa-bg-base-dark rounded-sm",
"border-medusa-border-base dark:border-medusa-border-base-dark border border-solid",
"shadow-modal dark:shadow-modal-dark",
"w-[90%] md:h-auto md:w-[75%] lg:w-[560px]",
modalContainerClassName
)}
>
{title && <ModalHeader title={title} />}
<div className={clsx("overflow-auto py-1.5 px-2", contentClassName)}>
{children}
</div>
{actions && actions?.length > 0 && <ModalFooter actions={actions} />}
{footerContent && <ModalFooter>{footerContent}</ModalFooter>}
</div>
</dialog>
)
})
export default Modal