docs: redesign search + re-introduce ai assistant in v2 docs (#8678)

* docs: redesign search + re-introduce ai assistant in v2

* change version in ui

* show icon in case of error

* fixes based on feedback
This commit is contained in:
Shahed Nasser
2024-08-23 10:42:37 +03:00
committed by GitHub
parent c63a08fb03
commit 320b01f45d
23 changed files with 553 additions and 347 deletions

View File

@@ -4,6 +4,8 @@ import {
usePageLoading,
SearchProvider as UiSearchProvider,
searchFiltersV2,
AiAssistantIcon,
AiAssistantProvider,
} from "docs-ui"
import { config } from "../config"
import basePathUrl from "../utils/base-path-url"
@@ -33,15 +35,14 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
items: [
"Install Medusa with create-medusa-app",
"What is an API route?",
"What is a Module?",
"What is a Workflow?",
],
},
{
title: "Developing with Medusa",
items: [
"How to create a Module",
"How to create an API route",
"How to create a module",
"How to create a data model",
"How to create an admin widget",
],
@@ -52,6 +53,28 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
),
filterOptions: searchFiltersV2,
}}
commands={[
{
name: "ai-assistant",
icon: <AiAssistantIcon />,
component: (
<AiAssistantProvider
apiUrl={process.env.NEXT_PUBLIC_AI_ASSISTANT_URL || "temp"}
websiteId={process.env.NEXT_PUBLIC_AI_WEBSITE_ID || "temp"}
recaptchaSiteKey={
process.env.NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY ||
"temp"
}
/>
),
title: "AI Assistant",
badge: {
variant: "blue",
badgeType: "shaded",
children: "Beta",
},
},
]}
>
{children}
</UiSearchProvider>

View File

@@ -1,6 +1,11 @@
"use client"
import { SearchProvider as UiSearchProvider, searchFiltersV2 } from "docs-ui"
import {
AiAssistantIcon,
AiAssistantProvider,
SearchProvider as UiSearchProvider,
searchFiltersV2,
} from "docs-ui"
import { config } from "../config"
type SearchProviderProps = {
@@ -47,6 +52,28 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
),
filterOptions: searchFiltersV2,
}}
commands={[
{
name: "ai-assistant",
icon: <AiAssistantIcon />,
component: (
<AiAssistantProvider
apiUrl={process.env.NEXT_PUBLIC_AI_ASSISTANT_URL || "temp"}
websiteId={process.env.NEXT_PUBLIC_AI_WEBSITE_ID || "temp"}
recaptchaSiteKey={
process.env.NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY ||
"temp"
}
/>
),
title: "AI Assistant",
badge: {
variant: "blue",
badgeType: "shaded",
children: "Beta",
},
},
]}
initialDefaultFilters={["book"]}
>
{children}

View File

@@ -1,6 +1,11 @@
"use client"
import { SearchProvider as UiSearchProvider, searchFiltersV2 } from "docs-ui"
import {
AiAssistantIcon,
AiAssistantProvider,
SearchProvider as UiSearchProvider,
searchFiltersV2,
} from "docs-ui"
import { config } from "../config"
type SearchProviderProps = {
@@ -28,15 +33,36 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
items: [
"Medusa Configurations",
"Commerce Modules",
"Medusa JS Reference",
"Medusa React Reference",
"Workflows API Reference",
"Medusa Workflows Reference",
"Storefront Development",
],
},
],
checkInternalPattern: new RegExp(`^${config.baseUrl}/v2/resources/.*`),
filterOptions: searchFiltersV2,
}}
commands={[
{
name: "ai-assistant",
icon: <AiAssistantIcon />,
component: (
<AiAssistantProvider
apiUrl={process.env.NEXT_PUBLIC_AI_ASSISTANT_URL || "temp"}
websiteId={process.env.NEXT_PUBLIC_AI_WEBSITE_ID || "temp"}
recaptchaSiteKey={
process.env.NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY ||
"temp"
}
/>
),
title: "AI Assistant",
badge: {
variant: "blue",
badgeType: "shaded",
children: "Beta",
},
},
]}
initialDefaultFilters={["resources"]}
>
{children}

View File

@@ -49,6 +49,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
process.env.NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY ||
"temp"
}
version="v1"
/>
),
title: "AI Assistant",

View File

