build(deps): upgrade TailwindCSS to v4

- Upgrade TailwindCSS to v4
- Upgrade daisyUI to v5 beta.
- Delete the PostCSS TailwindCSS compatibility layer.
- Delete Sass dependency because TailwindCSS v4 will generate nested CSS, so we don't need Sass anymore.
This commit is contained in:
HPCesia 2025-02-07 21:39:05 +08:00
parent 2cc5107c7f
commit 8a8bf19e35
35 changed files with 251 additions and 299 deletions

View File

@ -5,7 +5,7 @@ import { remarkExcerpt } from './src/plugins/remark-excerpt';
import { remarkReadingTime } from './src/plugins/remark-reading-time.mjs'; import { remarkReadingTime } from './src/plugins/remark-reading-time.mjs';
import { rehypeHeadingIds } from '@astrojs/markdown-remark'; import { rehypeHeadingIds } from '@astrojs/markdown-remark';
import sitemap from '@astrojs/sitemap'; import sitemap from '@astrojs/sitemap';
import tailwind from '@astrojs/tailwind'; import tailwindcss from '@tailwindcss/vite';
import icon from 'astro-icon'; import icon from 'astro-icon';
import pagefind from 'astro-pagefind'; import pagefind from 'astro-pagefind';
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
@ -21,7 +21,6 @@ export default defineConfig({
output: 'static', output: 'static',
trailingSlash: 'ignore', trailingSlash: 'ignore',
integrations: [ integrations: [
tailwind({ nesting: true, applyBaseStyles: false }),
icon(), icon(),
sitemap({ filter: (page) => !page.includes('/archives/') && !page.includes('/about/') }), sitemap({ filter: (page) => !page.includes('/archives/') && !page.includes('/about/') }),
pagefind(), pagefind(),
@ -76,4 +75,7 @@ export default defineConfig({
rehypeWrapTables, rehypeWrapTables,
], ],
}, },
vite: {
plugins: [tailwindcss()],
},
}); });

View File

@ -16,15 +16,15 @@
"@astrojs/markdown-remark": "^6.1.0", "@astrojs/markdown-remark": "^6.1.0",
"@astrojs/rss": "^4.0.11", "@astrojs/rss": "^4.0.11",
"@astrojs/sitemap": "^3.2.1", "@astrojs/sitemap": "^3.2.1",
"@astrojs/tailwind": "^5.1.5",
"@iconify-json/material-symbols": "^1.2.14", "@iconify-json/material-symbols": "^1.2.14",
"@iconify-json/mdi": "^1.2.3", "@iconify-json/mdi": "^1.2.3",
"@tailwindcss/vite": "^4.0.4",
"astro": "^5.2.5", "astro": "^5.2.5",
"astro-compress": "2.3.5", "astro-compress": "2.3.5",
"astro-icon": "^1.1.5", "astro-icon": "^1.1.5",
"astro-pagefind": "^1.8.0", "astro-pagefind": "^1.8.0",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"daisyui": "^4.12.23", "daisyui": "5.0.0-beta.7",
"mdast-util-to-string": "^4.0.0", "mdast-util-to-string": "^4.0.0",
"postcss-load-config": "^6.0.1", "postcss-load-config": "^6.0.1",
"reading-time": "^1.5.0", "reading-time": "^1.5.0",
@ -32,9 +32,8 @@
"rehype-mathjax": "^6.0.0", "rehype-mathjax": "^6.0.0",
"remark-github-beta-blockquote-admonitions": "^3.1.1", "remark-github-beta-blockquote-admonitions": "^3.1.1",
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"sass": "^1.84.0",
"sharp": "^0.33.5", "sharp": "^0.33.5",
"tailwindcss": "^3.4.17", "tailwindcss": "^4.0.4",
"typescript": "^5.7.3", "typescript": "^5.7.3",
"unist-util-visit": "^5.0.0" "unist-util-visit": "^5.0.0"
}, },
@ -55,7 +54,6 @@
"prettier-plugin-tailwindcss": "^0.6.11", "prettier-plugin-tailwindcss": "^0.6.11",
"stylelint": "^16.14.1", "stylelint": "^16.14.1",
"stylelint-config-html": "^1.1.0", "stylelint-config-html": "^1.1.0",
"stylelint-config-standard-scss": "^14.0.0",
"typescript-eslint": "^8.23.0" "typescript-eslint": "^8.23.0"
} }
} }

View File

@ -1,12 +0,0 @@
import postcssImport from 'postcss-import';
import tailwindcss from 'tailwindcss';
import postcssNesting from 'tailwindcss/nesting/index.js';
/** @type {import('postcss-load-config').Config} */
export default {
plugins: {
'postcss-import': postcssImport, // to combine multiple css files
'tailwindcss/nesting': postcssNesting,
tailwindcss: tailwindcss,
},
};

View File

