+
+
+ }>
+ Home
+
+
+ Hosting
+
+ } disabled />
+
+ Billing
+
+
+ SEO
+
+
+
+ General settings content
+
+
+ Hosting configuration content
+
+
+ Editor preferences content
+
+
+ Billing information content
+
+
+ SEO settings content
+
+
+
{/* Assets */}
{/*
diff --git a/apps/www/utils/routes.ts b/apps/www/utils/routes.ts
index 7abaafde4..ec81d801b 100644
--- a/apps/www/utils/routes.ts
+++ b/apps/www/utils/routes.ts
@@ -92,7 +92,7 @@ export const primitivesRoutes = [
},
{ title: "Switch", slug: "docs/primitives/components/switch", newBadge: true },
{ title: "Slider", slug: "docs/primitives/components/slider", newBadge: true },
- { title: "Tabs", slug: "docs/primitives/components/tabs" },
+ { title: "Tabs", slug: "docs/primitives/components/tabs", newBadge: true },
{ title: "Table", slug: "docs/primitives/components/table" },
{
title: "Text",
diff --git a/packages/raystack/tabs/tabs.tsx b/packages/raystack/tabs/tabs.tsx
index 1d9492b4c..107be1c9f 100644
--- a/packages/raystack/tabs/tabs.tsx
+++ b/packages/raystack/tabs/tabs.tsx
@@ -4,16 +4,25 @@ import React, { ComponentPropsWithoutRef } from "react";
import styles from "./tabs.module.css";
const root = cva(styles.root);
+
+/**
+ * @deprecated Use Tabs from '@raystack/apsara/v1' instead.
+ */
export interface TabsRootProps
extends ComponentPropsWithoutRef,
VariantProps {}
+
+/**
+ * @deprecated Use TabsRoot from '@raystack/apsara/v1' instead.
+ */
const TabsRoot = ({ className, ...props }: TabsRootProps) => (
);
TabsRoot.displayName = TabsPrimitive.Root.displayName;
+
const tablist = cva(styles.tablist, {
variants: {
underline: {
@@ -24,10 +33,18 @@ const tablist = cva(styles.tablist, {
},
},
});
+
+/**
+ * @deprecated Use TabsListProps from '@raystack/apsara/v1' instead.
+ */
export interface TabsListProps
extends ComponentPropsWithoutRef,
VariantProps {}
+
+/**
+ * @deprecated Use TabsList from '@raystack/apsara/v1' instead.
+ */
const TabsList = React.forwardRef<
React.ElementRef,
TabsListProps
@@ -40,28 +57,48 @@ const TabsList = React.forwardRef<
));
TabsList.displayName = TabsPrimitive.List.displayName;
+
const content = cva(styles.content);
+
+/**
+ * @deprecated Use ContentProps from '@raystack/apsara/v1' instead.
+ */
export interface ContentProps
extends ComponentPropsWithoutRef,
VariantProps {}
+
+/**
+ * @deprecated Use Tabs from '@raystack/apsara/v1' instead.
+ */
const TabsContent = ({ className, ...props }: ContentProps) => (
);
TabsContent.displayName = TabsPrimitive.Content.displayName;
+
const trigger = cva(styles.trigger);
+
+/**
+ * @deprecated Use Tabs from '@raystack/apsara/v1' instead.
+ */
export interface TabsTriggerProps
extends ComponentPropsWithoutRef,
VariantProps {}
+/**
+ * @deprecated Use Tabs from '@raystack/apsara/v1' instead.
+ */
const TabsTrigger = ({ className, ...props }: TabsTriggerProps) => (
);
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
+/**
+ * @deprecated Use Tabs from '@raystack/apsara/v1' instead.
+ */
export const Tabs = Object.assign(TabsRoot, {
Trigger: TabsTrigger,
Content: TabsContent,
diff --git a/packages/raystack/v1/components/tabs/index.tsx b/packages/raystack/v1/components/tabs/index.tsx
new file mode 100644
index 000000000..c17b64023
--- /dev/null
+++ b/packages/raystack/v1/components/tabs/index.tsx
@@ -0,0 +1 @@
+export { Tabs } from "./tabs";
\ No newline at end of file
diff --git a/packages/raystack/v1/components/tabs/tabs.module.css b/packages/raystack/v1/components/tabs/tabs.module.css
new file mode 100644
index 000000000..8580cf9cb
--- /dev/null
+++ b/packages/raystack/v1/components/tabs/tabs.module.css
@@ -0,0 +1,77 @@
+.root {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+}
+
+.list {
+ display: flex;
+ align-items: center;
+ gap: var(--rs-space-2);
+ background-color: var(--rs-color-background-neutral-secondary);
+ padding: var(--rs-space-1);
+ border-radius: var(--rs-radius-3);
+ width: 100%;
+ box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.04) inset;
+}
+
+.trigger {
+ all: unset;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: var(--rs-space-2);
+ font-size: 12px;
+ font-weight: 500;
+ padding: var(--rs-space-2) var(--rs-space-3);
+ font-family: var(--rs-font-body);
+ color: var(--rs-color-text-base-secondary);
+ cursor: pointer;
+ border-radius: var(--rs-radius-2);
+ transition: all 0.2s ease;
+ flex: 1;
+ text-align: center;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ height: 28px;
+ line-height: 1;
+ box-sizing: border-box;
+}
+
+.trigger:hover:not([data-disabled]) {
+ color: var(--rs-color-text-base-primary);
+}
+
+.trigger[data-state='active'] {
+ background-color: var(--rs-color-background-base-primary);
+ color: var(--rs-color-text-base-primary);
+ box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.06), 0px 4px 4px -1px rgba(0, 0, 0, 0.02);
+ font-size: 12px;
+ font-weight: 500;
+}
+
+.trigger[data-disabled] {
+ opacity: 0.5;
+ cursor: not-allowed;
+ color: var(--rs-color-text-base-secondary);
+ pointer-events: none;
+}
+
+.trigger-icon {
+ display: inline-flex;
+ width: 16px;
+ height: 16px;
+ color: currentColor;
+ justify-content: center;
+ align-items: center;
+ flex-shrink: 0;
+}
+
+.content {
+ outline: none;
+}
+
+.content[data-state='inactive'] {
+ display: none;
+}
\ No newline at end of file
diff --git a/packages/raystack/v1/components/tabs/tabs.tsx b/packages/raystack/v1/components/tabs/tabs.tsx
new file mode 100644
index 000000000..f15d9967f
--- /dev/null
+++ b/packages/raystack/v1/components/tabs/tabs.tsx
@@ -0,0 +1,86 @@
+import * as TabsPrimitive from "@radix-ui/react-tabs";
+import { cva, type VariantProps } from "class-variance-authority";
+import { ComponentPropsWithoutRef, ElementRef, forwardRef, ReactNode } from "react";
+
+import styles from "./tabs.module.css";
+
+const root = cva(styles.root);
+const list = cva(styles.list);
+const trigger = cva(styles.trigger);
+const content = cva(styles.content);
+
+interface TabsRootProps
+ extends ComponentPropsWithoutRef,
+ VariantProps {
+ defaultValue?: string;
+ 'aria-label'?: string;
+}
+
+interface TabsTriggerProps
+ extends ComponentPropsWithoutRef {
+ icon?: ReactNode;
+ disabled?: boolean;
+}
+
+const TabsRoot = forwardRef, TabsRootProps>(
+ ({ className, 'aria-label': ariaLabel, ...props }, ref) => (
+
+ )
+);
+
+const TabsList = forwardRef<
+ ElementRef,
+ ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+
+const TabsTrigger = forwardRef<
+ ElementRef,
+ TabsTriggerProps
+>(({ className, icon, children, disabled, ...props }, ref) => (
+
+ {icon && {icon}}
+ {children}
+
+));
+
+const TabsContent = forwardRef<
+ ElementRef,
+ ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+
+TabsRoot.displayName = TabsPrimitive.Root.displayName;
+TabsList.displayName = TabsPrimitive.List.displayName;
+TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
+TabsContent.displayName = TabsPrimitive.Content.displayName;
+
+export const Tabs = {
+ Root: TabsRoot,
+ List: TabsList,
+ Trigger: TabsTrigger,
+ Content: TabsContent,
+};
\ No newline at end of file
diff --git a/packages/raystack/v1/index.tsx b/packages/raystack/v1/index.tsx
index 7f86435a5..833a4743c 100644
--- a/packages/raystack/v1/index.tsx
+++ b/packages/raystack/v1/index.tsx
@@ -22,6 +22,7 @@ export { Tooltip } from "./components/tooltip";
export { TextArea } from "./components/text-area";
export { Switch } from "./components/switch";
export { Slider } from "./components/slider";
+export { Tabs } from "./components/tabs";
export {
ThemeProvider,
ThemeProviderProps,