Separate active tabs per request

This commit is contained in:
Gregory Schier
2024-09-03 07:52:35 -07:00
parent ff459d1570
commit d99fe98347
3 changed files with 35 additions and 40 deletions

View File

@@ -60,6 +60,7 @@ const TAB_BODY = 'body';
const TAB_PARAMS = 'params';
const TAB_HEADERS = 'headers';
const TAB_AUTH = 'auth';
const DEFAULT_TAB = TAB_BODY;
export const RequestPane = memo(function RequestPane({
@@ -108,12 +109,7 @@ export const RequestPane = memo(function RequestPane({
if (index >= 0) {
items[index]!.readOnlyName = true;
} else {
items.push({
name,
value: '',
enabled: true,
readOnlyName: true,
});
items.push({ name, value: '', enabled: true, readOnlyName: true });
}
}
return { urlParameterPairs: items, urlParametersKey: placeholderNames.join(',') };
@@ -358,13 +354,14 @@ export const RequestPane = memo(function RequestPane({
isLoading={isLoading}
/>
<Tabs
key={activeRequest.id} // Freshen tabs on request change
value={activeTab}
label="Request"
onChangeValue={setActiveTab}
tabs={tabs}
tabListClassName="mt-2 !mb-1.5"
>
<TabContent value="auth">
<TabContent value={TAB_AUTH}>
{activeRequest.authenticationType === AUTH_TYPE_BASIC ? (
<BasicAuth key={forceUpdateKey} request={activeRequest} />
) : activeRequest.authenticationType === AUTH_TYPE_BEARER ? (
@@ -375,21 +372,21 @@ export const RequestPane = memo(function RequestPane({
</EmptyStateText>
)}
</TabContent>
<TabContent value="headers">
<TabContent value={TAB_HEADERS}>
<HeadersEditor
forceUpdateKey={`${forceUpdateHeaderEditorKey}::${forceUpdateKey}`}
headers={activeRequest.headers}
onChange={handleHeadersChange}
/>
</TabContent>
<TabContent value="params">
<TabContent value={TAB_PARAMS}>
<UrlParametersEditor
forceUpdateKey={forceUpdateKey + urlParametersKey}
pairs={urlParameterPairs}
onChange={handleUrlParametersChange}
/>
</TabContent>
<TabContent value="body">
<TabContent value={TAB_BODY}>
{activeRequest.bodyType === BODY_TYPE_JSON ? (
<Editor
forceUpdateKey={forceUpdateKey}

View File

@@ -154,20 +154,15 @@ export const ResponsePane = memo(function ResponsePane({ style, className, activ
</Banner>
) : (
<Tabs
key={activeRequest.id} // Freshen tabs on request change
value={activeTab}
onChangeValue={setActiveTab}
label="Response"
tabs={tabs}
label="Response"
className="ml-3 mr-3 mb-3"
tabListClassName="mt-1.5"
>
<TabContent value="headers">
<ResponseHeaders response={activeResponse} />
</TabContent>
<TabContent value="info">
<ResponseInfo response={activeResponse} />
</TabContent>
<TabContent value="body">
<TabContent value={TAB_BODY}>
{!activeResponse.contentLength ? (
<div className="pb-2 h-full">
<EmptyStateText>Empty Body</EmptyStateText>
@@ -192,6 +187,12 @@ export const ResponsePane = memo(function ResponsePane({ style, className, activ
/>
)}
</TabContent>
<TabContent value={TAB_HEADERS}>
<ResponseHeaders response={activeResponse} />
</TabContent>
<TabContent value={TAB_INFO}>
<ResponseInfo response={activeResponse} />
</TabContent>
</Tabs>
)}
</div>

View File

@@ -1,6 +1,6 @@
import classNames from 'classnames';
import type { ReactNode } from 'react';
import { memo, useCallback, useRef } from 'react';
import { memo, useEffect, useRef } from 'react';
import { Icon } from '../Icon';
import type { RadioDropdownProps } from '../RadioDropdown';
import { RadioDropdown } from '../RadioDropdown';
@@ -39,26 +39,23 @@ export function Tabs({
}: Props) {
const ref = useRef<HTMLDivElement | null>(null);
const handleTabChange = useCallback(
(value: string) => {
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
for (const tab of tabs ?? []) {
const v = tab.getAttribute('data-tab');
if (v === value) {
tab.setAttribute('tabindex', '-1');
tab.setAttribute('data-state', 'active');
tab.setAttribute('aria-hidden', 'false');
tab.style.display = 'block';
} else {
tab.setAttribute('data-state', 'inactive');
tab.setAttribute('aria-hidden', 'true');
tab.style.display = 'none';
}
// Update tabs when value changes
useEffect(() => {
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
for (const tab of tabs ?? []) {
const v = tab.getAttribute('data-tab');
if (v === value) {
tab.setAttribute('tabindex', '-1');
tab.setAttribute('data-state', 'active');
tab.setAttribute('aria-hidden', 'false');
tab.style.display = 'block';
} else {
tab.setAttribute('data-state', 'inactive');
tab.setAttribute('aria-hidden', 'true');
tab.style.display = 'none';
}
onChangeValue(value);
},
[onChangeValue],
);
}
}, [value]);
return (
<div
@@ -98,7 +95,7 @@ export function Tabs({
onChange={t.options.onChange}
>
<button
onClick={isActive ? undefined : () => handleTabChange(t.value)}
onClick={isActive ? undefined : () => onChangeValue(t.value)}
className={btnClassName}
>
{option && 'shortLabel' in option
@@ -116,7 +113,7 @@ export function Tabs({
return (
<button
key={t.value}
onClick={() => handleTabChange(t.value)}
onClick={() => onChangeValue(t.value)}
className={btnClassName}
>
{t.label}