视频地址: https://www.bilibili.com/vide...

根底款式

如鼠标指针、背景图片等。

鼠标指针

* {    cursor: url('/default.cur'), default;}a,a *,button,button *,.btn,.btn *,.prose .post-image {    cursor: url('/pointer.cur'), pointer;}

背景图片切换

@layer components {  #background {    @apply fixed inset-0 saturate-150 z-[-1];    background: url('/images/bg.jpg') no-repeat center center fixed;    background-size: cover;    transition: all 0.25s ease-in-out;    transform-style: preserve-3d;  }  #background.dark {    @apply brightness-50 saturate-100;    transform: rotate(-3deg) scale(1.2);    /* scaleX(-1); */  }}

Header

Link 封装

locale-link:

import {  Link,  type LinkProps,  NavLink,  type NavLinkProps} from '@remix-run/react';import { useI18n } from 'remix-i18n';export function LocaleLink({  to,  children,  ...props}: LinkProps & { to: string }) {  const i18n = useI18n();  const path = `/${i18n.locale()}${to}`;  return (    <Link to={path} {...props}>      {children}    </Link>  );}export function LocaleNavLink({  to,  children,  ...props}: NavLinkProps & { to: string }) {  const i18n = useI18n();  const path = `/${i18n.locale()}${to}`;  return (    <NavLink to={path} {...props}>      {children}    </NavLink>  );}

router-link:

import { type NavLinkProps } from '@remix-run/react';import clsx from 'classnames';import { LocaleNavLink } from './locale-link';export function RouteLink({  children,  to}: Pick<NavLinkProps, 'children' | 'to'>) {  return LocaleNavLink({    to,    className: ({ isActive }) =>      clsx(isActive ? 'glass' : 'btn-ghost', 'btn btn-sm rounded-btn'),    children  });}

header 组件:

import { useI18n } from 'remix-i18n';import { LocaleLink } from './atom/locale-link';import { RouteLink } from './atom/router-link';import { ToggleLocale } from './atom/toggle-locale';import { ToggleTheme } from './atom/toggle-theme';export function Header() {  const i18n = useI18n();  const { t } = i18n;  return (    <header className='fixed w-full z-20 opacity-90 hover:opacity-100'>      <div className='navbar mb-2 shadow-lg bg-neutral text-neutral-content'>        <div className='px-2 mx-2 navbar-start'>          <LocaleLink to='/'>            <span className='text-lg font-bold'>Willin Wang</span>          </LocaleLink>        </div>        <div className='hidden px-2 mx-2 navbar-center lg:flex'>          <div className='flex items-stretch'>            <RouteLink to='/'>{t('nav.home')}</RouteLink>            <RouteLink to='/posts'>{t('nav.posts')}</RouteLink>            <RouteLink to='/projects'>{t('nav.projects')}</RouteLink>            <RouteLink to='/playground'>{t('nav.playground')}</RouteLink>            <RouteLink to='/about'>{t('nav.about')}</RouteLink>          </div>        </div>        <div className='navbar-end'>          <ToggleTheme />          <ToggleLocale />        </div>      </div>    </header>  );}

Footer

// import { useMatches } from '@remix-run/react';// import clsx from 'classnames';import { useI18n } from 'remix-i18n';import { LocaleLink } from './atom/locale-link';import { Github, CSDN, Juejin, SegmentFault, WillinLogo, Zhihu } from './svg';export function Footer() {  const { t } = useI18n();  // const matches = useMatches();  return (    <footer className='p-4 sm:p-6 bg-base-200 text-base-content opacity-90'>      <div className='md:flex md:justify-between'>        <div className='mb-6 md:mb-0'>          <LocaleLink to='/'>            <WillinLogo size='5em' />          </LocaleLink>        </div>        <div className='grid grid-cols-2 gap-8 sm:gap-6 sm:grid-cols-3'>          {/* <div className={clsx({ hidden: posts.length === 0 })}>            <ul>              {posts                .filter((x) => x.type === 'pages')                .map((page) => (                  <li key={page.slug}>                    <LocaleLink to={`/${page.slug}`}>{page.title}</LocaleLink>                  </li>                ))}            </ul>          </div> */}          <div>            <ul>              <li>                <LocaleLink to='/'>{t('nav.home')}</LocaleLink>              </li>              <li>                <LocaleLink to='/posts'>{t('nav.posts')}</LocaleLink>              </li>              <li>                <LocaleLink to='/playground'>{t('nav.playground')}</LocaleLink>              </li>            </ul>          </div>          {/* <div>            <ul>              <li className='mb-4'>                <a                  href='#'                  target='_blank'                  className='text-gray-600 hover:underline dark:text-gray-400'>                  Privacy Policy                </a>              </li>              <li>                <a                  href='#'                  target='_blank'                  className='text-gray-600 hover:underline dark:text-gray-400'>                  Terms &amp; Conditions                </a>              </li>            </ul>          </div> */}        </div>      </div>      <hr className='my-6 border-gray-200 sm:mx-auto dark:border-gray-700 lg:my-8' />      <div className='sm:flex sm:items-center sm:justify-between'>        <span className='text-sm text-gray-500 sm:text-center dark:text-gray-400'>          Willin Wang <small>&copy; 2002 ~ {new Date().getFullYear()}.</small>          <small>            Made with ❤️ and{' '}            <a              href='http://remix.run'              target='_blank'              rel='noopener noreferrer'>              Remix            </a>{' '}            |{' '}            <a              href='https://beian.miit.gov.cn/'              target='_blank'              rel='noopener noreferrer'>              苏ICP备17011988号-1            </a>          </small>        </span>        <div className='flex mt-4 space-x-6 sm:justify-center sm:mt-0'>          <a            href='https://segmentfault.com/u/willin'            target='_blank'            className='hover:text-secondary'            rel='noopener noreferrer'            aria-label='SegmentFault'>            <SegmentFault />          </a>          <a            href='https://blog.csdn.net/jslygwx?type=blog'            target='_blank'            className='hover:text-secondary'            rel='noopener noreferrer'            aria-label='CSDN'>            <CSDN />          </a>          <a            href='https://www.zhihu.com/people/willin'            target='_blank'            className='hover:text-secondary'            rel='noopener noreferrer'            aria-label='知乎'>            <Zhihu />          </a>          <a            href='https://juejin.cn/user/1873223546052391'            target='_blank'            className='hover:text-secondary'            rel='noopener noreferrer'            aria-label='掘金'>            <Juejin />          </a>          <a            href='https://github.com/willin'            target='_blank'            className='hover:text-secondary'            aria-label='Github'>            <Github />          </a>        </div>      </div>    </footer>  );}