feat(chapter2): set up styled app shell
Add the App Router page and nested layout, configure Tailwind and shadcn styling, include local fonts and background assets, and install the supporting UI and lint dependencies.
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
public
|
||||
node_modules
|
||||
src/database/migrations
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
docker
|
||||
Dockerfile*
|
||||
LICENSE
|
||||
yarn-error.log
|
||||
.next
|
||||
.history
|
||||
.dockerignore
|
||||
.DS_Store
|
||||
.eslintignore
|
||||
.editorconfig
|
||||
.gitignore
|
||||
.prettierignore
|
||||
.eslintcache
|
||||
*.lock
|
||||
*.png
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.eot
|
||||
*.ttf
|
||||
*.woff
|
||||
*.sql
|
||||
@@ -0,0 +1,11 @@
|
||||
const config = {
|
||||
singleQuote: true,
|
||||
trailingComma: 'all',
|
||||
printWidth: 100,
|
||||
proseWrap: 'never',
|
||||
endOfLine: 'auto',
|
||||
semi: true,
|
||||
tabWidth: 4,
|
||||
htmlWhitespaceSensitivity: 'strict',
|
||||
};
|
||||
export default config;
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "radix-nova",
|
||||
"rsc": true,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "",
|
||||
"css": "src/app/styles/tailwind.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"iconLibrary": "lucide",
|
||||
"rtl": false,
|
||||
"aliases": {
|
||||
"components": "@/app/_components/shadcn/ui",
|
||||
"utils": "@/app/_components/shadcn/ui",
|
||||
"ui": "@/app/_components/shadcn/utils",
|
||||
"lib": "@/app/_components/shadcn/libs",
|
||||
"hooks": "@/app/_components/shadcn/hooks"
|
||||
},
|
||||
"menuColor": "default",
|
||||
"menuAccent": "subtle",
|
||||
"registries": {}
|
||||
}
|
||||
+13
-2
@@ -11,9 +11,16 @@
|
||||
"lint:style": "stylelint \"**/*.css\" --fix --cache --cache-location node_modules/.cache/stylelint"
|
||||
},
|
||||
"dependencies": {
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^1.37.0",
|
||||
"next": "16.3.3",
|
||||
"radix-ui": "^1.6.7",
|
||||
"react": "19.2.8",
|
||||
"react-dom": "19.2.8"
|
||||
"react-dom": "19.2.8",
|
||||
"shadcn": "^4.19.0",
|
||||
"tailwind-merge": "^3.6.0",
|
||||
"tw-animate-css": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint-react/eslint-plugin": "^5.18.6",
|
||||
@@ -35,6 +42,7 @@
|
||||
"eslint-plugin-react-refresh": "^0.5.5",
|
||||
"eslint-plugin-unused-imports": "^4.4.1",
|
||||
"prettier": "^3.9.6",
|
||||
"rimraf": "^6.1.3",
|
||||
"stylelint": "^17.14.1",
|
||||
"stylelint-config-css-modules": "^4.6.0",
|
||||
"stylelint-config-recess-order": "^7.8.0",
|
||||
@@ -43,5 +51,8 @@
|
||||
"tailwindcss": "^4",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"packageManager": "pnpm@10.34.5"
|
||||
"packageManager": "pnpm@10.34.5",
|
||||
"imports": {
|
||||
"#tailwind.css": "./src/app/styles/tailwind.css"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+3314
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
/* src/app/(pages)/layout.module.css */
|
||||
@reference "#tailwind.css";
|
||||
|
||||
.layout {
|
||||
@apply tw:min-h-full tw:w-full tw:flex tw:flex-col tw:bg-background tw:bg-cover tw:bg-fixed tw:bg-center tw:bg-no-repeat tw:bg-[url('../styles/images/bg-light.png')] tw:p-0 tw:m-0;
|
||||
|
||||
html.dark &,
|
||||
html[data-theme='dark'] & {
|
||||
background-image: url('../styles/images/bg-dark.png');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// src/app/(pages)/layout.tsx
|
||||
import type { Metadata } from 'next';
|
||||
import type { FC, PropsWithChildren } from 'react';
|
||||
|
||||
import { Header } from '../_components/header';
|
||||
import $styles from './layout.module.css';
|
||||
export const metadata: Metadata = {
|
||||
title: 'pincman的博客',
|
||||
description:
|
||||
'pincman的个人博客,提供一些ts、react、node.js、php、golang相关的技术文档以及分享一些生活琐事',
|
||||
};
|
||||
|
||||
const AppLayout: FC<PropsWithChildren> = ({ children }) => (
|
||||
<div className={$styles.layout}>
|
||||
<Header />
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
export default AppLayout;
|
||||
@@ -0,0 +1,9 @@
|
||||
/* src/app/(pages)/page.module.css */
|
||||
@reference "#tailwind.css";
|
||||
|
||||
.block {
|
||||
@apply tw:page-container tw:flex tw:flex-col tw:flex-none! tw:w-full tw:space-y-4 tw:p-5 tw:items-center tw:justify-center
|
||||
tw:rounded-sm tw:backdrop-blur-sm tw:shadow-nysm tw:shadow-neutral-800 tw:duration-300
|
||||
tw:text-lg tw:text-center tw:text-white tw:bg-black/30
|
||||
tw:hover:shadow-nylg tw:font-lxgw;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// src/app/(pages)/page.tsx
|
||||
import { FC } from 'react';
|
||||
|
||||
import { ArrowBigRight } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
|
||||
import $styles from './page.module.css';
|
||||
import { Button } from '../_components/shadcn/ui/button';
|
||||
|
||||
const App: FC = () => (
|
||||
<main className={$styles.container}>
|
||||
<div className={$styles.block}>
|
||||
欢迎来到3R教室,这是Nextjs课程的开始
|
||||
<Button asChild>
|
||||
<Link href="https://3rcd.com" target="_blank">
|
||||
<ArrowBigRight /> 查看官网
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
export default App;
|
||||
@@ -0,0 +1 @@
|
||||
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 801 802"><defs><style>.cls-1{fill:#fff;}.cls-1,.cls-2{stroke:#000;stroke-miterlimit:10;}.cls-2{fill:#224740;}</style></defs><rect class="cls-1" x="0.5" y="0.5" width="800" height="801"/><path class="cls-2" d="M255.61,517.24,182.5,569.53c-16.57,13.4-68.15,8.09-74.37-.12-8.7-11.49-23.82-26.39-14-35.29s37.18-8.36,37.18-8.36l30.06-.58s19.51-4,27.92-4.89c11.23-1.23,13-3.43,10.56-5.93-.67.24-.48-.48-.48-.48-5.6-4.86-25.35-10.58-22.23-12.31l62-52.44c-1.87,1.12-163.29,65.48-163.29,65.48L62.67,526.27s-2.17-1.48-20.75,27.34c-2.5,3.88,37.87,28.51,37.87,28.51C209.06,671.81,328.12,475,353.3,420.12l-.24-2.29,5.15-5.58c18.53,15.86,32.57,37.32,45.87,45.14,20.4,12-.15-8.39,38.94,24.3s39.47,148.93,36.6,175.53-29.74,29.64-29.74,29.64,9.93-28.87,7.36-78.72c-2.57-49.16-81.43-51.44-83.41-51.51C471,602.21,394,738.52,394,738.52s35,4.34,93.39-56.92-25.93-226.14-20.1-253.09c2.69-12.37,95.24-19.54,95.24-19.54s117.86,1.61,120.76,5.78c5.4,7.7,9.11,22.5,4.08,46.84-5,23.83-78.09,90.15-81.16,93,2.29-.59,39.63-11.61,96.61-69.39,58.81-59.69-1.66-127.51-58.34-103.49S528,381.27,528,381.27c-7.7-8.51-11.89-18.92-13.46-30.47h0l-27.48-5.14,27.46-18.19h0c7.21-63.27,66.28-143.75,74.05-152.62,10.38-11.8,15.63-11.29,7.31-23-6.65-9.35-3-12.33-.71-13.37l.64-.2c-9.26,2.67-52.44,13.88-116.82,11.24-72-2.92-111-84.78-112-87.12l-2.21-2.86s-38.57,66-12.6,108.84c20.18,33.3,153.43,44.76,153.43,44.76s.82,14.78-9.7,21.19-32.69-2.77-72.55-15.43l-8.88-1.7c-11.23-1.51-36.36-13.58-64-40.62l-26.19,218,5.65,18-67.34,97.66c-2.6,2.47-2.6,2.47-6.91,7m68.6-122.67M407,285.14s13.38-5.44,25.85.58,19.25,21.2,19.25,21.2-13.37,5.47-25.84-.55S407,285.14,407,285.14Z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,11 @@
|
||||
// src/app/_components/header/index.tsx
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { HeaderLogo } from './logo';
|
||||
import $styles from './styles.module.css';
|
||||
|
||||
export const Header: FC = () => (
|
||||
<header className={$styles.header}>
|
||||
<HeaderLogo />
|
||||
</header>
|
||||
);
|
||||
@@ -0,0 +1,17 @@
|
||||
/* src/app/_components/header/logo.module.css */
|
||||
@reference "#tailwind.css";
|
||||
|
||||
.link {
|
||||
@apply tw:w-20 tw:h-20 tw:block tw:rounded-full tw:shadow-nymd tw:p-1 tw:bg-white;
|
||||
transition-duration: 300ms;
|
||||
animation: breathe-light 4s ease-in-out infinite;
|
||||
|
||||
&:hover {
|
||||
@apply tw:shadow-nylg tw:shadow-amber-400;
|
||||
transform: scale(1.2) rotate(360deg);
|
||||
}
|
||||
|
||||
& > img {
|
||||
@apply tw:rounded-full;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// src/app/_components/header/logo.tsx
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
|
||||
import Avatar from './avatar.svg';
|
||||
import $styles from './logo.module.css';
|
||||
|
||||
export const HeaderLogo = () => (
|
||||
<Link href="/" className={$styles.link}>
|
||||
<Image
|
||||
src={Avatar}
|
||||
alt="avatar logo"
|
||||
sizes="100vw"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 'auto',
|
||||
}}
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
@@ -0,0 +1,6 @@
|
||||
/* src/app/_components/header/styles.module.css */
|
||||
@reference "#tailwind.css";
|
||||
|
||||
.header {
|
||||
@apply tw:flex tw:justify-center tw:items-center tw:pt-6 tw:max-h-24 tw:flex-auto;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import * as React from "react"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { Slot } from "radix-ui"
|
||||
|
||||
import { cn } from "@/app/_components/shadcn/libs/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
||||
outline:
|
||||
"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
||||
ghost:
|
||||
"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
||||
destructive:
|
||||
"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default:
|
||||
"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
||||
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
||||
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
||||
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
||||
icon: "size-8",
|
||||
"icon-xs":
|
||||
"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
||||
"icon-sm":
|
||||
"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
|
||||
"icon-lg": "size-9",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
function Button({
|
||||
className,
|
||||
variant = "default",
|
||||
size = "default",
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<"button"> &
|
||||
VariantProps<typeof buttonVariants> & {
|
||||
asChild?: boolean
|
||||
}) {
|
||||
const Comp = asChild ? Slot.Root : "button"
|
||||
|
||||
return (
|
||||
<Comp
|
||||
data-slot="button"
|
||||
data-variant={variant}
|
||||
data-size={size}
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Button, buttonVariants }
|
||||
@@ -0,0 +1,103 @@
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/app/_components/shadcn/libs/utils"
|
||||
|
||||
function Card({
|
||||
className,
|
||||
size = "default",
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card"
|
||||
data-size={size}
|
||||
className={cn(
|
||||
"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-header"
|
||||
className={cn(
|
||||
"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-title"
|
||||
className={cn(
|
||||
"font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-description"
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-action"
|
||||
className={cn(
|
||||
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-content"
|
||||
className={cn("px-(--card-spacing)", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-footer"
|
||||
className={cn(
|
||||
"flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardAction,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
+11
-21
@@ -1,29 +1,19 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import "./globals.css";
|
||||
// src/app/layout.tsx
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
import './styles/index.css';
|
||||
|
||||
const geistMono = Geist_Mono({
|
||||
variable: "--font-geist-mono",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
import type { FC, PropsWithChildren } from 'react';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
title: 'nextapp',
|
||||
description: '3r教室Next.js全栈开发课程',
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: LayoutProps<"/">) {
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
|
||||
>
|
||||
<body className="min-h-full flex flex-col">{children}</body>
|
||||
const RootLayout: FC<PropsWithChildren> = ({ children }) => (
|
||||
<html lang="en">
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
export default RootLayout;
|
||||
@@ -1,69 +0,0 @@
|
||||
import Image from "next/image";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
|
||||
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
|
||||
<Image
|
||||
className="dark:invert h-5 w-[100px]"
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={100}
|
||||
height={20}
|
||||
priority
|
||||
/>
|
||||
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
|
||||
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
|
||||
To get started, edit the{" "}
|
||||
<code className="rounded bg-black/[.06] px-1.5 py-0.5 font-mono text-[0.9em] dark:bg-white/[.08]">
|
||||
page.tsx
|
||||
</code>{" "}
|
||||
file.
|
||||
</h1>
|
||||
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
|
||||
Looking for a starting point or more instructions? Head over to{" "}
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
>
|
||||
Templates
|
||||
</a>{" "}
|
||||
or the{" "}
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
>
|
||||
Learning
|
||||
</a>{" "}
|
||||
center.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className="dark:invert h-[14px] w-4"
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={16}
|
||||
height={14}
|
||||
/>
|
||||
Deploy Now
|
||||
</a>
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Documentation
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/* src/app/styles/app.css */
|
||||
.lucide {
|
||||
@apply tw:w-4 tw:h-4 tw:stroke-[1px];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
@font-face {
|
||||
font-family: 'Fira Code';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src:
|
||||
url('/fonts/firacode/woff2/FiraCode-Light.woff2') format('woff2'),
|
||||
url('/fonts/firacode/woff/FiraCode-Light.woff') format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira Code';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src:
|
||||
url('/fonts/firacode/woff2/FiraCode-Regular.woff2') format('woff2'),
|
||||
url('/fonts/firacode/woff/FiraCode-Regular.woff') format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira Code';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src:
|
||||
url('/fonts/firacode/woff2/FiraCode-Medium.woff2') format('woff2'),
|
||||
url('/fonts/firacode/woff/FiraCode-Medium.woff') format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira Code';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src:
|
||||
url('/fonts/firacode/woff2/FiraCode-SemiBold.woff2') format('woff2'),
|
||||
url('/fonts/firacode/woff/FiraCode-SemiBold.woff') format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira Code';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src:
|
||||
url('/fonts/firacode/woff2/FiraCode-Bold.woff2') format('woff2'),
|
||||
url('/fonts/firacode/woff/FiraCode-Bold.woff') format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira Code VF';
|
||||
font-style: normal;
|
||||
|
||||
/* font-weight requires a range: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide#Using_a_variable_font_font-face_changes */
|
||||
font-weight: 300 700;
|
||||
src:
|
||||
url('/fonts/firacode/woff2/FiraCode-VF.woff2') format('woff2-variations'),
|
||||
url('/fonts/firacode/woff/FiraCode-VF.woff') format('woff-variations');
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 257 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 923 KiB |
@@ -0,0 +1,5 @@
|
||||
@import './fonts/fira-code.css';
|
||||
@import './fonts/lxgwwenkai-regular.css';
|
||||
@import './fonts/lxgwwenkaimono-regular.css';
|
||||
@import './tailwind.css';
|
||||
@import './app.css';
|
||||
@@ -0,0 +1,118 @@
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-ring: var(--ring);
|
||||
--color-input: var(--input);
|
||||
--color-border: var(--border);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-card: var(--card);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(100% 0 0deg);
|
||||
--foreground: oklch(14.1% 0.005 285.823deg);
|
||||
--card: oklch(100% 0 0deg);
|
||||
--card-foreground: oklch(14.1% 0.005 285.823deg);
|
||||
--popover: oklch(100% 0 0deg);
|
||||
--popover-foreground: oklch(14.1% 0.005 285.823deg);
|
||||
--primary: oklch(21% 0.006 285.885deg);
|
||||
--primary-foreground: oklch(98.5% 0 0deg);
|
||||
--secondary: oklch(96.7% 0.001 286.375deg);
|
||||
--secondary-foreground: oklch(21% 0.006 285.885deg);
|
||||
--muted: oklch(96.7% 0.001 286.375deg);
|
||||
--muted-foreground: oklch(55.2% 0.016 285.938deg);
|
||||
--accent: oklch(96.7% 0.001 286.375deg);
|
||||
--accent-foreground: oklch(21% 0.006 285.885deg);
|
||||
--destructive: oklch(57.7% 0.245 27.325deg);
|
||||
--border: oklch(92% 0.004 286.32deg);
|
||||
--input: oklch(92% 0.004 286.32deg);
|
||||
--ring: oklch(70.5% 0.015 286.067deg);
|
||||
--chart-1: oklch(64.6% 0.222 41.116deg);
|
||||
--chart-2: oklch(60% 0.118 184.704deg);
|
||||
--chart-3: oklch(39.8% 0.07 227.392deg);
|
||||
--chart-4: oklch(82.8% 0.189 84.429deg);
|
||||
--chart-5: oklch(76.9% 0.188 70.08deg);
|
||||
--sidebar: oklch(98.5% 0 0deg);
|
||||
--sidebar-foreground: oklch(14.1% 0.005 285.823deg);
|
||||
--sidebar-primary: oklch(21% 0.006 285.885deg);
|
||||
--sidebar-primary-foreground: oklch(98.5% 0 0deg);
|
||||
--sidebar-accent: oklch(96.7% 0.001 286.375deg);
|
||||
--sidebar-accent-foreground: oklch(21% 0.006 285.885deg);
|
||||
--sidebar-border: oklch(92% 0.004 286.32deg);
|
||||
--sidebar-ring: oklch(70.5% 0.015 286.067deg);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(14.1% 0.005 285.823deg);
|
||||
--foreground: oklch(98.5% 0 0deg);
|
||||
--card: oklch(21% 0.006 285.885deg);
|
||||
--card-foreground: oklch(98.5% 0 0deg);
|
||||
--popover: oklch(21% 0.006 285.885deg);
|
||||
--popover-foreground: oklch(98.5% 0 0deg);
|
||||
--primary: oklch(92% 0.004 286.32deg);
|
||||
--primary-foreground: oklch(21% 0.006 285.885deg);
|
||||
--secondary: oklch(27.4% 0.006 286.033deg);
|
||||
--secondary-foreground: oklch(98.5% 0 0deg);
|
||||
--muted: oklch(27.4% 0.006 286.033deg);
|
||||
--muted-foreground: oklch(70.5% 0.015 286.067deg);
|
||||
--accent: oklch(27.4% 0.006 286.033deg);
|
||||
--accent-foreground: oklch(98.5% 0 0deg);
|
||||
--destructive: oklch(70.4% 0.191 22.216deg);
|
||||
--border: oklch(100% 0 0deg / 10%);
|
||||
--input: oklch(100% 0 0deg / 15%);
|
||||
--ring: oklch(55.2% 0.016 285.938deg);
|
||||
--chart-1: oklch(48.8% 0.243 264.376deg);
|
||||
--chart-2: oklch(69.6% 0.17 162.48deg);
|
||||
--chart-3: oklch(76.9% 0.188 70.08deg);
|
||||
--chart-4: oklch(62.7% 0.265 303.9deg);
|
||||
--chart-5: oklch(64.5% 0.246 16.439deg);
|
||||
--sidebar: oklch(21% 0.006 285.885deg);
|
||||
--sidebar-foreground: oklch(98.5% 0 0deg);
|
||||
--sidebar-primary: oklch(48.8% 0.243 264.376deg);
|
||||
--sidebar-primary-foreground: oklch(98.5% 0 0deg);
|
||||
--sidebar-accent: oklch(27.4% 0.006 286.033deg);
|
||||
--sidebar-accent-foreground: oklch(98.5% 0 0deg);
|
||||
--sidebar-border: oklch(100% 0 0deg / 10%);
|
||||
--sidebar-ring: oklch(55.2% 0.016 285.938deg);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply tw:border-border;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply tw:bg-background tw:text-foreground;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/* src/app/styles/tailwind.css */
|
||||
@layer theme, base, components, utilities;
|
||||
|
||||
@import 'tailwindcss' prefix(tw);
|
||||
@import 'tw-animate-css';
|
||||
|
||||
@import './tailwind/base.css';
|
||||
@import './tailwind/utilities.css';
|
||||
@import './tailwind/theme.css';
|
||||
@import './tailwind/shadcn.css';
|
||||
|
||||
@custom-variant dark (&:is(.dark, .dark *, [data-theme='dark'], [data-theme='dark'] *));
|
||||
|
||||
@theme inline {
|
||||
--font-heading: var(--font-sans);
|
||||
--font-sans: var(--font-sans);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-ring: var(--ring);
|
||||
--color-input: var(--input);
|
||||
--color-border: var(--border);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-card: var(--card);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-background: var(--background);
|
||||
--radius-sm: calc(var(--radius) * 0.6);
|
||||
--radius-md: calc(var(--radius) * 0.8);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) * 1.4);
|
||||
--radius-2xl: calc(var(--radius) * 1.8);
|
||||
--radius-3xl: calc(var(--radius) * 2.2);
|
||||
--radius-4xl: calc(var(--radius) * 2.6);
|
||||
}
|
||||
|
||||
:root {
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.87 0 0);
|
||||
--chart-2: oklch(0.556 0 0);
|
||||
--chart-3: oklch(0.439 0 0);
|
||||
--chart-4: oklch(0.371 0 0);
|
||||
--chart-5: oklch(0.269 0 0);
|
||||
--radius: 0.625rem;
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--chart-1: oklch(0.87 0 0);
|
||||
--chart-2: oklch(0.556 0 0);
|
||||
--chart-3: oklch(0.439 0 0);
|
||||
--chart-4: oklch(0.371 0 0);
|
||||
--chart-5: oklch(0.269 0 0);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply tw:border-border tw:outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply tw:bg-background tw:text-foreground;
|
||||
}
|
||||
html {
|
||||
@apply tw:font-sans;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/********************************************************* 自定义tailwind基本样式 *********************************************************/
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
/* 以下为自定义样式 */
|
||||
html,
|
||||
body {
|
||||
@apply tw:font-base tw:h-[100vh] tw:w-full tw:p-0 tw:m-0;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply tw:text-sm;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply tw:text-3xl;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@apply tw:text-2xl;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@apply tw:text-xl;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@apply tw:text-lg;
|
||||
}
|
||||
|
||||
h5 {
|
||||
@apply tw:text-sm;
|
||||
}
|
||||
|
||||
h6 {
|
||||
@apply tw:text-xs;
|
||||
}
|
||||
|
||||
button,
|
||||
[role='button'] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-ring: var(--ring);
|
||||
--color-input: var(--input);
|
||||
--color-border: var(--border);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-card: var(--card);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(100% 0 0deg);
|
||||
--foreground: oklch(14.1% 0.005 285.823deg);
|
||||
--card: oklch(100% 0 0deg);
|
||||
--card-foreground: oklch(14.1% 0.005 285.823deg);
|
||||
--popover: oklch(100% 0 0deg);
|
||||
--popover-foreground: oklch(14.1% 0.005 285.823deg);
|
||||
--primary: oklch(21% 0.006 285.885deg);
|
||||
--primary-foreground: oklch(98.5% 0 0deg);
|
||||
--secondary: oklch(96.7% 0.001 286.375deg);
|
||||
--secondary-foreground: oklch(21% 0.006 285.885deg);
|
||||
--muted: oklch(96.7% 0.001 286.375deg);
|
||||
--muted-foreground: oklch(55.2% 0.016 285.938deg);
|
||||
--accent: oklch(96.7% 0.001 286.375deg);
|
||||
--accent-foreground: oklch(21% 0.006 285.885deg);
|
||||
--destructive: oklch(57.7% 0.245 27.325deg);
|
||||
--border: oklch(92% 0.004 286.32deg);
|
||||
--input: oklch(92% 0.004 286.32deg);
|
||||
--ring: oklch(70.5% 0.015 286.067deg);
|
||||
--chart-1: oklch(64.6% 0.222 41.116deg);
|
||||
--chart-2: oklch(60% 0.118 184.704deg);
|
||||
--chart-3: oklch(39.8% 0.07 227.392deg);
|
||||
--chart-4: oklch(82.8% 0.189 84.429deg);
|
||||
--chart-5: oklch(76.9% 0.188 70.08deg);
|
||||
--sidebar: oklch(98.5% 0 0deg);
|
||||
--sidebar-foreground: oklch(14.1% 0.005 285.823deg);
|
||||
--sidebar-primary: oklch(21% 0.006 285.885deg);
|
||||
--sidebar-primary-foreground: oklch(98.5% 0 0deg);
|
||||
--sidebar-accent: oklch(96.7% 0.001 286.375deg);
|
||||
--sidebar-accent-foreground: oklch(21% 0.006 285.885deg);
|
||||
--sidebar-border: oklch(92% 0.004 286.32deg);
|
||||
--sidebar-ring: oklch(70.5% 0.015 286.067deg);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(14.1% 0.005 285.823deg);
|
||||
--foreground: oklch(98.5% 0 0deg);
|
||||
--card: oklch(21% 0.006 285.885deg);
|
||||
--card-foreground: oklch(98.5% 0 0deg);
|
||||
--popover: oklch(21% 0.006 285.885deg);
|
||||
--popover-foreground: oklch(98.5% 0 0deg);
|
||||
--primary: oklch(92% 0.004 286.32deg);
|
||||
--primary-foreground: oklch(21% 0.006 285.885deg);
|
||||
--secondary: oklch(27.4% 0.006 286.033deg);
|
||||
--secondary-foreground: oklch(98.5% 0 0deg);
|
||||
--muted: oklch(27.4% 0.006 286.033deg);
|
||||
--muted-foreground: oklch(70.5% 0.015 286.067deg);
|
||||
--accent: oklch(27.4% 0.006 286.033deg);
|
||||
--accent-foreground: oklch(98.5% 0 0deg);
|
||||
--destructive: oklch(70.4% 0.191 22.216deg);
|
||||
--border: oklch(100% 0 0deg / 10%);
|
||||
--input: oklch(100% 0 0deg / 15%);
|
||||
--ring: oklch(55.2% 0.016 285.938deg);
|
||||
--chart-1: oklch(48.8% 0.243 264.376deg);
|
||||
--chart-2: oklch(69.6% 0.17 162.48deg);
|
||||
--chart-3: oklch(76.9% 0.188 70.08deg);
|
||||
--chart-4: oklch(62.7% 0.265 303.9deg);
|
||||
--chart-5: oklch(64.5% 0.246 16.439deg);
|
||||
--sidebar: oklch(21% 0.006 285.885deg);
|
||||
--sidebar-foreground: oklch(98.5% 0 0deg);
|
||||
--sidebar-primary: oklch(48.8% 0.243 264.376deg);
|
||||
--sidebar-primary-foreground: oklch(98.5% 0 0deg);
|
||||
--sidebar-accent: oklch(27.4% 0.006 286.033deg);
|
||||
--sidebar-accent-foreground: oklch(98.5% 0 0deg);
|
||||
--sidebar-border: oklch(100% 0 0deg / 10%);
|
||||
--sidebar-ring: oklch(55.2% 0.016 285.938deg);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply tw:border-border;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply tw:bg-background tw:text-foreground;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/********************************************************* 自定义tailwind主题扩展 *********************************************************/
|
||||
|
||||
@theme {
|
||||
--breakpoint-xs: 30rem;
|
||||
--breakpoint-sm: 36rem;
|
||||
--breakpoint-md: 48rem;
|
||||
--breakpoint-lg: 62rem;
|
||||
--breakpoint-xl: 75rem;
|
||||
--breakpoint-2xl: 87.5rem;
|
||||
--shadow-nysm: 0 0 2px 0 rgb(0 0 0 / 5%);
|
||||
--shadow-ny: 0 0 3px 0 rgb(0 0 0 / 10%), 0 0 2px - 1px rgb(0 0 0 / 10%);
|
||||
--shadow-nymd: 0 0 6px -1px rgb(0 0 0 / 10%), 0 0 4px -2px rgb(0 0 0 / 10%);
|
||||
--shadow-nylg: 0 0 15px -3px rgb(0 0 0 / 10%), 0 0 6px -4px rgb(0 0 0 / 10%);
|
||||
--shadow-spread: 0 5px 40px rgb(0 0 0 / 10%);
|
||||
|
||||
/* 默认字体 */
|
||||
--font-base:
|
||||
-apple-system, blinkmacsystemfont, tahoma, arial, 'Hiragino Sans GB', 'Microsoft YaHei',
|
||||
'WenQuanYi Micro Hei', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
||||
'Noto Color Emoji';
|
||||
|
||||
/* 霞鹜文楷字体 */
|
||||
--font-lxgw:
|
||||
'LXGW WenKai', '楷体', 'STKaiti', -apple-system, blinkmacsystemfont, tahoma, arial,
|
||||
'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
|
||||
/* 默认代码字体 */
|
||||
--font-code:
|
||||
'Fira Code', -apple-system, blinkmacsystemfont, tahoma, arial, 'Hiragino Sans GB',
|
||||
'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/********************************************************* 自定义tailwind工具类 *********************************************************/
|
||||
@utility page-item {
|
||||
@apply tw:flex tw:flex-auto tw:flex-col tw:mt-20 tw:items-center;
|
||||
}
|
||||
|
||||
/* 页面包装容器 */
|
||||
@utility page-container {
|
||||
@apply tw:max-w-[90%] tw:md:max-w-[80%] tw:lg:max-w-[70%] tw:xl:max-w-[60%] tw:flex-auto tw:mb-5;
|
||||
}
|
||||
|
||||
/* 页面包装容器 */
|
||||
|
||||
/* 空白页样式,一般用于404和error页面 */
|
||||
@utility page-blank {
|
||||
@apply tw:bg-white/80 tw:backdrop-blur-sm tw:h-full tw:w-full tw:drop-shadow-lg tw:rounded-md tw:flex tw:justify-center tw:items-center;
|
||||
|
||||
html.dark & {
|
||||
@apply tw:bg-black/50;
|
||||
}
|
||||
}
|
||||
|
||||
/* 全透明图标按钮 */
|
||||
@utility btn-icon-transparent {
|
||||
@apply tw:block tw:w-auto! tw:border-none! tw:bg-transparent! tw:shadow-none! tw:ring-0! tw:hover:bg-transparent! tw:focus-visible:ring-0!;
|
||||
}
|
||||
|
||||
@utility page-block {
|
||||
@apply tw:bg-zinc-100/80;
|
||||
|
||||
html.dark & {
|
||||
@apply tw:bg-zinc-800/50;
|
||||
}
|
||||
}
|
||||
|
||||
@utility page-block-hover {
|
||||
@apply tw:hover:bg-white/90;
|
||||
|
||||
html.dark & {
|
||||
@apply tw:hover:bg-black/80;
|
||||
}
|
||||
}
|
||||
|
||||
/* 只显示一行文字, 溢出部分以省略号代替 */
|
||||
@utility ellips {
|
||||
@apply tw:inline-block tw:overflow-hidden tw:max-w-full tw:whitespace-nowrap tw:text-ellipsis tw:break-all;
|
||||
}
|
||||
|
||||
/* 鼠标移动到文字或链接出现动画下划线 */
|
||||
@utility animate-decoration {
|
||||
padding-bottom: 2px;
|
||||
background: linear-gradient(hsl(var(--foreground)), hsl(var(--foreground))) 0% 100% / 0% 1px
|
||||
no-repeat;
|
||||
transition: background-size ease-out 200ms;
|
||||
|
||||
&:not(:focus):hover {
|
||||
background-size: 100% 1px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 粗下划线 */
|
||||
@utility animate-decoration-lg {
|
||||
&:not(:focus):hover {
|
||||
background-size: 100% 2px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 取消下划线 */
|
||||
@utility none-animate-decoration {
|
||||
background-size: 0 !important;
|
||||
transition: none !important;
|
||||
|
||||
&:hover,
|
||||
&:not(:focus):hover {
|
||||
background-size: 100% 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 透明滚动条 */
|
||||
@utility transparent-scrollbar {
|
||||
&::-webkit-scrollbar {
|
||||
@apply tw:w-1 tw:h-1;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
@apply tw:bg-gray-100;
|
||||
}
|
||||
|
||||
html.dark &::-webkit-scrollbar-track {
|
||||
@apply tw:bg-zinc-800;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
@apply tw:bg-gray-300 tw:rounded;
|
||||
}
|
||||
|
||||
html.dark &::-webkit-scrollbar-thumb {
|
||||
@apply tw:bg-zinc-600;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-corner {
|
||||
@apply tw:bg-gray-100;
|
||||
}
|
||||
|
||||
html.dark &::-webkit-scrollbar-corner {
|
||||
@apply tw:bg-zinc-800;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user