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:
Shahed Nasser
2024-08-21 17:48:16 +03:00
committed by GitHub
parent 539266559c
commit 64283d0e83
10 changed files with 194 additions and 75 deletions

View File

@@ -16,7 +16,7 @@ export const singlePathHighlights = [
["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 {
MedusaRequest,
MedusaResponse,
@@ -45,7 +45,7 @@ export const multiplePathHighlights = [
["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 {
MedusaRequest,
MedusaResponse,
@@ -77,7 +77,7 @@ export const queryHighlights = [
["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 {
MedusaRequest,
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:
```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' \
-H 'Content-Type: application/json' \
--data-raw '{

View File

@@ -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>
)
}

View File

@@ -97,6 +97,7 @@ export const ApiRunnerParamInput = ({
? (paramValue as number)
: `${paramValue}`
}
className="w-full"
/>
)
}

View File

@@ -15,11 +15,9 @@ export const ApiRunnerParamInputs = ({
setValue,
}: ApiRunnerParamInputsProps) => {
return (
<div className="flex flex-col gap-docs_0.5">
<span className="text-compact-medium-plus text-medusa-fg-base">
{title}
</span>
<div className="flex gap-docs_0.5">
<div className="flex flex-col gap-docs_0.25 w-full">
<span className="txt-small-plus text-medusa-fg-subtle">{title}</span>
<div className="flex flex-col gap-docs_0.5">
{Object.keys(data).map((pathParam, index) => (
<ApiRunnerParamInput
paramName={pathParam}

View File

@@ -4,10 +4,13 @@ import React from "react"
import { useEffect, useMemo, useState } from "react"
import { useRequestRunner } from "../../hooks"
import { CodeBlock } from "../CodeBlock"
import { Card } from "../Card"
import { Button } from "../.."
import { ApiMethod, ApiTestingOptions } from "types"
import { ApiRunnerParamInputs } from "./ParamInputs"
import clsx from "clsx"
import { ArrowDownRightMini } from "@medusajs/icons"
import { ArrowRightDownIcon } from "../Icons/ArrowRightDown"
import { ApiRunnerFooterBackground } from "./FooterBackground"
type ApiRunnerProps = {
apiMethod: ApiMethod
@@ -71,54 +74,82 @@ export const ApiRunner = React.forwardRef<HTMLDivElement, ApiRunnerProps>(
}, [isRunning, ran])
return (
<div ref={ref}>
<div className="mb-docs_1" ref={ref}>
{manualTestTrigger && (
<Card className="font-base mb-docs_1" contentClassName="gap-docs_0.5">
{apiTestingOptions.pathData && (
<ApiRunnerParamInputs
data={apiTestingOptions.pathData}
title="Path Parameters"
baseObjPath="pathData"
setValue={
setApiTestingOptions as React.Dispatch<
React.SetStateAction<unknown>
>
}
/>
<div
className={clsx(
"bg-medusa-bg-component rounded-docs_DEFAULT",
"shadow-elevation-card-rest dark:shadow-elevation-card-rest-dark",
"mb-docs_0.75"
)}
{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>
>
}
/>
)}
<Button
onClick={() => {
setIsRunning(true)
setRan(false)
}}
>
<div
className={clsx(
"flex items-center gap-docs_0.75",
"px-docs_0.75 pb-docs_0.75 pt-docs_0.5"
)}
>
Send Request
</Button>
</Card>
<ArrowDownRightMini className="text-medusa-fg-muted" />
<div className="flex-1 flex items-center gap-docs_0.75">
{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) && (
<CodeBlock
@@ -126,12 +157,11 @@ export const ApiRunner = React.forwardRef<HTMLDivElement, ApiRunnerProps>(
lang="json"
title="Testing Result"
collapsed={true}
blockStyle="subtle"
noReport={true}
badgeLabel={responseCode}
badgeLabel={responseCode || "Failed"}
badgeColor={
!responseCode
? undefined
? "red"
: responseCode.startsWith("2")
? "green"
: "red"

View File

@@ -28,7 +28,7 @@ export const Button = ({
}: ButtonProps) => {
const variantClasses = {
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",
"hover:bg-medusa-button-inverted-hover hover:no-underline",
"active:bg-medusa-button-inverted-pressed",
@@ -44,7 +44,7 @@ export const Button = ({
"select-none",
],
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",
"hover:bg-medusa-button-neutral-hover hover:no-underline",
"active:bg-medusa-button-neutral-pressed",
@@ -58,7 +58,7 @@ export const Button = ({
"select-none",
],
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",
"text-compact-small-plus text-medusa-fg-base",
"hover:bg-medusa-button-transparent-hover",
@@ -68,7 +68,7 @@ export const Button = ({
"disabled:cursor-not-allowed disabled:text-medusa-fg-disabled",
],
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",
"text-compact-small-plus text-medusa-fg-muted",
"hover:bg-medusa-button-transparent-hover",
@@ -82,7 +82,7 @@ export const Button = ({
return (
<button
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 === "secondary" && variantClasses.secondary,
variant === "transparent" && variantClasses.transparent,

View File

@@ -221,7 +221,7 @@ export const CodeBlockLine = ({
key={tokenKey}
className={clsx(
tokenClassName,
(isTerminal || isTokenHighlighted || isLineHighlighted) &&
(isTokenHighlighted || isLineHighlighted) &&
"!text-medusa-contrast-fg-primary"
)}
{...rest}

View File

@@ -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) {
return <></>
}
@@ -314,11 +332,7 @@ export const CodeBlock = ({
)}
>
<Highlight
theme={
blockStyle === "loud" || colorMode === "dark"
? themes.vsDark
: themes.vsLight
}
theme={codeTheme}
code={source.trim()}
language={language}
{...rest}

View File

@@ -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>
)
}

View File

@@ -20,18 +20,17 @@ export const InputText = ({
<input
{...props}
className={clsx(
"bg-medusa-bg-field shadow-border-base dark:shadow-border-base-dark",
"border-medusa-border-base rounded-docs_sm border border-solid",
"px-docs_0.75 py-[9px]",
"hover:bg-medusa-bg-field-hover",
addGroupStyling && "group-hover:bg-medusa-bg-field-hover",
"bg-medusa-bg-field-component shadow-border-base dark:shadow-border-base-dark",
"rounded-docs_sm px-docs_0.5",
"hover:bg-medusa-bg-field-component-hover",
addGroupStyling && "group-hover:bg-medusa-bg-field-component-hover",
"focus:border-medusa-border-interactive",
"active:border-medusa-border-interactive",
"disabled:bg-medusa-bg-disabled",
"disabled:border-medusa-border-base",
"placeholder:text-medusa-fg-muted",
"disabled:placeholder:text-medusa-fg-disabled",
"text-compact-medium font-base",
"text-compact-small font-base",
className
)}
ref={passedRef}