Skip to content

Commit 24af992

Browse files
feat: switch to flat tabs for permission view in modals
Update src/components/Connections/ConnectionFormModal.tsx Co-authored-by: Moshe Immerman <[email protected]>
1 parent 230af1e commit 24af992

File tree

4 files changed

+172
-67
lines changed

4 files changed

+172
-67
lines changed

src/components/Connections/ConnectionFormModal.tsx

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Tab, Tabs } from "@flanksource-ui/ui/Tabs/Tabs";
1+
import FlatTabs from "@flanksource-ui/ui/Tabs/FlatTabs";
22
import React, { useEffect, useState } from "react";
33
import { Icon } from "../../ui/Icons/Icon";
44
import { Modal } from "../../ui/Modal";
@@ -128,44 +128,46 @@ export default function ConnectionFormModal({
128128
>
129129
{type ? (
130130
formValue?.id ? (
131-
<Tabs
131+
<FlatTabs
132132
activeTab={activeTab}
133-
onSelectTab={(label) => setActiveTab(label)}
134-
>
135-
<Tab
136-
label="Edit Connection"
137-
value={"form"}
138-
className="flex flex-1 flex-col"
139-
>
140-
<ConnectionForm
141-
handleBack={() => setConnectionType(undefined)}
142-
connectionType={type}
143-
onConnectionSubmit={onConnectionSubmit}
144-
onConnectionDelete={onConnectionDelete}
145-
formValue={formValue}
146-
className={className}
147-
isSubmitting={isSubmitting}
148-
isDeleting={isDeleting}
149-
/>
150-
</Tab>
151-
152-
<Tab
153-
label="Permissions"
154-
value={"permissions"}
155-
className="flex flex-1 flex-col"
156-
>
157-
<PermissionsView
158-
hideResourceColumn
159-
permissionRequest={{
160-
connectionId: formValue.id
161-
}}
162-
showAddPermission
163-
newPermissionData={{
164-
connection_id: formValue.id
165-
}}
166-
/>
167-
</Tab>
168-
</Tabs>
133+
setActiveTab={(label) => setActiveTab(label)}
134+
tabs={[
135+
{
136+
label: "Edit",
137+
key: "form",
138+
current: activeTab === "form",
139+
content: (
140+
<ConnectionForm
141+
handleBack={() => setConnectionType(undefined)}
142+
connectionType={type}
143+
onConnectionSubmit={onConnectionSubmit}
144+
onConnectionDelete={onConnectionDelete}
145+
formValue={formValue}
146+
className={className}
147+
isSubmitting={isSubmitting}
148+
isDeleting={isDeleting}
149+
/>
150+
)
151+
},
152+
{
153+
label: "Permissions",
154+
key: "permissions",
155+
current: activeTab === "permissions",
156+
content: (
157+
<PermissionsView
158+
hideResourceColumn
159+
permissionRequest={{
160+
connectionId: formValue.id
161+
}}
162+
showAddPermission
163+
newPermissionData={{
164+
connection_id: formValue.id
165+
}}
166+
/>
167+
)
168+
}
169+
]}
170+
/>
169171
) : (
170172
<ConnectionForm
171173
handleBack={() => setConnectionType(undefined)}

src/components/Playbooks/Settings/PlaybookSpecFormModal.tsx

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { PlaybookSpec } from "@flanksource-ui/api/types/playbooks";
22
import PermissionsView from "@flanksource-ui/components/Permissions/PermissionsView";
33
import { Modal } from "@flanksource-ui/ui/Modal";
4-
import { Tab, Tabs } from "@flanksource-ui/ui/Tabs/Tabs";
4+
import FlatTabs from "@flanksource-ui/ui/Tabs/FlatTabs";
55
import { useState } from "react";
66
import PlaybookSpecModalTitle from "../PlaybookSpecModalTitle";
77
import PlaybookSpecsForm from "./PlaybookSpecsForm";
@@ -37,35 +37,41 @@ export default function PlaybookSpecFormModal({
3737
helpLink="playbooks"
3838
>
3939
{playbook?.id ? (
40-
<Tabs
40+
<FlatTabs
4141
activeTab={activeTab}
42-
onSelectTab={(label) => setActiveTab(label)}
43-
>
44-
<Tab label="Edit" value={"form"} className="flex flex-1 flex-col">
45-
<PlaybookSpecsForm
46-
onClose={onClose}
47-
{...props}
48-
playbook={playbook}
49-
/>
50-
</Tab>
51-
52-
<Tab
53-
label="Permissions"
54-
value={"permissions"}
55-
className="flex flex-1 flex-col"
56-
>
57-
<PermissionsView
58-
hideResourceColumn
59-
permissionRequest={{
60-
playbookId: playbook.id
61-
}}
62-
showAddPermission
63-
newPermissionData={{
64-
playbook_id: playbook.id
65-
}}
66-
/>
67-
</Tab>
68-
</Tabs>
42+
setActiveTab={(label) => setActiveTab(label)}
43+
tabs={[
44+
{
45+
label: "Edit Playbook Spec",
46+
key: "form",
47+
current: activeTab === "form",
48+
content: (
49+
<PlaybookSpecsForm
50+
onClose={onClose}
51+
{...props}
52+
playbook={playbook}
53+
/>
54+
)
55+
},
56+
{
57+
label: "Permissions",
58+
key: "permissions",
59+
current: activeTab === "permissions",
60+
content: (
61+
<PermissionsView
62+
hideResourceColumn
63+
permissionRequest={{
64+
playbookId: playbook.id
65+
}}
66+
showAddPermission
67+
newPermissionData={{
68+
playbook_id: playbook.id
69+
}}
70+
/>
71+
)
72+
}
73+
]}
74+
/>
6975
) : (
7076
<PlaybookSpecsForm onClose={onClose} {...props} />
7177
)}

src/ui/Tabs/FlatTabs.stories.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Meta, StoryFn } from "@storybook/react";
2+
import { useState } from "react";
3+
import FlatTabs from "./FlatTabs";
4+
5+
export default {
6+
title: "ui/FlatTabs",
7+
component: FlatTabs
8+
} satisfies Meta<typeof FlatTabs>;
9+
10+
const Template: StoryFn<typeof FlatTabs> = () => {
11+
const [activeTab, setActiveTab] = useState<"tab1" | "tab2">("tab1");
12+
13+
return (
14+
<FlatTabs
15+
tabs={[
16+
{
17+
label: "Tab 1",
18+
key: "tab1",
19+
current: activeTab === "tab1",
20+
content: <div>Tab 1 content</div>
21+
},
22+
{
23+
label: "Tab 2",
24+
key: "tab2",
25+
current: activeTab === "tab2",
26+
content: <div>Tab 2 content</div>
27+
}
28+
]}
29+
activeTab={activeTab}
30+
setActiveTab={(t) => setActiveTab(t)}
31+
/>
32+
);
33+
};
34+
35+
export const Default = Template.bind({});
36+
Default.args = {};

src/ui/Tabs/FlatTabs.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import clsx from "clsx";
2+
3+
type FlatTabsProps<T extends string> = {
4+
tabs: {
5+
label: string;
6+
key: T;
7+
current: boolean;
8+
content: React.ReactNode;
9+
}[];
10+
activeTab: string;
11+
setActiveTab: (tab: T) => void;
12+
};
13+
14+
export default function FlatTabs<T extends string>({
15+
tabs,
16+
activeTab,
17+
setActiveTab
18+
}: FlatTabsProps<T>) {
19+
return (
20+
<div className="flex flex-1 flex-col">
21+
<div className="sm:hidden">
22+
<label htmlFor="tabs" className="sr-only">
23+
Select a tab
24+
</label>
25+
{/* Use an "onChange" listener to redirect the user to the selected tab URL. */}
26+
<select
27+
id="tabs"
28+
name="tabs"
29+
defaultValue={activeTab}
30+
className="block w-full rounded-md border-gray-300 focus:border-indigo-500 focus:ring-indigo-500"
31+
>
32+
{tabs.map((tab) => (
33+
<option key={tab.label}>{tab.label}</option>
34+
))}
35+
</select>
36+
</div>
37+
<div className="hidden flex-1 flex-col sm:flex">
38+
<div className="border-b border-gray-200">
39+
<nav aria-label="Tabs" className="-mb-px flex space-x-8">
40+
{tabs.map((tab) => (
41+
<button
42+
key={tab.label}
43+
onClick={() => setActiveTab(tab.key)}
44+
aria-current={tab.current ? "page" : undefined}
45+
className={clsx(
46+
tab.current
47+
? "border-indigo-500 text-indigo-600"
48+
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700",
49+
"group inline-flex items-center border-b-2 px-2 py-4 text-sm font-medium"
50+
)}
51+
>
52+
<span>{tab.label}</span>
53+
</button>
54+
))}
55+
</nav>
56+
</div>
57+
{tabs.find((tab) => tab.current)?.content}
58+
</div>
59+
</div>
60+
);
61+
}

0 commit comments

Comments
 (0)