Skip to content

Commit baa7040

Browse files
committed
Add rest console tabs
1 parent 8d6d153 commit baa7040

11 files changed

Lines changed: 767 additions & 835 deletions

File tree

Lines changed: 78 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,103 @@
1-
import type * as React from "react";
21
import { cva, type VariantProps } from "class-variance-authority";
2+
import type * as React from "react";
33
import { Input } from "#shadcn/components/ui/input";
44
import {
5-
Select,
6-
SelectContent,
7-
SelectItem,
8-
SelectTrigger,
9-
SelectValue,
5+
Select,
6+
SelectContent,
7+
SelectItem,
8+
SelectTrigger,
9+
SelectValue,
1010
} from "#shadcn/components/ui/select";
1111
import { cn } from "#shadcn/lib/utils";
1212
import { CopyIcon } from "./copy-icon";
1313

1414
const requestMethodVariants = cva(
15-
"min-w-26 border-r-0 rounded-r-none shadow-none typo-label text-left items-start",
16-
{
17-
variants: {
18-
method: {
19-
GET: "text-utility-green [&_svg]:text-utility-green",
20-
POST: "text-utility-yellow [&_svg]:text-utility-yellow",
21-
PUT: "text-utility-blue [&_svg]:text-utility-blue ",
22-
PATCH: "text-utility-violet [&_svg]:text-utility-violet",
23-
DELETE: "text-utility-red [&_svg]:text-utility-red",
24-
},
25-
},
26-
defaultVariants: {
27-
method: "GET",
28-
},
29-
}
15+
"border-r-0 rounded-r-none shadow-none typo-label text-left items-start",
16+
{
17+
variants: {
18+
method: {
19+
GET: "text-utility-green [&_svg]:text-utility-green",
20+
POST: "text-utility-yellow [&_svg]:text-utility-yellow",
21+
PUT: "text-utility-blue [&_svg]:text-utility-blue ",
22+
PATCH: "text-utility-violet [&_svg]:text-utility-violet",
23+
DELETE: "text-utility-red [&_svg]:text-utility-red",
24+
},
25+
},
26+
defaultVariants: {
27+
method: "GET",
28+
},
29+
},
3030
);
3131

3232
type RequestMethod = VariantProps<typeof requestMethodVariants>["method"];
3333

3434
interface RequestLineEditorProps extends React.ComponentProps<"div"> {
35-
selectedMethod: string;
36-
setMethod: (value: string) => void;
37-
methods: string[];
38-
inputValue?: string | undefined;
39-
onInputChange?: React.ChangeEventHandler<HTMLInputElement>;
35+
selectedMethod: string;
36+
setMethod: (value: string) => void;
37+
methods: string[];
38+
inputValue?: string | undefined;
39+
onInputChange?: React.ChangeEventHandler<HTMLInputElement>;
4040
}
4141

4242
function RequestMethodSelector({
43-
selectedMethod,
44-
setMethod,
45-
methods,
43+
selectedMethod,
44+
setMethod,
45+
methods,
4646
}: RequestLineEditorProps) {
47-
return (
48-
<Select value={selectedMethod} onValueChange={setMethod}>
49-
<SelectTrigger
50-
className={cn(
51-
requestMethodVariants({ method: selectedMethod as RequestMethod })
52-
)}
53-
>
54-
<SelectValue />
55-
</SelectTrigger>
56-
<SelectContent>
57-
{methods.map((method) => (
58-
<SelectItem key={method} value={method}>
59-
<span
60-
className={cn(
61-
requestMethodVariants({ method: method as RequestMethod })
62-
)}
63-
>
64-
{method}
65-
</span>
66-
</SelectItem>
67-
))}
68-
</SelectContent>
69-
</Select>
70-
);
47+
return (
48+
<Select value={selectedMethod} onValueChange={setMethod}>
49+
<SelectTrigger
50+
className={cn(
51+
"w-30",
52+
requestMethodVariants({ method: selectedMethod as RequestMethod }),
53+
)}
54+
>
55+
<SelectValue />
56+
</SelectTrigger>
57+
<SelectContent>
58+
{methods.map((method) => (
59+
<SelectItem key={method} value={method}>
60+
<span
61+
className={cn(
62+
requestMethodVariants({ method: method as RequestMethod }),
63+
)}
64+
>
65+
{method}
66+
</span>
67+
</SelectItem>
68+
))}
69+
</SelectContent>
70+
</Select>
71+
);
7172
}
7273

