diff --git a/src/app/auth/auth-v4/emailEntry.tsx b/src/app/auth/auth-v4/emailEntry.tsx index 94e46bb7..a6594fc5 100644 --- a/src/app/auth/auth-v4/emailEntry.tsx +++ b/src/app/auth/auth-v4/emailEntry.tsx @@ -1,9 +1,9 @@ 'use client' import InputField from '@annatarhe/lake-ui/form-input-field' import { useAutoAnimate } from '@formkit/auto-animate/react' -import { ChevronRight } from 'lucide-react' import { zodResolver } from '@hookform/resolvers/zod' import { Turnstile } from '@marsidev/react-turnstile' +import { ChevronRight } from 'lucide-react' import { useEffect } from 'react' import OTPInput from 'react-auth-code-input' import { Controller, useForm } from 'react-hook-form' diff --git a/src/app/auth/phone/layout.tsx b/src/app/auth/phone/layout.tsx index cf997d21..13b2a465 100644 --- a/src/app/auth/phone/layout.tsx +++ b/src/app/auth/phone/layout.tsx @@ -7,8 +7,9 @@ import { useEffect } from 'react' import logoDark from '@/assets/logo-dark.svg' import logoLight from '@/assets/logo-light.svg' -import Card from '@/components/card/card' import GithubLogo from '@/components/icons/github.logo.svg' +import DecorBlobs from '@/components/ui/decor-blobs/decor-blobs' +import Surface from '@/components/ui/surface/surface' import { GithubClientID } from '@/constants/config' import { useActionTrack, usePageTrack } from '@/hooks/tracke' import { useTranslation } from '@/i18n/client' @@ -34,58 +35,75 @@ function AuthPage(props: AuthPageProps) { const onGithubClick = useActionTrack('login:github') return ( -
- - <> -
- clippingkk logo - clippingkk logo -
-
- - {t('app.auth.phone')} - +
+ + +
+ clippingkk logo + clippingkk logo +

+ ClippingKK +

+
+ + - - {t('app.auth.signin')} - +
{children}
+ +
+
+
-
- {children} -
-
- - - +
+ + {t('app.auth.or') || 'or'} +
- - +
+ +
+ + + +
+
) } diff --git a/src/app/auth/signin/layout.tsx b/src/app/auth/signin/layout.tsx index b5f7672e..d2d70b6c 100644 --- a/src/app/auth/signin/layout.tsx +++ b/src/app/auth/signin/layout.tsx @@ -4,8 +4,9 @@ import type React from 'react' import logoDark from '@/assets/logo-dark.svg' import logoLight from '@/assets/logo-light.svg' -import Card from '@/components/card/card' import PageTrack from '@/components/track/page-track' +import DecorBlobs from '@/components/ui/decor-blobs/decor-blobs' +import Surface from '@/components/ui/surface/surface' import { getTranslation } from '@/i18n' import TrackedGithubLink from './tracked-github-link' @@ -19,53 +20,69 @@ async function AuthPage(props: AuthPageProps) { const { t } = await getTranslation() return ( -
+
+ - - <> -
- clippingkk logo - clippingkk logo -
-
- - {t('app.auth.phone')} - + +
+ clippingkk logo + clippingkk logo +

+ ClippingKK +

+
+ + - - {t('app.auth.signin')} - +
{children}
+ +
+
+
-
- {children} -
-
- +
+ + {t('app.auth.or') || 'or'} +
- - +
+ +
+ +
+
) } diff --git a/src/app/dash/[userid]/admin/page.tsx b/src/app/dash/[userid]/admin/page.tsx index 8f799ccb..49cad789 100644 --- a/src/app/dash/[userid]/admin/page.tsx +++ b/src/app/dash/[userid]/admin/page.tsx @@ -52,27 +52,29 @@ async function AdminPanel(props: PageProps) { }) return ( -
-
-
+
+
+
-
- +
+
-

{t('Homeless Books')}

-

+

+ {t('Homeless Books')} +

+

{t('Manage and sync unprocessed book entries')}

-
-
+
+
-
- +
+ {t('Showing books')} {offset + 1} -{' '} {offset + (data!.adminDashboard.uncheckedBooks?.length || 0)} @@ -80,10 +82,10 @@ async function AdminPanel(props: PageProps) {
@@ -92,7 +94,7 @@ async function AdminPanel(props: PageProps) { {t('Next')} @@ -107,7 +109,7 @@ async function AdminPanel(props: PageProps) {
{t('Load More Books')} @@ -115,7 +117,7 @@ async function AdminPanel(props: PageProps) {
-
+
) } diff --git a/src/app/dash/[userid]/clippings/[clippingid]/@content/page.tsx b/src/app/dash/[userid]/clippings/[clippingid]/@content/page.tsx index 32d7c926..86071863 100644 --- a/src/app/dash/[userid]/clippings/[clippingid]/@content/page.tsx +++ b/src/app/dash/[userid]/clippings/[clippingid]/@content/page.tsx @@ -1,9 +1,9 @@ import Image from 'next/image' import Link from 'next/link' -import { checkIsPremium } from '@/compute/user' import ElegantDivider from '@/components/divider/elegant-divider' import ClippingRichContent from '@/components/text-content/clipping-rich-content' +import { checkIsPremium } from '@/compute/user' import { getTranslation } from '@/i18n' import { isGrandAdmin } from '@/services/admin' import { resolveMediaUrl } from '@/utils/image' diff --git a/src/app/dash/[userid]/clippings/[clippingid]/layout.tsx b/src/app/dash/[userid]/clippings/[clippingid]/layout.tsx index 8045ddaa..6f7afbc7 100644 --- a/src/app/dash/[userid]/clippings/[clippingid]/layout.tsx +++ b/src/app/dash/[userid]/clippings/[clippingid]/layout.tsx @@ -47,18 +47,18 @@ function Layout(props: Props) {
- {/* Main card with gradient background */} -
- {/* Additional gradient overlay for depth */} -
+ {/* Main card with unified glass background */} +
+ {/* Subtle blue depth overlay */} +
{/* Content wrapper with responsive grid */} -
+
{/* Main content area */}
{content}
{/* Sidebar area */} -
+
{sidebar}
diff --git a/src/app/dash/[userid]/comments/loading.tsx b/src/app/dash/[userid]/comments/loading.tsx index 777c6536..248e92ba 100644 --- a/src/app/dash/[userid]/comments/loading.tsx +++ b/src/app/dash/[userid]/comments/loading.tsx @@ -1,6 +1,5 @@ -import { cn } from '@/lib/utils' - import { glassCardClass } from '@/components/card/glass-card' +import { cn } from '@/lib/utils' export default function CommentsLoading() { return ( diff --git a/src/app/dash/[userid]/comments/page.tsx b/src/app/dash/[userid]/comments/page.tsx index c2187fa2..950e3a03 100644 --- a/src/app/dash/[userid]/comments/page.tsx +++ b/src/app/dash/[userid]/comments/page.tsx @@ -1,7 +1,9 @@ +import { MessageSquare } from 'lucide-react' import type { Metadata } from 'next' import { cookies } from 'next/headers' import { notFound } from 'next/navigation' +import PageHeader from '@/components/ui/page-header/page-header' import { COOKIE_TOKEN_KEY } from '@/constants/storage' import { GetCommentListDocument, @@ -61,21 +63,13 @@ export default async function CommentsPage({ params }: Props) { } return ( -
-
- {/* Header */} -
-

- My Comments -

-

- View and manage all your comments and discussions -

-
- - {/* Comments List */} - -
-
+
+ } + title="My Comments" + description="View and manage all your comments and discussions" + /> + +
) } diff --git a/src/app/dash/[userid]/home/page.tsx b/src/app/dash/[userid]/home/page.tsx index 93fef1f5..484fc8e4 100644 --- a/src/app/dash/[userid]/home/page.tsx +++ b/src/app/dash/[userid]/home/page.tsx @@ -168,8 +168,8 @@ async function Page(props: PageProps) { return (
{firstBook && ( -
-

+
+

{t('app.home.reading')}

)}
-

+

{t('app.home.title')}

-
+
- {t('app.home.unchecked')} -
+ {t('app.home.unchecked')} +
{new Array(6).fill(1).map((_, i) => (
))}
@@ -14,8 +14,8 @@ export function BooksSkeleton() { function HomePageSkeleton() { return (
-
-
+
+
) diff --git a/src/app/dash/[userid]/loading.tsx b/src/app/dash/[userid]/loading.tsx index e8f3214e..9cc7acf7 100644 --- a/src/app/dash/[userid]/loading.tsx +++ b/src/app/dash/[userid]/loading.tsx @@ -1,10 +1,12 @@ -import Loading2Icon from '@/components/icons/loading2.svg' +import Spinner from '@/components/loading/spinner' function DashboardLoadingPage() { return ( -
- - Loading... +
+ + + Loading… +
) } diff --git a/src/app/dash/[userid]/not-found.tsx b/src/app/dash/[userid]/not-found.tsx index 0102102b..b26de10d 100644 --- a/src/app/dash/[userid]/not-found.tsx +++ b/src/app/dash/[userid]/not-found.tsx @@ -1,44 +1,50 @@ import { ArrowLeft, UserX } from 'lucide-react' import Link from 'next/link' +import DecorBlobs from '@/components/ui/decor-blobs/decor-blobs' +import Surface from '@/components/ui/surface/surface' import { getTranslation } from '@/i18n' async function UserNotFound() { const { t } = await getTranslation() return ( -
-
- {/* Decorative blur elements */} -
-
- -
-
- +
+ + +
+
+
-

+

404

-

+

{t('user_not_found')}

-

+

{t('user_not_found_message')}

- + {t('return_home')}
-
+
) } diff --git a/src/app/dash/[userid]/profile/page.tsx b/src/app/dash/[userid]/profile/page.tsx index 75e73eff..e6fac35e 100644 --- a/src/app/dash/[userid]/profile/page.tsx +++ b/src/app/dash/[userid]/profile/page.tsx @@ -80,44 +80,40 @@ async function Page(props: PageProps) {
- {/* Enhanced Activity chart section */} + {/* Activity chart section */}
- {/* Activity section glow */} -
+ {/* Subtle blue-toned glow behind the surface */} +
-
- {/* Subtle pattern overlay */} +
+ />
-
-
-
- - - -
-
-

+ + + + + +

{t('app.profile.activity')}

diff --git a/src/app/dash/[userid]/settings/exports/export-trigger-button.tsx b/src/app/dash/[userid]/settings/exports/export-trigger-button.tsx index aa4e7467..54fba1b0 100644 --- a/src/app/dash/[userid]/settings/exports/export-trigger-button.tsx +++ b/src/app/dash/[userid]/settings/exports/export-trigger-button.tsx @@ -7,7 +7,11 @@ type ExportTriggerButtonProps = { label: string } -function ExportTriggerButton({ onClick, icon, label }: ExportTriggerButtonProps) { +function ExportTriggerButton({ + onClick, + icon, + label, +}: ExportTriggerButtonProps) { return ( {t('error.goHome') || 'Return to home page'}
-
+
) diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index 68fd6afe..eff0774e 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -2,6 +2,8 @@ import { ArrowLeft, BookX } from 'lucide-react' import type { Metadata } from 'next' import Link from 'next/link' +import DecorBlobs from '@/components/ui/decor-blobs/decor-blobs' +import Surface from '@/components/ui/surface/surface' import { getTranslation } from '@/i18n' export const metadata: Metadata = { @@ -13,38 +15,42 @@ async function NotFound() { const { t } = await getTranslation() return ( -
-
- {/* Decorative blur elements */} -
-
- -
-
- +
+ + +
+
+
-

+

404

-

+

{t('page_not_found')}

-

+

{t('page_not_found_message')}

- + {t('return_home')}
-
+
) } diff --git a/src/app/page.tsx b/src/app/page.tsx index 7628941a..06a1407c 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,10 +4,7 @@ import { getBackgroundImageServer } from '../hooks/theme.server' import { PublicDataDocument, type PublicDataQuery } from '../schema/generated' import { getReactQueryClient } from '../services/ajax' import { doApolloServerQuery } from '../services/apollo.server' -import { - isValidDoubanId, - wenquBooksByIdsQueryOptions, -} from '../services/wenqu' +import { isValidDoubanId, wenquBooksByIdsQueryOptions } from '../services/wenqu' async function Page() { const data = await doApolloServerQuery({ diff --git a/src/app/payment/canceled/content.tsx b/src/app/payment/canceled/content.tsx index d8f04f1d..0bcc8cd6 100644 --- a/src/app/payment/canceled/content.tsx +++ b/src/app/payment/canceled/content.tsx @@ -1,13 +1,26 @@ +import { ArrowRight, XCircle } from 'lucide-react' import Link from 'next/link' function CanceledPageContent() { return ( - <> - Sorry we could not process your payment, please try again - - go to plans +
+ + + +

+ Payment canceled +

+

+ Sorry we could not process your payment. Please try again. +

+ + Go to plans + - +
) } diff --git a/src/app/payment/canceled/page.tsx b/src/app/payment/canceled/page.tsx index 9ff44f71..41144b70 100644 --- a/src/app/payment/canceled/page.tsx +++ b/src/app/payment/canceled/page.tsx @@ -1,15 +1,24 @@ import type { Metadata } from 'next' +import DecorBlobs from '@/components/ui/decor-blobs/decor-blobs' +import Surface from '@/components/ui/surface/surface' + import CanceledPageContent from './content' export const metadata: Metadata = { - title: 'Payemnt canceled', + title: 'Payment canceled', } function CanceledPage() { return ( -
- +
+ + + +
) } diff --git a/src/app/payment/success/content.tsx b/src/app/payment/success/content.tsx index 414eea35..c7f7a4b6 100644 --- a/src/app/payment/success/content.tsx +++ b/src/app/payment/success/content.tsx @@ -1,5 +1,6 @@ 'use client' import { useQuery } from '@tanstack/react-query' +import { ArrowRight, PartyPopper } from 'lucide-react' import Link from 'next/link' import party from 'party-js' import { useEffect } from 'react' @@ -39,11 +40,22 @@ function PaymentSuccessContent(props: PaymentSuccessContentProps) { }, [data]) return ( -
- Congratulation! - Welcome to join Premium - - go to my profile +
+ + + +

+ Congratulations! +

+

+ Welcome to ClippingKK Premium. +

+ + Go to my profile +
) diff --git a/src/app/payment/success/page.tsx b/src/app/payment/success/page.tsx index 5216c7cc..e57583c0 100644 --- a/src/app/payment/success/page.tsx +++ b/src/app/payment/success/page.tsx @@ -1,5 +1,7 @@ import { dehydrate, HydrationBoundary } from '@tanstack/react-query' +import DecorBlobs from '@/components/ui/decor-blobs/decor-blobs' +import Surface from '@/components/ui/surface/surface' import { getReactQueryClient } from '@/services/ajax' import { getPaymentOrderInfo } from '@/services/payment' @@ -21,13 +23,18 @@ async function PaymentSuccessPage(props: PaymentSuccessPageProps) { const d = dehydrate(rq) - // use server response const homeLink = `/dash/${uid}/home` return ( -
- +
+ + + +
) diff --git a/src/app/policy/support/page.tsx b/src/app/policy/support/page.tsx index bb0f23c0..0ef78ac4 100644 --- a/src/app/policy/support/page.tsx +++ b/src/app/policy/support/page.tsx @@ -1,6 +1,8 @@ import { Mail } from 'lucide-react' import PageTrack from '@/components/track/page-track' +import DecorBlobs from '@/components/ui/decor-blobs/decor-blobs' +import Surface from '@/components/ui/surface/surface' import { getTranslation } from '@/i18n' async function PolicySupportPage() { @@ -8,62 +10,48 @@ async function PolicySupportPage() { return ( <> -
- {/* Background with gradient orbs */} -
-
- - {/* Gradient orbs using the primary color #045fab */} -
-
-
-
- - {/* Content */} -
-
- {/* ClippingKK logo/title */} -

- ClippingKK -

- - {/* Support title */} -

- {t('support.title') || 'Support Information'} -

- - {/* Divider with gradient */} -
-
-
-
-
- - {t('support.contact') || 'Contact Us'} - -
+
+ + +

+ ClippingKK +

+ +

+ {t('support.title') || 'Support Information'} +

+ +
diff --git a/src/app/pricing/content.tsx b/src/app/pricing/content.tsx index fb68c516..4771499f 100644 --- a/src/app/pricing/content.tsx +++ b/src/app/pricing/content.tsx @@ -21,35 +21,29 @@ async function PricingContent(props: PricingContentProps) { return (
- {/* Enhanced decorative background elements */} -
- {/* Top left gradient orb */} -
- {/* Bottom right gradient orb */} -
- {/* Accent gradient */} -
- {/* Additional small accent */} -
- {/* Light texture overlay */} -
+ {/* Decorative gradient orbs, retuned to the unified blue/indigo palette */} +
+
+
+
+
-
- {/* Enhanced header section */} -
-
- - +
+ {/* Header */} +
+
+ + {t('unlock')}
-

+

{t('title')}

-

+

{t('subtitle')}

@@ -59,13 +53,10 @@ async function PricingContent(props: PricingContentProps) { {/* Decorative elements connecting the cards */}
- {/* Pulsing circle behind the arrow */} -
- {/* Gradient ring around the arrow */} -
- {/* Arrow icon */} -
- +
+
+
+
@@ -81,15 +72,15 @@ async function PricingContent(props: PricingContentProps) { href={ profile?.id ? `/dash/${profile.id}/home` : '/auth/auth-v4' } - className="group relative z-10 inline-flex w-full items-center justify-center overflow-hidden rounded-xl bg-[#045fab] px-6 py-4 text-xl font-bold text-white shadow-lg shadow-[#045fab]/30 transition-all duration-500 hover:-translate-y-1 hover:scale-[1.02] hover:shadow-xl hover:shadow-[#045fab]/50 active:scale-[0.98]" + className="group relative z-10 inline-flex w-full items-center justify-center overflow-hidden rounded-xl bg-blue-400 px-6 py-4 text-xl font-bold text-white shadow-lg shadow-blue-400/30 transition-all duration-500 hover:-translate-y-1 hover:scale-[1.02] hover:shadow-xl hover:shadow-blue-400/50 active:scale-[0.98]" > {t('plan.free.goto')} - {/* Fancy hover effects */} - + {/* Hover overlay */} + {/* Glow effect */} - + {/* Shine effect */} @@ -100,7 +91,7 @@ async function PricingContent(props: PricingContentProps) { +

{t('plan.premium.name')}

} @@ -112,32 +103,29 @@ async function PricingContent(props: PricingContentProps) { {isPremium ? ( {t('go')} - {/* Fancy hover effects */} - + {/* Glow effect */} - + {/* Animated accent */} ) : ( {t('plan.premium.goto')} - {/* Fancy hover effects */} - - {/* Glow effect */} - + + {/* Particle effect */} @@ -154,33 +142,29 @@ async function PricingContent(props: PricingContentProps) { />
- {/* Enhanced FAQ/Contact section */} -
- {/* Gradient divider instead of standard hr */} -
+ {/* FAQ / Contact */} + diff --git a/src/app/pricing/loading.tsx b/src/app/pricing/loading.tsx index 3b4db37e..52af4981 100644 --- a/src/app/pricing/loading.tsx +++ b/src/app/pricing/loading.tsx @@ -4,70 +4,70 @@ function Loading() { return (
{/* Decorative background elements */} -
-
-
+
+
+
{/* Header section skeleton */}
-
- -
+
+ +
-
-
-
+
+
+
{/* Pricing cards skeleton */}
{/* Decorative arrow */}
- +
{/* Free plan card skeleton */} -
-
-
+
+
+
{[...Array(5)].map((_, i) => (
-
-
+
+
))}
-
+
{/* Premium plan card skeleton */} -
-
-
+
+
+
{[...Array(7)].map((_, i) => (
-
-
+
+
))}
-
+
{/* FAQ section skeleton */}
-
-
+
+
diff --git a/src/components/RichTextEditor/markdown-components.tsx b/src/components/RichTextEditor/markdown-components.tsx index 0027a961..7432575d 100644 --- a/src/components/RichTextEditor/markdown-components.tsx +++ b/src/components/RichTextEditor/markdown-components.tsx @@ -24,7 +24,10 @@ const Heading = ({ level, children }: HeadingProps) => { return {children} } -export const MarkdownComponents: Record>>> = { +export const MarkdownComponents: Record< + string, + React.FC>> +> = { h1: ({ children, ...props diff --git a/src/components/avatar/avatar.tsx b/src/components/avatar/avatar.tsx index 7551c212..e32c05b2 100644 --- a/src/components/avatar/avatar.tsx +++ b/src/components/avatar/avatar.tsx @@ -37,9 +37,7 @@ function Avatar(props: AvatarProps) { onClick={props.onClick} /> ) : ( -
+
) } return ( diff --git a/src/components/book-cover/book-cover.module.css b/src/components/book-cover/book-cover.module.css deleted file mode 100644 index 4bfdd6cf..00000000 --- a/src/components/book-cover/book-cover.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.cover { -} - -.image { -} - -.cover:hover .image { - transform: translateY(-2rem) scale(1.1); -} diff --git a/src/components/book-cover/book-cover.tsx b/src/components/book-cover/book-cover.tsx index cc605d9d..4947d7ea 100644 --- a/src/components/book-cover/book-cover.tsx +++ b/src/components/book-cover/book-cover.tsx @@ -3,8 +3,6 @@ import Link from 'next/link' import type { WenquBook } from '../../services/wenqu' -import styles from './book-cover.module.css' - type TBookCoverProps = { book: WenquBook domain: string @@ -14,9 +12,7 @@ function BookCover({ book, domain }: TBookCoverProps) { return ( -
-

+
+

{book.title}

diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx index 9944a7d8..eef0317d 100644 --- a/src/components/button/button.tsx +++ b/src/components/button/button.tsx @@ -80,36 +80,35 @@ export function Button({ switch (variant) { case 'primary': return [ - 'bg-gradient-to-br from-sky-400 via-blue-500 to-cyan-600 text-white shadow-lg shadow-blue-500/20', - 'hover:-translate-y-1 hover:shadow-[0_0_20px_3px] hover:shadow-blue-500/30', - 'after:absolute after:inset-0 after:z-0 after:rounded-lg after:bg-gradient-to-r after:from-blue-500 after:via-sky-600 after:to-cyan-600 after:opacity-0 after:transition-opacity after:duration-300 hover:after:opacity-100', - 'before:absolute before:-inset-1 before:z-0 before:scale-[1.05] before:rounded-lg before:bg-gradient-to-r before:from-sky-400 before:to-blue-500 before:opacity-0 before:blur-md before:transition-all before:duration-300 hover:before:opacity-50', + 'bg-gradient-to-br from-blue-400 via-blue-500 to-indigo-500 text-white shadow-lg shadow-blue-400/20', + 'hover:-translate-y-0.5 hover:shadow-[0_0_20px_3px] hover:shadow-blue-400/30', + 'after:absolute after:inset-0 after:z-0 after:rounded-lg after:bg-gradient-to-r after:from-blue-500 after:via-blue-500 after:to-indigo-500 after:opacity-0 after:transition-opacity after:duration-300 hover:after:opacity-100', + 'before:absolute before:-inset-1 before:z-0 before:scale-[1.05] before:rounded-lg before:bg-gradient-to-r before:from-blue-400 before:to-indigo-500 before:opacity-0 before:blur-md before:transition-all before:duration-300 hover:before:opacity-50', ].join(' ') case 'secondary': return [ - 'bg-gradient-to-br from-cyan-500/80 to-blue-600/80 text-white/90 backdrop-blur-sm', - 'hover:-translate-y-1 hover:text-white hover:shadow-lg hover:shadow-cyan-500/20', - 'after:absolute after:inset-0 after:z-0 after:rounded-lg after:bg-gradient-to-r after:from-blue-500/40 after:to-cyan-500/40 after:opacity-0 after:transition-opacity after:duration-300 hover:after:opacity-100', + 'bg-gradient-to-br from-blue-400/80 to-indigo-500/80 text-white/95 backdrop-blur-sm', + 'hover:-translate-y-0.5 hover:text-white hover:shadow-lg hover:shadow-blue-400/20', + 'after:absolute after:inset-0 after:z-0 after:rounded-lg after:bg-gradient-to-r after:from-blue-500/50 after:to-indigo-500/50 after:opacity-0 after:transition-opacity after:duration-300 hover:after:opacity-100', ].join(' ') case 'outline': return [ - 'border-2 border-[#045fab] bg-transparent text-[#045fab] dark:text-white', - 'hover:-translate-y-1 hover:bg-[#045fab]/10 hover:shadow-lg hover:shadow-[#045fab]/20', - 'dark:border-white/70 dark:hover:bg-white/10 dark:hover:shadow-white/10', + 'border-2 border-blue-400 bg-transparent text-blue-500 dark:border-blue-400 dark:text-blue-300', + 'hover:-translate-y-0.5 hover:bg-blue-400/10 hover:shadow-lg hover:shadow-blue-400/20', ].join(' ') case 'ghost': return [ 'bg-transparent text-slate-700 hover:bg-slate-100 dark:text-slate-200 dark:hover:bg-slate-800/60', - 'hover:-translate-y-1', + 'hover:-translate-y-0.5', ].join(' ') case 'danger': return [ - 'bg-gradient-to-br from-red-500 to-rose-600 text-white shadow-lg shadow-red-500/20', - 'hover:-translate-y-1 hover:shadow-[0_0_20px_3px] hover:shadow-red-500/30', - 'after:absolute after:inset-0 after:z-0 after:rounded-lg after:bg-gradient-to-r after:from-rose-600 after:to-red-600 after:opacity-0 after:transition-opacity after:duration-300 hover:after:opacity-100', + 'bg-gradient-to-br from-rose-500 to-rose-600 text-white shadow-lg shadow-rose-500/20', + 'hover:-translate-y-0.5 hover:shadow-[0_0_20px_3px] hover:shadow-rose-500/30', + 'after:absolute after:inset-0 after:z-0 after:rounded-lg after:bg-gradient-to-r after:from-rose-600 after:to-rose-700 after:opacity-0 after:transition-opacity after:duration-300 hover:after:opacity-100', ].join(' ') case 'link': - return 'bg-transparent p-0 text-[#045fab] underline-offset-4 hover:underline dark:text-blue-400' + return 'bg-transparent p-0 text-blue-500 underline-offset-4 hover:underline dark:text-blue-300' default: return '' } diff --git a/src/components/card/card.tsx b/src/components/card/card.tsx index 0cb55e1a..4c2a29a8 100644 --- a/src/components/card/card.tsx +++ b/src/components/card/card.tsx @@ -1,5 +1,7 @@ import type React from 'react' +import { cn } from '@/lib/utils' + type cardProps = { className?: string style?: object @@ -8,11 +10,24 @@ type cardProps = { glow?: boolean } +/** + * Card — legacy wrapper kept API-compatible with existing call sites. + * Visually matches the canonical `Surface` primitive (see + * `src/components/ui/surface/surface.tsx`). Prefer `Surface` for new code. + */ function Card(props: cardProps) { const { className = '', style, onClick, glow, children } = props - const cls = `m-4 p-4 rounded-sm shadow-sm bg-slate-400 bg-opacity-50 ${className}` return ( -
+
{children}
) diff --git a/src/components/card/glass-card.ts b/src/components/card/glass-card.ts index 3c09dc3b..41e1ce27 100644 --- a/src/components/card/glass-card.ts +++ b/src/components/card/glass-card.ts @@ -1,2 +1,7 @@ +/** + * Canonical glass-surface class string. Kept for backward compatibility + * with existing imports; new code should use the `Surface` primitive from + * `src/components/ui/surface/surface.tsx`. + */ export const glassCardClass = - 'rounded-2xl border border-white/40 bg-white/80 p-6 backdrop-blur-xl dark:border-gray-700/40 dark:bg-gray-900/80' + 'rounded-2xl border border-white/40 bg-white/70 p-6 shadow-sm backdrop-blur-xl dark:border-slate-800/40 dark:bg-slate-900/70' diff --git a/src/components/dashboard-container/container.tsx b/src/components/dashboard-container/container.tsx index f7e0651e..6e6ca207 100644 --- a/src/components/dashboard-container/container.tsx +++ b/src/components/dashboard-container/container.tsx @@ -13,6 +13,7 @@ import { COOKIE_TOKEN_KEY } from '../../constants/storage' import { doApolloServerQuery } from '../../services/apollo.server' import Footer from '../footer/Footer' import NavigationBar from '../navigation-bar/navigation-bar' +import DecorBlobs from '../ui/decor-blobs/decor-blobs' type DashboardContainerProps = { uidOrDomain?: number | string @@ -65,14 +66,13 @@ async function DashboardContainer(props: DashboardContainerProps) { } return ( -
-
+
+ +
{header ?? } -
{children}
+
+ {children} +
diff --git a/src/components/footer/Footer.tsx b/src/components/footer/Footer.tsx index 069b6ec7..b09cdbdb 100644 --- a/src/components/footer/Footer.tsx +++ b/src/components/footer/Footer.tsx @@ -56,8 +56,8 @@ async function Footer() { {/* Glow effects */}
-
-
+
+
{/* Subtle gradient lines */}
@@ -69,7 +69,7 @@ async function Footer() { {/* Left column - About */}
-

+

ClippingKK

diff --git a/src/components/galleryBackgroundView.tsx b/src/components/galleryBackgroundView.tsx index d6a14027..b8846435 100644 --- a/src/components/galleryBackgroundView.tsx +++ b/src/components/galleryBackgroundView.tsx @@ -1,9 +1,6 @@ import type { PublicDataQuery } from '../schema/generated' import { getReactQueryClient } from '../services/ajax' -import { - isValidDoubanId, - wenquBooksByIdsQueryOptions, -} from '../services/wenqu' +import { isValidDoubanId, wenquBooksByIdsQueryOptions } from '../services/wenqu' import BookCover from './book-cover/book-cover' import ClippingLite from './clipping-item/clipping-lite' import InfiniteLooper from './infinite-looper/infinite-looper' diff --git a/src/components/input.tsx b/src/components/input.tsx index fe4ab644..6fa903cb 100644 --- a/src/components/input.tsx +++ b/src/components/input.tsx @@ -1,6 +1,8 @@ import type React from 'react' import { useTranslation } from 'react-i18next' +import { cn } from '@/lib/utils' + export enum FieldInputSize { small, normal, @@ -8,9 +10,9 @@ export enum FieldInputSize { } const sizeWidth = { - [FieldInputSize.large]: 'lg:w-144 w-96', - [FieldInputSize.small]: 'lg:w-96 w-64', - [FieldInputSize.normal]: 'lg:w-144 w-96', + [FieldInputSize.large]: 'w-full max-w-xl', + [FieldInputSize.small]: 'w-full max-w-xs', + [FieldInputSize.normal]: 'w-full max-w-md', } type FieldInputProps = { @@ -24,31 +26,45 @@ type FieldInputProps = { tail?: React.ReactElement } +/** + * FieldInput — modernized labelled input used by the onboarding flow. + * Visually aligned with `@annatarhe/lake-ui/form-input-field` (rounded-lg, + * blue-400 focus ring, subtle borders, dark-mode aware). Kept as a thin + * local component because the sole caller needs a bespoke API around file + * inputs. + */ function FieldInput(props: FieldInputProps) { const { t } = useTranslation() const size = props.size ?? FieldInputSize.large + const label = t(`app.auth.${props.name}`) ?? '' return ( -

+
- - {props.tail} +
+ + {props.tail} +
{props.error && ( - + {props.error} )} diff --git a/src/components/loading/center-page.tsx b/src/components/loading/center-page.tsx index fceac0e6..df947b2d 100644 --- a/src/components/loading/center-page.tsx +++ b/src/components/loading/center-page.tsx @@ -1,7 +1,7 @@ function CenterPageLoading() { return ( -
-
+
+
) } diff --git a/src/components/loading/spinner.tsx b/src/components/loading/spinner.tsx index 819b0ffe..4e74e65d 100644 --- a/src/components/loading/spinner.tsx +++ b/src/components/loading/spinner.tsx @@ -2,7 +2,7 @@ function SpinnerIcon() { return ( + {profileData.name} diff --git a/src/components/navigation-bar/navigation-bar.tsx b/src/components/navigation-bar/navigation-bar.tsx index c2034ac4..5d9e8947 100644 --- a/src/components/navigation-bar/navigation-bar.tsx +++ b/src/components/navigation-bar/navigation-bar.tsx @@ -93,7 +93,7 @@ function NavigationBar(props: NavigationBarProps) { {!profile ? ( Login @@ -119,7 +119,9 @@ function NavigationBar(props: NavigationBarProps) { )} > - {t(`app.menu.${item.alt}`) ?? ''} + + {t(`app.menu.${item.alt}`) ?? ''} + ) diff --git a/src/components/noun/noun-edit.tsx b/src/components/noun/noun-edit.tsx index ed2ef6ee..f9afca5e 100644 --- a/src/components/noun/noun-edit.tsx +++ b/src/components/noun/noun-edit.tsx @@ -127,7 +127,7 @@ function NounEditContent(props: NounEditContentProps) { if (id > 0 && loading) { return (
- +
) } @@ -214,7 +214,7 @@ function NounEditContent(props: NounEditContentProps) {