@@ -1,13 +1,8 @@
import React, { useState } from "react"
import { ThreadType } from "../.."
import clsx from "clsx"
import {
Button,
type ButtonProps,
ThumbDownIcon,
ThumbUpIcon,
} from "@/components"
import { Check, SquareTwoStack } from "@medusajs/icons"
import { Button, type ButtonProps } from "@/components"
import { Check, SquareTwoStackMini, ThumbDown, ThumbUp } from "@medusajs/icons"
import { useCopy } from "@/hooks"
import { AiAssistantFeedbackType, useAiAssistant } from "@/providers"
@@ -43,21 +38,17 @@ export const AiAssistantThreadItemActions = ({
return (
<div
className={clsx(
"hidden md:flex gap-docs_0.25",
"text-medusa-fg-muted",
"sticky top-docs_1"
)}
className={clsx("hidden md:flex gap-docs_0.25", "text-medusa-fg-muted")}
>
<ActionButton onClick={handleCopy}>
{isCopied ? <Check /> : <SquareTwoStack />}
{isCopied ? <Check /> : <SquareTwoStackMini />}
</ActionButton>
{(feedback === null || feedback === "upvote") && (
<ActionButton
onClick={async () => handleFeedback("upvote", item.question_id)}
className={clsx(feedback === "upvote" && "!text-medusa-fg-subtle")}
>
<ThumbUpIcon />
<ThumbUp />
</ActionButton>
)}
{(feedback === null || feedback === "downvote") && (
@@ -65,7 +56,7 @@ export const AiAssistantThreadItemActions = ({
onClick={async () => handleFeedback("downvote", item.question_id)}
className={clsx(feedback === "downvote" && "!text-medusa-fg-subtle")}
>
<ThumbDownIcon />
<ThumbDown />
</ActionButton>
)}
</div>
@@ -79,7 +70,7 @@ const ActionButton = ({ children, className, ...props }: ButtonProps) => {
className={clsx(
"text-medusa-fg-muted hover:text-medusa-fg-subtle",
"hover:bg-medusa-bg-subtle-hover",
"p-docs_0.125 rounded-docs_sm",
"!p-[4.5px] rounded-docs_sm",
className
)}
{...props}

View File

@@ -1,8 +1,7 @@
import clsx from "clsx"
import React from "react"
import { ThreadType } from ".."
import { DotsLoading, MarkdownContent, QuestionMarkIcon } from "@/components"
import { ExclamationCircle, Sparkles } from "@medusajs/icons"
import { AiAssistantIcon, DotsLoading, MarkdownContent } from "@/components"
import { AiAssistantThreadItemActions } from "./Actions"
export type AiAssistantThreadItemProps = {
@@ -13,39 +12,37 @@ export const AiAssistantThreadItem = ({ item }: AiAssistantThreadItemProps) => {
return (
<div
className={clsx(
"p-docs_1 flex justify-start gap-docs_1 items-start",
"text-medusa-fg-subtle border-solid border-0 border-b",
"border-medusa-border-base text-medium relative",
item.type === "question" && "bg-medusa-bg-base",
item.type === "answer" && "bg-medusa-bg-subtle"
"p-docs_0.5 flex gap-docs_0.75 items-start",
item.type === "question" && "justify-end",
item.type === "answer" && "!pr-[20px]"
)}
>
<span
{item.type !== "question" && <AiAssistantIcon />}
<div
className={clsx(
"border border-solid border-medusa-border-base",
"rounded-docs_sm p-docs_0.125 bg-medusa-bg-component",
"text-medusa-fg-muted flex"
"txt-small text-medusa-fg-subtle",
item.type === "question" && [
"rounded-docs_xl bg-medusa-tag-neutral-bg",
"px-docs_0.75 py-docs_0.5",
],
item.type !== "question" && "flex-1",
item.type === "answer" && "text-pretty"
)}
>
{item.type === "question" && <QuestionMarkIcon />}
{item.type === "answer" && <Sparkles />}
{item.type === "error" && <ExclamationCircle />}
</span>
<div className="md:max-w-[calc(100%-134px)] md:w-[calc(100%-134px)]">
{item.type === "question" && <>{item.content}</>}
{item.type === "answer" && (
<>
<div className="flex flex-col gap-docs_0.75">
{!item.question_id && item.content.length === 0 && <DotsLoading />}
<MarkdownContent>{item.content}</MarkdownContent>
</>
<MarkdownContent className="[&>*:last-child]:mb-0">
{item.content}
</MarkdownContent>
{item.question_id && <AiAssistantThreadItemActions item={item} />}
</div>
)}
{item.type === "error" && (
<span className="text-medusa-fg-error">{item.content}</span>
)}
</div>
{item.type === "answer" && item.question_id && (
<AiAssistantThreadItemActions item={item} />
)}
</div>
)
}

View File

@@ -11,10 +11,9 @@ import {
SearchHitGroupName,
Tooltip,
Link,
AiAssistantIcon,
} from "@/components"
import { useAiAssistant, useSearch } from "@/providers"
import { ArrowUturnLeft, XMarkMini } from "@medusajs/icons"
import { ArrowUturnLeft } from "@medusajs/icons"
import clsx from "clsx"
import { useSearchNavigation } from "@/hooks"
import { AiAssistantThreadItem } from "./ThreadItem"
@@ -77,26 +76,50 @@ export const AiAssistant = () => {
const [answer, setAnswer] = useState("")
const [identifiers, setIdentifiers] = useState<IdentifierType | null>(null)
const [loading, setLoading] = useState(false)
const { getAnswer } = useAiAssistant()
const { getAnswer, version } = useAiAssistant()
const { setCommand } = useSearch()
const inputRef = useRef<HTMLInputElement>(null)
const contentRef = useRef<HTMLDivElement>(null)
const suggestions: SearchSuggestionType[] = [
{
title: "FAQ",
items: [
"What is Medusa?",
"How can I create an ecommerce store with Medusa?",
"How can I build a marketplace with Medusa?",
"How can I build subscription-based purchases with Medusa?",
"How can I build digital products with Medusa?",
"What can I build with Medusa?",
"What is Medusa Admin?",
"How do I configure the database in Medusa?",
],
},
]
const suggestions: SearchSuggestionType[] = useMemo(() => {
return version === "v2"
? [
{
title: "FAQ",
items: [
"What is Medusa?",
"How can I create a module?",
"How can I create a data model?",
"How do I create a workflow?",
"How can I extend a data model in the Product Module?",
],
},
{
title: "Recipes",
items: [
"How do I build a marketplace with Medusa?",
"How do I build digital products with Medusa?",
"How do I build subscription-based purchases with Medusa?",
"What other recipes are available in the Medusa documentation?",
],
},
]
: [
{
title: "FAQ",
items: [
"What is Medusa?",
"How can I create an ecommerce store with Medusa?",
"How can I build a marketplace with Medusa?",
"How can I build subscription-based purchases with Medusa?",
"How can I build digital products with Medusa?",
"What can I build with Medusa?",
"What is Medusa Admin?",
"How do I configure the database in Medusa?",
],
},
]
}, [version])
const handleSubmit = (selectedQuestion?: string) => {
if (!selectedQuestion?.length && !question.length) {
@@ -292,6 +315,22 @@ export const AiAssistant = () => {
return (
<div className="h-full">
<div className={clsx("px-docs_1 pt-docs_1")}>
<Tooltip
tooltipChildren={
<>
This site is protected by reCAPTCHA and the{" "}
<Link href="https://policies.google.com/privacy">
Google Privacy Policy
</Link>{" "}
and <Link href="https://policies.google.com/terms">ToS</Link>{" "}
apply
</>
}
>
<Badge variant="neutral">AI Assistant</Badge>
</Tooltip>
</div>
<div
className={clsx(
"flex gap-docs_1 px-docs_1 py-docs_0.75",
@@ -302,7 +341,7 @@ export const AiAssistant = () => {
<Button
variant="transparent"
onClick={() => setCommand(null)}
className="text-medusa-fg-subtle p-[5px]"
className="text-medusa-fg-muted p-[6.5px]"
>
<ArrowUturnLeft />
</Button>
@@ -311,7 +350,7 @@ export const AiAssistant = () => {
onChange={(e) => setQuestion(e.target.value)}
className={clsx(
"bg-transparent border-0 focus:outline-none hover:!bg-transparent",
"shadow-none flex-1 text-medusa-fg-base",
"!shadow-none flex-1 text-medusa-fg-base",
"disabled:!bg-transparent disabled:cursor-not-allowed"
)}
placeholder="Ask me a question about Medusa..."
@@ -319,23 +358,22 @@ export const AiAssistant = () => {
passedRef={inputRef}
disabled={loading}
/>
<Button
variant="transparent"
<span
onClick={() => {
setQuestion("")
inputRef.current?.focus()
}}
className={clsx(
"text-medusa-fg-subtle p-[5px]",
"text-medusa-fg-muted hover:text-medusa-fg-subtle",
"absolute top-docs_0.75 right-docs_1",
"hover:bg-medusa-bg-base-hover rounded-docs_sm",
"cursor-pointer",
question.length === 0 && "hidden"
)}
>
<XMarkMini />
</Button>
Clear
</span>
</div>
<div className="h-[calc(100%-120px)] md:h-[calc(100%-114px)] lg:max-h-[calc(100%-114px)] lg:min-h-[calc(100%-114px)] overflow-auto">
<div className="h-[calc(100%-95px)] lg:max-h-[calc(100%-140px)] lg:min-h-[calc(100%-140px)] overflow-auto">
<div ref={contentRef}>
{!thread.length && (
<div className="mx-docs_0.5">
@@ -372,35 +410,12 @@ export const AiAssistant = () => {
</div>
<div
className={clsx(
"py-docs_0.75 flex items-center justify-between px-docs_1",
"border-0 border-solid",
"py-docs_0.75 hidden md:flex items-center justify-end px-docs_1",
"border-medusa-border-base border-t",
"bg-medusa-bg-base h-[57px]"
"bg-medusa-bg-field-component"
)}
>
<Tooltip
tooltipChildren={
<>
This site is protected by reCAPTCHA and the{" "}
<Link href="https://policies.google.com/privacy">
Google Privacy Policy
</Link>{" "}
and <Link href="https://policies.google.com/terms">ToS</Link>{" "}
apply
</>
}
>
<div
className={clsx(
"flex items-center gap-docs_0.75 text-compact-small-plus"
)}
>
<AiAssistantIcon />
<span className="text-medusa-fg-subtle">Medusa AI Assistant</span>
<Badge variant="purple">Beta</Badge>
</div>
</Tooltip>
<div className="hidden items-center gap-docs_1 md:flex">
<div className="flex items-center gap-docs_0.75">
<div className="flex items-center gap-docs_0.5">
{thread.length === 0 && (
<>
@@ -412,9 +427,23 @@ export const AiAssistant = () => {
>
Navigate FAQ
</span>
<span className="gap-docs_0.25 flex">
<Kbd></Kbd>
<Kbd></Kbd>
<span className="gap-[5px] flex">
<Kbd
className={clsx(
"!bg-medusa-bg-field-component !border-medusa-border-strong",
"!text-medusa-fg-subtle h-[18px] w-[18px] p-0"
)}
>
</Kbd>
<Kbd
className={clsx(
"!bg-medusa-bg-field-component !border-medusa-border-strong",
"!text-medusa-fg-subtle h-[18px] w-[18px] p-0"
)}
>
</Kbd>
</span>
</>
)}
@@ -426,13 +455,23 @@ export const AiAssistant = () => {
</span>
)}
</div>
<div
className={clsx("h-docs_0.75 w-px bg-medusa-border-strong")}
></div>
<div className="flex items-center gap-docs_0.5">
<span
className={clsx("text-medusa-fg-subtle", "text-compact-x-small")}
>
Ask Question
</span>
<Kbd></Kbd>
<Kbd
className={clsx(
"!bg-medusa-bg-field-component !border-medusa-border-strong",
"!text-medusa-fg-subtle h-[18px] w-[18px] p-0"
)}
>
</Kbd>
</div>
</div>
</div>

View File

@@ -11,27 +11,38 @@ export const AiAssistantIcon = (props: IconProps) => {
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g filter="url(#filter0_diii_7480_20594)">
<g filter="url(#filter0_diii_10448_46450)">
<circle
cx="9.5"
cy="9.00002"
cx="9.50002"
cy="8.99989"
r="7.11"
fill="url(#paint0_linear_7480_20594)"
fill="url(#paint0_linear_10448_46450)"
/>
<circle
cx="9.5"
cy="9.00002"
cx="9.50002"
cy="8.99989"
r="7.11"
fill="url(#paint1_linear_7480_20594)"
fill="url(#paint1_linear_10448_46450)"
/>
</g>
<g filter="url(#filter1_f_7480_20594)">
<circle cx="9.5" cy="6.5" r="4" fill="url(#paint2_linear_7480_20594)" />
<g
style={{
mixBlendMode: "plus-lighter",
}}
opacity="0.8"
filter="url(#filter1_f_10448_46450)"
>
<circle
cx="9.5"
cy="6.5"
r="4"
fill="url(#paint2_linear_10448_46450)"
/>
<circle
cx="9.5"
cy="6.5"
r="3.9"
stroke="url(#paint3_linear_7480_20594)"
stroke="url(#paint3_linear_10448_46450)"
strokeWidth="0.2"
/>
</g>
@@ -39,14 +50,15 @@ export const AiAssistantIcon = (props: IconProps) => {
style={{
mixBlendMode: "plus-lighter",
}}
filter="url(#filter2_f_7480_20594)"
opacity="0.8"
filter="url(#filter2_f_10448_46450)"
>
<circle cx="12" cy="10" r="4" fill="url(#paint4_linear_7480_20594)" />
<circle cx="12" cy="10" r="4" fill="url(#paint4_linear_10448_46450)" />
<circle
cx="12"
cy="10"
r="3.9"
stroke="url(#paint5_linear_7480_20594)"
stroke="url(#paint5_linear_10448_46450)"
strokeWidth="0.2"
/>
</g>
@@ -54,21 +66,22 @@ export const AiAssistantIcon = (props: IconProps) => {
style={{
mixBlendMode: "plus-lighter",
}}
filter="url(#filter3_f_7480_20594)"
opacity="0.8"
filter="url(#filter3_f_10448_46450)"
>
<circle
cx="4"
cy="4"
r="4"
transform="matrix(-1 0 0 1 11 4)"
fill="url(#paint6_linear_7480_20594)"
fill="url(#paint6_linear_10448_46450)"
/>
<circle
cx="4"
cy="4"
r="3.9"
transform="matrix(-1 0 0 1 11 4)"
stroke="url(#paint7_linear_7480_20594)"
stroke="url(#paint7_linear_10448_46450)"
strokeWidth="0.2"
/>
</g>
@@ -76,46 +89,53 @@ export const AiAssistantIcon = (props: IconProps) => {
style={{
mixBlendMode: "plus-lighter",
}}
filter="url(#filter4_f_7480_20594)"
opacity="0.8"
filter="url(#filter4_f_10448_46450)"
>
<circle
cx="4"
cy="4"
r="4"
transform="matrix(0 -1 -1 0 13.5 13)"
fill="url(#paint8_linear_7480_20594)"
fill="url(#paint8_linear_10448_46450)"
/>
<circle
cx="4"
cy="4"
r="3.9"
transform="matrix(0 -1 -1 0 13.5 13)"
stroke="url(#paint9_linear_7480_20594)"
stroke="url(#paint9_linear_10448_46450)"
strokeWidth="0.2"
/>
</g>
<g filter="url(#filter5_f_7480_20594)">
<g
style={{
mixBlendMode: "plus-lighter",
}}
opacity="0.8"
filter="url(#filter5_f_10448_46450)"
>
<circle
cx="4"
cy="4"
r="4"
transform="matrix(-1 0 0 1 13.5 7.5)"
fill="url(#paint10_linear_7480_20594)"
fill="url(#paint10_linear_10448_46450)"
/>
<circle
cx="4"
cy="4"
r="3.9"
transform="matrix(-1 0 0 1 13.5 7.5)"
stroke="url(#paint11_linear_7480_20594)"
stroke="url(#paint11_linear_10448_46450)"
strokeWidth="0.2"
/>
</g>
<defs>
<filter
id="filter0_diii_7480_20594"
x="0.389999"
y="0.890015"
id="filter0_diii_10448_46450"
x="0.390015"
y="0.889893"
width="18.22"
height="18.22"
filterUnits="userSpaceOnUse"
@@ -138,12 +158,12 @@ export const AiAssistantIcon = (props: IconProps) => {
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_7480_20594"
result="effect1_dropShadow_10448_46450"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_7480_20594"
in2="effect1_dropShadow_10448_46450"
result="shape"
/>
<feColorMatrix
@@ -161,7 +181,7 @@ export const AiAssistantIcon = (props: IconProps) => {
<feBlend
mode="normal"
in2="shape"
result="effect2_innerShadow_7480_20594"
result="effect2_innerShadow_10448_46450"
/>
<feColorMatrix
in="SourceAlpha"
@@ -173,12 +193,12 @@ export const AiAssistantIcon = (props: IconProps) => {
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"
/>
<feBlend
mode="normal"
in2="effect2_innerShadow_7480_20594"
result="effect3_innerShadow_7480_20594"
in2="effect2_innerShadow_10448_46450"
result="effect3_innerShadow_10448_46450"
/>
<feColorMatrix
in="SourceAlpha"
@@ -195,12 +215,12 @@ export const AiAssistantIcon = (props: IconProps) => {
/>
<feBlend
mode="normal"
in2="effect3_innerShadow_7480_20594"
result="effect4_innerShadow_7480_20594"
in2="effect3_innerShadow_10448_46450"
result="effect4_innerShadow_10448_46450"
/>
</filter>
<filter
id="filter1_f_7480_20594"
id="filter1_f_10448_46450"
x="5"
y="2"
width="9"
@@ -217,11 +237,11 @@ export const AiAssistantIcon = (props: IconProps) => {
/>
<feGaussianBlur
stdDeviation="0.25"
result="effect1_foregroundBlur_7480_20594"
result="effect1_foregroundBlur_10448_46450"
/>
</filter>
<filter
id="filter2_f_7480_20594"
id="filter2_f_10448_46450"
x="7.5"
y="5.5"
width="9"
@@ -238,11 +258,11 @@ export const AiAssistantIcon = (props: IconProps) => {
/>
<feGaussianBlur
stdDeviation="0.25"
result="effect1_foregroundBlur_7480_20594"
result="effect1_foregroundBlur_10448_46450"
/>
</filter>
<filter
id="filter3_f_7480_20594"
id="filter3_f_10448_46450"
x="2.5"
y="3.5"
width="9"
@@ -259,11 +279,11 @@ export const AiAssistantIcon = (props: IconProps) => {
/>
<feGaussianBlur
stdDeviation="0.25"
result="effect1_foregroundBlur_7480_20594"
result="effect1_foregroundBlur_10448_46450"
/>
</filter>
<filter
id="filter4_f_7480_20594"
id="filter4_f_10448_46450"
x="5"
y="4.5"
width="9"
@@ -280,11 +300,11 @@ export const AiAssistantIcon = (props: IconProps) => {
/>
<feGaussianBlur
stdDeviation="0.25"
result="effect1_foregroundBlur_7480_20594"
result="effect1_foregroundBlur_10448_46450"
/>
</filter>
<filter
id="filter5_f_7480_20594"
id="filter5_f_10448_46450"
x="5"
y="7"
width="9"
@@ -301,44 +321,44 @@ export const AiAssistantIcon = (props: IconProps) => {
/>
<feGaussianBlur
stdDeviation="0.25"
result="effect1_foregroundBlur_7480_20594"
result="effect1_foregroundBlur_10448_46450"
/>
</filter>
<linearGradient
id="paint0_linear_7480_20594"
x1="9.5"
y1="1.89002"
x2="9.5"
y2="16.11"
id="paint0_linear_10448_46450"
x1="9.50001"
y1="1.88989"
x2="9.50001"
y2="16.1099"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.2" stopColor="#8952FD" />
<stop offset="0.8" stopColor="#48EAEB" />
<stop offset="0.2" stopColor="#C686FF" />
<stop offset="0.8" stopColor="#8D99FF" />
</linearGradient>
<linearGradient
id="paint1_linear_7480_20594"
x1="5.11519"
y1="8.96784"
id="paint1_linear_10448_46450"
x1="5.1152"
y1="8.96772"
x2="13.4627"
y2="12.0584"
y2="12.0583"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#5B53FF" stopOpacity="0.8" />
<stop stopColor="#FF6778" stopOpacity="0.8" />
<stop offset="1" stopColor="white" stopOpacity="0.1" />
</linearGradient>
<linearGradient
id="paint2_linear_7480_20594"
id="paint2_linear_10448_46450"
x1="9.5"
y1="6.5"
x2="13.5"
y2="6.5"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#5B53FF" stopOpacity="0.1" />
<stop stopColor="#8D99FF" stopOpacity="0.1" />
<stop offset="1" stopColor="white" stopOpacity="0.3" />
</linearGradient>
<linearGradient
id="paint3_linear_7480_20594"
id="paint3_linear_10448_46450"
x1="13.5"
y1="6.5"
x2="9.5"
@@ -349,84 +369,84 @@ export const AiAssistantIcon = (props: IconProps) => {
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient
id="paint4_linear_7480_20594"
id="paint4_linear_10448_46450"
x1="12"
y1="10"
x2="16"
y2="10"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#5B53FF" stopOpacity="0.1" />
<stop stopColor="#8D99FF" stopOpacity="0.1" />
<stop offset="1" stopColor="white" stopOpacity="0.3" />
</linearGradient>
<linearGradient
id="paint5_linear_7480_20594"
id="paint5_linear_10448_46450"
x1="16"
y1="10"
x2="12"
y2="10"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#3B82F6" />
<stop offset="1" stopColor="#3B82F6" stopOpacity="0" />
<stop stopColor="#8D99FF" />
<stop offset="1" stopColor="#8D99FF" stopOpacity="0" />
</linearGradient>
<linearGradient
id="paint6_linear_7480_20594"
id="paint6_linear_10448_46450"
x1="4"
y1="4"
x2="8"
y2="4"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#5B53FF" stopOpacity="0.1" />
<stop stopColor="#8D99FF" stopOpacity="0.1" />
<stop offset="1" stopColor="white" stopOpacity="0.3" />
</linearGradient>
<linearGradient
id="paint7_linear_7480_20594"
id="paint7_linear_10448_46450"
x1="8"
y1="4"
x2="4"
y2="4"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#48EAEB" />
<stop offset="1" stopColor="#48EAEB" stopOpacity="0" />
<stop stopColor="#8D99FF" />
<stop offset="1" stopColor="#8D99FF" stopOpacity="0" />
</linearGradient>
<linearGradient
id="paint8_linear_7480_20594"
id="paint8_linear_10448_46450"
x1="4"
y1="4"
x2="8"
y2="4"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#5B53FF" stopOpacity="0.1" />
<stop stopColor="#8D99FF" stopOpacity="0.1" />
<stop offset="1" stopColor="white" stopOpacity="0.3" />
</linearGradient>
<linearGradient
id="paint9_linear_7480_20594"
id="paint9_linear_10448_46450"
x1="8"
y1="4"
x2="4"
y2="4"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#3B82F6" />
<stop offset="1" stopColor="#3B82F6" stopOpacity="0" />
<stop stopColor="#8D99FF" />
<stop offset="1" stopColor="#8D99FF" stopOpacity="0" />
</linearGradient>
<linearGradient
id="paint10_linear_7480_20594"
id="paint10_linear_10448_46450"
x1="4"
y1="4"
x2="8"
y2="4"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#5B53FF" stopOpacity="0.1" />
<stop stopColor="#8D99FF" stopOpacity="0.1" />
<stop offset="1" stopColor="white" stopOpacity="0.3" />
</linearGradient>
<linearGradient
id="paint11_linear_7480_20594"
id="paint11_linear_10448_46450"
x1="8"
y1="4"
x2="4"

View File

@@ -16,17 +16,17 @@ export const ShadedBgIcon = ({
switch (variant) {
case "neutral":
case "code":
return "#E4E4E7"
return "var(--docs-tags-neutral-border)"
case "blue":
return "#BFDBFE"
return "var(--docs-tags-blue-border)"
case "purple":
return "#DDD6FE"
return "var(--docs-tags-purple-border)"
case "green":
return "#A7F3D0"
return "var(--docs-tags-green-border)"
case "orange":
return "#FED7AA"
return "var(--docs-tags-orange-border)"
case "red":
return "#FECDD3"
return "var(--docs-tags-red-border)"
}
}, [variant])

View File

@@ -89,7 +89,7 @@ export const Modal = ({
className={clsx(
"fixed top-0 left-0 flex h-screen w-screen items-center justify-center",
"bg-medusa-bg-overlay z-50",
"hidden open:flex border-0 p-0",
"hidden open:flex border-0 px-docs_0.5 lg:p-0",
className
)}
onClick={handleClick}
@@ -99,17 +99,17 @@ export const Modal = ({
>
<div
className={clsx(
"bg-medusa-bg-base rounded-docs_sm",
"border-medusa-border-base border border-solid",
"bg-medusa-bg-base rounded-docs_lg",
"shadow-elevation-modal dark:shadow-elevation-modal-dark",
"w-[90%] md:h-auto md:w-[75%] lg:w-[560px]",
"max-w-full sm:max-w-modal-sm md:max-w-modal-md lg:max-w-modal-lg",
"h-auto w-full",
modalContainerClassName
)}
>
{title && <ModalHeader title={title} />}
<div
className={clsx(
"overflow-auto py-docs_1.5 px-docs_2",
"overflow-auto py-docs_1.5 px-docs_2 rounded-docs_lg",
contentClassName
)}
>

View File

@@ -0,0 +1,59 @@
import clsx from "clsx"
import React from "react"
import { Kbd } from "../../.."
export const SearchFooter = () => {
return (
<div
className={clsx(
"py-docs_0.75 hidden md:flex items-center justify-end px-docs_1",
"border-medusa-border-base border-t",
"bg-medusa-bg-field"
)}
>
<div className="flex items-center gap-docs_0.75">
<div className="flex items-center gap-docs_0.5">
<span
className={clsx("text-medusa-fg-subtle", "text-compact-x-small")}
>
Navigation
</span>
<span className="gap-[5px] flex">
<Kbd
className={clsx(
"!bg-medusa-bg-field-component !border-medusa-border-strong",
"!text-medusa-fg-subtle h-[18px] w-[18px] p-0"
)}
>
</Kbd>
<Kbd
className={clsx(
"!bg-medusa-bg-field-component !border-medusa-border-strong",
"!text-medusa-fg-subtle h-[18px] w-[18px] p-0"
)}
>
</Kbd>
</span>
</div>
<div className={clsx("h-docs_0.75 w-px bg-medusa-border-strong")}></div>
<div className="flex items-center gap-docs_0.5">
<span
className={clsx("text-medusa-fg-subtle", "text-compact-x-small")}
>
Open Result
</span>
<Kbd
className={clsx(
"!bg-medusa-bg-field-component !border-medusa-border-strong",
"!text-medusa-fg-subtle h-[18px] w-[18px] p-0"
)}
>
</Kbd>
</div>
</div>
</div>
)
}

View File

@@ -9,7 +9,7 @@ export const SearchHitGroupName = ({ name }: SearchHitGroupNameProps) => {
return (
<span
className={clsx(
"pb-docs_0.25 flex px-docs_0.5 pt-docs_1",
"pb-docs_0.25 flex px-docs_0.5 pt-docs_0.75",
"text-medusa-fg-muted",
"text-compact-x-small-plus"
)}

View File

@@ -70,7 +70,7 @@ export const SearchHitsWrapper = ({
}
return (
<div className="h-full overflow-auto">
<div className="h-full overflow-auto px-docs_0.5">
{status !== "loading" && showNoResults && <SearchNoResult />}
{indices.map((indexName, index) => (
<Index indexName={indexName} key={index}>

View File

@@ -1,4 +1,4 @@
import { ExclamationCircleSolid } from "@medusajs/icons"
import { MagnifierAlert } from "@medusajs/icons"
import clsx from "clsx"
import React from "react"
@@ -6,14 +6,24 @@ export const SearchNoResult = () => {
return (
<div
className={clsx(
"flex h-full w-full flex-col items-center justify-center gap-docs_1",
"text-medusa-fg-muted"
"flex h-full w-full flex-col items-center justify-center gap-docs_0.75"
)}
>
<ExclamationCircleSolid />
<span className="text-compact-small">
No results found. Try changing selected filters.
</span>
<MagnifierAlert className="text-medusa-fg-base" />
<div
className={clsx(
"flex flex-col justify-center items-center gap-docs_0.25",
"max-w-[360px]"
)}
>
<span className="text-compact-small-plus text-medusa-fg-subtle">
No results found.
</span>
<span className="text-medusa-fg-muted txt-small text-center">
We couldn&apos;t find any matches for your search. Please try changing
the filters or using different keywords.
</span>
</div>
</div>
)
}

View File

@@ -14,7 +14,7 @@ export const SearchSuggestionItem = ({
return (
<div
className={clsx(
"flex items-center",
"flex items-center justify-between gap-docs_0.75",
"cursor-pointer rounded-docs_sm p-docs_0.5",
"hover:bg-medusa-bg-base-hover",
"focus:bg-medusa-bg-base-hover",

View File

@@ -21,7 +21,7 @@ export const SearchSuggestions = ({ suggestions }: SearchSuggestionsProps) => {
const { commands, setCommand } = useSearch()
return (
<div className="h-full overflow-auto">
<div className="h-full overflow-auto px-docs_0.5">
{commands.length > 0 && (
<>
<SearchHitGroupName name={"Commands"} />
@@ -30,12 +30,9 @@ export const SearchSuggestions = ({ suggestions }: SearchSuggestionsProps) => {
onClick={() => setCommand(command)}
key={index}
tabIndex={index}
className="justify-between"
>
<span className="flex gap-docs_0.75">
{command.icon}
<span>{command.title}</span>
</span>
{command.icon}
<span className="flex-1">{command.title}</span>
{command.badge && <Badge {...command.badge} />}
</SearchSuggestionItem>
))}

View File

@@ -8,9 +8,10 @@ import { SearchSuggestions, type SearchSuggestionType } from "./Suggestions"
import { AlgoliaProps, useSearch } from "@/providers"
import { checkArraySameElms } from "@/utils"
import { SearchHitsWrapper } from "./Hits"
import { Button, Kbd, SelectBadge } from "@/components"
import { Button, Kbd, SelectBadge, SpinnerLoading } from "@/components"
import { MagnifyingGlass, XMark } from "@medusajs/icons"
import { useSearchNavigation, type OptionType } from "@/hooks"
import { SearchFooter } from "./Footer"
export type SearchProps = {
algolia: AlgoliaProps
@@ -68,7 +69,31 @@ export const Search = ({
})
return (
<div className="h-full">
<div className="h-full flex flex-col">
{filterOptions.length && (
<SelectBadge
multiple
options={filterOptions}
value={filters}
setSelected={(value) =>
setFilters(Array.isArray(value) ? [...value] : [value])
}
addSelected={(value) => setFilters((prev) => [...prev, value])}
removeSelected={(value) =>
setFilters((prev) => prev.filter((v) => v !== value))
}
showClearButton={false}
placeholder="Filters"
handleAddAll={(isAllSelected: boolean) => {
if (isAllSelected) {
setFilters(defaultFilters)
} else {
setFilters(filterOptions.map((option) => option.value))
}
}}
className="px-docs_1 pt-docs_1 bg-medusa-bg-base"
/>
)}
<InstantSearch
indexName={algolia.mainIndexName}
searchClient={searchClient}
@@ -86,27 +111,25 @@ export const Search = ({
),
form: clsx("h-full md:rounded-t-docs_xl bg-transparent"),
input: clsx(
"w-full h-full pl-docs_3 text-medusa-fg-base",
"placeholder:text-medusa-fg-muted",
"md:rounded-t-docs_xl text-compact-medium bg-transparent",
"w-full h-full px-docs_1 py-docs_0.75 text-medusa-fg-base",
"placeholder:text-medusa-fg-muted bg-medusa-bg-base",
"md:rounded-t-docs_xl text-compact-medium",
"appearance-none search-cancel:hidden border-0 active:outline-none focus:outline-none"
),
submit: clsx("absolute top-[18px] left-docs_1 btn-clear p-0"),
reset: clsx(
"absolute top-docs_0.75 right-docs_1 hover:bg-medusa-bg-base-hover",
"p-[5px] md:rounded-docs_DEFAULT btn-clear"
),
reset: clsx("absolute top-[18px] right-docs_1", "btn-clear"),
loadingIndicator: clsx("absolute top-[18px] right-docs_1"),
}}
submitIconComponent={() => (
<MagnifyingGlass className="text-medusa-fg-muted" />
)}
submitIconComponent={() => <></>}
resetIconComponent={() => (
<XMark className="hidden md:block text-medusa-fg-subtle" />
<span className="text-medusa-fg-muted text-compact-small-plus hover:text-medusa-fg-subtle">
Clear
</span>
)}
placeholder="Find something..."
autoFocus
formRef={searchBoxRef}
loadingIconComponent={() => <SpinnerLoading />}
/>
<Button
variant="transparent"
@@ -121,7 +144,7 @@ export const Search = ({
<XMark className="text-medusa-fg-muted" />
</Button>
</div>
<div className="mx-docs_0.5 md:flex-initial h-[calc(100%-120px)] md:h-[calc(100%-114px)] lg:max-h-[calc(100%-114px)] lg:min-h-[calc(100%-114px)]">
<div className="md:flex-initial h-[calc(100%-95px)] lg:max-h-[calc(100%-140px)] lg:min-h-[calc(100%-140px)]">
<SearchEmptyQueryBoundary
fallback={<SearchSuggestions suggestions={suggestions} />}
>
@@ -135,59 +158,7 @@ export const Search = ({
</SearchEmptyQueryBoundary>
</div>
</InstantSearch>
<div
className={clsx(
"py-docs_0.75 flex items-center justify-between px-docs_1",
"border-0 border-solid h-[57px]",
"border-medusa-border-base border-t",
"bg-medusa-bg-base"
)}
>
{filterOptions.length && (
<SelectBadge
multiple
options={filterOptions}
value={filters}
setSelected={(value) =>
setFilters(Array.isArray(value) ? [...value] : [value])
}
addSelected={(value) => setFilters((prev) => [...prev, value])}
removeSelected={(value) =>
setFilters((prev) => prev.filter((v) => v !== value))
}
showClearButton={false}
placeholder="Filters"
handleAddAll={(isAllSelected: boolean) => {
if (isAllSelected) {
setFilters(defaultFilters)
} else {
setFilters(filterOptions.map((option) => option.value))
}
}}
/>
)}
<div className="hidden items-center gap-docs_1 md:flex">
<div className="flex items-center gap-docs_0.5">
<span
className={clsx("text-medusa-fg-subtle", "text-compact-x-small")}
>
Navigation
</span>
<span className="gap-docs_0.25 flex">
<Kbd></Kbd>
<Kbd></Kbd>
</span>
</div>
<div className="flex items-center gap-docs_0.5">
<span
className={clsx("text-medusa-fg-subtle", "text-compact-x-small")}
>
Open Result
</span>
<Kbd></Kbd>
</div>
</div>
</div>
<SearchFooter />
</div>
)
}

View File

@@ -4,6 +4,7 @@ import React, { useCallback, useRef, useState } from "react"
import { useSelect } from "@/hooks"
import clsx from "clsx"
import { SelectDropdown, SelectProps } from ".."
import { TriangleDownMini } from "@medusajs/icons"
export const SelectBadge = ({
value,
@@ -20,16 +21,21 @@ export const SelectBadge = ({
const [open, setOpen] = useState(false)
const ref = useRef<HTMLDivElement>(null)
const dropdownRef = useRef<HTMLDivElement>(null)
const { isValueSelected, isAllSelected, handleChange, handleSelectAll } =
useSelect({
value,
options,
multiple,
setSelected,
removeSelected,
addSelected,
handleAddAll,
})
const {
isValueSelected,
isAllSelected,
handleChange,
handleSelectAll,
setSelectedValues,
} = useSelect({
value,
options,
multiple,
setSelected,
removeSelected,
addSelected,
handleAddAll,
})
const getSelectedText = useCallback(() => {
let str = ""
@@ -38,7 +44,7 @@ export const SelectBadge = ({
)
if (isAllSelected) {
str = "All Areas"
str = "All areas"
} else {
if (
(!Array.isArray(value) && !value) ||
@@ -54,37 +60,28 @@ export const SelectBadge = ({
<>
<span
className={clsx(
"text-medusa-fg-base",
"text-compact-x-small-plus",
"inline-block max-w-[60px] overflow-hidden text-ellipsis"
"text-compact-x-small-plus text-medusa-tag-neutral-text"
)}
>
{str}
{!isAllSelected && selectedOptions.length > 1 && (
<> + {selectedOptions.length - 1}</>
)}
</span>
{!isAllSelected && selectedOptions.length > 1 && (
<span
className={clsx("text-medusa-fg-subtle", "text-compact-x-small")}
>
{" "}
+ {selectedOptions.length}
</span>
)}
</>
)
}, [isAllSelected, options, value])
return (
<div className={clsx("relative", className)}>
<div className={clsx("relative w-fit", className)}>
<div
className={clsx(
"border-medusa-border-base rounded-docs_sm border border-solid",
"hover:bg-medusa-bg-subtle-hover",
"py-docs_0.25 h-fit cursor-pointer px-docs_0.5",
"flex items-center gap-[6px] whitespace-nowrap",
"border-medusa-tag-neutral-border rounded-docs_sm border border-solid",
"h-fit cursor-pointer pl-docs_0.25 pr-[3px] text-medusa-tag-neutral-text",
"bg-medusa-tag-neutral-bg",
"flex items-center gap-[3px] whitespace-nowrap",
"text-medusa-fg-subtle",
!open && "bg-medusa-bg-subtle",
open && "bg-medusa-bg-subtle-hover",
className
open && "bg-medusa-tag-neutral-bg-hover"
)}
ref={ref}
onClick={(e) => {
@@ -93,10 +90,8 @@ export const SelectBadge = ({
}
}}
>
<span className={clsx("text-medusa-fg-subtle", "text-compact-x-small")}>
Show results from:{" "}
</span>
{getSelectedText()}
<TriangleDownMini className="text-medusa-tag-neutral-icon" />
</div>
<input
type="hidden"
@@ -115,10 +110,7 @@ export const SelectBadge = ({
handleChange={handleChange}
parentRef={ref}
passedRef={dropdownRef}
className={clsx(
"!top-[unset] !bottom-full",
open && "!-translate-y-docs_0.5"
)}
setSelectedValues={setSelectedValues}
/>
</div>
)

View File

@@ -19,6 +19,7 @@ export type SelectDropdownProps = {
parentRef?: React.RefObject<HTMLDivElement>
className?: string
passedRef?: Ref<HTMLDivElement>
setSelectedValues?: (values: string[]) => void
}
export const SelectDropdown = ({
@@ -34,6 +35,7 @@ export const SelectDropdown = ({
parentRef,
className,
passedRef,
setSelectedValues,
}: SelectDropdownProps) => {
const ref = useRef<HTMLDivElement | null>(null)
const setRefs = useCallback(
@@ -50,7 +52,11 @@ export const SelectDropdown = ({
)
const handleChange = (clickedValue: string, wasSelected: boolean) => {
handleSelectChange?.(clickedValue, wasSelected)
if (isAllSelected && setSelectedValues) {
setSelectedValues([clickedValue])
} else {
handleSelectChange?.(clickedValue, wasSelected)
}
if (!multiple) {
setOpen(false)
}
@@ -78,43 +84,75 @@ export const SelectDropdown = ({
}, [handleOutsideClick])
const getSelectOption = (option: OptionType, index: number) => {
const isSelected = option.isAllOption
? isAllSelected
: isValueSelected(option.value)
const originalIsSelected = isValueSelected(option.value)
const isSelected = isAllSelected
? option.isAllOption || false
: originalIsSelected
return (
<li
key={index}
className={clsx(
"pr-docs_0.75 relative rounded-docs_sm py-docs_0.5 pl-docs_2.5",
"hover:bg-medusa-bg-base-hover",
"[&>svg]:left-docs_0.75 cursor-pointer [&>svg]:absolute [&>svg]:top-docs_0.5",
!isSelected && "text-compact-small",
isSelected && "text-compact-small-plus"
"px-docs_0.25",
index <= 0 && "rounded-t-docs_DEFAULT",
index === options.length - 1 && "rounded-b-docs_DEFAULT"
)}
onClick={() => {
if (option.isAllOption) {
handleSelectAll()
} else {
handleChange(option.value, isSelected)
handleChange(option.value, originalIsSelected)
}
}}
>
{isSelected && (
<>
{multiple && <CheckMini className="text-medusa-fg-base" />}
{!multiple && <EllipseMiniSolid className="text-medusa-fg-base" />}
</>
)}
{option.label}
<div
className={clsx(
"px-docs_0.5 py-docs_0.25 flex-1 min-w-max rounded-docs_xs",
"hover:bg-medusa-bg-component-hover cursor-pointer",
"flex gap-docs_0.5 text-medusa-fg-base items-center",
!isSelected && "text-compact-small",
isSelected && "text-compact-small-plus"
)}
>
<span>
{isSelected && (
<>
{option.isAllOption && <EllipseMiniSolid />}
{!option.isAllOption && (
<>
{multiple && <CheckMini />}
{!multiple && <EllipseMiniSolid />}
</>
)}
</>
)}
{!isSelected && <EllipseMiniSolid className="invisible" />}
</span>
<span className="flex-1">{option.label}</span>
</div>
</li>
)
}
const getDivider = () => (
<svg
width="176"
height="8"
viewBox="0 0 176 8"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect width="168" height="8" transform="translate(4)" fill="#FAFAFA" />
<rect y="4" width="176" height="1" fill="white" />
<rect y="3" width="176" height="1" fill="#E4E4E7" />
</svg>
)
return (
<div
className={clsx(
"absolute top-full left-0 w-full",
"absolute left-0 md:left-docs_1",
"z-10",
"h-0 translate-y-0 overflow-hidden transition-transform",
open && "h-auto translate-y-docs_0.5 !overflow-visible",
className
@@ -123,20 +161,25 @@ export const SelectDropdown = ({
>
<ul
className={clsx(
"p-docs_0.25 mb-0 w-full overflow-auto rounded-docs_DEFAULT",
"bg-medusa-bg-base text-medusa-fg-base",
"shadow-elevation-flyout dark:shadow-elevation-flyout-dark list-none"
"mb-0 py-docs_0.25 overflow-auto rounded-docs_DEFAULT",
"bg-medusa-bg-component text-medusa-fg-base",
"shadow-elevation-flyout dark:shadow-elevation-flyout-dark list-none",
"flex flex-col"
)}
>
{addAll &&
getSelectOption(
{
value: "all",
label: "All Areas",
isAllOption: true,
},
-1
)}
{addAll && (
<>
{getSelectOption(
{
value: "all",
label: "All Areas",
isAllOption: true,
},
-1
)}
{getDivider()}
</>
)}
{options.map(getSelectOption)}
</ul>
</div>

View File

@@ -79,6 +79,10 @@ export const useSelect = ({
}
}
const setSelectedValues = (values: string[]) => {
setSelected?.(values)
}
return {
isValueSelected,
hasSelectedValue,
@@ -87,5 +91,6 @@ export const useSelect = ({
isAllSelected,
handleChange,
handleSelectAll,
setSelectedValues,
}
}

View File

@@ -13,6 +13,7 @@ export type AiAssistantContextType = {
questionId: string,
reaction: AiAssistantFeedbackType
) => Promise<Response>
version: "v1" | "v2"
}
const AiAssistantContext = createContext<AiAssistantContextType | null>(null)
@@ -22,12 +23,14 @@ export type AiAssistantProviderProps = {
apiUrl: string
recaptchaSiteKey: string
websiteId: string
version?: "v1" | "v2"
}
export const AiAssistantProvider = ({
apiUrl,
recaptchaSiteKey,
websiteId,
version = "v2",
children,
}: AiAssistantProviderProps) => {
const { analytics } = useAnalytics()
@@ -90,6 +93,7 @@ export const AiAssistantProvider = ({
value={{
getAnswer,
sendFeedback,
version,
}}
>
{children}

View File

@@ -131,14 +131,9 @@ export const SearchProvider = ({
<Modal
contentClassName={clsx(
"!p-0 overflow-hidden relative h-full",
"rounded-none md:rounded-docs_lg flex flex-col justify-between"
)}
modalContainerClassName={clsx(
"!rounded-none md:!rounded-docs_lg",
"md:!h-[480px] h-screen",
"md:!w-[640px] w-screen",
"bg-medusa-bg-base"
"flex flex-col justify-between"
)}
modalContainerClassName="sm:h-[480px] sm:max-h-[480px]"
open={isOpen}
onClose={() => setIsOpen(false)}
passedRef={modalRef}
@@ -156,7 +151,7 @@ export const SearchProvider = ({
? "animate-fadeOutLeft animate-fast"
: "animate-fadeOutRight animate-fast",
}}
timeout={300}
timeout={250}
key={command?.name || "search"}
>
<>

View File

@@ -310,8 +310,14 @@ module.exports = {
"inner-content-xxl": "640px",
"inner-content-xxxl": "640px",
// wide layout
"wide-content": "1112px",
"xl-wide-content": "1112px",
"lg-wide-content": "800px",
// modal
"modal-xs": "304px",
"modal-sm": "624px",
"modal-md": "752px",
"modal-lg": "640px",
},
minWidth: {
xl: "1419px",