From 58aebf50a2f6b40430b81d90e03c9110845ca94e Mon Sep 17 00:00:00 2001 From: Lumither Tao Date: Thu, 14 Mar 2024 00:38:24 +0800 Subject: [PATCH] feat(global) project init --- .gitignore | 6 ++ app/globals.css | 95 ++++++++++++++++------ app/header.tsx | 32 ++++++++ app/layout.tsx | 47 ++++++++--- app/page.tsx | 121 +++------------------------- components.json | 17 ++++ components/theme-provider.tsx | 9 +++ components/ui/avatar.tsx | 50 ++++++++++++ components/ui/navigation-menu.tsx | 128 ++++++++++++++++++++++++++++++ lib/utils.ts | 6 ++ package.json | 10 ++- tailwind.config.ts | 90 ++++++++++++++++++--- 12 files changed, 447 insertions(+), 164 deletions(-) create mode 100644 app/header.tsx create mode 100644 components.json create mode 100644 components/theme-provider.tsx create mode 100644 components/ui/avatar.tsx create mode 100644 components/ui/navigation-menu.tsx create mode 100644 lib/utils.ts diff --git a/.gitignore b/.gitignore index fd3dbb5..75dce35 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,9 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# bun +./bun.lockb + +# ide related +.idea diff --git a/app/globals.css b/app/globals.css index 875c01e..6a75725 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,33 +1,76 @@ @tailwind base; @tailwind components; @tailwind utilities; - -:root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; -} - -@media (prefers-color-scheme: dark) { + +@layer base { :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; } } - -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); -} - -@layer utilities { - .text-balance { - text-wrap: balance; + +@layer base { + * { + @apply border-border; } -} + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file diff --git a/app/header.tsx b/app/header.tsx new file mode 100644 index 0000000..f8ec987 --- /dev/null +++ b/app/header.tsx @@ -0,0 +1,32 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; + +export default function Header() { + const [ scrolled, setScrolled ] = useState(false); + + useEffect(() => { + const handleScroll = () => { + const isScrolled = window.scrollY > 0; + setScrolled(isScrolled); + }; + + window.addEventListener('scroll', handleScroll); + + return () => { + window.removeEventListener('scroll', handleScroll); + }; + }, []); + + return <> +
+ + + Tao + +

{ 'Lumither\'s Blog' }

+ +
+ ; +} diff --git a/app/layout.tsx b/app/layout.tsx index 3314e47..787a2f2 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,22 +1,43 @@ -import type { Metadata } from "next"; -import { Inter } from "next/font/google"; -import "./globals.css"; +import type { Metadata } from 'next'; +import './globals.css'; -const inter = Inter({ subsets: ["latin"] }); +import { Inter as FontSans } from 'next/font/google'; +import { cn } from '@/lib/utils'; +import React from 'react'; +import { ThemeProvider } from '@/components/theme-provider'; +import Header from '@/app/header'; + +const fontSans = FontSans({ + subsets: [ 'latin' ], + variable: '--font-sans' +}); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: 'Lumither\'s blog', + description: 'a little blog site...' }; export default function RootLayout({ - children, + children }: Readonly<{ - children: React.ReactNode; + children: React.ReactNode; }>) { - return ( - - {children} - - ); + return ( + + + +
+ { children } + + + + ); } diff --git a/app/page.tsx b/app/page.tsx index dc191aa..10889a6 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,113 +1,12 @@ -import Image from "next/image"; - export default function Home() { - return ( -
-
-

- Get started by editing  - app/page.tsx -

- -
- -
- Next.js Logo -
- -
- -

- Docs{" "} - - -> - -

-

- Find in-depth information about Next.js features and API. -

-
- - -

- Learn{" "} - - -> - -

-

- Learn about Next.js in an interactive course with quizzes! -

-
- - -

- Templates{" "} - - -> - -

-

- Explore starter templates for Next.js. -

-
- - -

- Deploy{" "} - - -> - -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-
-
-
- ); + let info = new Array(200).fill(

test

); + return ( +
+
    + { info.map((item, id) => ( +
  • { item }
  • + )) } +
+
+ ); } diff --git a/components.json b/components.json new file mode 100644 index 0000000..3040da4 --- /dev/null +++ b/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "app/globals.css", + "baseColor": "slate", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} \ No newline at end of file diff --git a/components/theme-provider.tsx b/components/theme-provider.tsx new file mode 100644 index 0000000..693b468 --- /dev/null +++ b/components/theme-provider.tsx @@ -0,0 +1,9 @@ +'use client'; + +import * as React from 'react'; +import { ThemeProvider as NextThemesProvider } from 'next-themes'; +import { type ThemeProviderProps } from 'next-themes/dist/types'; + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return { children }; +} diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx new file mode 100644 index 0000000..51e507b --- /dev/null +++ b/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/components/ui/navigation-menu.tsx b/components/ui/navigation-menu.tsx new file mode 100644 index 0000000..5841fb3 --- /dev/null +++ b/components/ui/navigation-menu.tsx @@ -0,0 +1,128 @@ +import * as React from "react" +import { ChevronDownIcon } from "@radix-ui/react-icons" +import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu" +import { cva } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const NavigationMenu = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + +)) +NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName + +const NavigationMenuList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName + +const NavigationMenuItem = NavigationMenuPrimitive.Item + +const navigationMenuTriggerStyle = cva( + "group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50" +) + +const NavigationMenuTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children}{" "} + +)) +NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName + +const NavigationMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName + +const NavigationMenuLink = NavigationMenuPrimitive.Link + +const NavigationMenuViewport = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ +
+)) +NavigationMenuViewport.displayName = + NavigationMenuPrimitive.Viewport.displayName + +const NavigationMenuIndicator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +
+ +)) +NavigationMenuIndicator.displayName = + NavigationMenuPrimitive.Indicator.displayName + +export { + navigationMenuTriggerStyle, + NavigationMenu, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuContent, + NavigationMenuTrigger, + NavigationMenuLink, + NavigationMenuIndicator, + NavigationMenuViewport, +} diff --git a/lib/utils.ts b/lib/utils.ts new file mode 100644 index 0000000..d084cca --- /dev/null +++ b/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/package.json b/package.json index b103241..cf89832 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,17 @@ "lint": "next lint" }, "dependencies": { + "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-navigation-menu": "^1.1.4", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "next": "14.1.3", + "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", - "next": "14.1.3" + "tailwind-merge": "^2.2.1", + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "typescript": "^5", diff --git a/tailwind.config.ts b/tailwind.config.ts index 7e4bd91..593f812 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,20 +1,84 @@ -import type { Config } from "tailwindcss"; +import type { Config } from "tailwindcss" +import { fontFamily } from 'tailwindcss/defaultTheme'; -const config: Config = { +const config = { + darkMode: ["class"], content: [ - "./pages/**/*.{js,ts,jsx,tsx,mdx}", - "./components/**/*.{js,ts,jsx,tsx,mdx}", - "./app/**/*.{js,ts,jsx,tsx,mdx}", - ], + './pages/**/*.{ts,tsx}', + './components/**/*.{ts,tsx}', + './app/**/*.{ts,tsx}', + './src/**/*.{ts,tsx}', + ], + prefix: "", theme: { + fontFamily: { + sans: ["var(--font-sans)", ...fontFamily.sans], + }, + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, extend: { - backgroundImage: { - "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", - "gradient-conic": - "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", + colors: { + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: "0" }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", }, }, }, - plugins: [], -}; -export default config; + plugins: [require("tailwindcss-animate")], +} satisfies Config + +export default config