diff --git a/package-lock.json b/package-lock.json
index dd73cb5..e807177 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -35,6 +35,8 @@
"react-hook-form": "^7.60.0",
"sonner": "^2.0.6",
"tailwind-merge": "^3.3.1",
+ "tailwindcss-safe-area": "^1.0.0",
+ "use-debounce": "^10.0.5",
"zod": "^4.0.5"
},
"devDependencies": {
@@ -6870,6 +6872,21 @@
"integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
"license": "MIT"
},
+ "node_modules/tailwindcss-safe-area": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/tailwindcss-safe-area/-/tailwindcss-safe-area-1.0.0.tgz",
+ "integrity": "sha512-cg4eFaTe4dFKZ4H6Vrobxqen6Jki/sSvssmHEYX5rFu1IojwGjTmab/eWzzN2gVrtMSIJoYSMS49p4TjBnWBeA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mvllow"
+ },
+ "peerDependencies": {
+ "tailwindcss": "^4.0.0"
+ }
+ },
"node_modules/tapable": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz",
@@ -7195,6 +7212,18 @@
}
}
},
+ "node_modules/use-debounce": {
+ "version": "10.0.5",
+ "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.5.tgz",
+ "integrity": "sha512-Q76E3lnIV+4YT9AHcrHEHYmAd9LKwUAbPXDm7FlqVGDHiSOhX3RDjT8dm0AxbJup6WgOb1YEcKyCr11kBJR5KQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16.0.0"
+ },
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
"node_modules/use-sidecar": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
diff --git a/package.json b/package.json
index edc62f4..2df1ac3 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,8 @@
"react-hook-form": "^7.60.0",
"sonner": "^2.0.6",
"tailwind-merge": "^3.3.1",
+ "tailwindcss-safe-area": "^1.0.0",
+ "use-debounce": "^10.0.5",
"zod": "^4.0.5"
},
"devDependencies": {
diff --git a/src/app/globals.css b/src/app/globals.css
index 087ba6a..709e8a5 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -1,6 +1,6 @@
@import "tailwindcss";
@import "tw-animate-css";
-
+@import "tailwindcss-safe-area";
@custom-variant dark (&:is(.dark *));
@theme inline {
@@ -47,6 +47,7 @@ body {
font-family: var(--font-geist), sans-serif;
background-color: var(--background);
}
+
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index d1b1f03..122224f 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,4 +1,4 @@
-import type { Metadata } from "next";
+import type { Metadata, Viewport } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { ReactNode } from "react";
import { SidebarProvider } from "@/components/ui/sidebar";
@@ -24,6 +24,15 @@ export const metadata: Metadata = {
description: "Desktop power right in your browser",
};
+export const viewport: Viewport = {
+ width: 'device-width',
+ initialScale: 1,
+ viewportFit: 'cover',
+ themeColor: [
+ { media: "(prefers-color-scheme: dark)", color: "#0a0a0a" },
+ { media: "(prefers-color-scheme: light)", color: "#ffffff" }
+ ]
+};
export default async function RootLayout({
children,
@@ -35,7 +44,6 @@ export default async function RootLayout({
-
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 851ba17..1bae159 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -5,7 +5,7 @@ import { useLiveQuery } from "dexie-react-hooks";
import { db } from "@/lib/db";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";
-import { CopyIcon, EditIcon, EllipsisIcon, InfoIcon, ListCheckIcon, PencilIcon, PlusIcon, TrashIcon } from "lucide-react";
+import { CheckCheckIcon, CopyIcon, EditIcon, EllipsisIcon, InfoIcon, ListCheckIcon, PencilIcon, PlusIcon, TrashIcon } from "lucide-react";
import { Toggle } from "@/components/ui/toggle";
import Search from "@/components/search";
import { useIsMobile } from "@/hooks/use-mobile";
@@ -23,6 +23,7 @@ import { generateUUID } from "@/lib/uuid";
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
+import { useDebounce } from "use-debounce";
const ProjectInfoFormSchema = z.object({
title: z.string().nonempty("Title cannot be empty"),
@@ -118,6 +119,7 @@ const DeleteProjectDialog = ({ project }: { project: Project }) => {
const ProjectDropdown = ({ project }: { project: Project }): ReactNode => {
const [renameDialogOpen, setRenameDialogOpen] = useState(false);
const [deleteAlertOpen, setDeleteAlertOpen] = useState(false);
+ const isMobile = useIsMobile();
const handleDuplicate = async () => {
const newProject = {
@@ -138,7 +140,7 @@ const ProjectDropdown = ({ project }: { project: Project }): ReactNode => {
-
+
{project.title}
setRenameDialogOpen(true)}>
@@ -221,10 +223,11 @@ const ProjectContainer = ({
export default function Home(): ReactNode {
const isMobile = useIsMobile();
const [search, setSearch] = useState('');
+ const [debouncedSearch] = useDebounce(search, 300);
- const projects = useLiveQuery(() => {
- return db.projects.filter((project) => project.title.includes(search)).toArray();
- });
+ const projects = useLiveQuery(() => (
+ db.projects.filter((project) => project.title.toLowerCase().includes(debouncedSearch.toLowerCase())).toArray()
+ ), [debouncedSearch]);
const newProjectForm = useForm>({
resolver: zodResolver(ProjectInfoFormSchema),
diff --git a/src/components/dashboard/Dashboard.tsx b/src/components/dashboard/Dashboard.tsx
index 1ff7364..3fd74c2 100644
--- a/src/components/dashboard/Dashboard.tsx
+++ b/src/components/dashboard/Dashboard.tsx
@@ -33,7 +33,7 @@ const items: DashboardItem[] = [
export const Dashboard = (): ReactNode => {
return (
-
+
ClipFusion
@@ -84,7 +84,7 @@ export const Dashboard = (): ReactNode => {
-
+
Links
diff --git a/src/components/search/Search.tsx b/src/components/search/Search.tsx
index 66384ac..1b0dae5 100644
--- a/src/components/search/Search.tsx
+++ b/src/components/search/Search.tsx
@@ -7,7 +7,7 @@ export const Search = (props: ComponentProps): ReactNode => (
diff --git a/tailwind.config.js b/tailwind.config.js
index 69ee36f..ce3cc1e 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,5 +1,5 @@
module.exports = {
plugins: [
- require("@tailwindcss/line-clamp"),
+ require("@tailwindcss/line-clamp")
]
};
\ No newline at end of file