mirror of
https://github.com/JOYCEQL/magic-resume.git
synced 2026-07-03 14:07:11 +02:00
style: global theme update
This commit is contained in:
@@ -309,7 +309,7 @@ export default function LandingPage() {
|
||||
<Moon className="h-5 w-5" />
|
||||
)}
|
||||
</Button>
|
||||
<EditButton className="bg-indigo-600 text-white px-6 py-2 rounded-full hover:bg-indigo-700 transition-colors flex items-center space-x-1">
|
||||
<EditButton className="bg-primary text-white px-6 py-2 rounded-full hover:bg-indigo-700 transition-colors flex items-center space-x-1">
|
||||
<span>开始制作</span>
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</EditButton>
|
||||
@@ -331,7 +331,7 @@ export default function LandingPage() {
|
||||
<TypewriterText text="每一处细节,都由你掌控。打造真正与众不同的个人简历。" />
|
||||
</p>
|
||||
|
||||
<EditButton className="mt-8 bg-indigo-600 text-white px-6 py-2 rounded-full hover:bg-indigo-700 transition-colors">
|
||||
<EditButton className="mt-8 bg-primary text-white px-6 py-2 rounded-full hover:bg-indigo-700 transition-colors">
|
||||
<span>开始定制</span>
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</EditButton>
|
||||
|
||||
@@ -78,8 +78,20 @@ export default function Home() {
|
||||
setPanelSizes(newSizes);
|
||||
setLayoutKey((prev) => prev + 1);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.documentElement.classList.remove("dark");
|
||||
const savedTheme = window?.localStorage?.getItem("theme");
|
||||
const prefersDark = window?.matchMedia?.(
|
||||
"(prefers-color-scheme: dark)"
|
||||
).matches;
|
||||
|
||||
const theme = savedTheme ? savedTheme === "dark" : prefersDark;
|
||||
|
||||
if (theme) {
|
||||
document.documentElement.classList.add("dark");
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -276,7 +288,7 @@ export default function Home() {
|
||||
className={cn(
|
||||
"w-full h-screen overflow-hidden",
|
||||
theme === "dark"
|
||||
? "dark bg-neutral-900 text-neutral-200"
|
||||
? "bg-neutral-900 text-neutral-200"
|
||||
: "bg-white text-gray-900"
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -61,8 +61,8 @@ export function EditPanel() {
|
||||
</span>
|
||||
<input
|
||||
className={cn(
|
||||
"flex-1 text-base font-medium hover:border-indigo-600 hover:text-indigo-600 border-black bg-transparent outline-none border-b pb-1 text-gray-700",
|
||||
"dark:text-neutral-200 dark:border-white dark:hover:border-indigo-600 dark:hover:text-indigo-600"
|
||||
"flex-1 text-base font-medium hover:border-primary hover:text-primary border-black bg-transparent outline-none border-b pb-1 text-gray-700",
|
||||
"dark:text-neutral-200 dark:border-white dark:hover:border-primary dark:hover:text-primary"
|
||||
)}
|
||||
type="text"
|
||||
value={menuSections?.find((s) => s.id === activeSection)?.title}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
"use client";
|
||||
import { CalendarIcon } from "lucide-react";
|
||||
import { format } from "date-fns";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { motion } from "framer-motion";
|
||||
import { format } from "date-fns";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
|
||||
import { Calendar } from "../ui/calendar";
|
||||
import { CalendarIcon } from "lucide-react";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger
|
||||
} from "@/components/ui/popover";
|
||||
import { Calendar } from "@/components/ui/calendar";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { useResumeStore } from "@/store/useResumeStore";
|
||||
import RichTextEditor from "@/components/shared/rich-editor/RichEditor";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
type FieldProps = {
|
||||
label?: string;
|
||||
@@ -44,25 +50,7 @@ const Field: React.FC<FieldProps> = ({
|
||||
const inputStyles = cn(
|
||||
"mt-1.5 block w-full transition-all duration-200",
|
||||
"rounded-lg px-4 py-2.5",
|
||||
"border",
|
||||
theme === "dark"
|
||||
? [
|
||||
"bg-neutral-900/30 border-neutral-800",
|
||||
"text-neutral-100",
|
||||
"focus:bg-neutral-900/50",
|
||||
"placeholder:text-neutral-500"
|
||||
]
|
||||
: [
|
||||
"bg-white border-gray-100",
|
||||
"text-gray-900",
|
||||
"hover:border-gray-200",
|
||||
"placeholder:text-gray-400"
|
||||
],
|
||||
"focus:ring-1 focus:ring-offset-1",
|
||||
theme === "dark"
|
||||
? "focus:ring-indigo-500/20 focus:ring-offset-neutral-900"
|
||||
: "focus:ring-indigo-500/20 focus:ring-offset-white",
|
||||
"focus:border-indigo-500"
|
||||
"border"
|
||||
);
|
||||
|
||||
if (type === "date") {
|
||||
@@ -70,62 +58,27 @@ const Field: React.FC<FieldProps> = ({
|
||||
|
||||
return (
|
||||
<label className="block">
|
||||
<span
|
||||
className={cn(
|
||||
"text-sm font-medium flex gap-1 items-center",
|
||||
theme === "dark" ? "text-neutral-300" : "text-gray-600"
|
||||
)}
|
||||
>
|
||||
<span className={cn("text-sm font-medium flex gap-1 items-center")}>
|
||||
{label}
|
||||
{required && <span className="text-red-500">*</span>}
|
||||
</span>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<motion.button
|
||||
type="button"
|
||||
className={cn(
|
||||
inputStyles,
|
||||
"flex items-center justify-between",
|
||||
!date && theme === "dark" ? "text-neutral-500" : "text-gray-400"
|
||||
)}
|
||||
whileHover={{ scale: 1.01 }}
|
||||
whileTap={{ scale: 0.99 }}
|
||||
<Button
|
||||
variant="outline"
|
||||
className={cn("w-full flex items-center justify-between")}
|
||||
>
|
||||
<span>{date ? format(date, "yyyy-MM-dd") : "选择日期"}</span>
|
||||
<CalendarIcon className="w-4 h-4 opacity-50" />
|
||||
</motion.button>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
className={cn(
|
||||
"w-auto p-0",
|
||||
theme === "dark"
|
||||
? "bg-neutral-900 border-neutral-800"
|
||||
: "bg-white border-gray-100",
|
||||
"shadow-lg rounded-lg"
|
||||
)}
|
||||
align="start"
|
||||
>
|
||||
<PopoverContent className="w-auto p-0" align="start">
|
||||
<Calendar
|
||||
mode="single"
|
||||
selected={date}
|
||||
onSelect={(date) => onChange(date ? date.toISOString() : "")}
|
||||
initialFocus
|
||||
className={cn(
|
||||
"rounded-lg p-3",
|
||||
theme === "dark"
|
||||
? [
|
||||
"bg-neutral-900",
|
||||
"[&_.rdp-day_button:hover]:bg-neutral-800",
|
||||
"[&_.rdp-day_button.rdp-day_selected]:bg-indigo-600",
|
||||
"text-neutral-200"
|
||||
]
|
||||
: [
|
||||
"bg-white",
|
||||
"[&_.rdp-day_button:hover]:bg-gray-50",
|
||||
"[&_.rdp-day_button.rdp-day_selected]:bg-indigo-600",
|
||||
"text-gray-900"
|
||||
]
|
||||
)}
|
||||
className={cn("rounded-lg p-3")}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
@@ -184,15 +137,13 @@ const Field: React.FC<FieldProps> = ({
|
||||
{label}
|
||||
{required && <span className="text-red-500">*</span>}
|
||||
</span>
|
||||
<motion.input
|
||||
<Input
|
||||
type="text"
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
className={inputStyles}
|
||||
required={required}
|
||||
whileHover={{ scale: 1.005 }}
|
||||
whileTap={{ scale: 0.995 }}
|
||||
/>
|
||||
</label>
|
||||
);
|
||||
|
||||
@@ -147,7 +147,7 @@ export function SidePanel() {
|
||||
<div
|
||||
key={item.id}
|
||||
className={cn(
|
||||
"rounded-lg group border mb-2 hover:border-indigo-600",
|
||||
"rounded-lg group border mb-2 hover:border-primary",
|
||||
theme === "dark"
|
||||
? "hover:bg-neutral-800 bg-neutral-900/50 border-neutral-800"
|
||||
: "hover:bg-gray-50 bg-white border-gray-100"
|
||||
@@ -194,7 +194,7 @@ export function SidePanel() {
|
||||
key={item.id}
|
||||
value={item}
|
||||
className={cn(
|
||||
"rounded-lg cursor-move group border hover:border-indigo-600",
|
||||
"rounded-lg cursor-move group border hover:border-primary",
|
||||
theme === "dark"
|
||||
? "hover:bg-neutral-800 bg-neutral-900/50 border-neutral-800"
|
||||
: "hover:bg-gray-50 bg-white border-gray-100"
|
||||
@@ -244,7 +244,7 @@ export function SidePanel() {
|
||||
)}
|
||||
>
|
||||
{item.enabled ? (
|
||||
<Eye className="w-4 h-4 text-indigo-600" />
|
||||
<Eye className="w-4 h-4 text-primary" />
|
||||
) : (
|
||||
<EyeOff className="w-4 h-4" />
|
||||
)}
|
||||
@@ -284,7 +284,7 @@ export function SidePanel() {
|
||||
whileHover={{ scale: 1.01 }}
|
||||
whileTap={{ scale: 0.9 }}
|
||||
onClick={handleCreateSection}
|
||||
className="flex justify-center w-full rounded-lg items-center gap-2 py-2 px-3 text-sm font-medium text-indigo-600 bg-indigo-50"
|
||||
className="flex justify-center w-full rounded-lg items-center gap-2 py-2 px-3 text-sm font-medium text-primary bg-indigo-50"
|
||||
>
|
||||
添加自定义模块
|
||||
</motion.button>
|
||||
|
||||
@@ -108,7 +108,7 @@ const CustomField: React.FC<CustomFieldProps> = ({
|
||||
|
||||
{field.visible ? (
|
||||
<Eye
|
||||
className="w-4 h-4 cursor-pointer text-indigo-600"
|
||||
className="w-4 h-4 cursor-pointer text-primary"
|
||||
onClick={() => onUpdate({ ...field, visible: !field.visible })}
|
||||
/>
|
||||
) : (
|
||||
@@ -297,7 +297,7 @@ const BasicPanel: React.FC = () => {
|
||||
onClick={() => toggleFieldVisibility(field.id, !field.visible)}
|
||||
>
|
||||
{field.visible ? (
|
||||
<Eye className="w-4 h-4 text-indigo-600" />
|
||||
<Eye className="w-4 h-4 text-primary" />
|
||||
) : (
|
||||
<EyeOff className="w-4 h-4" />
|
||||
)}
|
||||
|
||||
@@ -162,10 +162,10 @@ const CustomItem = ({
|
||||
dragControls={dragControls}
|
||||
className={cn(
|
||||
"rounded-lg border overflow-hidden flex group",
|
||||
"bg-white hover:border-indigo-600",
|
||||
"bg-white hover:border-primary",
|
||||
"dark:bg-neutral-900/30",
|
||||
"border-gray-100 dark:border-neutral-800",
|
||||
"dark:hover:border-indigo-600"
|
||||
"dark:hover:border-primary"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
@@ -228,7 +228,7 @@ const CustomItem = ({
|
||||
onClick={handleVisibilityToggle}
|
||||
>
|
||||
{item.visible ? (
|
||||
<Eye className="w-4 h-4 text-indigo-600" />
|
||||
<Eye className="w-4 h-4 text-primary" />
|
||||
) : (
|
||||
<EyeOff className="w-4 h-4" />
|
||||
)}
|
||||
|
||||
@@ -228,10 +228,10 @@ const EducationItem = ({ education }: { education: Education }) => {
|
||||
dragControls={dragControls}
|
||||
className={cn(
|
||||
"rounded-lg border overflow-hidden flex group",
|
||||
"bg-white hover:border-indigo-600",
|
||||
"bg-white hover:border-primary",
|
||||
"dark:bg-neutral-900/30",
|
||||
"border-gray-100 dark:border-neutral-800",
|
||||
"dark:hover:border-indigo-600"
|
||||
"dark:hover:border-primary"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
@@ -317,7 +317,7 @@ const EducationItem = ({ education }: { education: Education }) => {
|
||||
onClick={handleVisibilityToggle}
|
||||
>
|
||||
{education.visible ? (
|
||||
<Eye className="w-4 h-4 text-indigo-600" />
|
||||
<Eye className="w-4 h-4 text-primary" />
|
||||
) : (
|
||||
<EyeOff className="w-4 h-4" />
|
||||
)}
|
||||
|
||||
@@ -194,10 +194,10 @@ const ExperienceItem = ({ experience }: { experience: Experience }) => {
|
||||
}}
|
||||
className={cn(
|
||||
"rounded-lg border overflow-hidden flex group",
|
||||
"bg-white hover:border-indigo-600",
|
||||
"bg-white hover:border-primary",
|
||||
"dark:bg-neutral-900/30",
|
||||
"border-gray-100 dark:border-neutral-800",
|
||||
"dark:hover:border-indigo-600"
|
||||
"dark:hover:border-primary"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
@@ -274,7 +274,7 @@ const ExperienceItem = ({ experience }: { experience: Experience }) => {
|
||||
onClick={handleVisibilityToggle}
|
||||
>
|
||||
{experience.visible ? (
|
||||
<Eye className="w-4 h-4 text-indigo-600" />
|
||||
<Eye className="w-4 h-4 text-primary" />
|
||||
) : (
|
||||
<EyeOff className="w-4 h-4" />
|
||||
)}
|
||||
|
||||
@@ -200,10 +200,10 @@ const ProjectItem = ({ project }: { project: Project }) => {
|
||||
}}
|
||||
className={cn(
|
||||
"rounded-lg border overflow-hidden flex group",
|
||||
"bg-white hover:border-indigo-600",
|
||||
"bg-white hover:border-primary",
|
||||
"dark:bg-neutral-900/30",
|
||||
"border-gray-100 dark:border-neutral-800",
|
||||
"dark:hover:border-indigo-600"
|
||||
"dark:hover:border-primary"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
@@ -280,7 +280,7 @@ const ProjectItem = ({ project }: { project: Project }) => {
|
||||
onClick={handleVisibilityToggle}
|
||||
>
|
||||
{project.visible ? (
|
||||
<Eye className="w-4 h-4 text-indigo-600" />
|
||||
<Eye className="w-4 h-4 text-primary" />
|
||||
) : (
|
||||
<EyeOff className="w-4 h-4" />
|
||||
)}
|
||||
|
||||
@@ -372,7 +372,7 @@ const PhotoConfigDrawer: React.FC<Props> = ({
|
||||
"h-9",
|
||||
config.aspectRatio === ratio
|
||||
? theme === "dark"
|
||||
? "bg-indigo-600 text-white"
|
||||
? "bg-primary text-white"
|
||||
: "bg-neutral-900 text-white"
|
||||
: theme === "dark"
|
||||
? "bg-[#262626] text-white border-none"
|
||||
@@ -409,7 +409,7 @@ const PhotoConfigDrawer: React.FC<Props> = ({
|
||||
"h-9",
|
||||
config.borderRadius === radius
|
||||
? theme === "dark"
|
||||
? "bg-indigo-600 text-white"
|
||||
? "bg-primary text-white"
|
||||
: "bg-neutral-900 text-white"
|
||||
: theme === "dark"
|
||||
? "bg-[#262626] text-white"
|
||||
|
||||
@@ -318,10 +318,19 @@ export const useResumeStore = create<ResumeStore>()(
|
||||
experience: state.experience.filter((p) => p.id !== id)
|
||||
})),
|
||||
|
||||
toggleTheme: () =>
|
||||
set((state) => ({
|
||||
theme: state.theme === "light" ? "dark" : "light"
|
||||
})),
|
||||
toggleTheme: () => {
|
||||
set((state) => {
|
||||
const newTheme = state.theme === "light" ? "dark" : "light";
|
||||
document.documentElement.classList.toggle(
|
||||
"dark",
|
||||
newTheme === "dark"
|
||||
);
|
||||
// 本地存储也调整
|
||||
window?.localStorage?.setItem("theme", newTheme);
|
||||
|
||||
return { theme: newTheme };
|
||||
});
|
||||
},
|
||||
updateGlobalSettings: (settings) =>
|
||||
set((state) => {
|
||||
const newSettings = {
|
||||
|
||||
@@ -8,7 +8,7 @@ export const getThemeConfig = (isDark: boolean) => ({
|
||||
hover: isDark ? "hover:bg-zinc-800" : "hover:bg-gray-100",
|
||||
input: isDark ? "bg-zinc-800/50 border-zinc-700" : "bg-white border-gray-200",
|
||||
button: isDark ? "bg-zinc-800" : "bg-white",
|
||||
buttonPrimary: isDark ? "bg-indigo-500" : "bg-indigo-600",
|
||||
buttonPrimary: isDark ? "bg-indigo-500" : "bg-primary",
|
||||
preview: isDark ? "bg-zinc-900" : "bg-white"
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Config } from "tailwindcss";
|
||||
|
||||
const config = {
|
||||
important: true,
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./pages/**/*.{ts,tsx}",
|
||||
@@ -101,6 +100,9 @@ const config = {
|
||||
}
|
||||
}
|
||||
},
|
||||
colors: {
|
||||
primary: "262.1 83.3% 57.8%"
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")]
|
||||
} satisfies Config;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user