From d9f8115412e986a5d6345242b1c7fae089650062 Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Wed, 15 May 2024 21:44:49 +0500 Subject: [PATCH 1/2] feat(saas): Rewapping www ui --- apps/www/package.json | 1 - .../app/(app)/_components/highlight-tabs.tsx | 88 ------------- .../src/app/(app)/_components/side-header.tsx | 67 ---------- apps/www/src/app/(app)/layout.tsx | 16 --- apps/www/src/app/(marketing)/page.tsx | 9 ++ .../forms}/early-access-form.tsx | 2 +- apps/www/src/components/icons.tsx | 116 +++++++++++++++--- .../layout/marketing-footer.tsx} | 2 +- .../components/layout/marketing-header.tsx | 35 ++++++ .../layout/marketing-mobile-nav.tsx} | 2 +- .../layout/marketing-nav.tsx} | 2 +- apps/www/src/components/marketing-layout.tsx | 16 +++ apps/www/src/styles/globals.css | 2 +- pnpm-lock.yaml | 3 - 14 files changed, 163 insertions(+), 198 deletions(-) delete mode 100644 apps/www/src/app/(app)/_components/highlight-tabs.tsx delete mode 100644 apps/www/src/app/(app)/_components/side-header.tsx delete mode 100644 apps/www/src/app/(app)/layout.tsx create mode 100644 apps/www/src/app/(marketing)/page.tsx rename apps/www/src/{app/(app)/_components => components/forms}/early-access-form.tsx (98%) rename apps/www/src/{app/(app)/_components/site-footer.tsx => components/layout/marketing-footer.tsx} (96%) create mode 100644 apps/www/src/components/layout/marketing-header.tsx rename apps/www/src/{app/(app)/_components/mobile-nav.tsx => components/layout/marketing-mobile-nav.tsx} (98%) rename apps/www/src/{app/(app)/_components/main-nav.tsx => components/layout/marketing-nav.tsx} (97%) create mode 100644 apps/www/src/components/marketing-layout.tsx diff --git a/apps/www/package.json b/apps/www/package.json index 09d7617..9cf45f1 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -24,7 +24,6 @@ "@vercel/analytics": "^1.2.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", - "geist": "^1.2.2", "lucide-react": "^0.343.0", "next": "^14.1.0", "next-themes": "^0.2.1", diff --git a/apps/www/src/app/(app)/_components/highlight-tabs.tsx b/apps/www/src/app/(app)/_components/highlight-tabs.tsx deleted file mode 100644 index 489157a..0000000 --- a/apps/www/src/app/(app)/_components/highlight-tabs.tsx +++ /dev/null @@ -1,88 +0,0 @@ -"use client"; - -import { cn } from "@/lib/utils"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import type { TabsProps } from "@radix-ui/react-tabs"; -import { SaasStarterkitHighlight } from "@/app/(app)/_components/saas-startkit-highlight"; -import React from "react"; - -const highlights = [ - { - id: "saas-starterkit", - title: "SaaS Starterkit", - description: - "Auth, Dashboard, Landing Pages, billing and more — everything you need to launch your MVP faster.", - badge: "Almost Ready", - }, - { - id: "blocks", - title: "Blocks", - description: - "Auth forms, modals, hero sections, pricing tables, and more — all customizable and open source.", - disabled: true, - badge: "Soon", - }, - { - id: "guides", - title: "Guides", - description: - "Authenticating users, setting up billing, and more — all the guides you need to launch your app.", - disabled: true, - badge: "Soon", - }, -]; - -type HighlightNavProps = TabsProps; - -export function HighlightTabs({ className, ...props }: HighlightNavProps) { - const [selectedHighlight, setSelectedHighlight] = React.useState( - highlights[0]?.id, - ); - - const activeHighlight = highlights.find( - (highlight) => highlight.id === selectedHighlight, - ); - - return ( - setSelectedHighlight(value)} - {...props} - > -
- - {highlights.map((highlight) => ( - -
-

- {highlight.title} -

- {highlight?.badge && ( - - {highlight.badge} - - )} -
-

- {highlight.description} -

-
- ))} -
- -

- {activeHighlight?.description} -

-
- - - -
- ); -} diff --git a/apps/www/src/app/(app)/_components/side-header.tsx b/apps/www/src/app/(app)/_components/side-header.tsx deleted file mode 100644 index 9c3f71a..0000000 --- a/apps/www/src/app/(app)/_components/side-header.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { MainNav } from "@/app/(app)/_components/main-nav"; -import { ThemeToggle } from "@/components/theme-toggle"; -import { MoonIcon, SunIcon } from "lucide-react"; -import { Button, buttonVariants } from "@/components/ui/button"; -import { siteUrls } from "@/config/urls"; -import Link from "next/link"; -import { Icons } from "@/components/icons"; -import { MobileNav } from "@/app/(app)/_components/mobile-nav"; - -export function SiteHeader() { - return ( -
-
-
- - - - - - - -
- - -
-
- ); -} diff --git a/apps/www/src/app/(app)/layout.tsx b/apps/www/src/app/(app)/layout.tsx deleted file mode 100644 index 34a12d0..0000000 --- a/apps/www/src/app/(app)/layout.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { SiteHeader } from "@/app/(app)/_components/side-header"; -import { SiteFooter } from "@/app/(app)/_components/site-footer"; - -interface AppLayoutProps { - children: React.ReactNode; -} - -export default function AppLayout({ children }: AppLayoutProps) { - return ( - <> - -
{children}
- - - ); -} diff --git a/apps/www/src/app/(marketing)/page.tsx b/apps/www/src/app/(marketing)/page.tsx new file mode 100644 index 0000000..df7b94d --- /dev/null +++ b/apps/www/src/app/(marketing)/page.tsx @@ -0,0 +1,9 @@ +import { MarketingLayout } from "@/components/marketing-layout"; + +export default function HomePage() { + return ( + +

Marketing Page

+
+ ); +} diff --git a/apps/www/src/app/(app)/_components/early-access-form.tsx b/apps/www/src/components/forms/early-access-form.tsx similarity index 98% rename from apps/www/src/app/(app)/_components/early-access-form.tsx rename to apps/www/src/components/forms/early-access-form.tsx index cd3c7db..2e53a8f 100644 --- a/apps/www/src/app/(app)/_components/early-access-form.tsx +++ b/apps/www/src/components/forms/early-access-form.tsx @@ -104,7 +104,7 @@ export function EarlyAccessForm() { size="lg" > {isPending ? ( - + ) : null} Join Early Access diff --git a/apps/www/src/components/icons.tsx b/apps/www/src/components/icons.tsx index 0172887..b5faa47 100644 --- a/apps/www/src/components/icons.tsx +++ b/apps/www/src/components/icons.tsx @@ -1,6 +1,5 @@ import { siteConfig } from "@/config/site"; import { cn } from "@/lib/utils"; -import { Loader2Icon } from "lucide-react"; import type { ElementType } from "react"; export type IconProps = React.HTMLAttributes; @@ -19,23 +18,53 @@ export const Icons = { }) => { const Comp = as ?? "div"; return ( - + - {siteConfig.name} + + {siteConfig.name} + ); }, logoIcon: (props: IconProps) => ( - - + + + + + ), twitter: (props: IconProps) => ( @@ -55,14 +84,65 @@ export const Icons = { > ), - loader: (props: IconProps) => ( - ) => ( + + > + + + + + + + + + ), hamburger: (props: IconProps) => (
diff --git a/apps/www/src/components/layout/marketing-header.tsx b/apps/www/src/components/layout/marketing-header.tsx new file mode 100644 index 0000000..d184511 --- /dev/null +++ b/apps/www/src/components/layout/marketing-header.tsx @@ -0,0 +1,35 @@ +import { Icons } from "@/components/icons"; +import { buttonVariants } from "@/components/ui/button"; +import { siteUrls } from "@/config/urls"; +import Link from "next/link"; + +export function MarketingHeader() { + return ( +
+
+ + + + +
+ + Get Started + + + + Pricing + +
+
+
+ ); +} diff --git a/apps/www/src/app/(app)/_components/mobile-nav.tsx b/apps/www/src/components/layout/marketing-mobile-nav.tsx similarity index 98% rename from apps/www/src/app/(app)/_components/mobile-nav.tsx rename to apps/www/src/components/layout/marketing-mobile-nav.tsx index 2eaa843..20432c3 100644 --- a/apps/www/src/app/(app)/_components/mobile-nav.tsx +++ b/apps/www/src/components/layout/marketing-mobile-nav.tsx @@ -11,7 +11,7 @@ import Link from "next/link"; import { useRouter } from "next/navigation"; import React from "react"; -export function MobileNav() { +export function MarketingMobileNav() { const [isOpen, setIsOpen] = React.useState(false); return ( diff --git a/apps/www/src/app/(app)/_components/main-nav.tsx b/apps/www/src/components/layout/marketing-nav.tsx similarity index 97% rename from apps/www/src/app/(app)/_components/main-nav.tsx rename to apps/www/src/components/layout/marketing-nav.tsx index 0eb625c..aacdfbb 100644 --- a/apps/www/src/app/(app)/_components/main-nav.tsx +++ b/apps/www/src/components/layout/marketing-nav.tsx @@ -5,7 +5,7 @@ import { usePathname } from "next/navigation"; import { cn } from "@/lib/utils"; import Link from "next/link"; -export function MainNav() { +export function MarketingMainNav() { const pathname = usePathname(); return ( diff --git a/apps/www/src/components/marketing-layout.tsx b/apps/www/src/components/marketing-layout.tsx new file mode 100644 index 0000000..8d9366f --- /dev/null +++ b/apps/www/src/components/marketing-layout.tsx @@ -0,0 +1,16 @@ +// import { MarketingFooter } from "@/components/layout/marketing-footer"; +import { MarketingHeader } from "@/components/layout/marketing-header"; + +interface MarketingLayoutProps { + children?: React.ReactNode; +} + +export function MarketingLayout({ children }: MarketingLayoutProps) { + return ( +
+ +
{children}
+ {/* */} +
+ ); +} diff --git a/apps/www/src/styles/globals.css b/apps/www/src/styles/globals.css index 94e3eed..ef8a7c3 100644 --- a/apps/www/src/styles/globals.css +++ b/apps/www/src/styles/globals.css @@ -32,7 +32,7 @@ --input: 240 5.9% 90%; --ring: 240 10% 3.9%; - --radius: 0.8rem; + --radius: 0.6rem; } :root[class~="dark"] { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7bde3f0..6e259d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,9 +62,6 @@ importers: clsx: specifier: ^2.1.0 version: 2.1.1 - geist: - specifier: ^1.2.2 - version: 1.3.0(next@14.2.3) lucide-react: specifier: ^0.343.0 version: 0.343.0(react@18.2.0) From df0483a205094fa11c2a003855347dba12a61c20 Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Thu, 16 May 2024 00:56:51 +0500 Subject: [PATCH 2/2] feat(www): Marketing header ui --- apps/www/src/app/(marketing)/page.tsx | 5 +- apps/www/src/app/saas-starterkit/page.tsx | 9 ++ apps/www/src/components/icons.tsx | 63 ++++++++++-- .../components/layout/marketing-header.tsx | 37 ++++--- .../{ => layout}/marketing-layout.tsx | 0 .../layout/marketing-mobile-nav.tsx | 99 ------------------- .../src/components/layout/marketing-nav.tsx | 76 +++++++++++--- apps/www/src/components/ui/button.tsx | 2 +- apps/www/src/config/nav.ts | 33 ------- apps/www/src/config/pages.ts | 30 ++++++ apps/www/src/config/site.ts | 2 + apps/www/src/server/actions/github.ts | 15 +++ 12 files changed, 203 insertions(+), 168 deletions(-) create mode 100644 apps/www/src/app/saas-starterkit/page.tsx rename apps/www/src/components/{ => layout}/marketing-layout.tsx (100%) delete mode 100644 apps/www/src/components/layout/marketing-mobile-nav.tsx delete mode 100644 apps/www/src/config/nav.ts create mode 100644 apps/www/src/config/pages.ts create mode 100644 apps/www/src/server/actions/github.ts diff --git a/apps/www/src/app/(marketing)/page.tsx b/apps/www/src/app/(marketing)/page.tsx index df7b94d..2fb8fff 100644 --- a/apps/www/src/app/(marketing)/page.tsx +++ b/apps/www/src/app/(marketing)/page.tsx @@ -1,4 +1,4 @@ -import { MarketingLayout } from "@/components/marketing-layout"; +import { MarketingLayout } from "@/components/layout/marketing-layout"; export default function HomePage() { return ( @@ -7,3 +7,6 @@ export default function HomePage() { ); } + +export const dynamic = "force-static"; +export const revalidate = 60 * 60; diff --git a/apps/www/src/app/saas-starterkit/page.tsx b/apps/www/src/app/saas-starterkit/page.tsx new file mode 100644 index 0000000..3e1b101 --- /dev/null +++ b/apps/www/src/app/saas-starterkit/page.tsx @@ -0,0 +1,9 @@ +import { MarketingLayout } from "@/components/layout/marketing-layout"; + +export default function SaasStarterKitPage() { + return ( + +
saas starter kit
+
+ ); +} diff --git a/apps/www/src/components/icons.tsx b/apps/www/src/components/icons.tsx index b5faa47..7b3e585 100644 --- a/apps/www/src/components/icons.tsx +++ b/apps/www/src/components/icons.tsx @@ -2,7 +2,7 @@ import { siteConfig } from "@/config/site"; import { cn } from "@/lib/utils"; import type { ElementType } from "react"; -export type IconProps = React.HTMLAttributes; +export type IconProps = React.SVGProps; export const Icons = { logo: ({ @@ -23,12 +23,7 @@ export const Icons = { className={cn("h-6 w-6 fill-primary", iconProps?.className)} {...iconProps} /> - + {siteConfig.name} @@ -84,7 +79,7 @@ export const Icons = { > ), - spinner: (props: React.SVGProps) => ( + spinner: (props: IconProps) => ( ), + star: (props: IconProps) => ( + + + + ), + chevronRight: (props: IconProps) => ( + + + + ), + circle: (props: IconProps) => ( + + + + ), }; diff --git a/apps/www/src/components/layout/marketing-header.tsx b/apps/www/src/components/layout/marketing-header.tsx index d184511..0ccc6d9 100644 --- a/apps/www/src/components/layout/marketing-header.tsx +++ b/apps/www/src/components/layout/marketing-header.tsx @@ -1,32 +1,43 @@ import { Icons } from "@/components/icons"; +import { MarketingMainNav } from "@/components/layout/marketing-nav"; import { buttonVariants } from "@/components/ui/button"; import { siteUrls } from "@/config/urls"; +import { getGithubRepoStars } from "@/server/actions/github"; import Link from "next/link"; -export function MarketingHeader() { +export async function MarketingHeader() { + const stars = await getGithubRepoStars(); + return (
- - - - -
- - Get Started +
+ + + +
+ +
+ + + {stars} + + + - Pricing + Get Started
diff --git a/apps/www/src/components/marketing-layout.tsx b/apps/www/src/components/layout/marketing-layout.tsx similarity index 100% rename from apps/www/src/components/marketing-layout.tsx rename to apps/www/src/components/layout/marketing-layout.tsx diff --git a/apps/www/src/components/layout/marketing-mobile-nav.tsx b/apps/www/src/components/layout/marketing-mobile-nav.tsx deleted file mode 100644 index 20432c3..0000000 --- a/apps/www/src/components/layout/marketing-mobile-nav.tsx +++ /dev/null @@ -1,99 +0,0 @@ -"use client"; - -import { Icons } from "@/components/icons"; -import { Button } from "@/components/ui/button"; -import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; -import { navConfig } from "@/config/nav"; -import { siteUrls } from "@/config/urls"; -import { cn } from "@/lib/utils"; -import type { LinkProps } from "next/link"; -import Link from "next/link"; -import { useRouter } from "next/navigation"; -import React from "react"; - -export function MarketingMobileNav() { - const [isOpen, setIsOpen] = React.useState(false); - - return ( - setIsOpen(o)}> - - - - -
- - - -
- -
- {navConfig.items.map((item) => ( - - {item.label} - - ))} -
-
-
- ); -} - -interface MobileLinkProps extends LinkProps { - onOpenChange?: (open: boolean) => void; - children: React.ReactNode; - className?: string; - disabled?: boolean; -} - -function MobileLink({ - href, - onOpenChange, - className, - children, - disabled, - ...props -}: MobileLinkProps) { - const router = useRouter(); - return ( - { - void router.push(String(href)); - onOpenChange?.(false); - }} - className={cn( - disabled && "pointer-events-none opacity-60", - className, - )} - {...props} - > - {children} - - ); -} diff --git a/apps/www/src/components/layout/marketing-nav.tsx b/apps/www/src/components/layout/marketing-nav.tsx index aacdfbb..3caaf39 100644 --- a/apps/www/src/components/layout/marketing-nav.tsx +++ b/apps/www/src/components/layout/marketing-nav.tsx @@ -1,32 +1,82 @@ "use client"; -import { navConfig } from "@/config/nav"; import { usePathname } from "next/navigation"; import { cn } from "@/lib/utils"; import Link from "next/link"; +import { marketingPageConfig } from "@/config/pages"; +import { Icons } from "@/components/icons"; +import React from "react"; export function MarketingMainNav() { const pathname = usePathname(); + const [isHovered, setIsHovered] = React.useState(false); + const [currentHovered, setCurrentHovered] = React.useState(""); return (
-