@@ -3,34 +3,20 @@ import { cn } from "../../../lib/utils";
33import { CodeBlock } from "../Code" ;
44import { Details } from "../Details" ;
55import { Heading } from "../Heading" ;
6- import { Paragraph } from "../Paragraph" ;
76import { RequestExample } from "./RequestExample" ;
87
9- export type APIParameter =
10- | {
11- name : string ;
12- required : false ;
13- description : React . ReactNode ;
14- type ?: string ;
15- example ?:
16- | string
17- | boolean
18- | number
19- | object
20- | Array < string | boolean | number | object > ;
21- }
22- | {
23- name : string ;
24- required : true ;
25- example :
26- | string
27- | boolean
28- | number
29- | object
30- | Array < string | boolean | number | object > ;
31- description : React . ReactNode ;
32- type ?: string ;
33- } ;
8+ export type APIParameter = {
9+ name : string ;
10+ required : boolean ;
11+ description : React . ReactNode ;
12+ type ?: string ;
13+ example ?:
14+ | string
15+ | boolean
16+ | number
17+ | object
18+ | Array < string | boolean | number | object > ;
19+ } ;
3420
3521export type ApiEndpointMeta = {
3622 title : string ;
@@ -98,33 +84,34 @@ export function ApiEndpoint(props: { metadata: ApiEndpointMeta }) {
9884 endpointUrl = { props . metadata . path }
9985 method = { props . metadata . method }
10086 />
101- </ div >
10287
103- < div className = "mt-4" >
104- { request . headers . length > 0 && (
105- < ParameterSection parameters = { request . headers } title = "Headers" />
106- ) }
107-
108- { request . pathParameters . length > 0 && (
109- < ParameterSection
110- parameters = { request . pathParameters }
111- title = "Path Parameters"
112- />
113- ) }
114-
115- { request . queryParameters . length > 0 && (
116- < ParameterSection
117- parameters = { request . queryParameters }
118- title = "Query Parameters"
119- />
120- ) }
121-
122- { request . bodyParameters . length > 0 && (
123- < ParameterSection
124- parameters = { request . bodyParameters }
125- title = "Request Body"
126- />
127- ) }
88+ { /* Parameters section inside the card */ }
89+ < div className = "border-t" >
90+ { request . headers . length > 0 && (
91+ < ParameterSection parameters = { request . headers } title = "Headers" />
92+ ) }
93+
94+ { request . pathParameters . length > 0 && (
95+ < ParameterSection
96+ parameters = { request . pathParameters }
97+ title = "Path Parameters"
98+ />
99+ ) }
100+
101+ { request . queryParameters . length > 0 && (
102+ < ParameterSection
103+ parameters = { request . queryParameters }
104+ title = "Query Parameters"
105+ />
106+ ) }
107+
108+ { request . bodyParameters . length > 0 && (
109+ < ParameterSection
110+ parameters = { request . bodyParameters }
111+ title = "Request Body"
112+ />
113+ ) }
114+ </ div >
128115 </ div >
129116 </ div >
130117
@@ -174,84 +161,75 @@ function ParameterSection(props: {
174161 parameters : APIParameter [ ] ;
175162} ) {
176163 return (
177- < div className = "mb-5" >
178- < h6 className = "my-2 break-words text-foreground text-sm font-semibold" >
179- { props . title }
180- </ h6 >
181- < div className = "flex flex-col" >
182- { props . parameters
183- . sort ( ( a , b ) => {
184- if ( a . required === b . required ) {
185- return 0 ;
186- }
187- return a . required ? - 1 : 1 ;
188- } )
189- . map ( ( param ) => (
190- < ParameterItem key = { param . name } param = { param } />
191- ) ) }
192- </ div >
164+ < div className = "border-b last:border-b-0" >
165+ < Details
166+ summary = {
167+ < div className = "flex items-center gap-3" >
168+ < span className = "text-sm font-medium" > { props . title } </ span >
169+ < span className = "text-xs text-muted-foreground bg-muted px-2 py-1 rounded" >
170+ { props . parameters . length }
171+ </ span >
172+ </ div >
173+ }
174+ accordionItemClassName = "border-0 my-0"
175+ accordionTriggerClassName = "p-4 hover:bg-muted/50 transition-colors"
176+ >
177+ < div className = "px-4 pb-4" >
178+ { props . parameters
179+ . sort ( ( a , b ) => {
180+ if ( a . required === b . required ) {
181+ return 0 ;
182+ }
183+ return a . required ? - 1 : 1 ;
184+ } )
185+ . map ( ( param ) => (
186+ < InlineParameterItem key = { param . name } param = { param } />
187+ ) ) }
188+ </ div >
189+ </ Details >
193190 </ div >
194191 ) ;
195192}
196193
197- function ParameterItem ( { param } : { param : APIParameter } ) {
194+ function InlineParameterItem ( { param } : { param : APIParameter } ) {
198195 return (
199- < Details
200- accordionItemClassName = "my-1"
201- accordionTriggerClassName = "font-mono"
202- summary = {
203- < div className = "flex items-center gap-2" >
204- < span > { param . name } </ span >
205- { param . type && (
206- < span className = "text-xs text-muted-foreground px-1.5 py-0.5 bg-muted rounded" >
207- { param . type }
208- </ span >
209- ) }
210- </ div >
211- }
212- tags = { param . required ? [ "Required" ] : [ ] }
213- >
214- < div className = { "flex flex-col gap-3" } >
215- { param . description && (
216- < div >
217- < h5 className = "text-sm font-medium mb-1" > Description</ h5 >
218- < Paragraph className = "text-sm" > { param . description } </ Paragraph >
219- </ div >
220- ) }
221-
196+ < div className = "flex flex-col gap-2 p-3 bg-muted/30 rounded-lg" >
197+ < div className = "flex items-center gap-2 flex-wrap" >
198+ < code className = "text-foreground text-sm font-mono bg-background px-2 py-1 rounded border" >
199+ { param . name }
200+ </ code >
222201 { param . type && (
223- < div >
224- < h5 className = "text-sm font-medium mb-1" > Type</ h5 >
225- < div className = "rounded-lg border" >
226- < CodeBlock
227- className = "border-none"
228- code = { param . type }
229- containerClassName = "mb-0"
230- lang = "typescript"
231- />
232- </ div >
233- </ div >
202+ < span className = "text-xs text-muted-foreground px-2 py-1 bg-muted rounded" >
203+ { param . type }
204+ </ span >
234205 ) }
235-
236- { param . example !== undefined && (
237- < div >
238- < h5 className = "text-sm font-medium mb-1" > Example</ h5 >
239- < div className = "rounded-lg border" >
240- < CodeBlock
241- className = "border-none"
242- code = {
243- typeof param . example === "object"
244- ? JSON . stringify ( param . example , null , 2 )
245- : String ( param . example )
246- }
247- containerClassName = "mb-0"
248- lang = { typeof param . example === "object" ? "json" : "text" }
249- />
250- </ div >
251- </ div >
206+ { param . required && (
207+ < span className = "text-xs text-warning-text px-2 py-1 rounded border border-warning-text" >
208+ Required
209+ </ span >
252210 ) }
253211 </ div >
254- </ Details >
212+
213+ { param . description && (
214+ < div className = "text-sm text-muted-foreground" > { param . description } </ div >
215+ ) }
216+
217+ { param . example !== undefined && (
218+ < div className = "text-sm flex flex-col gap-2" >
219+ < span className = "text-muted-foreground" > Example: </ span >
220+ < CodeBlock
221+ code = {
222+ typeof param . example === "object"
223+ ? JSON . stringify ( param . example )
224+ : String ( param . example )
225+ }
226+ containerClassName = "m-0"
227+ lang = "json"
228+ scrollContainerClassName = "max-h-[200px]"
229+ />
230+ </ div >
231+ ) }
232+ </ div >
255233 ) ;
256234}
257235
@@ -335,7 +313,7 @@ function createFetchCommand(params: { metadata: ApiEndpointMeta }) {
335313 }
336314
337315 if ( Object . keys ( bodyObj ) . length > 0 ) {
338- fetchOptions . body = JSON . stringify ( bodyObj ) ;
316+ fetchOptions . body = bodyObj ;
339317 }
340318
341319 return `fetch('${ url } ', ${ JSON . stringify ( fetchOptions , null , 2 ) } )` ;
0 commit comments