From b394c78be2b348bdbabb75e14898f1205464dc61 Mon Sep 17 00:00:00 2001 From: KM Koushik Date: Tue, 6 May 2025 22:00:50 +1000 Subject: [PATCH] feat: add new theme (#157) --- .cursorrules => .cursor/rules/general.mdc | 9 +- apps/web/postcss.config.cjs | 1 + .../campaigns/[campaignId]/page.tsx | 4 +- .../(dashboard)/campaigns/campaign-list.tsx | 169 +--- .../(dashboard)/campaigns/delete-campaign.tsx | 6 +- .../campaigns/duplicate-campaign.tsx | 5 +- .../[contactBookId]/delete-contact.tsx | 6 +- .../contacts/[contactBookId]/edit-contact.tsx | 2 +- .../contacts/delete-contact-book.tsx | 2 +- .../contacts/edit-contact-book.tsx | 2 +- .../src/app/(dashboard)/dasboard-layout.tsx | 217 +---- .../(dashboard)/dashboard/dashboard-chart.tsx | 6 +- .../dev-settings/api-keys/delete-api-key.tsx | 4 +- .../dev-settings/settings-nav-button.tsx | 6 +- .../domains/[domainId]/delete-domain.tsx | 9 +- .../(dashboard)/domains/[domainId]/page.tsx | 4 +- .../app/(dashboard)/domains/domain-list.tsx | 4 +- .../app/(dashboard)/emails/email-details.tsx | 2 +- apps/web/src/app/(dashboard)/nav-button.tsx | 53 -- .../settings/team/delete-team-invite.tsx | 5 +- .../(dashboard)/templates/delete-template.tsx | 6 +- .../templates/duplicate-template.tsx | 5 +- .../(dashboard)/templates/template-list.tsx | 2 +- apps/web/src/app/layout.tsx | 4 +- apps/web/src/app/login/login-page.tsx | 2 +- apps/web/src/components/AppSideBar.tsx | 236 ++++++ apps/web/src/components/team/JoinTeam.tsx | 4 +- .../src/components/theme/ThemeSwitcher.tsx | 53 +- .../email-editor/src/nodes/image-resize.tsx | 2 +- packages/email-editor/src/nodes/variable.tsx | 2 +- packages/tailwind-config/tailwind.config.ts | 14 + packages/ui/src/badge.tsx | 2 +- packages/ui/src/dialog.tsx | 4 +- packages/ui/src/hooks/use-mobile.tsx | 21 + packages/ui/src/select.tsx | 2 +- packages/ui/src/sheet.tsx | 5 +- packages/ui/src/sidebar.tsx | 773 ++++++++++++++++++ packages/ui/src/skeleton.tsx | 15 + packages/ui/src/switch.tsx | 2 +- packages/ui/styles/globals.css | 60 +- 40 files changed, 1236 insertions(+), 494 deletions(-) rename .cursorrules => .cursor/rules/general.mdc (87%) delete mode 100644 apps/web/src/app/(dashboard)/nav-button.tsx create mode 100644 apps/web/src/components/AppSideBar.tsx create mode 100644 packages/ui/src/hooks/use-mobile.tsx create mode 100644 packages/ui/src/sidebar.tsx create mode 100644 packages/ui/src/skeleton.tsx diff --git a/.cursorrules b/.cursor/rules/general.mdc similarity index 87% rename from .cursorrules rename to .cursor/rules/general.mdc index 2117545..8162f5d 100644 --- a/.cursorrules +++ b/.cursor/rules/general.mdc @@ -1,11 +1,16 @@ +--- +description: +globs: +alwaysApply: false +--- You are a Staff Engineer and an Expert in ReactJS, NextJS, JavaScript, TypeScript, HTML, CSS, NodeJS, Prisma, Postgres, and modern UI/UX frameworks (e.g., TailwindCSS, Shadcn, Radix). You are also great at scalling things. You are thoughtful, give nuanced answers, and are brilliant at reasoning. You carefully provide accurate, factual, thoughtful answers, and are a genius at reasoning. -- Follow the user’s requirements carefully & to the letter. +- Follow the user's requirements carefully & to the letter. - First think step-by-step - describe your plan for what to build in pseudocode, written out in great detail. - Always write correct, best practice, bug free, fully functional and working code also it should be aligned to listed rules down below at Code Implementation Guidelines . - Focus on easy and readability code, over being performant. - Fully implement all requested functionality. -- Leave NO todo’s, placeholders or missing pieces. +- Leave NO todo's, placeholders or missing pieces. - Ensure code is complete! Verify thoroughly finalised. - Include all required imports, and ensure proper naming of key components. - Be concise Minimize any other prose. diff --git a/apps/web/postcss.config.cjs b/apps/web/postcss.config.cjs index 4cdb2f4..e305dd9 100644 --- a/apps/web/postcss.config.cjs +++ b/apps/web/postcss.config.cjs @@ -1,6 +1,7 @@ const config = { plugins: { tailwindcss: {}, + autoprefixer: {}, }, }; diff --git a/apps/web/src/app/(dashboard)/campaigns/[campaignId]/page.tsx b/apps/web/src/app/(dashboard)/campaigns/[campaignId]/page.tsx index ef52115..8c802eb 100644 --- a/apps/web/src/app/(dashboard)/campaigns/[campaignId]/page.tsx +++ b/apps/web/src/app/(dashboard)/campaigns/[campaignId]/page.tsx @@ -28,7 +28,7 @@ export default function CampaignDetailsPage({ if (isLoading) { return (
- +
); } @@ -94,7 +94,7 @@ export default function CampaignDetailsPage({
{card.status.toLowerCase()}
-
+
{card.count}
{card.status !== "total" ? ( diff --git a/apps/web/src/app/(dashboard)/campaigns/campaign-list.tsx b/apps/web/src/app/(dashboard)/campaigns/campaign-list.tsx index 87f4082..2fae9c2 100644 --- a/apps/web/src/app/(dashboard)/campaigns/campaign-list.tsx +++ b/apps/web/src/app/(dashboard)/campaigns/campaign-list.tsx @@ -89,7 +89,7 @@ export default function CampaignList() { ); } - -// "use client"; - -// import { -// Table, -// TableHeader, -// TableRow, -// TableHead, -// TableBody, -// TableCell, -// } from "@unsend/ui/src/table"; -// import { api } from "~/trpc/react"; -// import { useUrlState } from "~/hooks/useUrlState"; -// import { Button } from "@unsend/ui/src/button"; -// import Spinner from "@unsend/ui/src/spinner"; -// import { formatDistanceToNow } from "date-fns"; -// import { CampaignStatus } from "@prisma/client"; -// import DeleteCampaign from "./delete-campaign"; -// import Link from "next/link"; -// import DuplicateCampaign from "./duplicate-campaign"; -// import { motion } from "framer-motion"; -// import { useRouter } from "next/navigation"; -// import { -// Select, -// SelectTrigger, -// SelectContent, -// SelectItem, -// } from "@unsend/ui/src/select"; - -// export default function CampaignList() { -// const [page, setPage] = useUrlState("page", "1"); -// const [status, setStatus] = useUrlState("status"); - -// const pageNumber = Number(page); - -// const campaignsQuery = api.campaign.getCampaigns.useQuery({ -// page: pageNumber, -// status: status as CampaignStatus | null, -// }); - -// const router = useRouter(); - -// return ( -//
-//
-// -//
- -// {campaignsQuery.isLoading ? ( -//
-// -//
-// ) : ( -//
-// {campaignsQuery.data?.campaigns.map((campaign) => ( -// -//
-// -//
-//
-//
-// - -//
-//
router.push(`/campaigns/${campaign.id}`)} -// > -//
-//
-//
-// {campaign.name} -//
-//
-// {campaign.status.toLowerCase()} -//
-//
-//
-// {formatDistanceToNow(campaign.createdAt, { -// addSuffix: true, -// })} -//
-//
-//
- -//
-// -// -//
-//
-//
-// -// ))} -//
-// )} - -// {campaignsQuery.data?.totalPage && campaignsQuery.data.totalPage > 1 ? ( -//
-// -// -//
-// ) : null} -//
-// ); -// } diff --git a/apps/web/src/app/(dashboard)/campaigns/delete-campaign.tsx b/apps/web/src/app/(dashboard)/campaigns/delete-campaign.tsx index 763a76a..584b1c1 100644 --- a/apps/web/src/app/(dashboard)/campaigns/delete-campaign.tsx +++ b/apps/web/src/app/(dashboard)/campaigns/delete-campaign.tsx @@ -83,8 +83,10 @@ export const DeleteCampaign: React.FC<{ Delete Campaign Are you sure you want to delete{" "} - {campaign.name}? - You can't reverse this. + + {campaign.name} + + ? You can't reverse this.
diff --git a/apps/web/src/app/(dashboard)/campaigns/duplicate-campaign.tsx b/apps/web/src/app/(dashboard)/campaigns/duplicate-campaign.tsx index 17079be..90fa3b2 100644 --- a/apps/web/src/app/(dashboard)/campaigns/duplicate-campaign.tsx +++ b/apps/web/src/app/(dashboard)/campaigns/duplicate-campaign.tsx @@ -54,7 +54,10 @@ export const DuplicateCampaign: React.FC<{ Duplicate Campaign Are you sure you want to duplicate{" "} - {campaign.name}? + + {campaign.name} + + ?
diff --git a/apps/web/src/app/(dashboard)/contacts/[contactBookId]/delete-contact.tsx b/apps/web/src/app/(dashboard)/contacts/[contactBookId]/delete-contact.tsx index a26c914..1f03843 100644 --- a/apps/web/src/app/(dashboard)/contacts/[contactBookId]/delete-contact.tsx +++ b/apps/web/src/app/(dashboard)/contacts/[contactBookId]/delete-contact.tsx @@ -87,8 +87,10 @@ export const DeleteContact: React.FC<{ Delete Contact Are you sure you want to delete{" "} - {contact.email}? - You can't reverse this. + + {contact.email} + + ? You can't reverse this.
diff --git a/apps/web/src/app/(dashboard)/contacts/[contactBookId]/edit-contact.tsx b/apps/web/src/app/(dashboard)/contacts/[contactBookId]/edit-contact.tsx index dc42a54..909dfe0 100644 --- a/apps/web/src/app/(dashboard)/contacts/[contactBookId]/edit-contact.tsx +++ b/apps/web/src/app/(dashboard)/contacts/[contactBookId]/edit-contact.tsx @@ -145,7 +145,7 @@ export const EditContact: React.FC<{ diff --git a/apps/web/src/app/(dashboard)/contacts/delete-contact-book.tsx b/apps/web/src/app/(dashboard)/contacts/delete-contact-book.tsx index 90695cf..b29ac1e 100644 --- a/apps/web/src/app/(dashboard)/contacts/delete-contact-book.tsx +++ b/apps/web/src/app/(dashboard)/contacts/delete-contact-book.tsx @@ -86,7 +86,7 @@ export const DeleteContactBook: React.FC<{ Delete Contact Book Are you sure you want to delete{" "} - + {contactBook.name} ? You can't reverse this. diff --git a/apps/web/src/app/(dashboard)/contacts/edit-contact-book.tsx b/apps/web/src/app/(dashboard)/contacts/edit-contact-book.tsx index 94278c5..a63b8f3 100644 --- a/apps/web/src/app/(dashboard)/contacts/edit-contact-book.tsx +++ b/apps/web/src/app/(dashboard)/contacts/edit-contact-book.tsx @@ -78,7 +78,7 @@ export const EditContactBook: React.FC<{ className="p-0 hover:bg-transparent" onClick={(e) => e.stopPropagation()} > - + diff --git a/apps/web/src/app/(dashboard)/dasboard-layout.tsx b/apps/web/src/app/(dashboard)/dasboard-layout.tsx index ad8271d..a5efd6f 100644 --- a/apps/web/src/app/(dashboard)/dasboard-layout.tsx +++ b/apps/web/src/app/(dashboard)/dasboard-layout.tsx @@ -1,211 +1,26 @@ "use client"; -import { useSession } from "next-auth/react"; -import Link from "next/link"; -import { LogoutButton, NavButton } from "./nav-button"; -import { - BookOpenText, - BookUser, - CircleUser, - Code, - Cog, - Globe, - Home, - LayoutDashboard, - LayoutTemplate, - LineChart, - Mail, - Menu, - Package, - Package2, - Server, - Settings, - ShoppingCart, - Users, - Volume2, -} from "lucide-react"; -import { env } from "~/env"; -import { Sheet, SheetContent, SheetTrigger } from "@unsend/ui/src/sheet"; -import { Button } from "@unsend/ui/src/button"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@unsend/ui/src/dropdown-menu"; -import { ThemeSwitcher } from "~/components/theme/ThemeSwitcher"; -import { isCloud, isSelfHosted } from "~/utils/common"; +import { AppSidebar } from "~/components/AppSideBar"; +import { SidebarInset, SidebarTrigger } from "@unsend/ui/src/sidebar"; +import { SidebarProvider } from "@unsend/ui/src/sidebar"; +import { useIsMobile } from "@unsend/ui/src/hooks/use-mobile"; export function DashboardLayout({ children }: { children: React.ReactNode }) { - const { data: session } = useSession(); + const isMobile = useIsMobile(); return ( -
-
-
-
- - Unsend - - - Early access - -
-
- -
-
-
-
-
-
- - - - - - -
-
-
- - - - - - My Account - - Settings - Support - - Logout - - -
-
-
+
+ + + +
+ {isMobile ? ( + + ) : null} {children} -
-
-
+ + +
); } diff --git a/apps/web/src/app/(dashboard)/dashboard/dashboard-chart.tsx b/apps/web/src/app/(dashboard)/dashboard/dashboard-chart.tsx index abf08c5..336c288 100644 --- a/apps/web/src/app/(dashboard)/dashboard/dashboard-chart.tsx +++ b/apps/web/src/app/(dashboard)/dashboard/dashboard-chart.tsx @@ -235,11 +235,13 @@ const DashboardItemCard: React.FC = ({
{status.toLowerCase()}
-
+
{count}
{status !== "total" ? ( -
{count > 0 ? (percentage * 100).toFixed(0) : 0}%
+
+ {count > 0 ? (percentage * 100).toFixed(0) : 0}% +
) : null}
diff --git a/apps/web/src/app/(dashboard)/dev-settings/api-keys/delete-api-key.tsx b/apps/web/src/app/(dashboard)/dev-settings/api-keys/delete-api-key.tsx index 4a66aaa..c95264e 100644 --- a/apps/web/src/app/(dashboard)/dev-settings/api-keys/delete-api-key.tsx +++ b/apps/web/src/app/(dashboard)/dev-settings/api-keys/delete-api-key.tsx @@ -83,8 +83,8 @@ export const DeleteApiKey: React.FC<{ Delete API key Are you sure you want to delete{" "} - {apiKey.name}? - You can't reverse this. + {apiKey.name} + ? You can't reverse this.
diff --git a/apps/web/src/app/(dashboard)/dev-settings/settings-nav-button.tsx b/apps/web/src/app/(dashboard)/dev-settings/settings-nav-button.tsx index aa41063..1c350ac 100644 --- a/apps/web/src/app/(dashboard)/dev-settings/settings-nav-button.tsx +++ b/apps/web/src/app/(dashboard)/dev-settings/settings-nav-button.tsx @@ -15,9 +15,9 @@ export const SettingsNavButton: React.FC<{ if (comingSoon) { return ( -
+
{children}
@@ -31,7 +31,7 @@ export const SettingsNavButton: React.FC<{ return ( {children} diff --git a/apps/web/src/app/(dashboard)/domains/[domainId]/delete-domain.tsx b/apps/web/src/app/(dashboard)/domains/[domainId]/delete-domain.tsx index c096145..8122cc6 100644 --- a/apps/web/src/app/(dashboard)/domains/[domainId]/delete-domain.tsx +++ b/apps/web/src/app/(dashboard)/domains/[domainId]/delete-domain.tsx @@ -5,9 +5,10 @@ import { Input } from "@unsend/ui/src/input"; import { Dialog, DialogContent, - DialogDescription, DialogHeader, + DialogDescription, + DialogHeader, DialogTitle, - DialogTrigger + DialogTrigger, } from "@unsend/ui/src/dialog"; import { @@ -84,8 +85,8 @@ export const DeleteDomain: React.FC<{ domain: Domain }> = ({ domain }) => { Delete domain Are you sure you want to delete{" "} - {domain.name}? - You can't reverse this. + {domain.name} + ? You can't reverse this.
diff --git a/apps/web/src/app/(dashboard)/domains/[domainId]/page.tsx b/apps/web/src/app/(dashboard)/domains/[domainId]/page.tsx index c464f4c..2ed57e2 100644 --- a/apps/web/src/app/(dashboard)/domains/[domainId]/page.tsx +++ b/apps/web/src/app/(dashboard)/domains/[domainId]/page.tsx @@ -274,7 +274,7 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
@@ -288,7 +288,7 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
diff --git a/apps/web/src/app/(dashboard)/domains/domain-list.tsx b/apps/web/src/app/(dashboard)/domains/domain-list.tsx index 1dad6a8..2d86634 100644 --- a/apps/web/src/app/(dashboard)/domains/domain-list.tsx +++ b/apps/web/src/app/(dashboard)/domains/domain-list.tsx @@ -104,7 +104,7 @@ const DomainItem: React.FC<{ domain: Domain }> = ({ domain }) => {
@@ -112,7 +112,7 @@ const DomainItem: React.FC<{ domain: Domain }> = ({ domain }) => {
diff --git a/apps/web/src/app/(dashboard)/emails/email-details.tsx b/apps/web/src/app/(dashboard)/emails/email-details.tsx index 1d70176..e409031 100644 --- a/apps/web/src/app/(dashboard)/emails/email-details.tsx +++ b/apps/web/src/app/(dashboard)/emails/email-details.tsx @@ -115,7 +115,7 @@ export default function EmailDetails({ emailId }: { emailId: string }) {
{formatDate(evt.createdAt, "MMM dd, hh:mm a")}
-
+
= ({ href, children, comingSoon }) => { - const pathname = usePathname(); - - const isActive = pathname?.startsWith(href); - - if (comingSoon) { - return ( -
-
- {children} -
-
- soon -
-
- ); - } - - return ( - - {children} - - ); -}; - -export const LogoutButton: React.FC = () => { - return ( - - ); -}; diff --git a/apps/web/src/app/(dashboard)/settings/team/delete-team-invite.tsx b/apps/web/src/app/(dashboard)/settings/team/delete-team-invite.tsx index b0ff28a..d0480a0 100644 --- a/apps/web/src/app/(dashboard)/settings/team/delete-team-invite.tsx +++ b/apps/web/src/app/(dashboard)/settings/team/delete-team-invite.tsx @@ -55,7 +55,10 @@ export const DeleteTeamInvite: React.FC<{ Cancel Invite Are you sure you want to cancel the invite for{" "} - {invite.email}? + + {invite.email} + + ?
diff --git a/apps/web/src/app/(dashboard)/templates/delete-template.tsx b/apps/web/src/app/(dashboard)/templates/delete-template.tsx index de07ece..73ef6c2 100644 --- a/apps/web/src/app/(dashboard)/templates/delete-template.tsx +++ b/apps/web/src/app/(dashboard)/templates/delete-template.tsx @@ -83,8 +83,10 @@ export const DeleteTemplate: React.FC<{ Delete Template Are you sure you want to delete{" "} - {template.name}? - You can't reverse this. + + {template.name} + + ? You can't reverse this.
diff --git a/apps/web/src/app/(dashboard)/templates/duplicate-template.tsx b/apps/web/src/app/(dashboard)/templates/duplicate-template.tsx index 7f4359d..cc11935 100644 --- a/apps/web/src/app/(dashboard)/templates/duplicate-template.tsx +++ b/apps/web/src/app/(dashboard)/templates/duplicate-template.tsx @@ -54,7 +54,10 @@ export const DuplicateTemplate: React.FC<{ Duplicate Template Are you sure you want to duplicate{" "} - {template.name}? + + {template.name} + + ?
diff --git a/apps/web/src/app/(dashboard)/templates/template-list.tsx b/apps/web/src/app/(dashboard)/templates/template-list.tsx index abaded7..9218d70 100644 --- a/apps/web/src/app/(dashboard)/templates/template-list.tsx +++ b/apps/web/src/app/(dashboard)/templates/template-list.tsx @@ -57,7 +57,7 @@ export default function TemplateList() { {template.name} diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index 7060f9e..9651148 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -24,8 +24,8 @@ export default async function RootLayout({ children: React.ReactNode; }) { return ( - - + + {children} diff --git a/apps/web/src/app/login/login-page.tsx b/apps/web/src/app/login/login-page.tsx index 7540fbe..5941b05 100644 --- a/apps/web/src/app/login/login-page.tsx +++ b/apps/web/src/app/login/login-page.tsx @@ -130,7 +130,7 @@ export default function LoginPage({ {isSignup ? "Already have an account?" : "New to Unsend?"} {isSignup ? "Sign in" : "Create new account"} diff --git a/apps/web/src/components/AppSideBar.tsx b/apps/web/src/components/AppSideBar.tsx new file mode 100644 index 0000000..247ef00 --- /dev/null +++ b/apps/web/src/components/AppSideBar.tsx @@ -0,0 +1,236 @@ +"use client"; + +import { + BookUser, + Calendar, + Code, + Cog, + Globe, + Home, + Inbox, + LayoutDashboard, + LayoutTemplate, + LogOut, + Mail, + Search, + Server, + Settings, + Volume2, + BookOpenText, + ChartColumnBig, + ChartArea, +} from "lucide-react"; +import { signOut } from "next-auth/react"; + +import { + Sidebar, + SidebarContent, + SidebarFooter, + SidebarGroup, + SidebarGroupContent, + SidebarGroupLabel, + SidebarHeader, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + useSidebar, +} from "@unsend/ui/src/sidebar"; +import Link from "next/link"; +import { MiniThemeSwitcher, ThemeSwitcher } from "./theme/ThemeSwitcher"; +import { useSession } from "next-auth/react"; +import { isSelfHosted } from "~/utils/common"; +import { usePathname } from "next/navigation"; +import { Badge } from "@unsend/ui/src/badge"; + +// General items +const generalItems = [ + { + title: "Analytics", + url: "/dashboard", + icon: ChartColumnBig, + }, + { + title: "Emails", + url: "/emails", + icon: Mail, + }, + { + title: "Templates", + url: "/templates", + icon: LayoutTemplate, + }, +]; + +// Marketing items +const marketingItems = [ + { + title: "Contacts", + url: "/contacts", + icon: BookUser, + }, + { + title: "Campaigns", + url: "/campaigns", + icon: Volume2, + }, +]; + +// Settings items +const settingsItems = [ + { + title: "Domains", + url: "/domains", + icon: Globe, + }, + { + title: "Developer settings", + url: "/dev-settings", + icon: Code, + }, + { + title: "Settings", + url: "/settings", + icon: Cog, + }, + // TODO: Add conditional logic for Admin item based on isSelfHosted() || session?.user.isAdmin + { + title: "Admin", + url: "/admin", + icon: Server, + isAdmin: true, + isSelfHosted: true, + }, +]; + +export function AppSidebar() { + const { data: session } = useSession(); + const { state, open } = useSidebar(); + + const pathname = usePathname(); + + return ( + + + +
+ + Unsend + + Beta +
+
+
+ + + + General + + + + {generalItems.map((item) => { + const isActive = pathname?.startsWith(item.url); + return ( + + + + + {item.title} + + + + ); + })} + + + + + + Marketing + + + + {marketingItems.map((item) => { + const isActive = pathname?.startsWith(item.url); + return ( + + + + + {item.title} + + + + ); + })} + + + + + + Settings + + + + {settingsItems.map((item) => { + const isActive = pathname?.startsWith(item.url); + + if (item.isAdmin && !session?.user.isAdmin) { + return null; + } + if (item.isSelfHosted && !isSelfHosted()) { + return null; + } + return ( + + + + + {item.title} + + + + ); + })} + + + + + + + + + signOut()} tooltip="Logout"> + + Logout + + + + + + + Docs + + + + + + + + + +
+ ); +} diff --git a/apps/web/src/components/team/JoinTeam.tsx b/apps/web/src/components/team/JoinTeam.tsx index b893961..df0fc5f 100644 --- a/apps/web/src/components/team/JoinTeam.tsx +++ b/apps/web/src/components/team/JoinTeam.tsx @@ -123,11 +123,11 @@ export default function JoinTeam({ Accept Team Invitation Are you sure you want to join{" "} - + {selectedInvite?.team.name} ? You will be added as a{" "} - + {selectedInvite?.role.toLowerCase()} . diff --git a/apps/web/src/components/theme/ThemeSwitcher.tsx b/apps/web/src/components/theme/ThemeSwitcher.tsx index 6099e9e..6c6948b 100644 --- a/apps/web/src/components/theme/ThemeSwitcher.tsx +++ b/apps/web/src/components/theme/ThemeSwitcher.tsx @@ -3,19 +3,22 @@ import { Button } from "@unsend/ui/src/button"; import { Monitor, Sun, Moon, SunMoonIcon } from "lucide-react"; export const ThemeSwitcher = () => { - const { theme, setTheme, systemTheme } = useTheme(); + const { theme, setTheme } = useTheme(); return ( -
-

+

+

Theme

-
+
); }; + +export const MiniThemeSwitcher = () => { + const { theme, setTheme } = useTheme(); + + const cycleTheme = () => { + if (theme === "light") { + setTheme("dark"); + } else if (theme === "dark") { + setTheme("system"); + } else { + setTheme("light"); + } + }; + + const renderIcon = () => { + switch (theme) { + case "light": + return ; + case "dark": + return ; + default: + return ; + } + }; + + return ( + + ); +}; diff --git a/packages/email-editor/src/nodes/image-resize.tsx b/packages/email-editor/src/nodes/image-resize.tsx index 100b277..6d11edd 100644 --- a/packages/email-editor/src/nodes/image-resize.tsx +++ b/packages/email-editor/src/nodes/image-resize.tsx @@ -206,7 +206,7 @@ export function ResizableImageTemplate(props: NodeViewProps) { className="flex items-center justify-center opacity-70" />
- +
) : ( diff --git a/packages/email-editor/src/nodes/variable.tsx b/packages/email-editor/src/nodes/variable.tsx index 4e62f58..1ae350a 100644 --- a/packages/email-editor/src/nodes/variable.tsx +++ b/packages/email-editor/src/nodes/variable.tsx @@ -180,7 +180,7 @@ export function VariableComponent(props: NodeViewProps) { + ); +}); +SidebarTrigger.displayName = "SidebarTrigger"; + +const SidebarRail = React.forwardRef< + HTMLButtonElement, + React.ComponentProps<"button"> +>(({ className, ...props }, ref) => { + const { toggleSidebar } = useSidebar(); + + return ( +