diff --git a/apps/dashboard/knip.json b/apps/dashboard/knip.json
index 096ded6dc71..9d3a56b9ed3 100644
--- a/apps/dashboard/knip.json
+++ b/apps/dashboard/knip.json
@@ -1,21 +1,22 @@
{
- "$schema": "https://unpkg.com/knip@5/schema.json",
- "ignore": [
- "src/@/components/ui/**",
- "src/@/components/misc/AnnouncementBanner.tsx",
- "src/@/components/cmd-k-search/index.tsx",
- "src/@/lib/search.ts"
- ],
- "ignoreBinaries": ["only-allow"],
- "ignoreDependencies": [
- "@thirdweb-dev/service-utils",
- "@thirdweb-dev/vault-sdk",
- "thirdweb",
- "@types/color",
- "fast-xml-parser",
- "@workspace/ui",
- "tailwindcss-animate"
- ],
- "next": true,
- "project": ["src/**"]
+ "$schema": "https://unpkg.com/knip@5/schema.json",
+ "ignore": [
+ "src/@/components/ui/**",
+ "src/@/components/misc/AnnouncementBanner.tsx",
+ "src/@/components/cmd-k-search/index.tsx",
+ "src/@/lib/search.ts"
+ ],
+ "ignoreBinaries": ["only-allow"],
+ "ignoreDependencies": [
+ "@thirdweb-dev/service-utils",
+ "@thirdweb-dev/vault-sdk",
+ "thirdweb",
+ "@types/color",
+ "fast-xml-parser",
+ "@workspace/ui",
+ "tailwindcss-animate",
+ "@radix-ui/react-tooltip"
+ ],
+ "next": true,
+ "project": ["src/**"]
}
diff --git a/apps/dashboard/src/@/components/ui/breadcrumb.tsx b/apps/dashboard/src/@/components/ui/breadcrumb.tsx
index 60e4b7848a3..81387aa654e 100644
--- a/apps/dashboard/src/@/components/ui/breadcrumb.tsx
+++ b/apps/dashboard/src/@/components/ui/breadcrumb.tsx
@@ -1,119 +1,9 @@
-import { Slot } from "@radix-ui/react-slot";
-import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-
-const Breadcrumb = React.forwardRef<
- HTMLElement,
- React.ComponentPropsWithoutRef<"nav"> & {
- separator?: React.ReactNode;
- }
->(({ ...props }, ref) => );
-Breadcrumb.displayName = "Breadcrumb";
-
-const BreadcrumbList = React.forwardRef<
- HTMLOListElement,
- React.ComponentPropsWithoutRef<"ol">
->(({ className, ...props }, ref) => (
-
-));
-BreadcrumbList.displayName = "BreadcrumbList";
-
-const BreadcrumbItem = React.forwardRef<
- HTMLLIElement,
- React.ComponentPropsWithoutRef<"li">
->(({ className, ...props }, ref) => (
-
-));
-BreadcrumbItem.displayName = "BreadcrumbItem";
-
-const BreadcrumbLink = React.forwardRef<
- HTMLAnchorElement,
- React.ComponentPropsWithoutRef<"a"> & {
- asChild?: boolean;
- }
->(({ asChild, className, ...props }, ref) => {
- const Comp = asChild ? Slot : "a";
-
- return (
-
- );
-});
-BreadcrumbLink.displayName = "BreadcrumbLink";
-
-const BreadcrumbPage = React.forwardRef<
- HTMLSpanElement,
- React.ComponentPropsWithoutRef<"span">
->(({ className, ...props }, ref) => (
- // biome-ignore lint/a11y/useFocusableInteractive: required
-
-));
-BreadcrumbPage.displayName = "BreadcrumbPage";
-
-const BreadcrumbSeparator = ({
- children,
- className,
- ...props
-}: React.ComponentProps<"li">) => (
- svg]:size-3.5", className)}
- role="presentation"
- {...props}
- >
- {children ?? }
-
-);
-BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
-
-const BreadcrumbEllipsis = ({
- className,
- ...props
-}: React.ComponentProps<"span">) => (
-
-
- More
-
-);
-BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";
-
export {
Breadcrumb,
- BreadcrumbList,
+ BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
+ BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
- BreadcrumbEllipsis,
-};
+} from "@workspace/ui/components/breadcrumb";
diff --git a/apps/dashboard/src/@/components/ui/table.tsx b/apps/dashboard/src/@/components/ui/table.tsx
index 45a19a3f65b..6e0ee05fa4b 100644
--- a/apps/dashboard/src/@/components/ui/table.tsx
+++ b/apps/dashboard/src/@/components/ui/table.tsx
@@ -1,156 +1,11 @@
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-import { ScrollShadow } from "./ScrollShadow";
-
-const Table = React.forwardRef<
- HTMLTableElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-Table.displayName = "Table";
-
-const TableHeader = React.forwardRef<
- HTMLTableSectionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-
-TableHeader.displayName = "TableHeader";
-
-const TableBody = React.forwardRef<
- HTMLTableSectionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-TableBody.displayName = "TableBody";
-
-const TableFooter = React.forwardRef<
- HTMLTableSectionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
- tr]:last:border-b-0",
- className,
- )}
- ref={ref}
- {...props}
- />
-));
-TableFooter.displayName = "TableFooter";
-
-const TableRow = React.forwardRef<
- HTMLTableRowElement,
- React.HTMLAttributes & {
- /**
- * Contain the absolutely position elements inside the row with position:relative + transform:translate(0)
- * transform:translate(0) is required because position:relative on tr element does not work on webkit
- */
- linkBox?: boolean;
- }
->(({ className, linkBox, ...props }, ref) => (
-
-));
-TableRow.displayName = "TableRow";
-
-const TableHead = React.forwardRef<
- HTMLTableCellElement,
- React.ThHTMLAttributes
->(({ className, ...props }, ref) => (
- |
-));
-TableHead.displayName = "TableHead";
-
-const TableCell = React.forwardRef<
- HTMLTableCellElement,
- React.TdHTMLAttributes
->(({ className, ...props }, ref) => (
- |
-));
-TableCell.displayName = "TableCell";
-
-const TableCaption = React.forwardRef<
- HTMLTableCaptionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-TableCaption.displayName = "TableCaption";
-
-function TableContainer(props: {
- children: React.ReactNode;
- className?: string;
- scrollableContainerClassName?: string;
-}) {
- return (
-
- {props.children}
-
- );
-}
-
export {
Table,
- TableHeader,
TableBody,
+ TableCaption,
+ TableCell,
+ TableContainer,
TableFooter,
TableHead,
+ TableHeader,
TableRow,
- TableCell,
- TableCaption,
- TableContainer,
-};
+} from "@workspace/ui/components/table";
diff --git a/apps/dashboard/src/@/components/ui/tooltip.tsx b/apps/dashboard/src/@/components/ui/tooltip.tsx
index 687bfe4fac7..aaec58492d3 100644
--- a/apps/dashboard/src/@/components/ui/tooltip.tsx
+++ b/apps/dashboard/src/@/components/ui/tooltip.tsx
@@ -1,70 +1,9 @@
"use client";
-import * as TooltipPrimitive from "@radix-ui/react-tooltip";
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-
-const TooltipProvider = TooltipPrimitive.Provider;
-
-const Tooltip = TooltipPrimitive.Root;
-
-const TooltipTrigger = TooltipPrimitive.Trigger;
-
-const TooltipContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, sideOffset = 4, ...props }, ref) => (
-
-));
-TooltipContent.displayName = TooltipPrimitive.Content.displayName;
-
-export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
-
-export function ToolTipLabel(props: {
- children: React.ReactNode;
- label: React.ReactNode;
- rightIcon?: React.ReactNode;
- leftIcon?: React.ReactNode;
- hoverable?: boolean;
- contentClassName?: string;
- side?: "top" | "right" | "bottom" | "left";
- align?: "center" | "start" | "end";
-}) {
- if (!props.label) {
- return props.children;
- }
-
- return (
-
-
-
- {props.children}
-
-
-
- {props.leftIcon}
- {props.label}
- {props.rightIcon}
-
-
-
-
- );
-}
+export {
+ ToolTipLabel,
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@workspace/ui/components/tooltip";
diff --git a/apps/playground-web/knip.json b/apps/playground-web/knip.json
index 5953eef3678..c4187581b15 100644
--- a/apps/playground-web/knip.json
+++ b/apps/playground-web/knip.json
@@ -1,7 +1,12 @@
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"ignore": ["src/components/ui/**", "src/app/insight/utils.ts"],
- "ignoreDependencies": ["server-only", "@workspace/ui", "tailwindcss-animate"],
+ "ignoreDependencies": [
+ "server-only",
+ "@workspace/ui",
+ "tailwindcss-animate",
+ "@radix-ui/react-tooltip"
+ ],
"next": true,
"project": ["src/**"]
}
diff --git a/apps/playground-web/src/components/ui/breadcrumb.tsx b/apps/playground-web/src/components/ui/breadcrumb.tsx
index 0ea38b62151..81387aa654e 100644
--- a/apps/playground-web/src/components/ui/breadcrumb.tsx
+++ b/apps/playground-web/src/components/ui/breadcrumb.tsx
@@ -1,116 +1,9 @@
-import { Slot } from "@radix-ui/react-slot";
-import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-
-const Breadcrumb = React.forwardRef<
- HTMLElement,
- React.ComponentPropsWithoutRef<"nav"> & {
- separator?: React.ReactNode;
- }
->(({ ...props }, ref) => );
-Breadcrumb.displayName = "Breadcrumb";
-
-const BreadcrumbList = React.forwardRef<
- HTMLOListElement,
- React.ComponentPropsWithoutRef<"ol">
->(({ className, ...props }, ref) => (
-
-));
-BreadcrumbList.displayName = "BreadcrumbList";
-
-const BreadcrumbItem = React.forwardRef<
- HTMLLIElement,
- React.ComponentPropsWithoutRef<"li">
->(({ className, ...props }, ref) => (
-
-));
-BreadcrumbItem.displayName = "BreadcrumbItem";
-
-const BreadcrumbLink = React.forwardRef<
- HTMLAnchorElement,
- React.ComponentPropsWithoutRef<"a"> & {
- asChild?: boolean;
- }
->(({ asChild, className, ...props }, ref) => {
- const Comp = asChild ? Slot : "a";
-
- return (
-
- );
-});
-BreadcrumbLink.displayName = "BreadcrumbLink";
-
-const BreadcrumbPage = React.forwardRef<
- HTMLSpanElement,
- React.ComponentPropsWithoutRef<"span">
->(({ className, ...props }, ref) => (
- // biome-ignore lint/a11y/useFocusableInteractive: required
-
-));
-BreadcrumbPage.displayName = "BreadcrumbPage";
-
-const BreadcrumbSeparator = ({
- children,
- className,
- ...props
-}: React.ComponentProps<"li">) => (
- svg]:size-3.5", className)}
- role="presentation"
- {...props}
- >
- {children ?? }
-
-);
-BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
-
-const BreadcrumbEllipsis = ({
- className,
- ...props
-}: React.ComponentProps<"span">) => (
-
-
- More
-
-);
-BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";
-
export {
Breadcrumb,
- BreadcrumbList,
+ BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
+ BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
- BreadcrumbEllipsis,
-};
+} from "@workspace/ui/components/breadcrumb";
diff --git a/apps/playground-web/src/components/ui/table.tsx b/apps/playground-web/src/components/ui/table.tsx
index 45a19a3f65b..6e0ee05fa4b 100644
--- a/apps/playground-web/src/components/ui/table.tsx
+++ b/apps/playground-web/src/components/ui/table.tsx
@@ -1,156 +1,11 @@
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-import { ScrollShadow } from "./ScrollShadow";
-
-const Table = React.forwardRef<
- HTMLTableElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-Table.displayName = "Table";
-
-const TableHeader = React.forwardRef<
- HTMLTableSectionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-
-TableHeader.displayName = "TableHeader";
-
-const TableBody = React.forwardRef<
- HTMLTableSectionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-TableBody.displayName = "TableBody";
-
-const TableFooter = React.forwardRef<
- HTMLTableSectionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
- tr]:last:border-b-0",
- className,
- )}
- ref={ref}
- {...props}
- />
-));
-TableFooter.displayName = "TableFooter";
-
-const TableRow = React.forwardRef<
- HTMLTableRowElement,
- React.HTMLAttributes & {
- /**
- * Contain the absolutely position elements inside the row with position:relative + transform:translate(0)
- * transform:translate(0) is required because position:relative on tr element does not work on webkit
- */
- linkBox?: boolean;
- }
->(({ className, linkBox, ...props }, ref) => (
-
-));
-TableRow.displayName = "TableRow";
-
-const TableHead = React.forwardRef<
- HTMLTableCellElement,
- React.ThHTMLAttributes
->(({ className, ...props }, ref) => (
- |
-));
-TableHead.displayName = "TableHead";
-
-const TableCell = React.forwardRef<
- HTMLTableCellElement,
- React.TdHTMLAttributes
->(({ className, ...props }, ref) => (
- |
-));
-TableCell.displayName = "TableCell";
-
-const TableCaption = React.forwardRef<
- HTMLTableCaptionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-TableCaption.displayName = "TableCaption";
-
-function TableContainer(props: {
- children: React.ReactNode;
- className?: string;
- scrollableContainerClassName?: string;
-}) {
- return (
-
- {props.children}
-
- );
-}
-
export {
Table,
- TableHeader,
TableBody,
+ TableCaption,
+ TableCell,
+ TableContainer,
TableFooter,
TableHead,
+ TableHeader,
TableRow,
- TableCell,
- TableCaption,
- TableContainer,
-};
+} from "@workspace/ui/components/table";
diff --git a/apps/playground-web/src/components/ui/tooltip.tsx b/apps/playground-web/src/components/ui/tooltip.tsx
index 28ab2e10b6b..aaec58492d3 100644
--- a/apps/playground-web/src/components/ui/tooltip.tsx
+++ b/apps/playground-web/src/components/ui/tooltip.tsx
@@ -1,70 +1,9 @@
"use client";
-import * as TooltipPrimitive from "@radix-ui/react-tooltip";
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-
-const TooltipProvider = TooltipPrimitive.Provider;
-
-const Tooltip = TooltipPrimitive.Root;
-
-const TooltipTrigger = TooltipPrimitive.Trigger;
-
-const TooltipContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, sideOffset = 4, ...props }, ref) => (
-
-));
-TooltipContent.displayName = TooltipPrimitive.Content.displayName;
-
-export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
-
-export function ToolTipLabel(props: {
- children: React.ReactNode;
- label: React.ReactNode;
- rightIcon?: React.ReactNode;
- leftIcon?: React.ReactNode;
- hoverable?: boolean;
- contentClassName?: string;
- side?: "top" | "right" | "bottom" | "left";
- align?: "center" | "start" | "end";
-}) {
- if (!props.label) {
- return props.children;
- }
-
- return (
-
-
-
- {props.children}
-
-
-
- {props.leftIcon}
- {props.label}
- {props.rightIcon}
-
-
-
-
- );
-}
+export {
+ ToolTipLabel,
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@workspace/ui/components/tooltip";
diff --git a/apps/portal/knip.json b/apps/portal/knip.json
index eef6701a4fc..e7b605cc90e 100644
--- a/apps/portal/knip.json
+++ b/apps/portal/knip.json
@@ -2,8 +2,6 @@
"$schema": "https://unpkg.com/knip@5/schema.json",
"entry": [
"next.config.{js,ts,cjs,mjs}",
- "app/**/route.{js,jsx,ts,tsx}",
- "app/**/{icon,apple-icon}.{js,jsx,ts,tsx}",
"src/app/**/{error,layout,loading,not-found,page,template,default}.{js,jsx,ts,tsx,mdx}",
"scripts/*.ts"
],
@@ -21,7 +19,8 @@
"@types/flexsearch",
"@radix-ui/react-slot",
"tailwindcss-animate",
- "class-variance-authority"
+ "class-variance-authority",
+ "@radix-ui/react-tooltip"
],
"next": true,
"project": ["src/**"]
diff --git a/apps/portal/src/components/ui/table.tsx b/apps/portal/src/components/ui/table.tsx
index fa180a3c829..6e0ee05fa4b 100644
--- a/apps/portal/src/components/ui/table.tsx
+++ b/apps/portal/src/components/ui/table.tsx
@@ -1,151 +1,11 @@
-import * as React from "react";
-import { ScrollShadow } from "@/components/ui/ScrollShadow"; // Path within portal/components/ui
-import { cn } from "@/lib/utils"; // Adjusted path for portal
-
-const Table = React.forwardRef<
- HTMLTableElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-Table.displayName = "Table";
-
-const TableHeader = React.forwardRef<
- HTMLTableSectionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-
-TableHeader.displayName = "TableHeader";
-
-const TableBody = React.forwardRef<
- HTMLTableSectionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-TableBody.displayName = "TableBody";
-
-const TableFooter = React.forwardRef<
- HTMLTableSectionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
- tr]:last:border-b-0",
- className,
- )}
- ref={ref}
- {...props}
- />
-));
-TableFooter.displayName = "TableFooter";
-
-const TableRow = React.forwardRef<
- HTMLTableRowElement,
- React.HTMLAttributes & {
- linkBox?: boolean;
- }
->(({ className, linkBox, ...props }, ref) => (
-
-));
-TableRow.displayName = "TableRow";
-
-const TableHead = React.forwardRef<
- HTMLTableCellElement,
- React.ThHTMLAttributes
->(({ className, ...props }, ref) => (
- |
-));
-TableHead.displayName = "TableHead";
-
-const TableCell = React.forwardRef<
- HTMLTableCellElement,
- React.TdHTMLAttributes
->(({ className, ...props }, ref) => (
- |
-));
-TableCell.displayName = "TableCell";
-
-const TableCaption = React.forwardRef<
- HTMLTableCaptionElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-));
-TableCaption.displayName = "TableCaption";
-
-function TableContainer(props: {
- children: React.ReactNode;
- className?: string;
- scrollableContainerClassName?: string;
-}) {
- return (
-
- {props.children}
-
- );
-}
-
export {
Table,
- TableHeader,
TableBody,
+ TableCaption,
+ TableCell,
+ TableContainer,
TableFooter,
TableHead,
+ TableHeader,
TableRow,
- TableCell,
- TableCaption,
- TableContainer,
-};
+} from "@workspace/ui/components/table";
diff --git a/apps/portal/src/components/ui/tooltip.tsx b/apps/portal/src/components/ui/tooltip.tsx
index 28ab2e10b6b..aaec58492d3 100644
--- a/apps/portal/src/components/ui/tooltip.tsx
+++ b/apps/portal/src/components/ui/tooltip.tsx
@@ -1,70 +1,9 @@
"use client";
-import * as TooltipPrimitive from "@radix-ui/react-tooltip";
-import * as React from "react";
-
-import { cn } from "@/lib/utils";
-
-const TooltipProvider = TooltipPrimitive.Provider;
-
-const Tooltip = TooltipPrimitive.Root;
-
-const TooltipTrigger = TooltipPrimitive.Trigger;
-
-const TooltipContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, sideOffset = 4, ...props }, ref) => (
-
-));
-TooltipContent.displayName = TooltipPrimitive.Content.displayName;
-
-export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
-
-export function ToolTipLabel(props: {
- children: React.ReactNode;
- label: React.ReactNode;
- rightIcon?: React.ReactNode;
- leftIcon?: React.ReactNode;
- hoverable?: boolean;
- contentClassName?: string;
- side?: "top" | "right" | "bottom" | "left";
- align?: "center" | "start" | "end";
-}) {
- if (!props.label) {
- return props.children;
- }
-
- return (
-
-
-
- {props.children}
-
-
-
- {props.leftIcon}
- {props.label}
- {props.rightIcon}
-
-
-
-
- );
-}
+export {
+ ToolTipLabel,
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@workspace/ui/components/tooltip";
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 56d9cbad813..b07a58afcb9 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -16,6 +16,7 @@
"dependencies": {
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-slot": "^1.2.3",
+ "@radix-ui/react-tooltip": "1.2.7",
"@tanstack/react-query": "5.81.5",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
diff --git a/packages/ui/src/components/breadcrumb.tsx b/packages/ui/src/components/breadcrumb.tsx
new file mode 100644
index 00000000000..60e4b7848a3
--- /dev/null
+++ b/packages/ui/src/components/breadcrumb.tsx
@@ -0,0 +1,119 @@
+import { Slot } from "@radix-ui/react-slot";
+import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Breadcrumb = React.forwardRef<
+ HTMLElement,
+ React.ComponentPropsWithoutRef<"nav"> & {
+ separator?: React.ReactNode;
+ }
+>(({ ...props }, ref) => );
+Breadcrumb.displayName = "Breadcrumb";
+
+const BreadcrumbList = React.forwardRef<
+ HTMLOListElement,
+ React.ComponentPropsWithoutRef<"ol">
+>(({ className, ...props }, ref) => (
+
+));
+BreadcrumbList.displayName = "BreadcrumbList";
+
+const BreadcrumbItem = React.forwardRef<
+ HTMLLIElement,
+ React.ComponentPropsWithoutRef<"li">
+>(({ className, ...props }, ref) => (
+
+));
+BreadcrumbItem.displayName = "BreadcrumbItem";
+
+const BreadcrumbLink = React.forwardRef<
+ HTMLAnchorElement,
+ React.ComponentPropsWithoutRef<"a"> & {
+ asChild?: boolean;
+ }
+>(({ asChild, className, ...props }, ref) => {
+ const Comp = asChild ? Slot : "a";
+
+ return (
+
+ );
+});
+BreadcrumbLink.displayName = "BreadcrumbLink";
+
+const BreadcrumbPage = React.forwardRef<
+ HTMLSpanElement,
+ React.ComponentPropsWithoutRef<"span">
+>(({ className, ...props }, ref) => (
+ // biome-ignore lint/a11y/useFocusableInteractive: required
+
+));
+BreadcrumbPage.displayName = "BreadcrumbPage";
+
+const BreadcrumbSeparator = ({
+ children,
+ className,
+ ...props
+}: React.ComponentProps<"li">) => (
+ svg]:size-3.5", className)}
+ role="presentation"
+ {...props}
+ >
+ {children ?? }
+
+);
+BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
+
+const BreadcrumbEllipsis = ({
+ className,
+ ...props
+}: React.ComponentProps<"span">) => (
+
+
+ More
+
+);
+BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";
+
+export {
+ Breadcrumb,
+ BreadcrumbList,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+ BreadcrumbEllipsis,
+};
diff --git a/apps/dashboard/src/@/components/ui/table.stories.tsx b/packages/ui/src/components/table.stories.tsx
similarity index 97%
rename from apps/dashboard/src/@/components/ui/table.stories.tsx
rename to packages/ui/src/components/table.stories.tsx
index 5bc9e7bccda..c6a8acfed29 100644
--- a/apps/dashboard/src/@/components/ui/table.stories.tsx
+++ b/packages/ui/src/components/table.stories.tsx
@@ -1,5 +1,8 @@
import type { Meta, StoryObj } from "@storybook/nextjs";
import Link from "next/link";
+import { cn } from "@/lib/utils";
+import { BadgeContainer } from "@/storybook/utils";
+import { Badge } from "./badge";
import {
Table,
TableBody,
@@ -9,14 +12,11 @@ import {
TableHead,
TableHeader,
TableRow,
-} from "@/components/ui/table";
-import { BadgeContainer } from "@/storybook/utils";
-import { cn } from "../../lib/utils";
-import { Badge } from "./badge";
+} from "./table";
const meta = {
component: Component,
- title: "Shadcn/Table",
+ title: "ui/table",
} satisfies Meta;
export default meta;
diff --git a/packages/ui/src/components/table.tsx b/packages/ui/src/components/table.tsx
new file mode 100644
index 00000000000..cd575926071
--- /dev/null
+++ b/packages/ui/src/components/table.tsx
@@ -0,0 +1,155 @@
+import * as React from "react";
+import { cn } from "@/lib/utils";
+import { ScrollShadow } from "./scroll-shadow";
+
+const Table = React.forwardRef<
+ HTMLTableElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+Table.displayName = "Table";
+
+const TableHeader = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+
+TableHeader.displayName = "TableHeader";
+
+const TableBody = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableBody.displayName = "TableBody";
+
+const TableFooter = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+ tr]:last:border-b-0",
+ className,
+ )}
+ ref={ref}
+ {...props}
+ />
+));
+TableFooter.displayName = "TableFooter";
+
+const TableRow = React.forwardRef<
+ HTMLTableRowElement,
+ React.HTMLAttributes & {
+ /**
+ * Contain the absolutely position elements inside the row with position:relative + transform:translate(0)
+ * transform:translate(0) is required because position:relative on tr element does not work on webkit
+ */
+ linkBox?: boolean;
+ }
+>(({ className, linkBox, ...props }, ref) => (
+
+));
+TableRow.displayName = "TableRow";
+
+const TableHead = React.forwardRef<
+ HTMLTableCellElement,
+ React.ThHTMLAttributes
+>(({ className, ...props }, ref) => (
+ |
+));
+TableHead.displayName = "TableHead";
+
+const TableCell = React.forwardRef<
+ HTMLTableCellElement,
+ React.TdHTMLAttributes
+>(({ className, ...props }, ref) => (
+ |
+));
+TableCell.displayName = "TableCell";
+
+const TableCaption = React.forwardRef<
+ HTMLTableCaptionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableCaption.displayName = "TableCaption";
+
+function TableContainer(props: {
+ children: React.ReactNode;
+ className?: string;
+ scrollableContainerClassName?: string;
+}) {
+ return (
+
+ {props.children}
+
+ );
+}
+
+export {
+ Table,
+ TableHeader,
+ TableBody,
+ TableFooter,
+ TableHead,
+ TableRow,
+ TableCell,
+ TableCaption,
+ TableContainer,
+};
diff --git a/packages/ui/src/components/tooltip.tsx b/packages/ui/src/components/tooltip.tsx
new file mode 100644
index 00000000000..687bfe4fac7
--- /dev/null
+++ b/packages/ui/src/components/tooltip.tsx
@@ -0,0 +1,70 @@
+"use client";
+
+import * as TooltipPrimitive from "@radix-ui/react-tooltip";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const TooltipProvider = TooltipPrimitive.Provider;
+
+const Tooltip = TooltipPrimitive.Root;
+
+const TooltipTrigger = TooltipPrimitive.Trigger;
+
+const TooltipContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+));
+TooltipContent.displayName = TooltipPrimitive.Content.displayName;
+
+export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
+
+export function ToolTipLabel(props: {
+ children: React.ReactNode;
+ label: React.ReactNode;
+ rightIcon?: React.ReactNode;
+ leftIcon?: React.ReactNode;
+ hoverable?: boolean;
+ contentClassName?: string;
+ side?: "top" | "right" | "bottom" | "left";
+ align?: "center" | "start" | "end";
+}) {
+ if (!props.label) {
+ return props.children;
+ }
+
+ return (
+
+
+
+ {props.children}
+
+
+
+ {props.leftIcon}
+ {props.label}
+ {props.rightIcon}
+
+
+
+
+ );
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0474cbb8c04..eea6f78e480 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1483,6 +1483,9 @@ importers:
'@radix-ui/react-slot':
specifier: ^1.2.3
version: 1.2.3(@types/react@19.1.8)(react@19.1.0)
+ '@radix-ui/react-tooltip':
+ specifier: 1.2.7
+ version: 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tanstack/react-query':
specifier: 5.81.5
version: 5.81.5(react@19.1.0)
@@ -3272,24 +3275,12 @@ packages:
resolution: {integrity: sha512-ReZxZ8pdnoI3tP/dNnJdnmAk7uLT4FjsKDGW7YeDdvdOMz2XCQSmSCM9IWlrXuWtMF9zeSB6WJtEhCQ41gQOfw==}
hasBin: true
- '@floating-ui/core@1.7.2':
- resolution: {integrity: sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==}
-
'@floating-ui/core@1.7.3':
resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
- '@floating-ui/dom@1.7.2':
- resolution: {integrity: sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==}
-
'@floating-ui/dom@1.7.3':
resolution: {integrity: sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==}
- '@floating-ui/react-dom@2.1.4':
- resolution: {integrity: sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw==}
- peerDependencies:
- react: '>=16.8.0'
- react-dom: '>=16.8.0'
-
'@floating-ui/react-dom@2.1.5':
resolution: {integrity: sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==}
peerDependencies:
@@ -18102,30 +18093,15 @@ snapshots:
find-up: 5.0.0
js-yaml: 4.1.0
- '@floating-ui/core@1.7.2':
- dependencies:
- '@floating-ui/utils': 0.2.10
-
'@floating-ui/core@1.7.3':
dependencies:
'@floating-ui/utils': 0.2.10
- '@floating-ui/dom@1.7.2':
- dependencies:
- '@floating-ui/core': 1.7.2
- '@floating-ui/utils': 0.2.10
-
'@floating-ui/dom@1.7.3':
dependencies:
'@floating-ui/core': 1.7.3
'@floating-ui/utils': 0.2.10
- '@floating-ui/react-dom@2.1.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
- dependencies:
- '@floating-ui/dom': 1.7.2
- react: 19.1.0
- react-dom: 19.1.0(react@19.1.0)
-
'@floating-ui/react-dom@2.1.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@floating-ui/dom': 1.7.3
@@ -19982,7 +19958,7 @@ snapshots:
'@radix-ui/react-popper@1.2.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
- '@floating-ui/react-dom': 2.1.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@floating-ui/react-dom': 2.1.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0)