diff --git a/components/ThemeProvider.tsx b/components/ThemeProvider.tsx
new file mode 100644
index 0000000..d151146
--- /dev/null
+++ b/components/ThemeProvider.tsx
@@ -0,0 +1,10 @@
+'use client';
+
+import * as React from 'react';
+
+import { ThemeProvider as NextThemesProvider } from 'next-themes';
+import type { ThemeProviderProps } from 'next-themes/dist/types';
+
+export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
+ return {children};
+}
diff --git a/ui/AppLink.tsx b/components/ui/AppLink.tsx
similarity index 100%
rename from ui/AppLink.tsx
rename to components/ui/AppLink.tsx
diff --git a/ui/Avatar.tsx b/components/ui/Avatar.tsx
similarity index 100%
rename from ui/Avatar.tsx
rename to components/ui/Avatar.tsx
diff --git a/ui/Badge.tsx b/components/ui/Badge.tsx
similarity index 100%
rename from ui/Badge.tsx
rename to components/ui/Badge.tsx
diff --git a/components/ui/Button.tsx b/components/ui/Button.tsx
new file mode 100644
index 0000000..ae90bd5
--- /dev/null
+++ b/components/ui/Button.tsx
@@ -0,0 +1,50 @@
+import * as React from 'react';
+import { Slot } from '@radix-ui/react-slot';
+import { cva, type VariantProps } from 'class-variance-authority';
+
+import { cn } from '@/lib/utils';
+
+const buttonVariants = cva(
+ 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
+ {
+ variants: {
+ variant: {
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
+ destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
+ outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
+ secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
+ link: 'text-primary underline-offset-4 hover:underline',
+ brand: 'bg-gradient-to-tl from-brand to-brand-accent transition-opacity hover:opacity-90'
+ },
+ size: {
+ default: 'h-10 px-4 py-2',
+ sm: 'h-9 rounded-md px-3',
+ lg: 'h-11 rounded-md px-8',
+ icon: 'h-10 w-10'
+ }
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'default'
+ }
+ }
+);
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean;
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : 'button';
+ return (
+
+ );
+ }
+);
+Button.displayName = 'Button';
+
+export { Button, buttonVariants };
diff --git a/ui/Card.tsx b/components/ui/Card.tsx
similarity index 90%
rename from ui/Card.tsx
rename to components/ui/Card.tsx
index e8dbb01..cc8be00 100644
--- a/ui/Card.tsx
+++ b/components/ui/Card.tsx
@@ -1,7 +1,7 @@
import { getURL } from '@/lib/utils';
-import AppLink from './AppLink';
-import Icon from './Icon';
+import AppLink from '@/components/ui/AppLink';
+import { Icon } from '@/components/ui/Icon';
export default function Card({
isLoading,
@@ -19,7 +19,7 @@ export default function Card({
if (isLoading)
return (
-
+
diff --git a/ui/Console.tsx b/components/ui/Console.tsx
similarity index 100%
rename from ui/Console.tsx
rename to components/ui/Console.tsx
diff --git a/ui/Dialog.tsx b/components/ui/Dialog.tsx
similarity index 92%
rename from ui/Dialog.tsx
rename to components/ui/Dialog.tsx
index eff2215..2fd3084 100644
--- a/ui/Dialog.tsx
+++ b/components/ui/Dialog.tsx
@@ -1,7 +1,7 @@
import { cn } from '@/lib/utils';
import * as DialogPrimitive from '@radix-ui/react-dialog';
import type { ReactNode } from 'react';
-import Icon from './Icon';
+import { Icon, Icons } from '@/components/ui/Icon';
// import Tooltip from './Tooltip';
type DialogProps = {
@@ -42,7 +42,7 @@ export default function Dialog({