docs: redesign API runner (#8688)
* fix up block style + plain theme color * initial redesign * docs: redesign API Runner * revert yarn.lock changes
This commit is contained in:
1 parent
539266559c
commit
64283d0e83
10 files changed
+194
-75
No files matched your search
@@ -16,7 +16,7 @@ export const singlePathHighlights = [
|
|||||||
["11", "req.params.id", "Access the path parameter `id`"]
|
["11", "req.params.id", "Access the path parameter `id`"]
|
||||||
]
|
]
|
||||||
|
|
||||||
```ts title="src/api/store/hello-world/[id]/route.ts" highlights={singlePathHighlights} apiTesting testApiUrl="http://localhost:9000/store/hello-world/{id}" testApiMethod="GET" testPathParams={{ "id": "1" }}
|
```ts title="src/api/store/hello-world/[id]/route.ts" highlights={singlePathHighlights} apiTesting testApiUrl="http://localhost:9000/store/hello-world/{id}" testApiMethod="GET" testPathParams={{ "id": "" }}
|
||||||
import type {
|
import type {
|
||||||
MedusaRequest,
|
MedusaRequest,
|
||||||
MedusaResponse,
|
MedusaResponse,
|
||||||
@@ -45,7 +45,7 @@ export const multiplePathHighlights = [
|
|||||||
["13", "req.params.name", "Access the path parameter `name`"]
|
["13", "req.params.name", "Access the path parameter `name`"]
|
||||||
]
|
]
|
||||||
|
|
||||||
```ts title="src/api/store/hello-world/[id]/name/[name]/route.ts" highlights={multiplePathHighlights} apiTesting testApiUrl="http://localhost:9000/store/hello-world/{id}/name/{name}" testApiMethod="GET" testPathParams={{ "id": "1", "name": "John" }}
|
```ts title="src/api/store/hello-world/[id]/name/[name]/route.ts" highlights={multiplePathHighlights} apiTesting testApiUrl="http://localhost:9000/store/hello-world/{id}/name/{name}" testApiMethod="GET" testPathParams={{ "id": "", "name": "" }}
|
||||||
import type {
|
import type {
|
||||||
MedusaRequest,
|
MedusaRequest,
|
||||||
MedusaResponse,
|
MedusaResponse,
|
||||||
@@ -77,7 +77,7 @@ export const queryHighlights = [
|
|||||||
["11", "req.query.name", "Access the query parameter `name`"],
|
["11", "req.query.name", "Access the query parameter `name`"],
|
||||||
]
|
]
|
||||||
|
|
||||||
```ts title="src/api/store/hello-world/route.ts" highlights={queryHighlights} apiTesting testApiUrl="http://localhost:9000/store/hello-world" testApiMethod="GET" testQueryParams={{ "name": "John" }}
|
```ts title="src/api/store/hello-world/route.ts" highlights={queryHighlights} apiTesting testApiUrl="http://localhost:9000/store/hello-world" testApiMethod="GET" testQueryParams={{ "name": "" }}
|
||||||
import type {
|
import type {
|
||||||
MedusaRequest,
|
MedusaRequest,
|
||||||
MedusaResponse,
|
MedusaResponse,
|
||||||
@@ -130,7 +130,7 @@ In this example, you use the `name` request body parameter to create the message
|
|||||||
|
|
||||||
To test it out, send the following request to your Medusa application:
|
To test it out, send the following request to your Medusa application:
|
||||||
|
|
||||||
```bash apiTesting testApiUrl="http://localhost:9000/store/hello-world" testApiMethod="POST" testBodyParams={{ "name": "John" }}
|
```bash apiTesting testApiUrl="http://localhost:9000/store/hello-world" testApiMethod="POST" testBodyParams={{ "name": "" }}
|
||||||
curl -X POST 'http://localhost:9000/store/hello-world' \
|
curl -X POST 'http://localhost:9000/store/hello-world' \
|
||||||
-H 'Content-Type: application/json' \
|
-H 'Content-Type: application/json' \
|
||||||
--data-raw '{
|
--data-raw '{
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import React from "react"
|
||||||
|
|
||||||
|
export const ApiRunnerFooterBackground = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
viewBox="0 0 641 44"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className="absolute top-0 left-0"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
width="640"
|
||||||
|
height="44"
|
||||||
|
transform="translate(0.5)"
|
||||||
|
fill="var(--docs-bg-component)"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
width="640"
|
||||||
|
height="44"
|
||||||
|
transform="translate(0.5)"
|
||||||
|
fill="url(#pattern0_10459_12087)"
|
||||||
|
fillOpacity="0.04"
|
||||||
|
/>
|
||||||
|
<defs>
|
||||||
|
<pattern
|
||||||
|
id="pattern0_10459_12087"
|
||||||
|
patternContentUnits="objectBoundingBox"
|
||||||
|
width="0.009375"
|
||||||
|
height="0.136364"
|
||||||
|
>
|
||||||
|
<use
|
||||||
|
xlinkHref="#image0_10459_12087"
|
||||||
|
transform="scale(0.0015625 0.0227273)"
|
||||||
|
/>
|
||||||
|
</pattern>
|
||||||
|
<image
|
||||||
|
id="image0_10459_12087"
|
||||||
|
width="6"
|
||||||
|
height="6"
|
||||||
|
xlinkHref="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZSURBVHgBxcghAQAAAIMw+pf+C+CZHLilebfsBfsvTewEAAAAAElFTkSuQmCC"
|
||||||
|
/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -97,6 +97,7 @@ export const ApiRunnerParamInput = ({
|
|||||||
? (paramValue as number)
|
? (paramValue as number)
|
||||||
: `${paramValue}`
|
: `${paramValue}`
|
||||||
}
|
}
|
||||||
|
className="w-full"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -15,11 +15,9 @@ export const ApiRunnerParamInputs = ({
|
|||||||
setValue,
|
setValue,
|
||||||
}: ApiRunnerParamInputsProps) => {
|
}: ApiRunnerParamInputsProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-docs_0.5">
|
<div className="flex flex-col gap-docs_0.25 w-full">
|
||||||
<span className="text-compact-medium-plus text-medusa-fg-base">
|
<span className="txt-small-plus text-medusa-fg-subtle">{title}</span>
|
||||||
{title}
|
<div className="flex flex-col gap-docs_0.5">
|
||||||
</span>
|
|
||||||
<div className="flex gap-docs_0.5">
|
|
||||||
{Object.keys(data).map((pathParam, index) => (
|
{Object.keys(data).map((pathParam, index) => (
|
||||||
<ApiRunnerParamInput
|
<ApiRunnerParamInput
|
||||||
paramName={pathParam}
|
paramName={pathParam}
|
||||||
|
|||||||
@@ -4,10 +4,13 @@ import React from "react"
|
|||||||
import { useEffect, useMemo, useState } from "react"
|
import { useEffect, useMemo, useState } from "react"
|
||||||
import { useRequestRunner } from "../../hooks"
|
import { useRequestRunner } from "../../hooks"
|
||||||
import { CodeBlock } from "../CodeBlock"
|
import { CodeBlock } from "../CodeBlock"
|
||||||
import { Card } from "../Card"
|
|
||||||
import { Button } from "../.."
|
import { Button } from "../.."
|
||||||
import { ApiMethod, ApiTestingOptions } from "types"
|
import { ApiMethod, ApiTestingOptions } from "types"
|
||||||
import { ApiRunnerParamInputs } from "./ParamInputs"
|
import { ApiRunnerParamInputs } from "./ParamInputs"
|
||||||
|
import clsx from "clsx"
|
||||||
|
import { ArrowDownRightMini } from "@medusajs/icons"
|
||||||
|
import { ArrowRightDownIcon } from "../Icons/ArrowRightDown"
|
||||||
|
import { ApiRunnerFooterBackground } from "./FooterBackground"
|
||||||
|
|
||||||
type ApiRunnerProps = {
|
type ApiRunnerProps = {
|
||||||
apiMethod: ApiMethod
|
apiMethod: ApiMethod
|
||||||
@@ -71,54 +74,82 @@ export const ApiRunner = React.forwardRef<HTMLDivElement, ApiRunnerProps>(
|
|||||||
}, [isRunning, ran])
|
}, [isRunning, ran])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div className="mb-docs_1" ref={ref}>
|
||||||
{manualTestTrigger && (
|
{manualTestTrigger && (
|
||||||
<Card className="font-base mb-docs_1" contentClassName="gap-docs_0.5">
|
<div
|
||||||
{apiTestingOptions.pathData && (
|
className={clsx(
|
||||||
<ApiRunnerParamInputs
|
"bg-medusa-bg-component rounded-docs_DEFAULT",
|
||||||
data={apiTestingOptions.pathData}
|
"shadow-elevation-card-rest dark:shadow-elevation-card-rest-dark",
|
||||||
title="Path Parameters"
|
"mb-docs_0.75"
|
||||||
baseObjPath="pathData"
|
|
||||||
setValue={
|
|
||||||
setApiTestingOptions as React.Dispatch<
|
|
||||||
React.SetStateAction<unknown>
|
|
||||||
>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
{apiTestingOptions.bodyData && (
|
>
|
||||||
<ApiRunnerParamInputs
|
<div
|
||||||
data={apiTestingOptions.bodyData}
|
className={clsx(
|
||||||
title="Request Body Parameters"
|
"flex items-center gap-docs_0.75",
|
||||||
baseObjPath="bodyData"
|
"px-docs_0.75 pb-docs_0.75 pt-docs_0.5"
|
||||||
setValue={
|
)}
|
||||||
setApiTestingOptions as React.Dispatch<
|
|
||||||
React.SetStateAction<unknown>
|
|
||||||
>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{apiTestingOptions.queryData && (
|
|
||||||
<ApiRunnerParamInputs
|
|
||||||
data={apiTestingOptions.queryData}
|
|
||||||
title="Request Query Parameters"
|
|
||||||
baseObjPath="queryData"
|
|
||||||
setValue={
|
|
||||||
setApiTestingOptions as React.Dispatch<
|
|
||||||
React.SetStateAction<unknown>
|
|
||||||
>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
setIsRunning(true)
|
|
||||||
setRan(false)
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Send Request
|
<ArrowDownRightMini className="text-medusa-fg-muted" />
|
||||||
</Button>
|
<div className="flex-1 flex items-center gap-docs_0.75">
|
||||||
</Card>
|
{apiTestingOptions.pathData && (
|
||||||
|
<ApiRunnerParamInputs
|
||||||
|
data={apiTestingOptions.pathData}
|
||||||
|
title="Path Parameters"
|
||||||
|
baseObjPath="pathData"
|
||||||
|
setValue={
|
||||||
|
setApiTestingOptions as React.Dispatch<
|
||||||
|
React.SetStateAction<unknown>
|
||||||
|
>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{apiTestingOptions.bodyData && (
|
||||||
|
<ApiRunnerParamInputs
|
||||||
|
data={apiTestingOptions.bodyData}
|
||||||
|
title="Request Body Parameters"
|
||||||
|
baseObjPath="bodyData"
|
||||||
|
setValue={
|
||||||
|
setApiTestingOptions as React.Dispatch<
|
||||||
|
React.SetStateAction<unknown>
|
||||||
|
>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{apiTestingOptions.queryData && (
|
||||||
|
<ApiRunnerParamInputs
|
||||||
|
data={apiTestingOptions.queryData}
|
||||||
|
title="Request Query Parameters"
|
||||||
|
baseObjPath="queryData"
|
||||||
|
setValue={
|
||||||
|
setApiTestingOptions as React.Dispatch<
|
||||||
|
React.SetStateAction<unknown>
|
||||||
|
>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<ArrowRightDownIcon className="text-medusa-fg-muted" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
"border-t border-medusa-border-base",
|
||||||
|
"py-docs_0.5 px-docs_0.75 relative",
|
||||||
|
"flex justify-end items-center gap-docs_0.5"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ApiRunnerFooterBackground />
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setIsRunning(true)
|
||||||
|
setRan(false)
|
||||||
|
}}
|
||||||
|
className="relative"
|
||||||
|
variant="secondary"
|
||||||
|
>
|
||||||
|
Send Request
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{(isRunning || ran) && (
|
{(isRunning || ran) && (
|
||||||
<CodeBlock
|
<CodeBlock
|
||||||
@@ -126,12 +157,11 @@ export const ApiRunner = React.forwardRef<HTMLDivElement, ApiRunnerProps>(
|
|||||||
lang="json"
|
lang="json"
|
||||||
title="Testing Result"
|
title="Testing Result"
|
||||||
collapsed={true}
|
collapsed={true}
|
||||||
blockStyle="subtle"
|
|
||||||
noReport={true}
|
noReport={true}
|
||||||
badgeLabel={responseCode}
|
badgeLabel={responseCode || "Failed"}
|
||||||
badgeColor={
|
badgeColor={
|
||||||
!responseCode
|
!responseCode
|
||||||
? undefined
|
? "red"
|
||||||
: responseCode.startsWith("2")
|
: responseCode.startsWith("2")
|
||||||
? "green"
|
? "green"
|
||||||
: "red"
|
: "red"
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export const Button = ({
|
|||||||
}: ButtonProps) => {
|
}: ButtonProps) => {
|
||||||
const variantClasses = {
|
const variantClasses = {
|
||||||
primary: [
|
primary: [
|
||||||
"px-[10px] py-[6px] rounded-docs_sm cursor-pointer",
|
"px-docs_0.5 py-docs_0.25 rounded-docs_sm cursor-pointer",
|
||||||
"bg-medusa-button-inverted",
|
"bg-medusa-button-inverted",
|
||||||
"hover:bg-medusa-button-inverted-hover hover:no-underline",
|
"hover:bg-medusa-button-inverted-hover hover:no-underline",
|
||||||
"active:bg-medusa-button-inverted-pressed",
|
"active:bg-medusa-button-inverted-pressed",
|
||||||
@@ -44,7 +44,7 @@ export const Button = ({
|
|||||||
"select-none",
|
"select-none",
|
||||||
],
|
],
|
||||||
secondary: [
|
secondary: [
|
||||||
"px-[10px] py-[6px] rounded-docs_sm cursor-pointer",
|
"px-docs_0.5 py-docs_0.25 rounded-docs_sm cursor-pointer",
|
||||||
"bg-medusa-button-neutral",
|
"bg-medusa-button-neutral",
|
||||||
"hover:bg-medusa-button-neutral-hover hover:no-underline",
|
"hover:bg-medusa-button-neutral-hover hover:no-underline",
|
||||||
"active:bg-medusa-button-neutral-pressed",
|
"active:bg-medusa-button-neutral-pressed",
|
||||||
@@ -58,7 +58,7 @@ export const Button = ({
|
|||||||
"select-none",
|
"select-none",
|
||||||
],
|
],
|
||||||
transparent: [
|
transparent: [
|
||||||
"px-[10px] py-[6px] rounded-docs_sm cursor-pointer",
|
"px-docs_0.5 py-docs_0.25 rounded-docs_sm cursor-pointer",
|
||||||
"bg-transparent shadow-none border-0 outline-none",
|
"bg-transparent shadow-none border-0 outline-none",
|
||||||
"text-compact-small-plus text-medusa-fg-base",
|
"text-compact-small-plus text-medusa-fg-base",
|
||||||
"hover:bg-medusa-button-transparent-hover",
|
"hover:bg-medusa-button-transparent-hover",
|
||||||
@@ -68,7 +68,7 @@ export const Button = ({
|
|||||||
"disabled:cursor-not-allowed disabled:text-medusa-fg-disabled",
|
"disabled:cursor-not-allowed disabled:text-medusa-fg-disabled",
|
||||||
],
|
],
|
||||||
transparentClear: [
|
transparentClear: [
|
||||||
"px-[10px] py-[6px] rounded-docs_sm cursor-pointer",
|
"px-docs_0.5 py-docs_0.25 rounded-docs_sm cursor-pointer",
|
||||||
"bg-transparent shadow-none border-0 outline-none",
|
"bg-transparent shadow-none border-0 outline-none",
|
||||||
"text-compact-small-plus text-medusa-fg-muted",
|
"text-compact-small-plus text-medusa-fg-muted",
|
||||||
"hover:bg-medusa-button-transparent-hover",
|
"hover:bg-medusa-button-transparent-hover",
|
||||||
@@ -82,7 +82,7 @@ export const Button = ({
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"inline-flex flex-row justify-center items-center gap-[6px]",
|
"inline-flex flex-row justify-center items-center gap-[6px] font-base",
|
||||||
variant === "primary" && variantClasses.primary,
|
variant === "primary" && variantClasses.primary,
|
||||||
variant === "secondary" && variantClasses.secondary,
|
variant === "secondary" && variantClasses.secondary,
|
||||||
variant === "transparent" && variantClasses.transparent,
|
variant === "transparent" && variantClasses.transparent,
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ export const CodeBlockLine = ({
|
|||||||
key={tokenKey}
|
key={tokenKey}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
tokenClassName,
|
tokenClassName,
|
||||||
(isTerminal || isTokenHighlighted || isLineHighlighted) &&
|
(isTokenHighlighted || isLineHighlighted) &&
|
||||||
"!text-medusa-contrast-fg-primary"
|
"!text-medusa-contrast-fg-primary"
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
|
|||||||
@@ -272,6 +272,24 @@ export const CodeBlock = ({
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const codeTheme = useMemo(() => {
|
||||||
|
const prismTheme =
|
||||||
|
blockStyle === "loud" || colorMode === "dark"
|
||||||
|
? themes.vsDark
|
||||||
|
: themes.vsLight
|
||||||
|
|
||||||
|
return {
|
||||||
|
...prismTheme,
|
||||||
|
plain: {
|
||||||
|
...prismTheme,
|
||||||
|
color:
|
||||||
|
colorMode === "light"
|
||||||
|
? "rgba(255, 255, 255, 0.88)"
|
||||||
|
: "rgba(250, 250, 250, 1)",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}, [blockStyle, colorMode])
|
||||||
|
|
||||||
if (!source.length) {
|
if (!source.length) {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
@@ -314,11 +332,7 @@ export const CodeBlock = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Highlight
|
<Highlight
|
||||||
theme={
|
theme={codeTheme}
|
||||||
blockStyle === "loud" || colorMode === "dark"
|
|
||||||
? themes.vsDark
|
|
||||||
: themes.vsLight
|
|
||||||
}
|
|
||||||
code={source.trim()}
|
code={source.trim()}
|
||||||
language={language}
|
language={language}
|
||||||
{...rest}
|
{...rest}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { IconProps } from "@medusajs/icons/dist/types"
|
||||||
|
|
||||||
|
export const ArrowRightDownIcon = (props: IconProps) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M8.66671 13.5558L8.66671 4.22242C8.66671 3.2402 7.87115 2.44464 6.88893 2.44464L3.33337 2.44464"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M4.88892 9.77802L8.66669 13.5558L12.4445 9.77802"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -20,18 +20,17 @@ export const InputText = ({
|
|||||||
<input
|
<input
|
||||||
{...props}
|
{...props}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-medusa-bg-field shadow-border-base dark:shadow-border-base-dark",
|
"bg-medusa-bg-field-component shadow-border-base dark:shadow-border-base-dark",
|
||||||
"border-medusa-border-base rounded-docs_sm border border-solid",
|
"rounded-docs_sm px-docs_0.5",
|
||||||
"px-docs_0.75 py-[9px]",
|
"hover:bg-medusa-bg-field-component-hover",
|
||||||
"hover:bg-medusa-bg-field-hover",
|
addGroupStyling && "group-hover:bg-medusa-bg-field-component-hover",
|
||||||
addGroupStyling && "group-hover:bg-medusa-bg-field-hover",
|
|
||||||
"focus:border-medusa-border-interactive",
|
"focus:border-medusa-border-interactive",
|
||||||
"active:border-medusa-border-interactive",
|
"active:border-medusa-border-interactive",
|
||||||
"disabled:bg-medusa-bg-disabled",
|
"disabled:bg-medusa-bg-disabled",
|
||||||
"disabled:border-medusa-border-base",
|
"disabled:border-medusa-border-base",
|
||||||
"placeholder:text-medusa-fg-muted",
|
"placeholder:text-medusa-fg-muted",
|
||||||
"disabled:placeholder:text-medusa-fg-disabled",
|
"disabled:placeholder:text-medusa-fg-disabled",
|
||||||
"text-compact-medium font-base",
|
"text-compact-small font-base",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
ref={passedRef}
|
ref={passedRef}
|
||||||
|
|||||||
Reference in new issue
Block a user