From de70b9d6c858576666dd1d702850eef94100dc6a Mon Sep 17 00:00:00 2001 From: Rishabh Date: Thu, 20 Aug 2026 14:14:58 +0530 Subject: [PATCH] feat: add copy to clipboard button in API test response panel Adds a CopyButton next to the Body/Headers switch in the "Try it out" response panel, copying the active view's content (pretty JSON body or raw header lines). Co-Authored-By: Claude Sonnet 5 --- .../api/playground-dialog.module.css | 6 +++++ .../src/components/api/playground-dialog.tsx | 25 ++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/chronicle/src/components/api/playground-dialog.module.css b/packages/chronicle/src/components/api/playground-dialog.module.css index 9e78160d..45bb5c07 100644 --- a/packages/chronicle/src/components/api/playground-dialog.module.css +++ b/packages/chronicle/src/components/api/playground-dialog.module.css @@ -198,6 +198,12 @@ flex-shrink: 0; } +.responseHeaderActions { + display: flex; + align-items: center; + gap: var(--rs-space-2); +} + .statusBar { display: flex; align-items: center; diff --git a/packages/chronicle/src/components/api/playground-dialog.tsx b/packages/chronicle/src/components/api/playground-dialog.tsx index e7a2d371..c2b3c9b3 100644 --- a/packages/chronicle/src/components/api/playground-dialog.tsx +++ b/packages/chronicle/src/components/api/playground-dialog.tsx @@ -269,6 +269,10 @@ export function PlaygroundDialog({ const responseLines = responseJson ? responseJson.split('\n') : [] + const responseHeadersText = responseData?.headers + ? Object.entries(responseData.headers).map(([k, v]) => `${k}: ${v}`).join('\n') + : '' + const curlSnippet = useMemo(() => { const headers: Record = { ...getAuthHeaders(), ...headerValues } if (body) headers['Content-Type'] = body.contentType ?? 'application/json' @@ -467,15 +471,18 @@ export function PlaygroundDialog({
Response {responseData && ( - - } />}> - {responseView === 'body' ? 'Body' : 'Headers'} - - - setResponseView('body')}>Body - setResponseView('headers')}>Headers - - +
+ + + } />}> + {responseView === 'body' ? 'Body' : 'Headers'} + + + setResponseView('body')}>Body + setResponseView('headers')}>Headers + + +
)}