@ -19,7 +19,7 @@ if (!title) title = 'Astral Halo';
<!-- Navbar --> <!-- Navbar -->
<div <div
id="navbar" id="navbar"
class="navbar fixed z-20 flex h-16 w-full items-center bg-base-200/50 backdrop-blur-md" class="navbar bg-base-200/50 fixed z-20 flex h-16 w-full items-center backdrop-blur-md"
> >
<div class="navbar-start"> <div class="navbar-start">
<Button id="site-name" href="/" class="group btn-ghost"> <Button id="site-name" href="/" class="group btn-ghost">
@ -94,7 +94,7 @@ if (!title) title = 'Astral Halo';
<div class="drawer-side z-50"> <div class="drawer-side z-50">
<!-- Sidebar --> <!-- Sidebar -->
<label for="sidebar-drawer" class="drawer-overlay"></label> <label for="sidebar-drawer" class="drawer-overlay"></label>
<ul class="menu min-h-full w-[min(calc(100%-3rem),20rem)] bg-base-200 p-4"> <ul class="menu bg-base-200 min-h-full w-[min(calc(100%-3rem),20rem)] p-4">
<li><DarkModeButton class="btn-ghost text-xl" showText={true} /></li> <li><DarkModeButton class="btn-ghost text-xl" showText={true} /></li>
{ {
navbarConfig.navbarCenterItems.map((item) => ( navbarConfig.navbarCenterItems.map((item) => (

View File

@ -4,9 +4,9 @@ import { footerConfig, profileConfig } from '@/config';
const currentYear = new Date().getFullYear(); const currentYear = new Date().getFullYear();
--- ---
<footer class="footer mt-auto flex-shrink-0"></footer> <footer class="footer mt-auto shrink-0"></footer>
<footer <footer
class="footer border-t border-base-300 bg-base-200 px-10 py-4 text-base text-base-content" class="footer border-base-300 bg-base-200 text-base-content flex flex-col justify-between border-t px-10 py-4 text-lg md:flex-row"
> >
<aside class="items-center"> <aside class="items-center">
<p> <p>
@ -16,7 +16,7 @@ const currentYear = new Date().getFullYear();
<a href="/about/" class="font-bold">{profileConfig.name}</a> <a href="/about/" class="font-bold">{profileConfig.name}</a>
</p> </p>
</aside> </aside>
<nav class="flex flex-row md:place-self-center md:justify-self-end"> <nav class="flex flex-row">
{ {
footerConfig.rightItems.map((item) => ( footerConfig.rightItems.map((item) => (
<span> <span>
@ -36,12 +36,12 @@ const currentYear = new Date().getFullYear();
</nav> </nav>
</footer> </footer>
<style lang="scss"> <style>
a { a {
@apply duration-150; @apply duration-150;
&:hover { &:hover {
@apply text-primary; color: var(--color-primary);
} }
} }
</style> </style>

View File

@ -7,7 +7,7 @@ import Pagefind from './search/Pagefind.astro';
<dialog id="search_modal" class="modal" transition:persist> <dialog id="search_modal" class="modal" transition:persist>
<div class="modal-box border-base-200 bg-base-300"> <div class="modal-box border-base-200 bg-base-300">
<form method="dialog"> <form method="dialog">
<button class="btn btn-circle btn-ghost btn-sm absolute right-2 top-2">✕</button> <button class="btn btn-circle btn-ghost btn-sm absolute top-2 right-2">✕</button>
</form> </form>
<div class="w-full p-4"> <div class="w-full p-4">
{ {
@ -21,7 +21,7 @@ import Pagefind from './search/Pagefind.astro';
})() })()
} }
</div> </div>
<div class="relative mt-auto w-full flex-shrink-0 pt-4 text-center"> <div class="relative mt-auto w-full shrink-0 pt-4 text-center">
Powered by { Powered by {
searchConfig.provider === 'pagefind' ? ( searchConfig.provider === 'pagefind' ? (
<a href="https://pagefind.app" target="_blank" class="text-primary"> <a href="https://pagefind.app" target="_blank" class="text-primary">

View File

@ -5,7 +5,7 @@ import Button from './widgets/Button.astro';
import DarkModeButton from './widgets/DarkModeButton.astro'; import DarkModeButton from './widgets/DarkModeButton.astro';
--- ---
<div id="side-toolbar" class="fixed bottom-10 right-0 z-30 grid grid-cols-1 gap-2"> <div id="side-toolbar" class="fixed right-0 bottom-10 z-30 grid grid-cols-1 gap-2">
<div <div
id="stb-hide" id="stb-hide"
class="grid translate-x-full grid-cols-1 gap-2 pr-4 duration-500 ease-in-out" class="grid translate-x-full grid-cols-1 gap-2 pr-4 duration-500 ease-in-out"
@ -24,7 +24,7 @@ import DarkModeButton from './widgets/DarkModeButton.astro';
{ {
articleConfig.toc && ( articleConfig.toc && (
<Fragment> <Fragment>
<Button id="stb-toc" class="btn-circle btn-primary btn-sm hidden xl:!hidden"> <Button id="stb-toc" class="btn-circle btn-primary btn-sm hidden xl:hidden!">
<Icon name="material-symbols:toc-rounded" /> <Icon name="material-symbols:toc-rounded" />
</Button> </Button>
<div <div

View File

@ -25,7 +25,7 @@ const { group } = Astro.props;
<Timeline items={group.months} class="ml-4"> <Timeline items={group.months} class="ml-4">
<fragment slot="title"> <fragment slot="title">
{(monthGroup: MonthArchives) => ( {(monthGroup: MonthArchives) => (
<div class="mb-6 ml-6 mt-3 flex items-center justify-between"> <div class="mt-3 mb-6 ml-6 flex items-center justify-between">
<h2 class="text-2xl font-bold">{monthGroup.month}</h2> <h2 class="text-2xl font-bold">{monthGroup.month}</h2>
</div> </div>
)} )}

View File

@ -38,36 +38,18 @@ const renderedItems = await Promise.all(
); );
--- ---
<div class:list={['relative flex flex-col', className]}> <div class:list={['relative flex flex-col empty:min-h-12', className]}>
<div <div
class="timeline absolute left-4 top-0 h-full w-0.5 bg-gradient-to-b from-blue-500 to-purple-500" class="timeline absolute top-0 left-4 h-full w-0.5 bg-linear-to-b from-blue-500 to-purple-500 opacity-60"
> >
</div> </div>
{ {
renderedItems.map((item) => ( renderedItems.map((item) => (
<div class="relative mb-12 pl-12"> <div class="relative mb-12 pl-12">
<div class="timeline-dot absolute left-2 top-5 h-4 w-4 rounded-full bg-blue-500" /> <div class="absolute top-5 left-2 h-4 w-4 rounded-full bg-blue-500 shadow-lg transition-transform duration-300 hover:scale-125" />
<Fragment set:html={item.title} /> <Fragment set:html={item.title} />
<Fragment set:html={item.body} /> <Fragment set:html={item.body} />
</div> </div>
)) ))
} }
</div> </div>
<style>
.flex-col:empty {
@apply min-h-[3rem];
}
.timeline {
@apply opacity-60;
}
.timeline-dot {
@apply shadow-lg transition-transform duration-300;
}
.timeline-dot:hover {
@apply scale-125;
}
</style>

View File

@ -1,5 +1,5 @@
--- ---
import '@/styles/twikoo.scss'; import '@/styles/twikoo.css';
import { CDN } from '@constants/cdn.mjs'; import { CDN } from '@constants/cdn.mjs';
--- ---

View File

@ -10,7 +10,7 @@ interface Props {
const { categories, currentCategory } = Astro.props; const { categories, currentCategory } = Astro.props;
--- ---
<div id="category-bar" class="card card-bordered mb-4 w-full border-2"> <div id="category-bar" class="card card-bordered border-base-300 mb-4 w-full border-2">
<div class="card-body flex flex-row items-center gap-2 overflow-auto px-2 py-3"> <div class="card-body flex flex-row items-center gap-2 overflow-auto px-2 py-3">
<a <a
href={`/`} href={`/`}

View File

@ -29,7 +29,7 @@ const infomations = [
]; ];
--- ---
<div class="card card-bordered my-4 border-2 bg-primary/25"> <div class="card card-bordered border-base-300 bg-primary/25 my-4 border-2">
<div class="card-body grid grid-cols-2 gap-x-4 p-4"> <div class="card-body grid grid-cols-2 gap-x-4 p-4">
{ {
infomations.map((info) => ( infomations.map((info) => (

View File

@ -12,13 +12,10 @@ const bundlePath = `${import.meta.env.BASE_URL}pagefind/`;
/> />
<template id="pagefind-result-template"> <template id="pagefind-result-template">
<a <a class="group hover:bg-primary/30 w-full rounded-md p-2 duration-150" href="#">
class="group w-full rounded-md p-2 duration-150 hover:bg-primary hover:bg-opacity-30"
href="#"
>
<div class="flex flex-row items-center gap-1 text-center"> <div class="flex flex-row items-center gap-1 text-center">
<span class="text-lg duration-150 group-hover:text-primary">Fake Result</span> <span class="group-hover:text-primary text-lg duration-150">Fake Result</span>
<Icon name="material-symbols:chevron-right" class="text-lg text-primary" /> <Icon name="material-symbols:chevron-right" class="text-primary text-lg" />
</div> </div>
<div id="pagefind-result-template-excerpt" class="text-sm opacity-60"> <div id="pagefind-result-template-excerpt" class="text-sm opacity-60">
This is a fake result. This is a fake result.
@ -81,7 +78,6 @@ const bundlePath = `${import.meta.env.BASE_URL}pagefind/`;
<style is:global> <style is:global>
[data-pagefind-ui] mark { [data-pagefind-ui] mark {
background-color: transparent; background-color: transparent;
color: var(--color-secondary);
@apply text-secondary;
} }
</style> </style>

View File

@ -1,5 +1,5 @@
--- ---
import '@/styles/markdown.scss'; import '@/styles/markdown.css';
import Button from '@components/widgets/Button.astro'; import Button from '@components/widgets/Button.astro';
import { isFirstInstance } from '@utils/component-utils'; import { isFirstInstance } from '@utils/component-utils';
import { Icon } from 'astro-icon/components'; import { Icon } from 'astro-icon/components';
@ -23,9 +23,9 @@ const firstHasPre = hasPre && (isFirstInstance('md-has-pre', Astro.url) || impor
firstHasPre && ( firstHasPre && (
<template <template
id="code-toolbar-template" id="code-toolbar-template"
class="code-block-wrapper collapse collapse-open relative my-4" class="code-block-wrapper collapse-open collapse relative my-4"
> >
<div class="z-10 flex items-center justify-between bg-primary/60 text-primary-content"> <div class="bg-primary/60 text-primary-content z-10 flex items-center justify-between">
<Button class="toggle-btn btn-ghost rounded-bl-none"> <Button class="toggle-btn btn-ghost rounded-bl-none">
<Icon <Icon
name="material-symbols:keyboard-arrow-down-rounded" name="material-symbols:keyboard-arrow-down-rounded"

View File

@ -9,7 +9,7 @@ const { class: className, ...rest } = Astro.props;
<Icon {...rest} class:list={['meta-icon', className]} /> <Icon {...rest} class:list={['meta-icon', className]} />
<style lang="scss"> <style>
.meta-icon { .meta-icon {
width: 1.5rem; width: 1.5rem;
height: 1.5rem; height: 1.5rem;
@ -17,7 +17,6 @@ const { class: className, ...rest } = Astro.props;
margin-right: 0.5rem; margin-right: 0.5rem;
display: flex; display: flex;
justify-content: center; justify-content: center;
color: var(--color-text-primary);
@apply text-primary;
} }
</style> </style>

View File

@ -101,7 +101,7 @@ else {
} }
</div> </div>
<style lang="scss"> <style>
/* hide arrows from number input */ /* hide arrows from number input */
input::-webkit-outer-spin-button, input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button { input::-webkit-inner-spin-button {

View File

@ -48,15 +48,13 @@ const metas: ({ icon: string; text: string; link?: string } | undefined)[] = [
<div <div
class:list={[ class:list={[
'card card-bordered flex w-full rounded-xl border-2 md:card-side max-md:flex-col-reverse', 'card card-bordered border-base-300 md:card-side flex w-full rounded-xl border-2 max-md:flex-col-reverse',
className, className,
]} ]}
> >
<div class="card-body"> <div class="card-body">
<a href={url} class="card-title">{title}</a> <a href={url} class="card-title">{title}</a>
<div <div class="text-base-content/60 mb-3 flex flex-wrap items-center gap-x-4 gap-y-2 text-sm">
class="mb-3 flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-base-content text-opacity-60"
>
{ {
metas.map((meta) => { metas.map((meta) => {
return ( return (

View File

@ -11,23 +11,15 @@ interface Props {
const { url, title, cover } = Astro.props; const { url, title, cover } = Astro.props;
--- ---
<a href={url} title={title} class="group"> <a
<div class="cover-mask"> href={url}
<Icon name="material-symbols:chevron-right-rounded" /> title={title}
class="group relative flex min-h-48 w-full overflow-hidden duration-100 active:brightness-75"
>
<div
class="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"
>
<Icon name="material-symbols:chevron-right-rounded" class="h-24 w-24 text-white" />
</div> </div>
<ImageWrapper src={cover} alt={title} /> <ImageWrapper src={cover} alt={title} />
</a> </a>
<style>
a {
@apply relative flex min-h-48 w-full overflow-hidden duration-100 active:brightness-75;
}
div.cover-mask {
@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 {
@apply h-24 w-24 text-white;
}
</style>

View File

@ -5,7 +5,11 @@ import { Icon } from 'astro-icon/components';
import Button from './Button.astro'; import Button from './Button.astro';
--- ---
<div id="profile-card" transition:name="profile-card" class="card card-bordered border-2"> <div
id="profile-card"
transition:name="profile-card"
class="card card-bordered border-base-300 border-2"
>
<figure class="px-4 pt-4"> <figure class="px-4 pt-4">
<a href="/about/"> <a href="/about/">
<ImageWrapper class="rounded-xl" src={profileConfig.avatar} alt={profileConfig.name} /> <ImageWrapper class="rounded-xl" src={profileConfig.avatar} alt={profileConfig.name} />

View File

@ -4,21 +4,19 @@ import { i18n } from '@i18n/translation';
import { Icon } from 'astro-icon/components'; import { Icon } from 'astro-icon/components';
import type { ComponentProps } from 'astro/types'; import type { ComponentProps } from 'astro/types';
type Props = Omit<ComponentProps<typeof Icon>, 'name'>; type Props = Omit<ComponentProps<typeof Icon>, 'name' | 'class'>;
const { href, title, ...rest } = Astro.props; const { href, title, ...rest } = Astro.props;
--- ---
<a href={href} title={title || i18n(I18nKey.more)}> <a
<Icon name="material-symbols:chevron-right-rounded" {...rest} /> href={href}
title={title || i18n(I18nKey.more)}
class="duration-150 hover:brightness-125 active:brightness-75 max-md:hidden"
>
<Icon
name="material-symbols:chevron-right-rounded"
{...rest}
class="bg-primary/40 text-primary h-full min-h-48 w-12"
/>
</a> </a>
<style>
a {
@apply duration-150 hover:brightness-125 active:brightness-75 max-md:hidden;
}
svg {
@apply h-full min-h-48 w-12 bg-primary/40 text-primary;
}
</style>

View File

@ -13,7 +13,7 @@ const maxLevel = 3;
<div <div
id="toc" id="toc"
class:list={['card card-bordered border-2 bg-base-100', className]} class:list={['card card-bordered border-base-300 bg-base-100 border-2', className]}
transition:name="toc-card" transition:name="toc-card"
> >
<div class="card-body p-2"> <div class="card-body p-2">
@ -29,21 +29,15 @@ const maxLevel = 3;
</div> </div>
</div> </div>
<style lang="scss"> <style>
$max-level: 3; $max-level: 3;
a { a {
display: block; display: block;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
@apply duration-200 ease-in-out; @apply duration-200;
@apply hover:scale-105; @apply hover:scale-105;
@apply active:scale-95; @apply active:scale-95;
@for $i from 1 through $max-level {
&.level-#{$i} {
padding-left: #{($i - 1) * 0.5 + 1}rem;
}
}
} }
</style> </style>

View File

@ -1,5 +1,6 @@
--- ---
import { profileConfig, siteConfig } from '@/config'; import { profileConfig, siteConfig } from '@/config';
import '@/styles/global.css';
import { ClientRouter } from 'astro:transitions'; import { ClientRouter } from 'astro:transitions';
interface Props { interface Props {
@ -46,7 +47,7 @@ const siteLang = lang.replace('_', '-');
<slot name="head" /> <slot name="head" />
</head> </head>
<body class="flex min-h-screen flex-col bg-base-100 text-base-content"> <body class="bg-base-100 text-base-content flex min-h-screen flex-col">
<slot /> <slot />
</body> </body>
</html> </html>
@ -65,7 +66,3 @@ const siteLang = lang.replace('_', '-');
document.addEventListener('astro:after-swap', applyDarkMode); document.addEventListener('astro:after-swap', applyDarkMode);
applyDarkMode(); applyDarkMode();
</script> </script>
<style is:global lang="scss">
@use '../styles/globals';
</style>

View File

@ -10,7 +10,7 @@ const { title, description, lang } = Astro.props;
--- ---
<MainLayout title={title} description={description} lang={lang}> <MainLayout title={title} description={description} lang={lang}>
<div class="mx-auto flex max-w-screen-xl flex-col gap-4"> <div class="mx-auto flex max-w-(--breakpoint-xl) flex-col gap-4">
<slot name="header-content" /> <slot name="header-content" />
<div class="flex gap-4"> <div class="flex gap-4">
<div id="main-content" class="my-4 w-full"> <div id="main-content" class="my-4 w-full">

View File

@ -15,7 +15,7 @@ const { Content } = aboutMd ? await render(aboutMd) : Fragment;
--- ---
<MainLayout title={i18n(I18nKey.about)}> <MainLayout title={i18n(I18nKey.about)}>
<div class="mx-auto flex max-w-screen-xl flex-col items-center justify-center"> <div class="mx-auto flex max-w-(--breakpoint-xl) flex-col items-center justify-center">
<div class="hero my-4 w-5/6 md:w-2/3"> <div class="hero my-4 w-5/6 md:w-2/3">
<div class="hero-content flex-col-reverse md:flex-row"> <div class="hero-content flex-col-reverse md:flex-row">
<div class="mr-auto flex flex-col"> <div class="mr-auto flex flex-col">

View File

@ -23,7 +23,7 @@ if (uncategorizedPosts.length > 0)
--- ---
<MainLayout title={i18n(I18nKey.categories)}> <MainLayout title={i18n(I18nKey.categories)}>
<div class="mx-auto flex max-w-screen-xl flex-col items-center"> <div class="mx-auto flex max-w-(--breakpoint-xl) flex-col items-center">
<h1 class="my-8 text-3xl font-bold">{i18n(I18nKey.categories)}</h1> <h1 class="my-8 text-3xl font-bold">{i18n(I18nKey.categories)}</h1>
<Timeline items={Array.from(categoryPosts.keys())}> <Timeline items={Array.from(categoryPosts.keys())}>
<fragment slot="title"> <fragment slot="title">
@ -34,7 +34,7 @@ if (uncategorizedPosts.length > 0)
<Button <Button
href={`/archives/categories/${category === i18n(I18nKey.uncategorized) ? I18nKey.uncategorized : category.replaceAll(/[\\/]/g, '-')}/1/`} href={`/archives/categories/${category === i18n(I18nKey.uncategorized) ? I18nKey.uncategorized : category.replaceAll(/[\\/]/g, '-')}/1/`}
title={category} title={category}
class="!pl-3" class="pl-3!"
> >
{i18n(I18nKey.more)} {i18n(I18nKey.more)}
<Icon name="material-symbols:chevron-right-rounded" class="text-2xl" /> <Icon name="material-symbols:chevron-right-rounded" class="text-2xl" />

View File

@ -36,7 +36,7 @@ const { tag } = Astro.params;
--- ---
<GridLayout title={tag}> <GridLayout title={tag}>
<div class="mx-auto flex max-w-screen-xl flex-col items-center"> <div class="mx-auto flex max-w-(--breakpoint-xl) flex-col items-center">
<h1 class="my-8 text-3xl font-bold">{tag}</h1> <h1 class="my-8 text-3xl font-bold">{tag}</h1>
</div> </div>
<PostPage posts={posts} currentPage={currentPage} baseUrl={`/archives/tags/${tag}`} /> <PostPage posts={posts} currentPage={currentPage} baseUrl={`/archives/tags/${tag}`} />

View File

@ -24,7 +24,7 @@ if (untaggedPosts.length > 0) tagPosts.set(i18n(I18nKey.untagged) as string, unt
--- ---
<MainLayout title={i18n(I18nKey.tags)}> <MainLayout title={i18n(I18nKey.tags)}>
<div class="mx-auto flex max-w-screen-xl flex-col items-center"> <div class="mx-auto flex max-w-(--breakpoint-xl) flex-col items-center">
<h1 class="my-8 text-3xl font-bold">{i18n(I18nKey.tags)}</h1> <h1 class="my-8 text-3xl font-bold">{i18n(I18nKey.tags)}</h1>
<Timeline items={Array.from(tagPosts.keys())}> <Timeline items={Array.from(tagPosts.keys())}>
<fragment slot="title"> <fragment slot="title">
@ -35,7 +35,7 @@ if (untaggedPosts.length > 0) tagPosts.set(i18n(I18nKey.untagged) as string, unt
<Button <Button
href={`/archives/tags/${tag === i18n(I18nKey.untagged) ? I18nKey.untagged : tag.replaceAll(/[\\/]/g, '-')}/1/`} href={`/archives/tags/${tag === i18n(I18nKey.untagged) ? I18nKey.untagged : tag.replaceAll(/[\\/]/g, '-')}/1/`}
title={tag} title={tag}
class="!pl-3" class="pl-3!"
> >
{i18n(I18nKey.more)} {i18n(I18nKey.more)}
<Icon name="material-symbols:chevron-right-rounded" class="text-2xl" /> <Icon name="material-symbols:chevron-right-rounded" class="text-2xl" />

View File

@ -35,7 +35,7 @@ const description = article.data.description || remarkPluginFrontmatter.excerpt;
class="mx-2 mt-4" class="mx-2 mt-4"
/> />
</Fragment> </Fragment>
<div class="card card-bordered rounded-xl border-2 px-6 py-4"> <div class="card card-bordered border-base-300 rounded-xl border-2 px-6 py-4">
<Markdown> <Markdown>
<Content /> <Content />
</Markdown> </Markdown>

View File

@ -1,16 +1,16 @@
import { toString } from 'mdast-util-to-string' import { toString } from 'mdast-util-to-string';
/* Use the post's first paragraph as the excerpt */ /* Use the post's first paragraph as the excerpt */
export function remarkExcerpt() { export function remarkExcerpt() {
return (tree, { data }) => { return (tree, { data }) => {
let excerpt = '' let excerpt = '';
for (let node of tree.children) { for (let node of tree.children) {
if (node.type !== 'paragraph') { if (node.type !== 'paragraph') {
continue continue;
} }
excerpt = toString(node) excerpt = toString(node);
break break;
} }
data.astro.frontmatter.excerpt = excerpt data.astro.frontmatter.excerpt = excerpt;
} };
} }

46
src/styles/global.css Normal file
View File

@ -0,0 +1,46 @@
@import 'tailwindcss';
@plugin 'daisyui' {
themes: light --default dark --prefersdark;
}
@plugin 'daisyui/theme' {
name: 'light';
default: false;
--color-primary: #bc4d2e;
--color-primary-content: #fefedb;
--color-secondary: #efbf89;
--color-secondary-content: #111;
--color-accent: #742c22;
--color-accent-content: #fff;
--color-base-100: #fffffd;
--color-base-200: #f6e7d2;
--color-base-300: #e6c9ac;
--color-base-content: #111;
}
@plugin 'daisyui/theme' {
name: dark;
--color-primary: #88b7dc;
--color-primary-content: #fff;
--color-secondary: #c47890;
--color-secondary-content: #fff;
--color-accent: #a343b0;
--color-accent-content: #fff;
--color-base-100: #272a3c;
--color-base-200: #18192a;
--color-base-300: #11121f;
--color-base-content: #eee;
}
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] * ));
@theme {
--tracking-extra-wide: 0.25em;
}
html {
scroll-behavior: smooth;
}

View File

@ -1,11 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
font-size: 17px;
}
html {
scroll-behavior: smooth;
}

View File

@ -1,7 +1,7 @@
@use './globals.scss' as global; @reference './global.css';
article { article {
// 标题通用样式 /* 标题通用样式 */
h1, h1,
h2, h2,
h3, h3,
@ -18,7 +18,7 @@ article {
padding: 0 0.5rem; padding: 0 0.5rem;
opacity: 0; opacity: 0;
text-decoration: none; text-decoration: none;
color: theme('colors.primary'); color: var(--color-primary);
transition: opacity 0.2s ease-in-out; transition: opacity 0.2s ease-in-out;
} }
@ -29,7 +29,7 @@ article {
} }
} }
// 各级标题特殊样式 /* 各级标题特殊样式 */
h1 { h1 {
@apply text-2xl; @apply text-2xl;
} }
@ -47,7 +47,7 @@ article {
@apply text-base; @apply text-base;
} }
// 基础文本元素 /* 基础文本元素 */
p { p {
margin: 0.5rem 0; margin: 0.5rem 0;
} }
@ -61,7 +61,7 @@ article {
} }
} }
// 媒体元素 /* 媒体元素 */
img { img {
position: relative; position: relative;
margin: 1rem auto; margin: 1rem auto;
@ -76,7 +76,7 @@ article {
border: 1px dashed; border: 1px dashed;
} }
// 列表样式 /* 列表样式 */
ul, ul,
ol { ol {
margin-top: 0.5rem; margin-top: 0.5rem;
@ -147,13 +147,13 @@ article {
position: absolute; position: absolute;
font-size: 0.75em; font-size: 0.75em;
line-height: 0.75em; line-height: 0.75em;
color: theme('colors.primary-content'); color: var(--colors-primary-content);
} }
} }
} }
} }
// 代码样式 /* 代码样式 */
pre { pre {
padding: 0.5rem; padding: 0.5rem;
counter-reset: line; counter-reset: line;
@ -190,7 +190,7 @@ article {
code:not(pre code) { code:not(pre code) {
padding: 0 0.25rem; padding: 0 0.25rem;
@apply rounded-md bg-primary/10 text-primary; @apply bg-primary/10 text-primary rounded-md;
} }
.astro-code, .astro-code,
@ -212,14 +212,14 @@ article {
} }
} }
// 引用块样式 /* 引用块样式 */
blockquote { blockquote {
padding: 0.25rem 0.25rem 0.25rem 0.75rem; padding: 0.25rem 0.25rem 0.25rem 0.75rem;
@apply my-2 rounded-sm border-l-4 border-primary bg-primary/10; @apply border-primary bg-primary/10 my-2 rounded-sm border-l-4;
} }
// GitHub Alert 样式 /* GitHub Alert 样式 */
.admonition { .admonition {
padding: 0.25rem 0.25rem 0.25rem 0.75rem; padding: 0.25rem 0.25rem 0.25rem 0.75rem;
@ -229,7 +229,7 @@ article {
font-weight: bold; font-weight: bold;
} }
&-note { &.admonition-note {
@apply border-info bg-info/10; @apply border-info bg-info/10;
.admonition-title { .admonition-title {
@ -237,7 +237,7 @@ article {
} }
} }
&-tip { &.admonition-tip {
@apply border-success bg-success/10; @apply border-success bg-success/10;
.admonition-title { .admonition-title {
@ -245,7 +245,7 @@ article {
} }
} }
&-important { &.admonition-important {
@apply border-accent bg-accent/10; @apply border-accent bg-accent/10;
.admonition-title { .admonition-title {
@ -253,7 +253,7 @@ article {
} }
} }
&-warning { &.admonition-warning {
@apply border-warning bg-warning/10; @apply border-warning bg-warning/10;
.admonition-title { .admonition-title {
@ -261,7 +261,7 @@ article {
} }
} }
&-caution { &.admonition-caution {
@apply border-error bg-error/10; @apply border-error bg-error/10;
.admonition-title { .admonition-title {
@ -270,12 +270,12 @@ article {
} }
} }
// 折叠块样式 /* 折叠块样式 */
details { details {
@apply w-full overflow-hidden rounded-xl border-2 border-base-300 duration-300; @apply border-base-300 w-full overflow-hidden rounded-xl border-2 duration-300;
summary { summary {
@apply w-full px-3 py-1 text-start text-2xl duration-300 hover:bg-primary/50; @apply hover:bg-primary/50 w-full px-3 py-1 text-start text-2xl duration-300;
&::marker { &::marker {
margin-right: 1.5rem; margin-right: 1.5rem;
@ -289,20 +289,20 @@ article {
} }
} }
// 表格样式 /* 表格样式 */
table { table {
@apply relative w-full text-left text-sm; @apply relative w-full text-left text-sm;
:where(thead tr, tbody tr:not(:last-child), tbody tr:first-child:last-child) { :where(thead tr, tbody tr:not(:last-child), tbody tr:first-child:last-child) {
@apply border-b-2 border-b-base-200; @apply border-b-base-200 border-b-2;
} }
:where(tfoot) { :where(tfoot) {
@apply border-t-2 border-t-base-200; @apply border-t-base-200 border-t-2;
} }
:where(thead, tfoot) { :where(thead, tfoot) {
@apply whitespace-nowrap bg-base-300/15 text-xs font-bold text-base-content/90; @apply bg-base-300/15 text-base-content/90 text-xs font-bold whitespace-nowrap;
} }
:where(th, td) { :where(th, td) {
@ -311,7 +311,7 @@ article {
} }
} }
// 数学样式 /* 数学样式 */
mjx-container[display='true'] { mjx-container[display='true'] {
overflow: auto; overflow: auto;
} }

View File

@ -1,12 +1,17 @@
/* stylelint-disable no-descending-specificity */ /* stylelint-disable no-descending-specificity */
/* stylelint-disable selector-class-pattern */ /* stylelint-disable selector-class-pattern */
@reference './global.css';
@use './globals.scss' as global;
.twikoo { .twikoo {
@apply relative flex h-fit w-full flex-col items-center; @apply relative flex h-fit w-full flex-col items-center;
} }
input,
textarea,
select {
border: none;
}
.tk-comments { .tk-comments {
@apply w-full; @apply w-full;
@ -18,7 +23,7 @@
@apply flex w-full flex-col gap-2; @apply flex w-full flex-col gap-2;
} }
// 回复框样式 /* 回复框样式 */
.tk-submit { .tk-submit {
@apply relative w-full; @apply relative w-full;
@ -26,17 +31,17 @@
display: none; display: none;
} }
// 输入框部分样式 /* 输入框部分样式 */
.tk-col { .tk-col {
@apply flex-col-reverse; @apply flex-col-reverse;
} }
// 文本框输入样式 /* 文本框输入样式 */
.el-textarea { .el-textarea {
@apply relative w-full overflow-hidden rounded-xl border-2 border-base-300 pb-9; @apply border-base-300 relative w-full overflow-hidden rounded-xl border-2 pb-9;
textarea { textarea {
@apply w-full bg-base-200/50 p-4; @apply bg-base-200/50 w-full p-4;
resize: none; resize: none;
@ -50,11 +55,11 @@
} }
.el-input__count { .el-input__count {
@apply absolute bottom-2 right-10 text-sm text-base-content/50; @apply text-base-content/50 absolute right-10 bottom-2 text-sm;
} }
} }
// 个人信息输入框样式 /* 个人信息输入框样式 */
.tk-meta-input { .tk-meta-input {
@apply flex w-[calc(100%-3.5rem)] flex-col items-center gap-2 md:w-[calc(100%-6.75rem)] md:flex-row; @apply flex w-[calc(100%-3.5rem)] flex-col items-center gap-2 md:w-[calc(100%-6.75rem)] md:flex-row;
} }
@ -71,20 +76,20 @@
} }
button { button {
@apply absolute border-base-300 bg-primary py-[0.95rem] md:py-[0.3rem]; @apply border-base-300 bg-primary absolute py-[0.95rem] md:py-[0.3rem];
&.tk-preview { &.tk-preview {
@apply bottom-[3.7rem] right-0 md:bottom-0 md:right-[3.35rem]; @apply right-0 bottom-[3.7rem] md:right-[3.35rem] md:bottom-0;
} }
&.tk-send { &.tk-send {
@apply bottom-0 right-0; @apply right-0 bottom-0;
} }
} }
} }
.__markdown { .__markdown {
@apply absolute bottom-[7.75rem] right-3 md:bottom-[2.75rem]; @apply absolute right-3 bottom-[7.75rem] md:bottom-[2.75rem];
} }
&:has(.tk-cancel) { &:has(.tk-cancel) {
@ -100,20 +105,20 @@
} }
&.tk-cancel { &.tk-cancel {
@apply bottom-[2.4rem] right-0 bg-error text-error-content md:bottom-0 md:right-[6.7rem]; @apply bg-error text-error-content right-0 bottom-[2.4rem] md:right-[6.7rem] md:bottom-0;
} }
} }
} }
.tk-preview-container { .tk-preview-container {
@apply mt-2 w-full rounded-xl border-2 border-base-300 bg-base-100 p-2; @apply border-base-300 bg-base-100 mt-2 w-full rounded-xl border-2 p-2;
} }
} }
// 表情框样式 /* 表情框样式 */
.OwO-body { .OwO-body {
/* stylelint-disable-next-line scss/operator-no-unspaced */ /* stylelint-disable-next-line scss/operator-no-unspaced */
@apply absolute -left-3 top-9 z-20 hidden w-[calc(100vw-3rem)] max-w-[30rem] rounded-xl border-2 border-base-300 bg-base-200/50 duration-300; @apply border-base-300 bg-base-200/50 absolute top-9 -left-3 z-20 hidden w-[calc(100vw-3rem)] max-w-[30rem] rounded-xl border-2 duration-300;
} }
.OwO-open .OwO-body { .OwO-open .OwO-body {
@ -141,10 +146,10 @@
} }
.OwO-packages { .OwO-packages {
@apply flex flex-wrap items-center text-nowrap px-4; @apply flex flex-wrap items-center px-4 text-nowrap;
> li { > li {
@apply flex h-8 cursor-pointer items-center px-3 text-center duration-300 hover:bg-primary/50; @apply hover:bg-primary/50 flex h-8 cursor-pointer items-center px-3 text-center duration-300;
&.OwO-package-active { &.OwO-package-active {
@apply bg-primary/50; @apply bg-primary/50;
@ -153,7 +158,7 @@
} }
.tk-comments-container { .tk-comments-container {
// 评论整体样式 /* 评论整体样式 */
@apply mt-4 flex w-full flex-col gap-4; @apply mt-4 flex w-full flex-col gap-4;
.tk-comments-title { .tk-comments-title {
@ -173,7 +178,7 @@
} }
> .tk-comment { > .tk-comment {
@apply p-4 max-md:rounded-xl max-md:border-2 max-md:border-base-300 max-md:bg-base-200/50; @apply max-md:border-base-300 max-md:bg-base-200/50 p-4 max-md:rounded-xl max-md:border-2;
> .tk-avatar { > .tk-avatar {
@apply top-3; @apply top-3;
@ -181,16 +186,16 @@
} }
.tk-replies { .tk-replies {
@apply ml-6 mt-4 flex flex-col gap-2; @apply mt-4 ml-6 flex flex-col gap-2;
&:not(.tk-replies-expand) { &:not(.tk-replies-expand) {
@apply max-h-32 overflow-y-hidden; @apply max-h-32 overflow-y-hidden;
} }
} }
// 详细样式 /* 详细样式 */
.tk-avatar { .tk-avatar {
@apply absolute top-0 h-8 min-h-8 w-8 min-w-8 overflow-hidden rounded-full border-2 border-base-300; @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 { .tk-main > .tk-row {
@ -199,7 +204,7 @@
.tk-meta { .tk-meta {
a { a {
@apply duration-300 hover:text-primary; @apply hover:text-primary duration-300;
} }
small { small {
@ -211,14 +216,14 @@
} }
} }
// 评论操作样式 /* 评论操作样式 */
.tk-main:not(:has(.tk-replies:hover)):hover > .tk-row .tk-meta .tk-actions { .tk-main:not(:has(.tk-replies:hover)):hover > .tk-row .tk-meta .tk-actions {
@apply opacity-100; @apply opacity-100;
} }
.tk-action { .tk-action {
.tk-action-link { .tk-action-link {
@apply relative flex items-center justify-center rounded-xl border-2 border-base-300 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 { .tk-action-icon-solid {
@apply absolute left-2 opacity-0 duration-300; @apply absolute left-2 opacity-0 duration-300;
@ -254,7 +259,7 @@
@apply flex flex-row gap-3; @apply flex flex-row gap-3;
.tk-extra { .tk-extra {
@apply flex flex-row items-center justify-center gap-2 rounded-md border-2 border-base-300 p-1 text-center text-xs text-base-content/50; @apply border-base-300 text-base-content/50 flex flex-row items-center justify-center gap-2 rounded-md border-2 p-1 text-center text-xs;
} }
.tk-icon { .tk-icon {
@ -263,8 +268,8 @@
} }
.tk-replies .tk-content > span:first-child { .tk-replies .tk-content > span:first-child {
// 回复提示回复xxx样式 /* 回复提示回复xxx样式 */
@apply text-xs text-base-content/50; @apply text-base-content/50 text-xs;
} }
.tk-expand-wrap, .tk-expand-wrap,
@ -273,25 +278,25 @@
} }
.tk-expand { .tk-expand {
@apply w-full cursor-pointer rounded-md bg-base-200/50 py-1 text-sm duration-300 hover:bg-primary/50; @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 { .tk-submit-action-icon {
@apply inline-block max-h-6 min-h-6 min-w-6 max-w-6 cursor-pointer fill-primary; @apply fill-primary inline-block max-h-6 min-h-6 max-w-6 min-w-6 cursor-pointer;
} }
.tk-action-icon { .tk-action-icon {
@apply inline-block max-h-5 min-h-5 min-w-5 max-w-5 overflow-clip fill-primary; @apply fill-primary inline-block max-h-5 min-h-5 max-w-5 min-w-5 overflow-clip;
} }
.tk-icon { .tk-icon {
@apply inline-block max-h-4 min-h-4 min-w-4 max-w-4 overflow-clip fill-primary; @apply fill-primary inline-block max-h-4 min-h-4 max-w-4 min-w-4 overflow-clip;
} }
.tk-tag { .tk-tag {
@apply rounded-lg border-2 border-base-300 p-1 text-xs; @apply border-base-300 rounded-lg border-2 p-1 text-xs;
} }
} }
@ -314,7 +319,11 @@
@apply relative flex h-full w-full items-center justify-center text-center; @apply relative flex h-full w-full items-center justify-center text-center;
.tk-admin-close { .tk-admin-close {
@apply absolute right-2 top-[0.65rem] z-50 h-8 w-8 fill-primary; @apply fill-primary absolute top-[0.65rem] right-2 z-50 h-4 w-4;
@variant md {
@apply top-4 right-3 h-8 w-8;
}
} }
> div { > div {
@ -334,26 +343,26 @@
@apply h-full w-full overflow-y-scroll; @apply h-full w-full overflow-y-scroll;
.tk-panel-title { .tk-panel-title {
@apply left-0 top-0 z-40 flex w-full flex-row items-center justify-between p-4; @apply top-0 left-0 z-40 flex w-full flex-row items-center justify-between p-4;
// 管理面板标题 /* 管理面板标题 */
div { div {
@apply text-xl font-bold; @apply text-xl font-bold;
} }
a { a {
@apply mx-6 rounded-xl border-2 border-base-300 bg-base-200/50 px-3 py-1 text-xs duration-300 hover:bg-primary; @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 { .tk-tabs {
@apply flex flex-row items-center justify-between border-b-2 border-base-300 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 { .tk-tab {
@apply w-full cursor-pointer py-1 duration-300 hover:bg-primary; @apply hover:bg-primary w-full min-w-fit cursor-pointer py-1 duration-300;
&.__active { &.__active {
@apply border-b-2 border-primary; @apply border-primary border-b-2;
} }
} }
} }
@ -366,7 +375,7 @@
} }
} }
// 评论管理样式 /* 评论管理样式 */
.tk-admin-comment { .tk-admin-comment {
@apply p-4; @apply p-4;
} }
@ -378,7 +387,7 @@
@apply w-full; @apply w-full;
input { input {
@apply w-full rounded-xl border-2 border-base-300 bg-base-200/50 px-2 py-1; @apply border-base-300 bg-base-200/50 w-full rounded-xl border-2 px-2 py-1;
&:focus { &:focus {
outline: none; outline: none;
@ -387,7 +396,7 @@
} }
select { select {
@apply w-1/4 rounded-xl border-2 border-base-300 bg-base-200/50 p-2; @apply border-base-300 bg-base-200/50 w-1/4 rounded-xl border-2 p-2;
} }
} }
@ -396,23 +405,23 @@
} }
.tk-admin-comment-item { .tk-admin-comment-item {
@apply border-b-2 border-base-300 py-1; @apply border-base-300 border-b-2 py-1;
} }
.tk-admin-comment-meta { .tk-admin-comment-meta {
@apply flex flex-row flex-wrap items-center gap-2 text-start; @apply flex flex-row flex-wrap items-center gap-2 text-start;
.tk-avatar { .tk-avatar {
@apply h-8 w-8 overflow-hidden rounded-full border-2 border-base-300; @apply border-base-300 h-8 w-8 overflow-hidden rounded-full border-2;
} }
a { a {
@apply duration-300 hover:text-primary; @apply hover:text-primary duration-300;
} }
span:last-child, span:last-child,
.tk-time { .tk-time {
@apply text-sm text-base-content/50; @apply text-base-content/50 text-sm;
} }
} }
@ -424,7 +433,7 @@
} }
input { input {
@apply w-16 rounded-xl border-2 border-base-300 bg-base-200/50 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-outer-spin-button,
&::-webkit-inner-spin-button { &::-webkit-inner-spin-button {
@ -442,14 +451,14 @@
} }
.tk-pagination-pager { .tk-pagination-pager {
@apply cursor-pointer rounded-md px-2 py-1 hover:bg-primary; @apply hover:bg-primary cursor-pointer rounded-md px-2 py-1;
&.__current { &.__current {
@apply bg-primary; @apply bg-primary;
} }
} }
// 配置管理样式 /* 配置管理样式 */
.tk-admin-config { .tk-admin-config {
@apply p-4; @apply p-4;
} }
@ -459,10 +468,10 @@
} }
details { details {
@apply w-full overflow-hidden rounded-xl border-2 border-base-300 duration-300; @apply border-base-300 w-full overflow-hidden rounded-xl border-2 duration-300;
summary { summary {
@apply w-full px-3 py-1 text-start text-2xl duration-300 hover:bg-primary/50; @apply hover:bg-primary/50 w-full px-3 py-1 text-start text-2xl duration-300;
&::marker { &::marker {
margin-right: 1.5rem; margin-right: 1.5rem;
@ -486,7 +495,7 @@
} }
input { input {
@apply w-full rounded-xl border-2 border-base-300 bg-base-200/50 px-2 py-1; @apply border-base-300 bg-base-200/50 w-full rounded-xl border-2 px-2 py-1;
&:focus { &:focus {
outline: none; outline: none;
@ -494,11 +503,11 @@
} }
.tk-admin-config-desc { .tk-admin-config-desc {
@apply whitespace-pre-wrap text-start text-sm text-base-content/50; @apply text-base-content/50 text-start text-sm whitespace-pre-wrap;
} }
} }
// 导入样式 /* 导入样式 */
.tk-admin-import { .tk-admin-import {
@apply flex flex-col items-start gap-4 p-4; @apply flex flex-col items-start gap-4 p-4;
@ -507,11 +516,11 @@
} }
select { select {
@apply w-full rounded-xl border-2 border-base-300 bg-base-200/50 p-2; @apply border-base-300 bg-base-200/50 w-full rounded-xl border-2 p-2;
} }
input { input {
@apply w-full rounded-xl border-2 border-base-300 bg-base-200/50 px-2 py-1; @apply border-base-300 bg-base-200/50 w-full rounded-xl border-2 px-2 py-1;
&:focus { &:focus {
outline: none; outline: none;
@ -522,7 +531,7 @@
@apply h-full w-full; @apply h-full w-full;
textarea { textarea {
@apply h-full w-full rounded-xl border-2 border-base-300 bg-base-200/50 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 { &:focus {
outline: none; outline: none;
@ -531,7 +540,7 @@
} }
} }
// 导出样式 /* 导出样式 */
.tk-admin-export { .tk-admin-export {
@apply p-4; @apply p-4;
} }
@ -539,10 +548,10 @@
} }
.el-input-group { .el-input-group {
@apply flex w-full flex-row items-center overflow-hidden rounded-xl border-2 border-base-300 bg-base-200/50 text-sm; @apply border-base-300 bg-base-200/50 flex w-full flex-row items-center overflow-hidden rounded-xl border-2 text-sm;
div { div {
@apply w-fit whitespace-nowrap bg-primary/50 px-2 py-1; @apply bg-primary/50 w-fit px-2 py-1 whitespace-nowrap;
} }
input { input {
@ -559,7 +568,7 @@
} }
.el-button { .el-button {
@apply text-nowrap rounded-xl border-2 border-base-300 bg-primary px-2 py-1 text-center text-sm duration-300; @apply border-base-300 bg-primary rounded-xl border-2 px-2 py-1 text-center text-sm text-nowrap duration-300;
&:not(.is-disabled) { &:not(.is-disabled) {
@apply hover:scale-105 hover:brightness-110 active:scale-95 active:brightness-90; @apply hover:scale-105 hover:brightness-110 active:scale-95 active:brightness-90;
@ -570,10 +579,10 @@
} }
} }
// Markdown 样式 /* Markdown 样式 */
.tk-content, .tk-content,
.tk-preview-container { .tk-preview-container {
// 标题通用样式 /* 标题通用样式 */
h1, h1,
h2, h2,
h3, h3,
@ -586,7 +595,7 @@
font-weight: bold; font-weight: bold;
} }
// 基础文本元素 /* 基础文本元素 */
p { p {
margin: 0.5rem 0; margin: 0.5rem 0;
} }
@ -600,16 +609,16 @@
} }
} }
// 代码样式 /* 代码样式 */
.code-toolbar { .code-toolbar {
@apply relative w-full; @apply relative w-full;
.toolbar { .toolbar {
@apply absolute right-3 top-1 flex flex-row-reverse items-center justify-between gap-4 text-xs; @apply absolute top-1 right-3 flex flex-row-reverse items-center justify-between gap-4 text-xs;
} }
.copy-to-clipboard-button { .copy-to-clipboard-button {
@apply rounded-md border-2 border-base-300 bg-primary 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 { &:hover .copy-to-clipboard-button {
@ -624,10 +633,10 @@
code:not(pre code) { code:not(pre code) {
padding: 0 0.25rem; padding: 0 0.25rem;
@apply rounded-md bg-primary/10 text-primary; @apply bg-primary/10 text-primary rounded-md;
} }
// 媒体元素 /* 媒体元素 */
img:not(.tk-owo-emotion) { img:not(.tk-owo-emotion) {
position: relative; position: relative;
margin: 1rem auto; margin: 1rem auto;
@ -641,25 +650,25 @@
@apply inline-block h-7 self-baseline; @apply inline-block h-7 self-baseline;
} }
// 分割线样式 /* 分割线样式 */
hr { hr {
margin: 1.5rem 0.25rem; margin: 1.5rem 0.25rem;
border: 1px dashed; border: 1px dashed;
} }
// 引用块样式 /* 引用块样式 */
blockquote { blockquote {
padding: 0.25rem 0.25rem 0.25rem 0.75rem; padding: 0.25rem 0.25rem 0.25rem 0.75rem;
@apply my-2 rounded-sm border-l-4 border-primary bg-primary/10; @apply border-primary bg-primary/10 my-2 rounded-sm border-l-4;
} }
// 折叠块样式 /* 折叠块样式 */
details { details {
@apply w-full overflow-hidden rounded-xl border-2 border-base-300 duration-300; @apply border-base-300 w-full overflow-hidden rounded-xl border-2 duration-300;
summary { summary {
@apply w-full px-3 py-1 text-start text-2xl duration-300 hover:bg-primary/50; @apply hover:bg-primary/50 w-full px-3 py-1 text-start text-2xl duration-300;
&::marker { &::marker {
margin-right: 1.5rem; margin-right: 1.5rem;

View File

@ -1,16 +1,22 @@
/** @type {import('stylelint').Config} */ /** @type {import('stylelint').Config} */
export default { export default {
extends: ['stylelint-config-standard-scss', 'stylelint-config-html/astro'], extends: ['stylelint-config-html/astro'],
rules: { rules: {
'scss/at-rule-no-unknown': [ 'at-rule-no-unknown': [
true, true,
{ {
ignoreAtRules: [ ignoreAtRules: [
// Tailwind CSS // Tailwind CSS
'tailwind', 'theme',
'source',
'utility',
'variant',
'custom-variant',
'apply', 'apply',
'layer', 'layer',
'config', 'config',
'plugin',
'reference',
], ],
}, },
], ],

View File

@ -1,46 +0,0 @@
import daisyui from 'daisyui';
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {
letterSpacing: {
'extra-wide': '0.25em',
},
},
},
darkMode: ['selector', '[data-theme="dark"]'],
plugins: [daisyui],
daisyui: {
base: false,
themes: [
{
light: {
primary: '#BC4D2E',
'primary-content': '#FEFEDB',
secondary: '#EFBF89',
'secondary-content': '#111',
accent: '#742C22',
'accent-content': '#FFF',
'base-100': '#FFFFFD',
'base-200': '#F6E7D2',
'base-300': '#E6C9AC',
'base-content': '#111',
},
dark: {
primary: '#88B7DC',
'primary-content': '#FFF',
secondary: '#C47890',
'secondary-content': '#FFF',
accent: '#A343B0',
'accent-content': '#FFF',
'base-100': '#272A3C',
'base-200': '#18192A',
'base-300': '#11121F',
'base-content': '#EEE',
},
},
],
},
};