Better response headers

This commit is contained in:
Gregory Schier
2023-04-02 10:45:41 -07:00
parent ceefbd1de1
commit 62a367cd0c
8 changed files with 59 additions and 34 deletions

View File

@@ -5,5 +5,9 @@ interface Props {
}
export function EmptyStateText({ children }: Props) {
return <div className="h-full text-gray-400 flex items-center justify-center">{children}</div>;
return (
<div className="rounded-lg border border-dashed border-highlight h-full text-gray-400 flex items-center justify-center">
{children}
</div>
);
}

View File

@@ -96,9 +96,7 @@ export const RequestPane = memo(function RequestPane({ style, fullHeight, classN
label: (
<div className="flex items-center">
Headers
<CountBadge
count={activeRequest.headers.filter((h) => h.name && h.value).length}
/>
<CountBadge count={activeRequest.headers.filter((h) => h.name).length} />
</div>
),
},
@@ -164,7 +162,7 @@ export const RequestPane = memo(function RequestPane({ style, fullHeight, classN
label="Request"
onChangeValue={setActiveTab}
tabs={tabs}
className="mt-1"
tabListClassName="mt-2"
>
<TabContent value="auth">
{activeRequest.authenticationType === AUTH_TYPE_BASIC ? (
@@ -199,7 +197,7 @@ export const RequestPane = memo(function RequestPane({ style, fullHeight, classN
onChange={() => null}
/>
</TabContent>
<TabContent value="body" className="mt-1">
<TabContent value="body">
{activeRequest.bodyType === BODY_TYPE_JSON ? (
<Editor
forceUpdateKey={forceUpdateKey}

View File

@@ -0,0 +1,26 @@
import classnames from 'classnames';
import type { HttpResponse } from '../lib/models';
import { HStack } from './core/Stacks';
interface Props {
headers: HttpResponse['headers'];
}
export function ResponseHeaders({ headers }: Props) {
return (
<dl className="font-mono text-xs table-fixed w-full">
{headers.map((h, i) => {
return (
<HStack
space={3}
key={i}
className={classnames(i > 0 && 'border-t border-highlightSecondary', 'py-1')}
>
<dd className="w-1/3 text-violet-600 select-text cursor-text">{h.name}</dd>
<dt className="w-2/3 text-blue-600 select-text cursor-text break-all">{h.value}</dt>
</HStack>
);
})}
</dl>
);
}

View File

@@ -21,6 +21,7 @@ import { StatusColor } from './core/StatusColor';
import { TabContent, Tabs } from './core/Tabs/Tabs';
import { Webview } from './core/Webview';
import { EmptyStateText } from './EmptyStateText';
import { ResponseHeaders } from './ResponseHeaders';
interface Props {
style?: CSSProperties;
@@ -81,7 +82,11 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
>
<HStack
alignItems="center"
className="italic text-gray-700 text-sm w-full flex-shrink-0 -mb-1"
className={classnames(
'italic text-gray-700 text-sm w-full flex-shrink-0',
// Remove a bit of space because the tabs have lots too
'-mb-1.5',
)}
>
{activeResponse && (
<>
@@ -171,14 +176,7 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
) : null}
</TabContent>
<TabContent value="headers">
<ul>
{activeResponse?.headers.map((h) => (
<li key={h.name} className="font-mono text-xs">
<span className="text-violet-600 select-text cursor-text">{h.name}</span>:{' '}
<span className="text-blue-600 select-text cursor-text">{h.value}</span>
</li>
))}
</ul>
<ResponseHeaders headers={activeResponse?.headers ?? []} />
</TabContent>
</Tabs>
)}

View File

@@ -5,8 +5,10 @@ interface Props {
export function CountBadge({ count }: Props) {
if (count === 0) return null;
return (
<div aria-hidden className="opacity-80 text-2xs border rounded px-1 mb-0.5 ml-1 h-4">
{count}
</div>
<>
<div aria-hidden className="opacity-70 text-3xs rounded mb-0.5 ml-1 h-4 font-mono">
{count}
</div>
</>
);
}

View File

@@ -117,13 +117,12 @@ export const PairEditor = memo(function PairEditor({
);
const handleFocus = useCallback(
(pair: PairContainer) => {
const isLast = pair.id === pairs[pairs.length - 1]?.id;
if (isLast) {
setPairs((pairs) => [...pairs, newPairContainer()]);
}
},
[pairs],
(pair: PairContainer) =>
setPairs((pairs) => {
const isLast = pair.id === pairs[pairs.length - 1]?.id;
return isLast ? [...pairs, newPairContainer()] : pairs;
}),
[],
);
// Ensure there's always at least one pair
@@ -138,7 +137,7 @@ export const PairEditor = memo(function PairEditor({
className={classnames(
className,
'@container',
'overflow-auto max-h-full pb-2 grid',
'pb-2 grid',
// Move over the width of the drag handle
'-ml-3',
)}

View File

@@ -73,18 +73,15 @@ export function Tabs({
aria-label={label}
className={classnames(
tabListClassName,
'h-md flex items-center overflow-x-auto hide-scrollbars',
// Give space for button focus states within overflow boundary
'flex items-center overflow-x-auto hide-scrollbars mt-1 mb-2',
// Give space for button focus states within overflow boundary.
'px-2 -mx-2',
)}
>
<HStack space={3} className="-ml-1 flex-shrink-0">
<HStack space={1} className="flex-shrink-0">
{tabs.map((t) => {
const isActive = t.value === value;
const btnClassName = classnames(
'!px-1',
isActive ? 'text-gray-900' : 'text-gray-600 hover:text-gray-800',
);
const btnClassName = classnames(isActive ? 'bg-highlightSecondary' : 'text-gray-600');
if ('options' in t) {
const option = t.options.items.find(
(i) => 'value' in i && i.value === t.options?.value,
@@ -148,7 +145,7 @@ export const TabContent = memo(function TabContent({
<div
tabIndex={-1}
data-tab={value}
className={classnames(className, 'tab-content', 'hidden w-full h-full')}
className={classnames(className, 'tab-content', 'overflow-auto hidden w-full h-full')}
>
{children}
</div>

View File

@@ -32,6 +32,7 @@ module.exports = {
"sans": ["Inter", "sans-serif"]
},
fontSize: {
'3xs': "0.6rem",
'2xs': "0.7rem",
xs: "0.8rem",
sm: "0.9rem",