diff --git a/console/package-lock.json b/console/package-lock.json
index 369a01cc0e7..141a304119d 100644
--- a/console/package-lock.json
+++ b/console/package-lock.json
@@ -87,6 +87,7 @@
"styled-components": "5.0.1",
"styled-system": "5.1.5",
"subscriptions-transport-ws": "0.9.16",
+ "tailwindcss-radix": "^2.5.0",
"ts-essentials": "7.0.3",
"uuid": "8.3.2",
"xstate": "^4.30.1",
@@ -38429,6 +38430,11 @@
"postcss": "^8.0.9"
}
},
+ "node_modules/tailwindcss-radix": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tailwindcss-radix/-/tailwindcss-radix-2.5.0.tgz",
+ "integrity": "sha512-vPIvolTmb0L6DlvIKBJRVGo+gB7ZU2jZbO8EpZw/5gBSTHx6PezRgQhR68kOuteh3F1q2PV3oBQgaIN4FxVmrw=="
+ },
"node_modules/tailwindcss/node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -71770,6 +71776,11 @@
}
}
},
+ "tailwindcss-radix": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tailwindcss-radix/-/tailwindcss-radix-2.5.0.tgz",
+ "integrity": "sha512-vPIvolTmb0L6DlvIKBJRVGo+gB7ZU2jZbO8EpZw/5gBSTHx6PezRgQhR68kOuteh3F1q2PV3oBQgaIN4FxVmrw=="
+ },
"tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
diff --git a/console/package.json b/console/package.json
index 2f2e351652e..b0d3caf76d8 100644
--- a/console/package.json
+++ b/console/package.json
@@ -140,6 +140,7 @@
"styled-components": "5.0.1",
"styled-system": "5.1.5",
"subscriptions-transport-ws": "0.9.16",
+ "tailwindcss-radix": "^2.5.0",
"ts-essentials": "7.0.3",
"uuid": "8.3.2",
"xstate": "^4.30.1",
diff --git a/console/src/new-components/Tabs/Tabs.stories.mdx b/console/src/new-components/Tabs/Tabs.stories.mdx
new file mode 100644
index 00000000000..98fb3e84d05
--- /dev/null
+++ b/console/src/new-components/Tabs/Tabs.stories.mdx
@@ -0,0 +1,97 @@
+import { Canvas, Meta, Story } from '@storybook/addon-docs';
+import { action } from '@storybook/addon-actions';
+
+import { TemplateStoriesFactory } from '@/utils/StoryUtils';
+import { Tabs } from '@/new-components/Tabs';
+
+
{Story()}
]}
+ argTypes={{
+ value: {
+ defaultValue: 'tab-1',
+ control: {
+ type: 'select',
+ options: ['tab-1', 'tab-2', 'tab-3'],
+ },
+ },
+ onValueChange: { action: 'onValueChange' },
+ }}
+/>
+
+# Tabs 🧬
+
+- [🧰 Overview](#-overview)
+- [🐙 Code on Github](https://github.com/hasura/graphql-engine-mono/tree/main/console/src/new-components/Tabs/Tabs.tsx)
+
+## 🧰 Overview
+
+A component that display tabbed content. It is a wrapper around [radix-ui](https://www.radix-ui.com/docs/primitives/components/tabs) component. It can be used either in a controlled or uncontrolled way.
+
+### Basic usage
+
+```ts
+import { Tabs } from '@/new-components/Tabs';
+```
+
+```tsx
+ setValue(value)}
+ items={[
+ { value: 'tab-1', label: 'Tab 1', content: 'Content 1' },
+ { value: 'tab-2', label: 'Tab 2', content: 'Content 2' },
+ { value: 'tab-3', label: 'Tab 3', content: 'Content 3' },
+ ]}
+/>
+```
+
+export const Template = ({ value, onValueChange, ...rest }) => (
+
+);
+
+
+
+
+
+#### 🚦 Usage
+
+The component accepts all the props of the radix-ui [Tabs](https://www.radix-ui.com/docs/primitives/components/tabs) root component.
+
+- If used in a controlled way (e.g. the state of tabs navigation is stored in the URL), you should pass:
+ - `value`: the id of the selected tab
+ - `onValueChange`: the callback to be called when the tab is changed
+- The `items` prop is an array of objects that contain the following properties:
+ - `value`: the id of the tab
+ - `label`: the label of the tab
+ - `content`: the content of the tab
+
+```
+
+```
diff --git a/console/src/new-components/Tabs/Tabs.tsx b/console/src/new-components/Tabs/Tabs.tsx
new file mode 100644
index 00000000000..2eb3449ded7
--- /dev/null
+++ b/console/src/new-components/Tabs/Tabs.tsx
@@ -0,0 +1,41 @@
+import React from 'react';
+import * as RadixTabs from '@radix-ui/react-tabs';
+import clsx from 'clsx';
+
+interface TabsItem {
+ value: string;
+ label: string;
+ content: React.ReactNode;
+}
+
+interface TabsProps extends React.ComponentProps {
+ items: TabsItem[];
+}
+
+export const Tabs: React.FC = props => {
+ const { items, ...rest } = props;
+ return (
+
+
+
+ {items.map(({ value: itemValue, label }) => (
+
+
+
+ ))}
+
+
+ {items.map(({ value: itemValue, content }) => (
+ {content}
+ ))}
+
+ );
+};
diff --git a/console/src/new-components/Tabs/index.tsx b/console/src/new-components/Tabs/index.tsx
new file mode 100644
index 00000000000..856dbbb347c
--- /dev/null
+++ b/console/src/new-components/Tabs/index.tsx
@@ -0,0 +1 @@
+export * from './Tabs';
diff --git a/console/tailwind.config.js b/console/tailwind.config.js
index eb4dfd32780..e5dc691f990 100644
--- a/console/tailwind.config.js
+++ b/console/tailwind.config.js
@@ -82,5 +82,9 @@ module.exports = {
},
},
},
- plugins: [require('@tailwindcss/typography'), require('@tailwindcss/forms')],
+ plugins: [
+ require('@tailwindcss/typography'),
+ require('@tailwindcss/forms'),
+ require('tailwindcss-radix')(),
+ ],
};