Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/next' into feat/clerk-migration
Browse files Browse the repository at this point in the history
  • Loading branch information
ixahmedxi committed May 25, 2024
2 parents 6788409 + 35de3af commit 7c53430
Show file tree
Hide file tree
Showing 18 changed files with 704 additions and 93 deletions.
Binary file modified bun.lockb
Binary file not shown.
7 changes: 7 additions & 0 deletions cspell.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,21 @@ ignorePaths:
- '**/*.svg'
- .vscode/extensions.json
- public
- tsconfig.tsbuildinfo
- playwright-report
- test-results
words:
- tsbuildinfo
- callees
- classname
- clsx
- commitlint
- compat
- ianvs
- ixahmedxi
- jiti
- lockb
- lucide
- mitigations
- nextjs
- packagejson
Expand Down
4 changes: 3 additions & 1 deletion e2e/example.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ import { expect, test } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('/');

await expect(page.getByText(/hello world/i)).toBeVisible();
await expect(
page.getByText(/rethinking student productivity/i),
).toBeVisible();
});
4 changes: 4 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ export default tseslint.config(
react: {
version: 'detect',
},
tailwindcss: {
callees: ['classnames', 'clsx', 'ctl', 'cn', 'cva'],
},
},
rules: {
'@typescript-eslint/no-unused-vars': [
Expand All @@ -105,6 +108,7 @@ export default tseslint.config(
],

'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',

// prettier figures out the lines between tags
'jsdoc/tag-lines': 'off',
Expand Down
15 changes: 9 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"type": "module",
"scripts": {
"build": "next build",
"clean": "rimraf --glob .next node_modules *.tsbuildinfo next-env.d.ts .eslintcache",
"clean": "rimraf --glob .next node_modules *.tsbuildinfo next-env.d.ts .eslintcache playwright-report test-results",
"commit": "git-cz",
"dev": "next dev --turbo",
"format": "pnpm format:write",
Expand Down Expand Up @@ -48,13 +48,16 @@
"@clerk/nextjs": "^5.0.12",
"@clerk/themes": "^2.1.6",
"@radix-ui/colors": "^3.0.0",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-slot": "^1.0.2",
"@t3-oss/env-nextjs": "^0.10.1",
"@upstash/ratelimit": "^1.1.3",
"@upstash/redis": "^1.31.1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"geist": "^1.3.0",
"jiti": "^1.21.0",
"lucide-react": "^0.378.0",
"next": "14.2.3",
"next-themes": "^0.3.0",
"react": "^18.3.1",
Expand All @@ -63,14 +66,14 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@changesets/cli": "^2.27.1",
"@changesets/cli": "^2.27.2",
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@commitlint/cz-commitlint": "^19.2.0",
"@eslint-community/eslint-plugin-eslint-comments": "^4.3.0",
"@eslint/compat": "^1.0.1",
"@eslint/eslintrc": "^3.0.2",
"@eslint/js": "^9.2.0",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.3.0",
"@happy-dom/global-registrator": "^14.11.0",
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
"@next/eslint-plugin-next": "^14.2.3",
Expand All @@ -90,7 +93,7 @@
"@types/react-dom": "^18.3.0",
"commitizen": "^4.3.0",
"cspell": "^8.8.1",
"eslint": "^9.2.0",
"eslint": "^9.3.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jsdoc": "^48.2.5",
"eslint-plugin-jsx-a11y": "^6.8.0",
Expand All @@ -99,7 +102,7 @@
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-regexp": "^2.5.0",
"eslint-plugin-security": "^3.0.0",
"eslint-plugin-tailwindcss": "^3.15.1",
"eslint-plugin-tailwindcss": "^3.15.2",
"eslint-plugin-testing-library": "^6.2.2",
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
Expand Down
Binary file added public/_static/dark-dashboard-preview.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/_static/light-dashboard-preview.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions public/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions src/app/(marketing)/_components/home-preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use client';

import { useEffect, useState } from 'react';
import { useTheme } from 'next-themes';
import Image from 'next/image';

/**
* This component renders the dashboard preview image that is used on the home
* marketing page, it will use the light or dark image depending on the theme.
*
* @returns A react component representing the dashboard preview image.
*/
export function HomePreview() {
const [mounted, setMounted] = useState(false);
const { resolvedTheme } = useTheme();

useEffect(() => {
setMounted(true);
}, []);

if (mounted && resolvedTheme === 'light') {
return (
<>
<Image
src="/_static/light-dashboard-preview.jpg"
width={1920}
height={1080}
alt="Dashboard Preview"
className="my-12 rounded-lg shadow-[0_50px_200px_75px] shadow-pink/10"
/>
</>
);
}

return (
<Image
src="/_static/dark-dashboard-preview.jpg"
width={1920}
height={1080}
alt="Dashboard Preview"
className="my-12 rounded-lg shadow-[0_50px_200px_75px] shadow-pink/10"
/>
);
}
215 changes: 215 additions & 0 deletions src/app/(marketing)/_components/navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
'use client';

import { forwardRef, useEffect, useState } from 'react';
import Image from 'next/image';
import Link from 'next/link';

import {
BotIcon,
ChevronRightIcon,
Edit2Icon,
FlaskRoundIcon,
ListChecksIcon,
} from 'lucide-react';

import { constants } from '@/constants';
import { cn } from '@/lib/utils';
import { Button } from '@/primitives/button';
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from '@/primitives/navigation-menu';

interface ListItemProps {
title: string;
href: string;
description: string;
icon: React.ReactNode;
}

// TODO: put in the correct links

const features: ListItemProps[] = [
{
title: 'Note Taking',
icon: <Edit2Icon size={18} />,
href: '/docs/primitives/alert-dialog',
description: 'Write your notes and we will take care of the rest.',
},
{
title: 'Noodle AI',
icon: <BotIcon size={18} />,
href: '/docs/primitives/hover-card',
description: 'Your very own assistant helping you stay on top of studies.',
},
{
title: 'Task Management',
icon: <ListChecksIcon size={18} />,
href: '/docs/primitives/progress',
description: 'Never miss a thing that you have to do for your modules.',
},
{
title: 'Flashcards & Quizzes',
icon: <FlaskRoundIcon size={18} />,
href: '/docs/primitives/progress',
description: 'Auto generated flashcards and quizzes from your notes.',
},
];

const ListItem = forwardRef<
React.ElementRef<'a'>,
React.ComponentPropsWithoutRef<'a'> & { icon: React.ReactNode }
>(({ className, title, children, icon, ...props }, ref) => {
return (
<li>
<NavigationMenuLink asChild>
<a
ref={ref}
className={cn(
'z-50 flex select-none items-start gap-3 rounded-md border border-transparent px-4 py-3 leading-none no-underline outline-none transition-colors hover:border-gray-element hover:bg-gray-element/30 hover:text-gray-foreground focus:border-gray-element focus:bg-gray-element/30 focus:text-gray-foreground',
className,
)}
{...props}
>
<div className="size-[18px]">{icon}</div>
<div className="space-y-2">
<div className="text-sm font-medium leading-none text-foreground">
{title}
</div>
<p className="line-clamp-2 text-xs leading-normal">{children}</p>
</div>
</a>
</NavigationMenuLink>
</li>
);
});
ListItem.displayName = 'ListItem';

export const Navbar = () => {
const [scroll, setScroll] = useState(false);

useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 50) {
setScroll(true);
} else {
setScroll(false);
}
};

window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);

return (
<nav
className={cn(
'sticky inset-x-0 top-0 z-50 w-full border-b border-transparent bg-transparent py-4 transition-colors duration-500',
scroll && 'border-gray-element bg-background/85 backdrop-blur-md',
)}
>
<div className="container flex items-center justify-between transition-all">
<Link href="/" className="flex items-center gap-3">
<Image src="/logo.svg" width={35} height={35} alt="Noodle Logo" />
<span>Noodle</span>
</Link>

<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Features</NavigationMenuTrigger>
<NavigationMenuContent>
<div className="absolute right-36 top-1/2 z-30 size-20 -translate-y-1/2 rounded-full bg-pink opacity-50 blur-3xl" />
<ul className="grid gap-3 p-3 md:w-[450px] lg:w-[550px] lg:grid-cols-[1fr_0.85fr]">
<div className="flex flex-col gap-3">
{features.map((feature) => (
<ListItem
key={feature.title}
href={feature.href}
title={feature.title}
icon={feature.icon}
>
{feature.description}
</ListItem>
))}
</div>
<li>
<NavigationMenuLink asChild>
<a
className="flex size-full select-none flex-col justify-end rounded-md border border-gray-element bg-[#191919]/50 px-6 py-3 no-underline outline-none backdrop-blur-lg transition-colors hover:bg-[#191919]/75 focus:shadow-md"
href="/"
>
<Image
src="/logo.svg"
width={35}
height={35}
alt="Noodle Logo"
/>
<div className="mb-2 mt-4 text-lg font-medium text-foreground">
{constants.shortName}
</div>
<p className="text-sm leading-snug text-foreground-muted">
Helping students stay productive and on top of their
work.
</p>

<Link
href="/docs"
className="mt-6 flex items-center gap-2 py-2 text-sm transition-colors hover:text-gray-foreground"
>
Explore all features <ChevronRightIcon size={13} />
</Link>
</a>
</NavigationMenuLink>
</li>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<Link href="/docs" legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Pricing
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
<NavigationMenuItem>
<Link href="/docs" legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Blog
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
<NavigationMenuItem>
<Link href="/docs" legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Changelog
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
<NavigationMenuItem>
<Link href="/docs" legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Contact
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
<div className="flex items-center gap-4">
<Button size="sm" asChild>
<Link href="/sign-in">
Dashboard <ChevronRightIcon size={16} />
</Link>
</Button>
</div>
</div>
</nav>
);
};
Loading

0 comments on commit 7c53430

Please sign in to comment.