7374
function RequestLineEditor({
74-
className,
75-
selectedMethod,
76-
setMethod,
77-
methods,
78-
inputValue,
79-
onInputChange,
75+
className,
76+
selectedMethod,
77+
setMethod,
78+
methods,
79+
inputValue,
80+
onInputChange,
8081
}: RequestLineEditorProps) {
81-
return (
82-
<div className={cn("flex", className)}>
83-
<RequestMethodSelector
84-
selectedMethod={selectedMethod}
85-
setMethod={setMethod}
86-
methods={methods}
87-
/>
88-
<Input
89-
className="rounded-l-none"
90-
value={inputValue}
91-
rightSlot={<CopyIcon text={`${selectedMethod} ${inputValue}`} />}
92-
{...(onInputChange !== undefined ? { onChange: onInputChange } : {})}
93-
/>
94-
</div>
95-
);
82+
return (
83+
<div className={cn("flex", className)}>
84+
<RequestMethodSelector
85+
selectedMethod={selectedMethod}
86+
setMethod={setMethod}
87+
methods={methods}
88+
/>
89+
<Input
90+
className="rounded-l-none"
91+
value={inputValue}
92+
rightSlot={<CopyIcon text={`${selectedMethod} ${inputValue}`} />}
93+
{...(onInputChange !== undefined ? { onChange: onInputChange } : {})}
94+
/>
95+
</div>
96+
);
9697
}
9798

9899
export {
99-
RequestLineEditor,
100-
type RequestLineEditorProps,
101-
requestMethodVariants,
100+
RequestLineEditor,
101+
type RequestLineEditorProps,
102+
requestMethodVariants,
102103
};

