diff --git a/package.json b/package.json
index a089d7c..e078076 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"dependencies": {
"@lukemorales/query-key-factory": "^1.3.2",
"@radix-ui/react-dialog": "^1.0.5",
+ "@radix-ui/react-slot": "^1.0.2",
"@tanstack/react-query": "^5.17.9",
"@tanstack/react-query-devtools": "^5.17.9",
"class-variance-authority": "^0.7.0",
@@ -18,8 +19,10 @@
"eslint-plugin-tailwindcss": "^3.13.1",
"lucide-react": "^0.312.0",
"next": "14.0.4",
+ "next-themes": "^0.2.1",
"react": "^18",
"react-dom": "^18",
+ "sonner": "^1.3.1",
"tailwind-merge": "^2.2.0",
"vaul": "^0.8.0",
"zustand": "^4.4.7"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1914e25..3347e4e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,6 +11,9 @@ dependencies:
'@radix-ui/react-dialog':
specifier: ^1.0.5
version: 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot':
+ specifier: ^1.0.2
+ version: 1.0.2(@types/react@18.2.47)(react@18.2.0)
'@tanstack/react-query':
specifier: ^5.17.9
version: 5.17.9(react@18.2.0)
@@ -32,12 +35,18 @@ dependencies:
next:
specifier: 14.0.4
version: 14.0.4(react-dom@18.2.0)(react@18.2.0)
+ next-themes:
+ specifier: ^0.2.1
+ version: 0.2.1(next@14.0.4)(react-dom@18.2.0)(react@18.2.0)
react:
specifier: ^18
version: 18.2.0
react-dom:
specifier: ^18
version: 18.2.0(react@18.2.0)
+ sonner:
+ specifier: ^1.3.1
+ version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
tailwind-merge:
specifier: ^2.2.0
version: 2.2.0
@@ -2332,6 +2341,18 @@ packages:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: true
+ /next-themes@0.2.1(next@14.0.4)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
+ peerDependencies:
+ next: '*'
+ react: '*'
+ react-dom: '*'
+ dependencies:
+ next: 14.0.4(react-dom@18.2.0)(react@18.2.0)
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/next@14.0.4(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==}
engines: {node: '>=18.17.0'}
@@ -2871,6 +2892,16 @@ packages:
engines: {node: '>=8'}
dev: true
+ /sonner@1.3.1(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-+rOAO56b2eI3q5BtgljERSn2umRk63KFIvgb2ohbZ5X+Eb5u+a/7/0ZgswYqgBMg8dyl7n6OXd9KasA8QF9ToA==}
+ peerDependencies:
+ react: ^18.0.0
+ react-dom: ^18.0.0
+ dependencies:
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/source-map-js@1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index ac3a187..a3617d3 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,12 +1,15 @@
import type { Metadata } from "next";
-import { Inter } from "next/font/google";
+import { Inter, Poppins, DM_Sans } from "next/font/google";
import "./globals.css";
import React from "react";
import { GlobalProvider } from "./global-provider";
import { cn } from "@/utils/cn";
-import NavigationBar from "@/components/common/NavigationBar";
+import NavigationBar from "@/components/common/navigation-bar";
+import { Toaster } from "@/components/ui/sonner";
const inter = Inter({ subsets: ["latin"] });
+const poppins = Poppins({ subsets: ["latin"], weight: ["400", "500", "600", "700"] });
+const dm_sans = DM_Sans({ subsets: ["latin"], weight: ["400", "500", "600", "700"] });
export const metadata: Metadata = {
title: "Create Next App",
@@ -16,11 +19,12 @@ export const metadata: Metadata = {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
-
+
-
{children}
+
{children}
+
diff --git a/src/app/ticker/_components/drawer.tsx b/src/app/ticker/_components/ticker-drawer.tsx
similarity index 100%
rename from src/app/ticker/_components/drawer.tsx
rename to src/app/ticker/_components/ticker-drawer.tsx
diff --git a/src/app/ticker/_components/ticker-list.tsx b/src/app/ticker/_components/ticker-list.tsx
new file mode 100644
index 0000000..58d575b
--- /dev/null
+++ b/src/app/ticker/_components/ticker-list.tsx
@@ -0,0 +1,41 @@
+"use client";
+
+import Toast from "@/components/common/toast/toast";
+import { Button } from "@/components/ui/button";
+import React from "react";
+import { toast } from "sonner";
+
+const TickerList = React.memo(() => {
+ const onTickerDelete = React.useCallback(() => {
+ toast.custom((t) => );
+ }, []);
+
+ return (
+
+ );
+});
+
+export default TickerList;
diff --git a/src/app/ticker/page.tsx b/src/app/ticker/page.tsx
index 0e4ee90..81825b3 100644
--- a/src/app/ticker/page.tsx
+++ b/src/app/ticker/page.tsx
@@ -1,13 +1,14 @@
import { Plus } from "lucide-react";
import { Drawer as DrawerPrimitive, DrawerTrigger } from "@/components/ui/drawer";
-import { TickerDrawer } from "./_components/drawer";
+import { TickerDrawer } from "./_components/ticker-drawer";
+import TickerList from "./_components/ticker-list";
const TickerPage = () => {
return (
-
+
You Added 0 Tickers
-
+
@@ -17,6 +18,7 @@ const TickerPage = () => {
+
diff --git a/src/components/common/NavigationBar.tsx b/src/components/common/navigation-bar.tsx
similarity index 100%
rename from src/components/common/NavigationBar.tsx
rename to src/components/common/navigation-bar.tsx
diff --git a/src/components/common/toast/toast.tsx b/src/components/common/toast/toast.tsx
new file mode 100644
index 0000000..6698b99
--- /dev/null
+++ b/src/components/common/toast/toast.tsx
@@ -0,0 +1,39 @@
+import { Button } from "@/components/ui/button";
+import { cn } from "@/utils/cn";
+import React from "react";
+import { toast } from "sonner";
+
+export interface ToastProps extends React.HTMLAttributes
{
+ t?: string | number;
+ title: string;
+ isRevertable?: boolean;
+}
+
+const Toast = React.memo(({ t, title, isRevertable, ...props }: ToastProps) => {
+ const onUndo = React.useCallback(() => {
+ toast.dismiss(t);
+ }, [t]);
+
+ return (
+
+
{title}
+ {isRevertable &&
}
+
+ );
+});
+
+const UndoButton = React.memo(({ onClick }: { onClick: () => void }) => {
+ return (
+
+ );
+});
+
+export default Toast;
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
new file mode 100644
index 0000000..30f1ad2
--- /dev/null
+++ b/src/components/ui/button.tsx
@@ -0,0 +1,46 @@
+import * as React from "react";
+import { Slot } from "@radix-ui/react-slot";
+import { cva, type VariantProps } from "class-variance-authority";
+import { cn } from "@/utils/cn";
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center whitespace-nowrap 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",
+ },
+ 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/src/components/ui/sonner.tsx b/src/components/ui/sonner.tsx
new file mode 100644
index 0000000..452f4d9
--- /dev/null
+++ b/src/components/ui/sonner.tsx
@@ -0,0 +1,31 @@
+"use client"
+
+import { useTheme } from "next-themes"
+import { Toaster as Sonner } from "sonner"
+
+type ToasterProps = React.ComponentProps
+
+const Toaster = ({ ...props }: ToasterProps) => {
+ const { theme = "system" } = useTheme()
+
+ return (
+
+ )
+}
+
+export { Toaster }