Commit 5fb33aa
Changed files (31)
src
components
search
utils
widgets
layouts
pages
posts
scripts
src/components/search/Pagefind.astro
@@ -12,15 +12,15 @@ const bundlePath = `${import.meta.env.BASE_URL}pagefind/`;
/>
<template id="pagefind-result-template">
- <a class="theme-card-bg hover:theme-card-bg-hl-trans group rounded-md p-2" href="#">
+ <a
+ class="hover:bg-primary group w-full rounded-md p-2 duration-150 hover:bg-opacity-30"
+ href="#"
+ >
<div class="flex flex-row items-center gap-1 text-center">
- <span class="group-hover:theme-text-hl-contrast text-lg">Fake Result</span>
- <Icon
- name="material-symbols:chevron-right-rounded"
- class="theme-text-hl-contrast text-lg"
- />
+ <span class="group-hover:text-primary text-lg duration-150">Fake Result</span>
+ <Icon name="material-symbols:chevron-right" class="text-primary text-lg" />
</div>
- <div id="pagefind-result-template-excerpt" class="theme-text-second">
+ <div id="pagefind-result-template-excerpt" class="text-sm opacity-60">
This is a fake result.
</div>
</a>
@@ -82,6 +82,6 @@ const bundlePath = `${import.meta.env.BASE_URL}pagefind/`;
[data-pagefind-ui] mark {
background-color: transparent;
- @apply text-[var(--theme-color-light-darken)] dark:text-[var(--theme-color-dark-lighten)];
+ @apply text-secondary;
}
</style>
src/components/search/SearchBaseUI.astro
@@ -1,4 +1,6 @@
---
+import I18nKey from '@i18n/I18nKey';
+import { i18n } from '@i18n/translation';
import { Icon } from 'astro-icon/components';
import type { HTMLAttributes } from 'astro/types';
@@ -8,29 +10,12 @@ const { class: className, ...rest } = Astro.props;
---
<div class:list={['w-full', className]} {...rest}>
- <div
- class="theme-bg theme-border mb-2 flex w-full flex-row items-center gap-2 rounded-md border-2 p-4 text-center"
- >
+ <label class="input input-bordered flex items-center gap-2">
+ <input type="text" class="grow" placeholder={i18n(I18nKey.search)} />
<Icon name="material-symbols:search-rounded" class="text-3xl" />
- <input type="text" class="theme-bg w-full py-1" />
- </div>
+ </label>
<div
- class="search-result flex h-fit max-h-[calc(60vh-8rem)] flex-col items-center gap-2 overflow-y-auto text-center"
+ class="search-result mt-4 flex h-fit max-h-[calc(60vh-8rem)] flex-col items-center gap-2 overflow-y-auto text-center"
>
</div>
</div>
-
-<style>
- input::-webkit-outer-spin-button,
- input::-webkit-inner-spin-button {
- appearance: none;
- }
-
- input[type='number'] {
- appearance: textfield;
- }
-
- input:focus {
- outline: none;
- }
-</style>
src/components/utils/Markdown.astro
@@ -23,20 +23,21 @@ const firstHasPre = hasPre && (isFirstInstance('md-has-pre', Astro.url) || impor
firstHasPre && (
<template
id="code-toolbar-template"
- class="code-block-wrapper relative my-4 overflow-hidden rounded-lg"
+ class="code-block-wrapper collapse-open collapse relative my-4"
>
- <div class="theme-border theme-card-bg-hl-trans z-10 flex items-center justify-between">
- <Button class="toggle-btn !bg-transparent">
+ <div class="bg-primary/60 text-primary-content z-10 flex items-center justify-between">
+ <Button class="toggle-btn btn-ghost rounded-bl-none">
<Icon
name="material-symbols:keyboard-arrow-down-rounded"
class="h-5 w-5 duration-300"
/>
</Button>
<span class="language font-mono text-sm" />
- <Button class="copy-btn !bg-transparent">
+ <Button class="copy-btn btn-ghost rounded-br-none">
<Icon name="material-symbols:file-copy-rounded" class="h-5 w-5 duration-300" />
</Button>
</div>
+ <div class="collapse-content p-0" />
</template>
)
}
@@ -61,14 +62,14 @@ const firstHasPre = hasPre && (isFirstInstance('md-has-pre', Astro.url) || impor
pre.parentNode?.insertBefore(wrapper, pre);
wrapper.appendChild(toolbar);
- wrapper.appendChild(pre);
+ wrapper.querySelector('.collapse-content')?.appendChild(pre);
const toggleBtn = wrapper.querySelector('.toggle-btn');
const copyBtn = wrapper.querySelector('.copy-btn');
toggleBtn?.addEventListener('click', () => {
toggleBtn.querySelector('svg')?.classList.toggle('-rotate-90');
- pre.classList.toggle('hidden');
+ wrapper.classList.toggle('collapse-open');
});
const code = pre.querySelector('code');
@@ -76,16 +77,16 @@ const firstHasPre = hasPre && (isFirstInstance('md-has-pre', Astro.url) || impor
try {
const text = code?.textContent || '';
await navigator.clipboard.writeText(text);
- copyBtn?.classList.add('text-green-500');
+ copyBtn?.classList.add('text-success');
setTimeout(() => {
- copyBtn?.classList.remove('text-green-500');
- }, 300);
+ copyBtn?.classList.remove('text-success');
+ }, 600);
} catch (err) {
console.error('Failed to copy:', err);
- copyBtn?.classList.add('text-red-500');
+ copyBtn?.classList.add('text-error');
setTimeout(() => {
- copyBtn?.classList.remove('text-red-500');
- }, 300);
+ copyBtn?.classList.remove('text-error');
+ }, 600);
}
});
};
src/components/widgets/Button.astro
@@ -1,43 +1,16 @@
---
-import { AstroParameterConflictError } from '@/types/Errors';
-import type { HTMLAttributes, HTMLTag } from 'astro/types';
+import type { HTMLAttributes } from 'astro/types';
-interface Props extends HTMLAttributes<'button'> {
- href?: string;
- prefetch?: boolean;
-}
-const { href, onclick, prefetch, class: className, ...rest } = Astro.props;
+type Props = HTMLAttributes<'button'> | HTMLAttributes<'a'>;
+let { class: className, ...rest } = Astro.props;
-if (href && onclick) throw new AstroParameterConflictError('href', 'onclick');
+function isAnchor(props: Props): props is HTMLAttributes<'a'> {
+ return 'href' in props;
+}
-const Tag = (href ? 'a' : Fragment) as HTMLTag;
+const Tag = isAnchor(rest) ? 'a' : 'button';
---
-<Tag {...{ href, 'data-astro-prefetch': prefetch as boolean }}>
- <button {...{ onclick, ...rest }} class:list={[className]}>
- <slot />
- </button>
+<Tag class:list={['btn', className]} {...rest as object}>
+ <slot />
</Tag>
-
-<style lang="scss">
- button {
- display: flex;
- align-items: center;
- padding: 0.5rem;
- margin: 0.5rem;
- text-align: center;
- transition-duration: 300ms;
- border-radius: 9999px;
- width: fit-content;
- height: fit-content;
- justify-content: center;
-
- &:hover {
- @apply bg-[var(--theme-color-light)] dark:bg-[var(--theme-color-dark)];
- }
-
- &:active {
- @apply scale-95 brightness-75;
- }
- }
-</style>
src/components/widgets/DarkModeButton.astro
@@ -13,70 +13,84 @@ const { class: className, showText, ...rest } = Astro.props;
---
<Button
- class:list={['darkmode-btn', className]}
+ class:list={['darkmode-btn swap swap-rotate', className]}
{...rest}
data-text-light={i18n(I18nKey.lightMode)}
data-text-dark={i18n(I18nKey.darkMode)}
data-text-auto={i18n(I18nKey.systemMode)}
>
- <Icon class="darkmode-icon-light" name="material-symbols:light-mode-rounded" />
- <Icon class="darkmode-icon-dark" name="material-symbols:dark-mode-rounded" />
- <Icon class="darkmode-icon-auto" name="material-symbols:night-sight-auto-rounded" />
- {showText && <span class="darkmode-text ml-auto mr-2 px-2" />}
+ <input type="checkbox" />
+ <Icon class="darkmode-icon-light swap-off" name="material-symbols:light-mode-rounded" />
+ <Icon class="darkmode-icon-dark swap-on" name="material-symbols:dark-mode-rounded" />
+ <Icon
+ class="darkmode-icon-auto swap-indeterminate"
+ name="material-symbols:night-sight-auto-rounded"
+ />
+ {showText && <span class="darkmode-text pl-6" />}
</Button>
<script>
function initDarkmodeButtons() {
const darkmodeBtns = document.querySelectorAll('button.darkmode-btn');
- function refreshButtons() {
- darkmodeBtns.forEach((btn) => {
- const iconLight = btn.querySelector('.darkmode-icon-light');
- const iconDark = btn.querySelector('.darkmode-icon-dark');
- const iconAuto = btn.querySelector('.darkmode-icon-auto');
- const text = btn.querySelector('.darkmode-text');
+ darkmodeBtns.forEach((btn) => {
+ const checkbox = btn.querySelector('input[type="checkbox"]') as HTMLInputElement;
+ const text = btn.querySelector('.darkmode-text');
+
+ // 初始化状态
+ if ('darkMode' in localStorage) {
+ checkbox.checked = localStorage.darkMode === 'true';
+ checkbox.indeterminate = false;
+ } else {
+ checkbox.indeterminate = true;
+ }
+
+ // 更新文本和标题
+ function updateText() {
+ if (!text) return;
- if ('darkMode' in localStorage && localStorage.darkMode === 'true') {
- iconLight?.classList.add('hidden');
- iconDark?.classList.remove('hidden');
- iconAuto?.classList.add('hidden');
- if (text) text.textContent = btn.getAttribute('data-text-dark');
- btn.setAttribute('title', btn.getAttribute('data-text-dark') || '');
- } else if ('darkMode' in localStorage && localStorage.darkMode === 'false') {
- iconLight?.classList.remove('hidden');
- iconDark?.classList.add('hidden');
- iconAuto?.classList.add('hidden');
- if (text) text.textContent = btn.getAttribute('data-text-light');
- btn.setAttribute('title', btn.getAttribute('data-text-light') || '');
+ const textContent = checkbox.indeterminate
+ ? btn.getAttribute('data-text-auto')
+ : checkbox.checked
+ ? btn.getAttribute('data-text-dark')
+ : btn.getAttribute('data-text-light');
+
+ text.textContent = textContent;
+ btn.setAttribute('title', textContent || '');
+ }
+
+ // 更新主题
+ function updateTheme() {
+ if (checkbox.indeterminate) {
+ localStorage.removeItem('darkMode');
+ const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
+ document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
} else {
- iconLight?.classList.add('hidden');
- iconDark?.classList.add('hidden');
- iconAuto?.classList.remove('hidden');
- if (text) text.textContent = btn.getAttribute('data-text-auto');
- btn.setAttribute('title', btn.getAttribute('data-text-auto') || '');
+ localStorage.darkMode = checkbox.checked;
+ document.documentElement.setAttribute(
+ 'data-theme',
+ checkbox.checked ? 'dark' : 'light'
+ );
}
- });
- }
+ }
- darkmodeBtns.forEach((btn) => {
btn.addEventListener('click', () => {
- if (!('darkMode' in localStorage)) {
- localStorage.darkMode = false;
- document.documentElement.classList.remove('dark');
- } else if (localStorage.darkMode === 'false') {
- localStorage.darkMode = true;
- document.documentElement.classList.add('dark');
+ if (checkbox.indeterminate) {
+ checkbox.indeterminate = false;
+ checkbox.checked = false;
+ } else if (!checkbox.checked) {
+ checkbox.checked = true;
} else {
- localStorage.removeItem('darkMode');
- if (window.matchMedia('(prefers-color-scheme: dark)').matches)
- document.documentElement.classList.add('dark');
- else document.documentElement.classList.remove('dark');
+ checkbox.indeterminate = true;
}
- refreshButtons();
+
+ updateText();
+ updateTheme();
});
- });
- refreshButtons();
+ updateText();
+ updateTheme();
+ });
}
document.addEventListener('astro:page-load', initDarkmodeButtons);
src/components/widgets/MetaIcon.astro
@@ -11,15 +11,13 @@ const { class: className, ...rest } = Astro.props;
<style lang="scss">
.meta-icon {
- width: 2rem;
- height: 2rem;
+ width: 1.5rem;
+ height: 1.5rem;
align-items: center;
margin-right: 0.5rem;
display: flex;
justify-content: center;
- @apply text-[var(--theme-color-light-darken)] dark:text-[var(--theme-color-dark-lighten)];
- @apply bg-[var(--theme-color-light-trans-1d2)] dark:bg-[var(--theme-color-dark-trans-1d2)];
- @apply rounded-md;
+ @apply text-primary;
}
</style>
src/components/widgets/Pagination.astro
@@ -46,36 +46,35 @@ else {
<div id="pagination" class="flex w-full">
{
current > 1 && (
- <Button
- id="prev-page-btn"
- class="theme-bg theme-border mr-auto !rounded-xl border-2"
- href={getPageUrl(current - 1)}
- >
+ <Button id="prev-page-btn" class="mr-auto rounded-xl" href={getPageUrl(current - 1)}>
<Icon name="material-symbols:keyboard-double-arrow-left-rounded" class="my-1" />
</Button>
)
}
<div class="mx-auto flex items-center justify-center gap-2">
- {
- pages.map((p) => {
- return (
- <Button
- class:list={[
- 'theme-bg theme-border !rounded-xl border-2',
- current === p.page && 'theme-card-bg-hl',
- ]}
- href={p.url}
- >
- <span class="mx-1">{`${p.page === -1 ? '...' : p.page}`}</span>
- </Button>
- );
- })
- }
+ <div class="join rounded-xl">
+ {
+ pages.map((p) => {
+ return (
+ <Button
+ class:list={[
+ 'join-item',
+ current === p.page && 'btn-active',
+ p.page === -1 && 'btn-disabled',
+ ]}
+ href={p.url}
+ >
+ <span class="mx-1">{`${p.page === -1 ? '...' : p.page}`}</span>
+ </Button>
+ );
+ })
+ }
+ </div>
{
total > 1 && (
- <div
+ <label
id="page-jumper"
- class="theme-card-bg theme-border mx-2 flex flex-row items-center rounded-xl border-2"
+ class="input input-bordered mx-2 flex flex-row items-center overflow-hidden rounded-xl px-0"
data-base-url={baseUrl}
data-special-pages={specialPages?.map((p) => `${p.page}:${p.url}`).join(',')}
>
@@ -84,25 +83,18 @@ else {
type="number"
min="1"
max={total}
- class="theme-bg !active:border-none border-none pl-4 duration-300"
+ class="pl-4 duration-300"
/>
- <Button
- id="page-jumper-button"
- class="theme-card-bg relative right-0 !m-0 !rounded-xl duration-300"
- >
+ <Button id="page-jumper-button" class="relative right-0 m-0 rounded-xl duration-300">
<Icon name="material-symbols:keyboard-double-arrow-right-rounded" class="my-1" />
</Button>
- </div>
+ </label>
)
}
</div>
{
current < total && (
- <Button
- id="next-page-btn"
- class="theme-bg theme-border ml-auto !rounded-xl border-2"
- href={getPageUrl(current + 1)}
- >
+ <Button id="next-page-btn" class="ml-auto rounded-xl" href={getPageUrl(current + 1)}>
<Icon name="material-symbols:keyboard-double-arrow-right-rounded" class="my-1" />
</Button>
)
src/components/widgets/PostCard.astro
@@ -48,14 +48,15 @@ const metas: ({ icon: string; text: string; link?: string } | undefined)[] = [
<div
class:list={[
- 'theme-card-bg theme-border',
- 'flex w-full rounded-xl border-2 p-4 max-md:flex-col-reverse',
+ 'card md:card-side card-bordered flex w-full rounded-xl border-2 max-md:flex-col-reverse',
className,
]}
>
- <div class="mr-auto h-full w-full items-center px-12 py-7">
- <div class="mb-5 text-2xl"><a href={url}>{title}</a></div>
- <div class="theme-text-second mb-3 flex flex-wrap items-center gap-x-4 gap-y-2">
+ <div class="card-body">
+ <a href={url} class="card-title">{title}</a>
+ <div
+ class="text-base-content mb-3 flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-opacity-60"
+ >
{
metas.map((meta) => {
return (
@@ -78,19 +79,13 @@ const metas: ({ icon: string; text: string; link?: string } | undefined)[] = [
</div>
{
hasCover ? (
- <PostCardCover url={url} title={title} cover={cover} />
+ <figure class="md:w-3/4 md:max-w-96">
+ <PostCardCover url={url} title={title} cover={cover} />
+ </figure>
) : (
- <ReadMoreButton href={url} title={title} />
+ <figure>
+ <ReadMoreButton href={url} title={title} />
+ </figure>
)
}
</div>
-
-<style>
- .meta-text {
- @apply text-sm font-medium;
- }
-
- a.meta-text {
- @apply duration-100 hover:brightness-125;
- }
-</style>
src/components/widgets/PostCardCover.astro
@@ -20,14 +20,11 @@ const { url, title, cover } = Astro.props;
<style>
a {
- @apply relative flex min-h-48 w-full overflow-hidden rounded-md md:w-3/4 md:max-w-96;
- @apply duration-100 active:scale-95 active:brightness-75;
+ @apply relative flex min-h-48 w-full overflow-hidden duration-100 active:brightness-75;
}
div.cover-mask {
- @apply absolute inset-0 z-10 h-full w-full bg-black/60;
- @apply flex items-center justify-center;
- @apply opacity-0 duration-300 group-hover:opacity-100;
+ @apply absolute inset-0 z-10 flex h-full w-full items-center justify-center bg-black/60 opacity-0 duration-300 group-hover:opacity-100;
}
svg {
src/components/widgets/ProfileCard.astro
@@ -5,33 +5,25 @@ import { Icon } from 'astro-icon/components';
import Button from './Button.astro';
---
-<div
- id="profile-card"
- transition:persist
- class="theme-card-bg theme-border flex flex-col items-center rounded-xl border-2 text-center"
->
- <div class="m-3 w-fit min-w-20">
+<div id="profile-card" transition:persist class="card card-bordered border-2">
+ <figure class="px-4 pt-4">
<a href="/about/">
- <ImageWrapper
- class="theme-border h-20 w-20 rounded-full border-4"
- src={profileConfig.avatar}
- alt={profileConfig.name}
- />
+ <ImageWrapper class="rounded-xl" src={profileConfig.avatar} alt={profileConfig.name} />
</a>
- </div>
- <div class="mx-3 flex w-full flex-col">
- <div class="mb-3 text-lg">
+ </figure>
+ <div class="card-body items-center p-5 text-center">
+ <div class="card-title">
<a href="/about/" class="font-bold">{profileConfig.name}</a>
</div>
<div>{profileConfig.bio}</div>
- </div>
- <div class="flex items-center justify-center">
- {
- profileConfig.links.map((link) => (
- <Button href={link.url} title={link.name} class="text-2xl">
- <Icon name={link.icon} />
- </Button>
- ))
- }
+ <div class="flex flex-row flex-wrap items-center justify-center gap-2">
+ {
+ profileConfig.links.map((link) => (
+ <Button href={link.url} title={link.name} class="btn-circle btn-ghost text-2xl">
+ <Icon name={link.icon} />
+ </Button>
+ ))
+ }
+ </div>
</div>
</div>
src/components/widgets/ReadMoreButton.astro
@@ -15,14 +15,10 @@ const { href, title, ...rest } = Astro.props;
<style>
a {
- @apply duration-100 max-md:hidden;
- @apply hover:brightness-125;
- @apply active:scale-95 active:brightness-75;
+ @apply duration-150 hover:brightness-125 active:brightness-75 max-md:hidden;
}
svg {
- @apply h-full min-h-48 w-12 rounded-md;
- @apply text-[var(--theme-color-light-darken)] dark:text-[var(--theme-color-dark-lighten)];
- @apply bg-[var(--theme-color-light-trans-1d2)] dark:bg-[var(--theme-color-dark-trans-1d2)];
+ @apply text-primary bg-primary/40 h-full min-h-48 w-12;
}
</style>
src/components/widgets/TOC.astro
@@ -11,17 +11,18 @@ const minDepth = Math.min(...headings.map((h) => h.depth));
const maxLevel = 3;
---
-<div id="toc" class:list={['theme-card-bg theme-border rounded-xl border-2 p-2', className]}>
- <div></div>
- {
- headings
- .filter((heading) => heading.depth < minDepth + maxLevel)
- .map((heading) => (
- <a class:list={[`level-${heading.depth - minDepth + 1}`]} href={`#${heading.slug}`}>
- {heading.text}
- </a>
- ))
- }
+<div id="toc" class:list={['card card-bordered border-2', className]}>
+ <div class="card-body p-2">
+ {
+ headings
+ .filter((heading) => heading.depth < minDepth + maxLevel)
+ .map((heading) => (
+ <a class:list={[`level-${heading.depth - minDepth + 1}`]} href={`#${heading.slug}`}>
+ {heading.text}
+ </a>
+ ))
+ }
+ </div>
</div>
<style lang="scss">
src/components/CategoryBar.astro
@@ -10,31 +10,26 @@ interface Props {
const { categories, currentCategory } = Astro.props;
---
-<div
- id="category-bar"
- class="theme-card-bg theme-border mb-4 flex w-full rounded-xl border-2 px-2 py-3"
->
- <a href={`/`} class:list={[currentCategory ? '' : 'theme-card-bg-hl']}>
- {i18n(I18nKey.recentPosts)}
- </a>
- {
- categories.map((category) => (
- <a
- href={`/archives/categories/${category}/1/`}
- class:list={[currentCategory === category ? 'theme-card-bg-hl' : '']}
- >
- {i18n(category)}
- </a>
- ))
- }
-</div>
-
-<style lang="scss">
- a {
- @apply mx-2 rounded-md px-2 py-1;
-
- &:hover {
- @apply bg-[var(--theme-color-light-lighten)] dark:bg-[var(--theme-color-dark-lighten)];
+<div id="category-bar" class="card card-bordered mb-4 w-full border-2">
+ <div class="card-body flex flex-row items-center gap-2 overflow-auto px-2 py-3">
+ <a
+ href={`/`}
+ class:list={['btn btn-ghost h-8 min-h-8 px-3 py-0', currentCategory ? '' : 'btn-active']}
+ >
+ {i18n(I18nKey.recentPosts)}
+ </a>
+ {
+ categories.map((category) => (
+ <a
+ href={`/archives/categories/${category}/1/`}
+ class:list={[
+ 'btn btn-ghost h-8 min-h-8 px-3 py-0',
+ currentCategory === category ? 'btn-active' : '',
+ ]}
+ >
+ {i18n(category)}
+ </a>
+ ))
}
- }
-</style>
+ </div>
+</div>
src/components/License.astro
@@ -29,8 +29,8 @@ const infomations = [
];
---
-<div class="theme-card-bg-hl-trans theme-border my-4 flex items-center rounded-xl border-2 p-4">
- <div class="mx-auto grid grid-cols-2 gap-x-4">
+<div class="card card-bordered bg-primary/25 my-4 border-2">
+ <div class="card-body grid grid-cols-2 gap-x-4 p-4">
{
infomations.map((info) => (
<Fragment>
src/components/Search.astro
@@ -4,14 +4,11 @@ import Algolia from './search/Algolia.astro';
import Pagefind from './search/Pagefind.astro';
---
-<div id="search-container" class="fixed z-30 hidden h-full w-full" transition:persist>
- <div
- class="fixed -z-10 h-full w-full bg-black/20 backdrop-blur-sm backdrop-saturate-100 duration-500 ease-in-out"
- >
- </div>
- <div
- class="theme-card-bg theme-border mx-auto mt-[min(10%,8rem)] flex w-11/12 flex-col items-center justify-center gap-4 overflow-hidden rounded-xl border-2 md:w-1/2"
- >
+<dialog id="search_modal" class="modal" transition:persist>
+ <div class="modal-box bg-base-300 border-base-200">
+ <form method="dialog">
+ <button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
+ </form>
<div class="w-full p-4">
{
(() => {
@@ -24,32 +21,21 @@ import Pagefind from './search/Pagefind.astro';
})()
}
</div>
- <div
- class="theme-card-bg-hl-trans relative mt-auto w-full flex-shrink-0 px-4 py-2 text-center"
- >
+ <div class="relative mt-auto w-full flex-shrink-0 pt-4 text-center">
Powered by {
searchConfig.provider === 'pagefind' ? (
- <a href="https://pagefind.app" target="_blank" class="text-blue-500">
+ <a href="https://pagefind.app" target="_blank" class="text-primary">
Pagefind
</a>
) : (
- <a href="https://www.algolia.com" target="_blank" class="text-blue-500">
+ <a href="https://www.algolia.com" target="_blank" class="text-primary">
Algolia
</a>
)
}
</div>
</div>
-</div>
-
-<script>
- function initSearchContainer() {
- const searchContainer = document.getElementById('search-container');
- const searchContainerMask = searchContainer?.querySelector(':first-child');
- searchContainerMask?.addEventListener('click', () => {
- searchContainer?.classList.add('hidden');
- });
- }
-
- document.addEventListener('astro:page-load', initSearchContainer);
-</script>
+ <form method="dialog" class="modal-backdrop">
+ <button>close</button>
+ </form>
+</dialog>
src/components/Sidebar.astro
@@ -1,100 +0,0 @@
----
-import { navbarConfig } from '@/config';
-import { i18n } from '@i18n/translation';
-import { Icon } from 'astro-icon/components';
-import Button from './widgets/Button.astro';
-import DarkModeButton from './widgets/DarkModeButton.astro';
----
-
-<div id="sidebar">
- <div
- id="sidebar-mask"
- class="pointer-events-none fixed z-40 h-full w-full bg-black/10 opacity-0 backdrop-blur-md backdrop-saturate-100 duration-500 ease-in-out"
- >
- </div>
- <div
- id="sidebar-menu"
- class="theme-border theme-card-bg fixed -right-1/2 z-50 h-full w-1/2 border-l-2 duration-500 ease-in-out"
- >
- <div id="sidebar-site-data"></div>
- <DarkModeButton
- showText={true}
- class="theme-border !w-[calc(100%-1rem)] border-2 text-lg"
- />
- <div id="sidebar-menu-text-items">
- {
- navbarConfig.navbarCenterItems.map((item) => (
- <Button
- id="sidebar-menu-item"
- {...('href' in item && item.href && { href: item.href })}
- title={i18n(item.text)}
- >
- <span class="text-xl">{i18n(item.text)}</span>
- </Button>
- ))
- }
- </div>
- <div id="sidebar-menu-icon-items" class="flex">
- {
- navbarConfig.navbarRightItems.onlyWide.map((item) => (
- <Button
- id="sidebar-menu-item"
- {...('href' in item && item.href && { href: item.href })}
- title={i18n(item.text)}
- {...('onclick' in item &&
- item.onclick &&
- (typeof item.onclick === 'string'
- ? { onclick: item.onclick }
- : { id: 'side-' + item.onclick.id }))}
- >
- <Icon name={item.icon} class="text-2xl" />
- </Button>
- ))
- }
- </div>
- </div>
-</div>
-
-<script>
- import { navbarConfig } from '@/config';
- const rightItems = navbarConfig.navbarRightItems.onlyWide;
-
- function initSidebar() {
- const toggleSidebarBtns = document.getElementById('nav-toggle-sidebar-btn');
- const sidebarMask = document.getElementById('sidebar-mask');
- const sidebarMenu = document.getElementById('sidebar-menu');
-
- toggleSidebarBtns?.addEventListener('click', () => {
- sidebarMask?.classList.remove('opacity-0');
- sidebarMask?.classList.remove('pointer-events-none');
- sidebarMenu?.classList.add('-translate-x-full');
- sidebarMenu?.removeAttribute('inert');
- });
-
- sidebarMask?.addEventListener('click', () => {
- sidebarMask?.classList.add('opacity-0');
- sidebarMask?.classList.add('pointer-events-none');
- sidebarMenu?.classList.remove('-translate-x-full');
- sidebarMenu?.setAttribute('inert', 'true');
- });
-
- window.addEventListener('resize', () => {
- if (window.innerWidth > 768) {
- sidebarMask?.classList.add('opacity-0');
- sidebarMask?.classList.add('pointer-events-none');
- sidebarMenu?.classList.remove('-translate-x-full');
- sidebarMenu?.setAttribute('inert', 'true');
- }
- });
-
- // 绑定设置的点击事件
- rightItems.forEach((item) => {
- if ('onclick' in item && item.onclick && typeof item.onclick !== 'string') {
- const element = document.getElementById('side-' + item.onclick.id);
- if (element) element.addEventListener('click', item.onclick.function);
- }
- });
- }
-
- document.addEventListener('astro:page-load', initSidebar);
-</script>
src/components/SideToolBar.astro
@@ -5,23 +5,23 @@ import Button from './widgets/Button.astro';
import DarkModeButton from './widgets/DarkModeButton.astro';
---
-<div id="side-toolbar" class="fixed bottom-10 right-0 z-30">
- <div id="stb-hide" class="translate-x-full duration-500 ease-in-out" inert>
- <DarkModeButton id="stb-dark-mode" class="" />
+<div id="side-toolbar" class="fixed bottom-10 right-0 z-30 grid grid-cols-1 gap-2">
+ <div id="stb-hide" class="translate-x-full duration-500 ease-in-out grid grid-cols-1 gap-2 pr-4" inert>
+ <DarkModeButton id="stb-dark-mode" class="btn-circle btn-primary btn-sm" />
</div>
- <div id="stb-show" class="translate-x-full duration-500 ease-in-out" inert>
- <Button id="stb-show-more">
+ <div id="stb-show" class="translate-x-full duration-500 ease-in-out grid grid-cols-1 gap-2 pr-4" inert>
+ <Button id="stb-show-more" class='btn-circle btn-primary btn-sm'>
<Icon name="material-symbols:settings-rounded" class="animate-spin" />
</Button>
{
articleConfig.toc && (
- <Button id="stb-toc" class="hidden xl:!hidden">
+ <Button id="stb-toc" class="hidden xl:!hidden btn-circle btn-primary btn-sm">
<Icon name="material-symbols:toc-rounded" />
</Button>
<div id="stb-toc-wrapper" class="absolute scale-0 hidden duration-300 bottom-10 max-w-72 w-[calc(100vw-4rem)]"></div>
)
}
- <Button id="stb-back-to-top" class="group">
+ <Button id="stb-back-to-top" class='group btn-circle btn-primary btn-sm'>
<span
id="stb-read-percentage"
class="absolute text-sm opacity-0 duration-300 group-hover:opacity-0"></span>
@@ -113,12 +113,3 @@ import DarkModeButton from './widgets/DarkModeButton.astro';
document.addEventListener('astro:page-load', initSideToolBar);
</script>
-<style lang="scss">
- button {
- @apply bg-[var(--theme-color-light)] dark:bg-[var(--theme-color-dark)];
-
- &:hover {
- @apply bg-[var(--theme-color-light-lighten)] dark:bg-[var(--theme-color-dark-lighten)];
- }
- }
-</style>
src/layouts/GlobalLayout.astro
@@ -46,7 +46,7 @@ const siteLang = lang.replace('_', '-');
<slot name="head" />
</head>
- <body class="theme-bg theme-text flex min-h-screen flex-col">
+ <body class="bg-base-100 text-base-content flex min-h-screen flex-col">
<slot />
</body>
</html>
@@ -59,8 +59,8 @@ const siteLang = lang.replace('_', '-');
(!('darkMode' in localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
- document.documentElement.classList.add('dark');
- } else document.documentElement.classList.remove('dark');
+ document.documentElement.setAttribute('data-theme', 'dark');
+ } else document.documentElement.setAttribute('data-theme', 'light');
}
document.addEventListener('astro:after-swap', applyDarkMode);
applyDarkMode();
src/layouts/MainLayout.astro
@@ -4,7 +4,6 @@ import Navbar from '@components/Navbar.astro';
import PageFooter from '@components/PageFooter.astro';
import Search from '@components/Search.astro';
import SideToolBar from '@components/SideToolBar.astro';
-import Sidebar from '@components/Sidebar.astro';
import GlobalLayout from './GlobalLayout.astro';
interface Props {
@@ -17,14 +16,14 @@ const { title, description, lang } = Astro.props;
<GlobalLayout title={title} description={description} lang={lang}>
<slot slot="head" name="head" />
- <Sidebar />
<SideToolBar />
- <Navbar />
- <slot name="header" />
- <div id="body-wrap" class="w-full items-center md:px-4">
- <!-- Main content -->
- <slot />
- </div>
+ <Navbar>
+ <slot name="header" />
+ <div id="body-wrap" class="w-full items-center md:px-4">
+ <!-- Main content -->
+ <slot />
+ </div>
+ </Navbar>
{searchConfig.enable && <Search />}
<PageFooter />
</GlobalLayout>
src/pages/posts/[article].astro
@@ -35,7 +35,7 @@ const wordCount = countWords(article.body || '');
class="mx-2 mt-4"
/>
</Fragment>
- <div class="theme-card-bg theme-border rounded-xl border-2 px-6 py-4">
+ <div class="card card-bordered rounded-xl border-2 px-6 py-4">
<Markdown>
<Content />
</Markdown>
src/pages/about.astro
@@ -13,32 +13,34 @@ const aboutMd = await getEntry('spec', 'about');
const { Content } = aboutMd ? await render(aboutMd) : Fragment;
---
-<MainLayout title={i18n(I18nKey.about)} comment={aboutMd?.data.comment}>
+<MainLayout title={i18n(I18nKey.about)}>
<div class="mx-auto flex max-w-screen-xl flex-col items-center justify-center">
- <div class="my-4 flex w-5/6 flex-row items-center justify-between gap-4 md:w-2/3">
- <div class="mb-5 mr-auto flex flex-col">
- <div>
- <span class="text-xl">Hi! I'm </span>
- <span class="text-2xl font-bold">{profileConfig.name}</span>
- </div>
- <div class="mt-2">
- {profileConfig.bio}
- </div>
- <div class="mt-4 flex">
- {
- profileConfig.links.map((link) => (
- <Button href={link.url} title={link.name} class="text-2xl">
- <Icon name={link.icon} />
- </Button>
- ))
- }
+ <div class="hero my-4 w-5/6 md:w-2/3">
+ <div class="hero-content flex-col-reverse md:flex-row">
+ <div class="mr-auto flex flex-col">
+ <h1>
+ <span class="text-xl">Hi! I'm </span>
+ <span class="text-2xl font-bold">{profileConfig.name}</span>
+ </h1>
+ <div class="mt-2">
+ {profileConfig.bio}
+ </div>
+ <div class="mt-4 flex">
+ {
+ profileConfig.links.map((link) => (
+ <Button href={link.url} title={link.name} class="btn-circle btn-ghost text-2xl">
+ <Icon name={link.icon} />
+ </Button>
+ ))
+ }
+ </div>
</div>
+ <ImageWrapper
+ class="h-0 min-h-48 w-0 min-w-48 rounded-lg shadow-2xl"
+ src={profileConfig.avatar}
+ alt={profileConfig.name}
+ />
</div>
- <ImageWrapper
- class="theme-border h-0 min-h-32 w-0 min-w-32 rounded-full border-4 md:min-h-48 md:min-w-48"
- src={profileConfig.avatar}
- alt={profileConfig.name}
- />
</div>
<Markdown class="w-5/6 md:w-3/4">
<Content />
src/scripts/utils.ts
@@ -36,8 +36,3 @@ export async function getRandomPost() {
console.error('Failed to get random post:', error);
}
}
-
-export function toggleSearch() {
- const searchContainer = document.getElementById('search-container');
- searchContainer?.classList.toggle('hidden');
-}
src/styles/globals.scss
@@ -1,106 +1,11 @@
-@use 'sass:color';
-@use './variables' as var;
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
- --theme-color-light: #{var.$theme-color-light};
- --theme-color-dark: #{var.$theme-color-dark};
- --theme-color-light-lighten: #{color.adjust(var.$theme-color-light, $lightness: 20%)};
- --theme-color-dark-lighten: #{color.adjust(var.$theme-color-dark, $lightness: 20%)};
- --theme-color-light-darken: #{color.adjust(var.$theme-color-light, $lightness: -20%)};
- --theme-color-dark-darken: #{color.adjust(var.$theme-color-dark, $lightness: -20%)};
-
- @for $i from 1 through 8 {
- $numerator: $i;
- $denominator: 8;
-
- @while $numerator % 2 == 0 and $denominator % 2 == 0 {
- $numerator: calc($numerator / 2);
- $denominator: calc($denominator / 2);
- }
-
- $alpha: calc($i / 8 - 1);
-
- --theme-color-light-trans-#{$numerator}d#{$denominator}: #{color.adjust(
- var.$theme-color-light,
- $alpha: $alpha
- )};
- --theme-color-dark-trans-#{$numerator}d#{$denominator}: #{color.adjust(
- var.$theme-color-dark,
- $alpha: $alpha
- )};
- }
-
- --theme-bg-color-light: #{var.$theme-bg-color-light};
- --theme-bg-color-dark: #{var.$theme-bg-color-dark};
- --theme-card-bg-color-light: #{var.$theme-card-bg-color-light};
- --theme-card-bg-color-dark: #{var.$theme-card-bg-color-dark};
- --theme-text-color-light: #{var.$theme-text-color-light};
- --theme-text-color-dark: #{var.$theme-text-color-dark};
- --theme-text-color-second-light: #{var.$theme-text-color-secondary-light};
- --theme-text-color-second-dark: #{var.$theme-text-color-secondary-dark};
- --theme-border-color-light: #{var.$theme-border-color-light};
- --theme-border-color-dark: #{var.$theme-border-color-dark};
-
font-size: 17px;
}
html {
scroll-behavior: smooth;
}
-
-@layer components {
- .theme-bg {
- @apply bg-[var(--theme-bg-color-light)] dark:bg-[var(--theme-bg-color-dark)];
- }
-
- .theme-card-bg {
- @apply bg-[var(--theme-card-bg-color-light)] dark:bg-[var(--theme-card-bg-color-dark)];
- }
-
- .theme-card-bg-hl {
- @apply bg-[var(--theme-color-light)] dark:bg-[var(--theme-color-dark)];
- }
-
- .theme-card-bg-hl-trans {
- @apply bg-[var(--theme-color-light-trans-1d2)] dark:bg-[var(--theme-color-dark-trans-1d2)];
- }
-
- .theme-card-bg-contrary {
- @apply bg-[var(--theme-bg-color-dark)] dark:bg-[var(--theme-bg-color-light)];
- }
-
- .theme-card-bg-contrary-hl {
- @apply bg-[var(--theme-color-dark)] dark:bg-[var(--theme-color-light)];
- }
-
- .theme-text {
- @apply text-[var(--theme-text-color-light)] dark:text-[var(--theme-text-color-dark)];
- }
-
- .theme-text-hl {
- @apply text-[var(--theme-color-light)] dark:text-[var(--theme-color-dark)];
- }
-
- .theme-text-hl-contrast {
- @apply text-[var(--theme-color-light-darken)] dark:text-[var(--theme-color-dark-lighten)];
- }
-
- .theme-text-second {
- @apply text-[var(--theme-text-color-second-light)] dark:text-[var(--theme-text-color-second-dark)];
- }
-
- .theme-text-contrary {
- @apply text-[var(--theme-text-color-dark)] dark:text-[var(--theme-text-color-light)];
- }
-
- .theme-border {
- @apply border-[var(--theme-border-color-light)] dark:border-[var(--theme-border-color-dark)];
- }
-
- .theme-border-hl {
- @apply border-[var(--theme-color-light)] dark:border-[var(--theme-color-dark)];
- }
-}
src/styles/markdown.scss
@@ -38,7 +38,7 @@ article {
}
a {
- @apply theme-text-hl-contrast underline decoration-dashed;
+ @apply text-primary underline decoration-dashed;
&[data-footnote-ref],
&[data-footnote-backref] {
@@ -81,8 +81,7 @@ article {
border: 0.25em solid;
border-radius: 9999px;
- @apply border-[var(--theme-color-light-trans-3d4)];
- @apply dark:border-[var(--theme-color-dark-trans-3d4)];
+ @apply border-primary/75;
}
}
@@ -106,7 +105,7 @@ article {
text-align: center;
border-radius: 9999px;
- @apply theme-card-bg-hl-trans theme-text-hl-contrast;
+ @apply bg-primary/50 text-primary;
}
p:first-child {
@@ -152,22 +151,22 @@ article {
code:not(pre code) {
padding: 0 0.25rem;
- @apply theme-text-hl-contrast rounded-md bg-[var(--theme-color-light-trans-1d8)] dark:bg-[var(--theme-color-dark-trans-1d8)];
+ @apply text-primary bg-primary/10 rounded-md;
}
// 引用块样式
blockquote {
padding: 0.25rem 0.25rem 0.25rem 0.75rem;
- @apply theme-border-hl rounded-sm border-l-4 bg-[var(--theme-color-light-trans-1d8)] dark:bg-[var(--theme-color-dark-trans-1d8)];
+ @apply border-primary bg-primary/10 rounded-sm border-l-4;
}
// 折叠块样式
details {
- @apply theme-border w-full overflow-hidden rounded-xl border-2 duration-300;
+ @apply border-base-300 w-full overflow-hidden rounded-xl border-2 duration-300;
summary {
- @apply hover:theme-card-bg-hl-trans w-full px-3 py-1 text-start text-2xl duration-300;
+ @apply hover:bg-primary/50 w-full px-3 py-1 text-start text-2xl duration-300;
&::marker {
margin-right: 1.5rem;
@@ -176,7 +175,7 @@ article {
&[open] {
summary {
- @apply theme-card-bg-hl-trans;
+ @apply bg-primary/50;
}
}
}
src/styles/twikoo.scss
@@ -33,10 +33,10 @@
// 文本框输入样式
.el-textarea {
- @apply theme-border relative w-full overflow-hidden rounded-xl border-2 pb-9;
+ @apply border-base-300 relative w-full overflow-hidden rounded-xl border-2 pb-9;
textarea {
- @apply theme-card-bg w-full p-4;
+ @apply bg-base-200/50 w-full p-4;
resize: none;
@@ -45,12 +45,12 @@
}
&::placeholder {
- @apply theme-text-second;
+ @apply text-base-content/50;
}
}
.el-input__count {
- @apply theme-text-second absolute bottom-2 right-10 text-sm;
+ @apply text-base-content/50 absolute bottom-2 right-10 text-sm;
}
}
@@ -71,7 +71,7 @@
}
button {
- @apply theme-border theme-card-bg-hl absolute py-[0.95rem] md:py-[0.3rem];
+ @apply border-base-300 bg-primary absolute py-[0.95rem] md:py-[0.3rem];
&.tk-preview {
@apply bottom-[3.7rem] right-0 md:bottom-0 md:right-[3.35rem];
@@ -100,20 +100,20 @@
}
&.tk-cancel {
- @apply theme-card-bg-contrary-hl theme-text-contrary bottom-[2.4rem] right-0 md:bottom-0 md:right-[6.7rem];
+ @apply bg-error text-error-content bottom-[2.4rem] right-0 md:bottom-0 md:right-[6.7rem];
}
}
}
.tk-preview-container {
- @apply theme-border theme-bg mt-2 w-full rounded-xl border-2 p-2;
+ @apply border-base-300 bg-base-100 mt-2 w-full rounded-xl border-2 p-2;
}
}
// 表情框样式
.OwO-body {
/* stylelint-disable-next-line scss/operator-no-unspaced */
- @apply theme-card-bg theme-border absolute -left-3 top-9 z-20 hidden w-[calc(100vw-3rem)] max-w-[30rem] rounded-xl border-2 duration-300;
+ @apply bg-base-200/50 border-base-300 absolute -left-3 top-9 z-20 hidden w-[calc(100vw-3rem)] max-w-[30rem] rounded-xl border-2 duration-300;
}
.OwO-open .OwO-body {
@@ -144,10 +144,10 @@
@apply flex flex-wrap items-center text-nowrap px-4;
> li {
- @apply hover:theme-card-bg-hl-trans flex h-8 cursor-pointer items-center px-3 text-center duration-300;
+ @apply hover:bg-primary/50 flex h-8 cursor-pointer items-center px-3 text-center duration-300;
&.OwO-package-active {
- @apply theme-card-bg-hl-trans;
+ @apply bg-primary/50;
}
}
}
@@ -173,7 +173,7 @@
}
> .tk-comment {
- @apply max-md:theme-card-bg max-md:theme-border p-4 max-md:rounded-xl max-md:border-2;
+ @apply max-md:bg-base-200/50 max-md:border-base-300 p-4 max-md:rounded-xl max-md:border-2;
> .tk-avatar {
@apply top-3;
@@ -190,7 +190,7 @@
// 详细样式
.tk-avatar {
- @apply theme-border absolute top-0 h-8 min-h-8 w-8 min-w-8 overflow-hidden rounded-full border-2;
+ @apply border-base-300 absolute top-0 h-8 min-h-8 w-8 min-w-8 overflow-hidden rounded-full border-2;
}
.tk-main > .tk-row {
@@ -199,11 +199,11 @@
.tk-meta {
a {
- @apply hover:theme-text-hl duration-300;
+ @apply hover:text-primary duration-300;
}
small {
- @apply theme-text-second;
+ @apply text-base-content/50;
}
.tk-actions {
@@ -218,7 +218,7 @@
.tk-action {
.tk-action-link {
- @apply theme-border relative flex items-center justify-center rounded-xl border-2 px-2 py-1 text-center duration-300;
+ @apply border-base-300 relative flex items-center justify-center rounded-xl border-2 px-2 py-1 text-center duration-300;
.tk-action-icon-solid {
@apply absolute left-2 opacity-0 duration-300;
@@ -237,7 +237,7 @@
}
&:hover {
- @apply theme-card-bg-hl;
+ @apply bg-primary;
.tk-action-icon-solid {
@apply opacity-100;
@@ -254,7 +254,7 @@
@apply flex flex-row gap-3;
.tk-extra {
- @apply theme-text-second theme-border flex flex-row items-center justify-center gap-2 rounded-md border-2 p-1 text-center text-xs;
+ @apply text-base-content/50 border-base-300 flex flex-row items-center justify-center gap-2 rounded-md border-2 p-1 text-center text-xs;
}
.tk-icon {
@@ -264,7 +264,7 @@
.tk-replies .tk-content > span:first-child {
// 回复提示(回复:xxx)样式
- @apply theme-text-second text-xs;
+ @apply text-base-content/50 text-xs;
}
.tk-expand-wrap,
@@ -273,25 +273,25 @@
}
.tk-expand {
- @apply theme-card-bg hover:theme-card-bg-hl-trans w-full cursor-pointer rounded-md py-1 text-sm duration-300;
+ @apply bg-base-200/50 hover:bg-primary/50 w-full cursor-pointer rounded-md py-1 text-sm duration-300;
}
}
// 图标样式
.tk-submit-action-icon {
- @apply inline-block max-h-6 min-h-6 min-w-6 max-w-6 cursor-pointer fill-[var(--theme-text-color-light)] dark:fill-[var(--theme-text-color-dark)];
+ @apply fill-primary inline-block max-h-6 min-h-6 min-w-6 max-w-6 cursor-pointer;
}
.tk-action-icon {
- @apply inline-block max-h-5 min-h-5 min-w-5 max-w-5 overflow-clip fill-[var(--theme-text-color-light)] dark:fill-[var(--theme-text-color-dark)];
+ @apply fill-primary inline-block max-h-5 min-h-5 min-w-5 max-w-5 overflow-clip;
}
.tk-icon {
- @apply inline-block max-h-4 min-h-4 min-w-4 max-w-4 overflow-clip fill-[var(--theme-text-color-light)] dark:fill-[var(--theme-text-color-dark)];
+ @apply fill-primary inline-block max-h-4 min-h-4 min-w-4 max-w-4 overflow-clip;
}
.tk-tag {
- @apply theme-border rounded-lg border-2 p-1 text-xs;
+ @apply border-base-300 rounded-lg border-2 p-1 text-xs;
}
}
@@ -299,7 +299,7 @@
@apply mt-4 w-full text-right text-sm;
a {
- @apply text-[var(--theme-color-light)] dark:text-[var(--theme-color-dark)];
+ @apply text-primary;
}
}
@@ -314,7 +314,7 @@
@apply relative flex h-full w-full items-center justify-center text-center;
.tk-admin-close {
- @apply absolute right-2 top-[0.65rem] z-50 h-8 w-8 fill-[var(--theme-text-color-light)] p-2 dark:fill-[var(--theme-text-color-dark)];
+ @apply fill-primary absolute right-2 top-[0.65rem] z-50 h-8 w-8;
}
> div {
@@ -342,18 +342,18 @@
}
a {
- @apply theme-border theme-card-bg hover:theme-card-bg-hl mx-6 rounded-xl border-2 px-3 py-1 text-xs duration-300;
+ @apply border-base-300 bg-base-200/50 hover:bg-primary mx-6 rounded-xl border-2 px-3 py-1 text-xs duration-300;
}
}
.tk-tabs {
- @apply theme-border flex flex-row items-center justify-between border-b-2 px-4 text-center text-lg;
+ @apply border-base-300 flex flex-row items-center justify-between border-b-2 px-4 text-center text-lg;
.tk-tab {
- @apply hover:theme-card-bg-hl w-full cursor-pointer py-1 duration-300;
+ @apply hover:bg-primary w-full cursor-pointer py-1 duration-300;
&.__active {
- @apply theme-border-hl border-b-2;
+ @apply border-primary border-b-2;
}
}
}
@@ -378,7 +378,7 @@
@apply w-full;
input {
- @apply theme-border theme-card-bg w-full rounded-xl border-2 px-2 py-1;
+ @apply border-base-300 bg-base-200/50 w-full rounded-xl border-2 px-2 py-1;
&:focus {
outline: none;
@@ -387,7 +387,7 @@
}
select {
- @apply theme-border theme-card-bg w-1/4 rounded-xl border-2 p-2;
+ @apply border-base-300 bg-base-200/50 w-1/4 rounded-xl border-2 p-2;
}
}
@@ -396,23 +396,23 @@
}
.tk-admin-comment-item {
- @apply theme-border border-b-2 py-1;
+ @apply border-base-300 border-b-2 py-1;
}
.tk-admin-comment-meta {
@apply flex flex-row flex-wrap items-center gap-2 text-start;
.tk-avatar {
- @apply theme-border h-8 w-8 overflow-hidden rounded-full border-2;
+ @apply border-base-300 h-8 w-8 overflow-hidden rounded-full border-2;
}
a {
- @apply hover:theme-text-hl duration-300;
+ @apply hover:text-primary duration-300;
}
span:last-child,
.tk-time {
- @apply theme-text-second text-sm;
+ @apply text-base-content/50 text-sm;
}
}
@@ -424,7 +424,7 @@
}
input {
- @apply theme-border theme-card-bg w-16 rounded-xl border-2 px-2 py-1;
+ @apply border-base-300 bg-base-200/50 w-16 rounded-xl border-2 px-2 py-1;
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
@@ -442,10 +442,10 @@
}
.tk-pagination-pager {
- @apply hover:theme-card-bg-hl cursor-pointer rounded-md px-2 py-1;
+ @apply hover:bg-primary cursor-pointer rounded-md px-2 py-1;
&.__current {
- @apply theme-card-bg-hl;
+ @apply bg-primary;
}
}
@@ -459,10 +459,10 @@
}
details {
- @apply theme-border w-full overflow-hidden rounded-xl border-2 duration-300;
+ @apply border-base-300 w-full overflow-hidden rounded-xl border-2 duration-300;
summary {
- @apply hover:theme-card-bg-hl-trans w-full px-3 py-1 text-start text-2xl duration-300;
+ @apply hover:bg-primary/50 w-full px-3 py-1 text-start text-2xl duration-300;
&::marker {
margin-right: 1.5rem;
@@ -471,7 +471,7 @@
&[open] {
summary {
- @apply theme-card-bg-hl-trans;
+ @apply bg-primary/50;
}
}
}
@@ -486,7 +486,7 @@
}
input {
- @apply theme-border theme-card-bg w-full rounded-xl border-2 px-2 py-1;
+ @apply border-base-300 bg-base-200/50 w-full rounded-xl border-2 px-2 py-1;
&:focus {
outline: none;
@@ -494,7 +494,7 @@
}
.tk-admin-config-desc {
- @apply theme-text-second whitespace-pre-wrap text-start text-sm;
+ @apply text-base-content/50 whitespace-pre-wrap text-start text-sm;
}
}
@@ -507,11 +507,11 @@
}
select {
- @apply theme-border theme-card-bg w-full rounded-xl border-2 p-2;
+ @apply border-base-300 bg-base-200/50 w-full rounded-xl border-2 p-2;
}
input {
- @apply theme-border theme-card-bg w-full rounded-xl border-2 px-2 py-1;
+ @apply border-base-300 bg-base-200/50 w-full rounded-xl border-2 px-2 py-1;
&:focus {
outline: none;
@@ -522,7 +522,7 @@
@apply h-full w-full;
textarea {
- @apply theme-border theme-card-bg h-full w-full rounded-xl border-2 px-2 py-1;
+ @apply border-base-300 bg-base-200/50 h-full w-full rounded-xl border-2 px-2 py-1;
&:focus {
outline: none;
@@ -539,10 +539,10 @@
}
.el-input-group {
- @apply theme-card-bg theme-border flex w-full flex-row items-center overflow-hidden rounded-xl border-2 text-sm;
+ @apply bg-base-200/50 border-base-300 flex w-full flex-row items-center overflow-hidden rounded-xl border-2 text-sm;
div {
- @apply theme-card-bg-hl-trans w-fit whitespace-nowrap px-2 py-1;
+ @apply bg-primary/50 w-fit whitespace-nowrap px-2 py-1;
}
input {
@@ -559,7 +559,7 @@
}
.el-button {
- @apply theme-border theme-card-bg-hl text-nowrap rounded-xl border-2 px-2 py-1 text-center text-sm duration-300;
+ @apply border-base-300 bg-primary text-nowrap rounded-xl border-2 px-2 py-1 text-center text-sm duration-300;
&:not(.is-disabled) {
@apply hover:scale-105 hover:brightness-110 active:scale-95 active:brightness-90;
@@ -592,7 +592,7 @@
}
a {
- @apply text-[var(--theme-color-light-darken)] underline decoration-dashed dark:text-[var(--theme-color-dark-lighten)];
+ @apply text-primary underline decoration-dashed;
&[data-footnote-ref],
&[data-footnote-backref] {
@@ -609,7 +609,7 @@
}
.copy-to-clipboard-button {
- @apply theme-border theme-card-bg-hl rounded-md border-2 px-2 py-1 opacity-0 duration-300;
+ @apply border-base-300 bg-primary rounded-md border-2 px-2 py-1 opacity-0 duration-300;
}
&:hover .copy-to-clipboard-button {
@@ -624,7 +624,7 @@
code:not(pre code) {
padding: 0 0.25rem;
- @apply theme-text-hl-contrast rounded-md bg-[var(--theme-color-light-trans-1d8)] dark:bg-[var(--theme-color-dark-trans-1d8)];
+ @apply text-primary bg-primary/10 rounded-md;
}
// 媒体元素
@@ -651,15 +651,15 @@
blockquote {
padding: 0.25rem 0.25rem 0.25rem 0.75rem;
- @apply theme-border-hl my-2 rounded-sm border-l-4 bg-[var(--theme-color-light-trans-1d8)] dark:bg-[var(--theme-color-dark-trans-1d8)];
+ @apply border-primary bg-primary/10 my-2 rounded-sm border-l-4;
}
// 折叠块样式
details {
- @apply theme-border w-full overflow-hidden rounded-xl border-2 duration-300;
+ @apply border-base-300 w-full overflow-hidden rounded-xl border-2 duration-300;
summary {
- @apply hover:theme-card-bg-hl-trans w-full px-3 py-1 text-start text-2xl duration-300;
+ @apply hover:bg-primary/50 w-full px-3 py-1 text-start text-2xl duration-300;
&::marker {
margin-right: 1.5rem;
@@ -668,7 +668,7 @@
&[open] {
summary {
- @apply theme-card-bg-hl-trans;
+ @apply bg-primary/50;
}
}
}
src/styles/variables.scss
@@ -1,12 +0,0 @@
-$theme-color-light: #f69279;
-$theme-color-dark: #2e6c8b;
-$theme-bg-color-light: theme('colors.neutral.50');
-$theme-bg-color-dark: theme('colors.neutral.900');
-$theme-card-bg-color-light: $theme-bg-color-light;
-$theme-card-bg-color-dark: $theme-bg-color-dark;
-$theme-text-color-light: theme('colors.neutral.900');
-$theme-text-color-dark: theme('colors.neutral.100');
-$theme-text-color-secondary-light: theme('colors.neutral.600');
-$theme-text-color-secondary-dark: theme('colors.neutral.400');
-$theme-border-color-light: theme('colors.neutral.200');
-$theme-border-color-dark: theme('colors.neutral.800');
src/config.ts
@@ -10,7 +10,7 @@ import type {
ToolBarConfig,
} from './types/config';
import I18nKey from '@i18n/I18nKey';
-import { getRandomPost, toggleSearch } from '@scripts/utils';
+import { getRandomPost } from '@scripts/utils';
export const siteConfig: SiteConfig = {
title: 'Astral Halo',
@@ -65,10 +65,7 @@ export const navbarConfig: NavbarConfig = {
{
icon: 'material-symbols:search-rounded',
text: I18nKey.search,
- onclick: {
- id: 'search-btn',
- function: toggleSearch,
- },
+ onclick: 'search_modal.showModal()',
},
],
},
package.json
@@ -23,6 +23,7 @@
"astro-icon": "^1.1.5",
"astro-pagefind": "^1.8.0",
"autoprefixer": "^10.4.20",
+ "daisyui": "^4.12.23",
"postcss-load-config": "^6.0.1",
"sass": "^1.83.4",
"sharp": "^0.33.5",
tailwind.config.mjs
@@ -1,3 +1,6 @@
+import daisyui from 'daisyui';
+import themes from 'daisyui/src/theming/themes';
+
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
@@ -8,6 +11,29 @@ export default {
},
},
},
- darkMode: 'selector',
- plugins: [],
+ darkMode: ['selector', '[data-theme="dark"]'],
+ plugins: [daisyui],
+ daisyui: {
+ base: false,
+ themes: [
+ {
+ light: {
+ ...themes['light'],
+ primary: '#BC4D2E',
+ 'primary-content': '#ffffff',
+ secondary: '#626437',
+ 'secondary-content': '#ffffff',
+ accent: '#512620',
+ },
+ dark: {
+ ...themes['dark'],
+ primary: '#3C8CC7',
+ 'primary-content': '#ffffff',
+ secondary: '#DB446B',
+ 'secondary-content': '#ffffff',
+ accent: '#D29F60',
+ },
+ },
+ ],
+ },
};