packages/react-components/src/components/rest-console-tabs.stories.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ function RestConsoleTabsWrapper({
2222
tabs: Tab[];
2323
selectedTabId: string;
2424
}) {
25-
const [currentSelectedTabId, setSelectedTabId] = React.useState(selectedTabId);
25+
const [currentSelectedTabId, setSelectedTabId] =
26+
React.useState(selectedTabId);
2627
const [currentTabs, setTabs] = React.useState(tabs);
2728

2829
const handleSelectTab = (tabId: string) => {
@@ -32,7 +33,7 @@ function RestConsoleTabsWrapper({
3233

3334
const handleCloseTab = (tabId: string) => {
3435
action("onCloseTab")(tabId);
35-
const updatedTabs = currentTabs.filter(tab => tab.id !== tabId);
36+
const updatedTabs = currentTabs.filter((tab) => tab.id !== tabId);
3637
setTabs(updatedTabs);
3738
};
3839

@@ -79,11 +80,10 @@ const manyTabs: Tab[] = [
7980
},
8081
];
8182

82-
8383
export const Default: Story = {
8484
args: {
8585
tabs: manyTabs,
8686
selectedTabId: "3",
8787
},
8888
render: (args) => <RestConsoleTabsWrapper {...args} />,
89-
};
89+
};
Lines changed: 77 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,84 @@
1+
import { X } from "lucide-react";
2+
import * as React from "react";
13
import { Button } from "#shadcn/components/ui/button.js";
24
import { Separator } from "#shadcn/components/ui/separator.js";
35
import { Tabs, TabsList, TabsTrigger } from "#shadcn/components/ui/tabs";
4-
import { Tooltip, TooltipContent, TooltipTrigger } from "#shadcn/components/ui/tooltip.js";
5-
import { X } from "lucide-react";
6-
import * as React from "react";
7-
import { requestMethodVariants } from "./request-line-editor.js";
6+
import {
7+
Tooltip,
8+
TooltipContent,
9+
TooltipTrigger,
10+
} from "#shadcn/components/ui/tooltip.js";
811
import { cn } from "#shadcn/lib/utils";
12+
import { requestMethodVariants } from "./request-line-editor.js";
913

1014
export type Tab = {
11-
id: string;
12-
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
13-
path: string;
14-
}
15-
15+
id: string;
16+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
17+
path: string;
18+
};
1619

17-
export const RestConsoleTabs = ({ tabs, selectedTabId, onSelectTab, onCloseTab }: { tabs: Tab[], selectedTabId: string, onSelectTab: (val: string) => void, onCloseTab: (val: string) => void }) => {
18-
return (
19-
<Tabs defaultValue={selectedTabId} className="overflow-x-auto overflow-y-hidden h-10">
20-
<TabsList className="w-full">
21-
{tabs.map((tab, index) => (
22-
<React.Fragment key={tab.id}>
23-
<TabsTrigger
24-
value={tab.id}
25-
className="max-w-80 w-50 min-w-30"
26-
onClick={() => onSelectTab(tab.id)}
27-
>
28-
<Tooltip delayDuration={400}>
29-
<TooltipTrigger asChild>
30-
<span className="w-full flex items-center justify-between">
31-
<span className="truncate">
32-
<span
33-
className={cn(requestMethodVariants({ method: tab.method }), "mr-1")}
34-
>
35-
{tab.method}
36-
</span>
37-
{tab.path || "New request"}
38-
</span>
39-
<Button
40-
variant="link"
41-
className="p-0 ml-2"
42-
asChild
43-
onClick={(e) => {
44-
e.stopPropagation()
45-
onCloseTab(tab.id)
46-
}}
47-
>
48-
<span>
49-
<X size={16} />
50-
</span>
51-
</Button>
52-
</span>
53-
</TooltipTrigger>
54-
<TooltipContent className="max-w-60">
55-
{tab.method} {tab.path}
56-
</TooltipContent>
57-
</Tooltip>
58-
</TabsTrigger>
59-
{index < tabs.length - 1 && <Separator orientation="vertical" />}
60-
</React.Fragment>
61-
))}
62-
</TabsList>
63-
</Tabs>
64-
)
65-
}
20+
export const RestConsoleTabs = ({
21+
tabs,
22+
selectedTabId,
23+
onSelectTab,
24+
onCloseTab,
25+
}: {
26+
tabs: Tab[];
27+
selectedTabId: string;
28+
onSelectTab: (val: string) => void;
29+
onCloseTab: (val: string) => void;
30+
}) => {
31+
return (
32+
<Tabs
33+
defaultValue={selectedTabId}
34+
className="overflow-x-auto overflow-y-hidden h-10"
35+
>
36+
<TabsList className="w-full">
37+
{tabs.map((tab, index) => (
38+
<React.Fragment key={tab.id}>
39+
<TabsTrigger
40+
value={tab.id}
41+
className="max-w-80 w-50 min-w-30"
42+
onClick={() => onSelectTab(tab.id)}
43+
>
44+
<Tooltip delayDuration={400}>
45+
<TooltipTrigger asChild>
46+
<span className="w-full flex items-center justify-between">
47+
<span className="truncate">
48+
<span
49+
className={cn(
50+
requestMethodVariants({ method: tab.method }),
51+
"mr-1",
52+
)}
53+
>
54+
{tab.method}
55+
</span>
56+
{tab.path || "New request"}
57+
</span>
58+
<Button
59+
variant="link"
60+
className="p-0 ml-2"
61+
asChild
62+
onClick={(e) => {
63+
e.stopPropagation();
64+
onCloseTab(tab.id);
65+
}}
66+
>
67+
<span>
68+
<X size={16} />
69+
</span>
70+
</Button>
71+
</span>
72+
</TooltipTrigger>
73+
<TooltipContent className="max-w-60">
74+
{tab.method} {tab.path}
75+
</TooltipContent>
76+
</Tooltip>
77+
</TabsTrigger>
78+
{index < tabs.length - 1 && <Separator orientation="vertical" />}
79+
</React.Fragment>
80+
))}
81+
</TabsList>
82+
</Tabs>
83+
);
84+
};

packages/react-components/src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
export * from "./components/code-editor";
44
export * from "./components/copy-icon";
55
export * from "./components/request-line-editor";
6+
export * from "./components/rest-console-tabs";
67
export * from "./shadcn/components/ui/accordion";
78
export * from "./shadcn/components/ui/alert";
89
export * from "./shadcn/components/ui/alert-dialog";

0 commit comments

Comments
 (0)