Refactor
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
---
|
||||
export interface Props {
|
||||
title: string;
|
||||
body: string;
|
||||
href: string;
|
||||
}
|
||||
const { href, title, body } = Astro.props;
|
||||
---
|
||||
|
||||
<li class="link-card">
|
||||
<a href={href}>
|
||||
<h2>
|
||||
{title}
|
||||
<span>→</span>
|
||||
</h2>
|
||||
<p>
|
||||
{body}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<style>
|
||||
:root {
|
||||
--link-gradient: linear-gradient(45deg, #4f39fa, #da62c4 30%, var(--color-border) 60%);
|
||||
}
|
||||
|
||||
.link-card {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
padding: 0.15rem;
|
||||
background-image: var(--link-gradient);
|
||||
background-size: 400%;
|
||||
border-radius: 0.5rem;
|
||||
background-position: 100%;
|
||||
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
.link-card>a {
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
line-height: 1.4;
|
||||
padding: 1em 1.3em;
|
||||
border-radius: 0.35rem;
|
||||
color: var(--text-color);
|
||||
background-color: white;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
h2 span {
|
||||
display: inline-block;
|
||||
transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) {
|
||||
background-position: 0;
|
||||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) h2 {
|
||||
color: #4f39fa;
|
||||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) h2 span {
|
||||
transform: translateX(2px);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
// TODO: Only execute when compiling Astro templates, so it will not be dynamically updated
|
||||
const today = new Date();
|
||||
---
|
||||
|
||||
<footer>
|
||||
<div class="footer-inner">
|
||||
<span>
|
||||
© {today.getFullYear()}
|
||||
<th:block th:text="${site.title}"></th:block>.
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
border-top: 1px solid var(--rule);
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
.footer-inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
width: 820px;
|
||||
max-width: calc(100% - 2.5rem);
|
||||
margin: 0 auto;
|
||||
padding: 1.5rem 0 2.5rem;
|
||||
color: var(--ink-3);
|
||||
font-size: 0.88rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
import ThemeSwitcher from "./ThemeSwitcher.vue";
|
||||
---
|
||||
|
||||
<header>
|
||||
<div class="header-inner">
|
||||
<a class="brand" href="/" th:text="${site.title}"></a>
|
||||
<nav
|
||||
th:with="menu = ${menuFinder.getPrimary()}"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
<a
|
||||
th:each="menuItem : ${menu.menuItems}"
|
||||
th:href="@{${menuItem.status.href}}"
|
||||
th:target="${menuItem.spec.target?.value}"
|
||||
th:text="${menuItem.status.displayName}"
|
||||
>
|
||||
</a>
|
||||
</nav>
|
||||
<ThemeSwitcher client:load />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
header {
|
||||
background: var(--bg);
|
||||
border-bottom: 1px solid var(--rule);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.header-inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 2rem;
|
||||
width: 820px;
|
||||
max-width: calc(100% - 2.5rem);
|
||||
margin: 0 auto;
|
||||
height: 58px;
|
||||
}
|
||||
|
||||
.brand {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: var(--ink);
|
||||
text-decoration: none;
|
||||
letter-spacing: -0.02em;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.brand:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
nav :global(a) {
|
||||
display: inline-block;
|
||||
padding: 0.3rem 0.65rem;
|
||||
border-radius: 6px;
|
||||
font-size: 0.9rem;
|
||||
color: var(--ink-2);
|
||||
text-decoration: none;
|
||||
transition:
|
||||
color 0.15s ease,
|
||||
background 0.15s ease;
|
||||
}
|
||||
|
||||
nav :global(a:hover) {
|
||||
color: var(--ink);
|
||||
background: var(--bg-raised);
|
||||
}
|
||||
|
||||
nav :global(a.active) {
|
||||
color: var(--ink);
|
||||
background: var(--bg-raised);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media (max-width: 680px) {
|
||||
.header-inner {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
height: auto;
|
||||
padding: 1rem 0;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
nav {
|
||||
flex-wrap: wrap;
|
||||
gap: 0.1rem;
|
||||
margin-left: -0.65rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,52 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { TransitionRoot } from "@headlessui/vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
const isShowing = ref(true);
|
||||
|
||||
function resetIsShowing() {
|
||||
isShowing.value = false;
|
||||
|
||||
setTimeout(() => {
|
||||
isShowing.value = true;
|
||||
}, 500);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<span class="text-xl font-bold" th:text="@{post.title}">Hello Halo</span>
|
||||
|
||||
<div class="flex flex-col items-center py-16">
|
||||
<div class="h-32 w-32">
|
||||
<TransitionRoot
|
||||
:show="isShowing"
|
||||
appear
|
||||
as="template"
|
||||
enter="transform transition duration-[400ms]"
|
||||
enter-from="opacity-0 rotate-[-120deg] scale-50"
|
||||
enter-to="opacity-100 rotate-0 scale-100"
|
||||
leave="transform duration-200 transition ease-in-out"
|
||||
leave-from="opacity-100 rotate-0 scale-100 "
|
||||
leave-to="opacity-0 scale-95 "
|
||||
>
|
||||
<div class="h-full w-full rounded-md bg-white shadow-lg" />
|
||||
</TransitionRoot>
|
||||
</div>
|
||||
<button
|
||||
class="mt-8 flex transform items-center rounded-full bg-black bg-opacity-20 px-3 py-2 text-sm font-medium text-white transition hover:scale-105 hover:bg-opacity-30 focus:outline-none active:bg-opacity-40"
|
||||
@click="resetIsShowing"
|
||||
>
|
||||
<svg class="h-5 w-5 opacity-70" fill="none" viewBox="0 0 20 20">
|
||||
<path
|
||||
d="M14.9497 14.9498C12.2161 17.6835 7.78392 17.6835 5.05025 14.9498C2.31658 12.2162 2.31658 7.784 5.05025 5.05033C7.78392 2.31666 12.2161 2.31666 14.9497 5.05033C15.5333 5.63385 15.9922 6.29475 16.3266 7M16.9497 2L17 7H16.3266M12 7L16.3266 7"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<span class="ml-3">Click to transition</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,90 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
|
||||
const isDark = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
isDark.value = document.documentElement.classList.contains("dark");
|
||||
});
|
||||
|
||||
function toggle() {
|
||||
isDark.value = !isDark.value;
|
||||
document.documentElement.classList.toggle("dark", isDark.value);
|
||||
localStorage.setItem("theme", isDark.value ? "dark" : "light");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
class="theme-toggle"
|
||||
type="button"
|
||||
:aria-label="isDark ? 'Switch to light mode' : 'Switch to dark mode'"
|
||||
@click="toggle"
|
||||
>
|
||||
<!-- Moon: shown in light mode -->
|
||||
<svg
|
||||
v-if="!isDark"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="17"
|
||||
height="17"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
|
||||
</svg>
|
||||
<!-- Sun: shown in dark mode -->
|
||||
<svg
|
||||
v-else
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="17"
|
||||
height="17"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle cx="12" cy="12" r="5" />
|
||||
<line x1="12" y1="1" x2="12" y2="3" />
|
||||
<line x1="12" y1="21" x2="12" y2="23" />
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
|
||||
<line x1="1" y1="12" x2="3" y2="12" />
|
||||
<line x1="21" y1="12" x2="23" y2="12" />
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
|
||||
</svg>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.theme-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: var(--ink-2);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background 0.15s ease,
|
||||
color 0.15s ease;
|
||||
}
|
||||
|
||||
.theme-toggle:hover {
|
||||
background: var(--bg-raised);
|
||||
color: var(--ink);
|
||||
}
|
||||
</style>
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
declare namespace astroHTML.JSX {
|
||||
interface HTMLAttributes {
|
||||
"th:each"?: string;
|
||||
"th:href"?: string;
|
||||
"th:text"?: string;
|
||||
"th:if"?: string;
|
||||
"th:unless"?: string;
|
||||
"th:utext"?: string;
|
||||
"th:src"?: string;
|
||||
"th:with"?: string;
|
||||
"th:target"?: string;
|
||||
}
|
||||
}
|
||||
+45
-62
@@ -1,69 +1,52 @@
|
||||
---
|
||||
export interface Props {
|
||||
title: string;
|
||||
import "../styles/global.css";
|
||||
import Footer from "../components/Footer.astro";
|
||||
import Header from "../components/Header.astro";
|
||||
|
||||
interface Props {
|
||||
pageTitle?: string;
|
||||
contentClass?: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props as Props;
|
||||
const { pageTitle, contentClass } = Astro.props;
|
||||
|
||||
const hasHeading = Boolean(pageTitle);
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="flex justify-between">
|
||||
<nav class="flex gap-3">
|
||||
<a href="/" th:href="@{/}">Home</a>
|
||||
<a href="/post" th:href="@{/post}">Post</a>
|
||||
<a href="/links" th:href="@{/links}">Links</a>
|
||||
</nav>
|
||||
<div>
|
||||
<a href="/">默认</a>
|
||||
<a href="/?language=zh">中文</a>
|
||||
<a href="/?language=en">英文</a>
|
||||
</div>
|
||||
</div>
|
||||
<slot />
|
||||
</body>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<script is:inline>
|
||||
(function () {
|
||||
var stored = localStorage.getItem("theme");
|
||||
var prefersDark = window.matchMedia(
|
||||
"(prefers-color-scheme: dark)",
|
||||
).matches;
|
||||
if (stored === "dark" || (!stored && prefersDark)) {
|
||||
document.documentElement.classList.add("dark");
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<slot name="head" />
|
||||
</head>
|
||||
<body>
|
||||
<Header />
|
||||
<main class="layout-main">
|
||||
<article class="page-shell">
|
||||
{
|
||||
hasHeading && (
|
||||
<header class="page-heading">
|
||||
{pageTitle && <h1>{pageTitle}</h1>}
|
||||
</header>
|
||||
)
|
||||
}
|
||||
<div class:list={["page-content", contentClass]}>
|
||||
<slot />
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
<style>
|
||||
:root {
|
||||
--font-size-base: clamp(1rem, 0.34vw + 0.91rem, 1.19rem);
|
||||
--font-size-lg: clamp(1.2rem, 0.7vw + 1.2rem, 1.5rem);
|
||||
--font-size-xl: clamp(2.44rem, 2.38vw + 1.85rem, 3.75rem);
|
||||
|
||||
--color-text: hsl(12, 5%, 4%);
|
||||
--color-bg: hsl(10, 21%, 95%);
|
||||
--color-border: hsl(17, 24%, 90%);
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--color-text);
|
||||
background-color: var(--color-bg);
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:global(h1) {
|
||||
font-size: var(--font-size-xl);
|
||||
}
|
||||
|
||||
:global(h2) {
|
||||
font-size: var(--font-size-lg);
|
||||
}
|
||||
|
||||
:global(code) {
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout pageTitle="归档">
|
||||
<Fragment slot="head">
|
||||
<title th:text="|归档 - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<section class="archive-list" aria-label="Archive list">
|
||||
<th:block th:each="archive : ${archives.items}">
|
||||
<th:block th:each="month : ${archive.months}">
|
||||
<div class="archive-group">
|
||||
<h2
|
||||
class="archive-group__year"
|
||||
th:text="|${archive.year} · ${month.month}|"
|
||||
>
|
||||
</h2>
|
||||
<ul class="archive-group__items">
|
||||
<li th:each="post : ${month.posts}" class="archive-entry">
|
||||
<span
|
||||
class="archive-entry__date"
|
||||
th:text="${#dates.format(post.spec.publishTime, 'MM/dd')}"
|
||||
></span>
|
||||
<div>
|
||||
<h3 class="archive-entry__title">
|
||||
<a
|
||||
th:href="@{${post.status.permalink}}"
|
||||
th:text="${post.spec.title}"></a>
|
||||
</h3>
|
||||
<p
|
||||
class="archive-entry__summary"
|
||||
th:text="${post.status.excerpt}"
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</th:block>
|
||||
</th:block>
|
||||
|
||||
<div th:if="${archives.total == 0}" class="archive-empty">暂无文章。</div>
|
||||
</section>
|
||||
|
||||
<nav
|
||||
th:if="${archives.totalPages gt 1}"
|
||||
class="pagination"
|
||||
aria-label="Pagination"
|
||||
>
|
||||
<a
|
||||
th:if="${archives.hasPrevious()}"
|
||||
th:href="@{${archives.prevUrl}}"
|
||||
class="pagination__prev">← 较新</a
|
||||
>
|
||||
<span
|
||||
class="pagination__info"
|
||||
th:text="|${archives.page} / ${archives.totalPages}|"></span>
|
||||
<a
|
||||
th:if="${archives.hasNext()}"
|
||||
th:href="@{${archives.nextUrl}}"
|
||||
class="pagination__next">较旧 →</a
|
||||
>
|
||||
</nav>
|
||||
</Layout>
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout pageTitle="分类">
|
||||
<Fragment slot="head">
|
||||
<title th:text="|分类 - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<nav class="taxonomy-list" aria-label="Category list">
|
||||
<div
|
||||
th:each="category : ${categories}"
|
||||
class="taxonomy-list__item"
|
||||
>
|
||||
<a
|
||||
class="taxonomy-list__link"
|
||||
th:href="@{${category.status.permalink}}"
|
||||
th:text="${category.spec.displayName}"
|
||||
>
|
||||
</a>
|
||||
<span class="taxonomy-list__count" th:text="|${category.postCount} 篇|">
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
</Layout>
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${category.spec.displayName} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<div class="page-heading">
|
||||
<h1 th:text="${category.spec.displayName}"></h1>
|
||||
<p class="page-meta">
|
||||
<span th:text="|${posts.total} 篇文章|"></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ul class="post-feed__list" role="list">
|
||||
<li th:each="post : ${posts.items}" class="post-feed__item">
|
||||
<a class="post-feed__link" th:href="@{${post.status.permalink}}">
|
||||
<div class="post-feed__body">
|
||||
<p
|
||||
class="post-feed__date"
|
||||
th:text="${#dates.format(post.spec.publishTime, 'yyyy-MM-dd')}"
|
||||
>
|
||||
</p>
|
||||
<h2 class="post-feed__title" th:text="${post.spec.title}"></h2>
|
||||
<p class="post-feed__excerpt" th:text="${post.status.excerpt}"></p>
|
||||
</div>
|
||||
<img
|
||||
th:unless="${#strings.isEmpty(post.spec.cover)}"
|
||||
class="post-feed__image"
|
||||
th:src="${post.spec.cover}"
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div th:if="${posts.total == 0}" class="feed-empty">暂无文章。</div>
|
||||
|
||||
<nav
|
||||
th:if="${posts.totalPages gt 1}"
|
||||
class="pagination"
|
||||
aria-label="Pagination"
|
||||
>
|
||||
<a
|
||||
th:if="${posts.hasPrevious()}"
|
||||
th:href="@{${posts.prevUrl}}"
|
||||
class="pagination__prev">← 较新</a
|
||||
>
|
||||
<span
|
||||
class="pagination__info"
|
||||
th:text="|${posts.page} / ${posts.totalPages}|"></span>
|
||||
<a
|
||||
th:if="${posts.hasNext()}"
|
||||
th:href="@{${posts.nextUrl}}"
|
||||
class="pagination__next">较旧 →</a
|
||||
>
|
||||
</nav>
|
||||
</Layout>
|
||||
+44
-90
@@ -1,95 +1,49 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import Card from "../components/Card.astro";
|
||||
import PostCard from "../components/PostCard.vue"
|
||||
---
|
||||
|
||||
<Layout title="Welcome to Astro.">
|
||||
<main>
|
||||
<h1>Welcome to <span class="text-gradient">Astro</span></h1>
|
||||
<p class="instructions">
|
||||
Check out the <code>src/pages</code> directory to get started.<br />
|
||||
<strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
|
||||
</p>
|
||||
<ul role="list" class="link-card-grid">
|
||||
<Card href="https://docs.astro.build/" title="Documentation"
|
||||
body="Learn how Astro works and explore the official API docs." />
|
||||
<Card href="https://astro.build/integrations/" title="Integrations"
|
||||
body="Supercharge your project with new frameworks and libraries." />
|
||||
<Card href="https://astro.build/themes/" title="Themes"
|
||||
body="Explore a galaxy of community-built starter themes." />
|
||||
<Card href="https://astro.build/chat/" title="Chat" body="Come say hi to our amazing Discord community. ❤️" />
|
||||
</ul>
|
||||
<ul class="list-decimal list-inside">
|
||||
<li th:text="#{foo}"></li>
|
||||
<li th:text="#{bar}"></li>
|
||||
<li th:text="#{hello('Ryan Wang')}"></li>
|
||||
</ul>
|
||||
<PostCard client:visible />
|
||||
<p th:each="post : ${postFinder.list(1, 10)}">
|
||||
<span th:text="${post.name}">Onions</span>
|
||||
</p>
|
||||
</main>
|
||||
<Layout>
|
||||
<Fragment slot="head">
|
||||
<title th:text="${site.title}"></title>
|
||||
</Fragment>
|
||||
<ul class="post-feed__list" role="list">
|
||||
<li th:each="post : ${posts.items}" class="post-feed__item">
|
||||
<a class="post-feed__link" th:href="@{${post.status.permalink}}">
|
||||
<div class="post-feed__body">
|
||||
<p
|
||||
class="post-feed__date"
|
||||
th:text="${#dates.format(post.spec.publishTime, 'yyyy-MM-dd')}"
|
||||
>
|
||||
</p>
|
||||
<h2 class="post-feed__title" th:text="${post.spec.title}"></h2>
|
||||
<p class="post-feed__excerpt" th:text="${post.status.excerpt}"></p>
|
||||
</div>
|
||||
<img
|
||||
th:unless="${#strings.isEmpty(post.spec.cover)}"
|
||||
class="post-feed__image"
|
||||
th:src="${post.spec.cover}"
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<nav
|
||||
th:if="${posts.totalPages gt 1}"
|
||||
class="pagination"
|
||||
aria-label="Pagination"
|
||||
>
|
||||
<a
|
||||
th:if="${posts.hasPrevious()}"
|
||||
th:href="@{${posts.prevUrl}}"
|
||||
class="pagination__prev">← 较新</a
|
||||
>
|
||||
<span
|
||||
class="pagination__info"
|
||||
th:text="|${posts.page} / ${posts.totalPages}|"></span>
|
||||
<a
|
||||
th:if="${posts.hasNext()}"
|
||||
th:href="@{${posts.nextUrl}}"
|
||||
class="pagination__next">较旧 →</a
|
||||
>
|
||||
</nav>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--astro-gradient: linear-gradient(0deg, #4f39fa, #da62c4);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
padding: 1em;
|
||||
max-width: 70ch;
|
||||
}
|
||||
|
||||
.text-gradient {
|
||||
font-weight: 900;
|
||||
background-image: var(--astro-gradient);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-size: 100% 200%;
|
||||
background-position-y: 100%;
|
||||
border-radius: 0.4rem;
|
||||
animation: pulse 4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
background-position-y: 0%;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-position-y: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.instructions {
|
||||
line-height: 1.6;
|
||||
margin: 1rem 0;
|
||||
background: #4f39fa;
|
||||
padding: 1rem;
|
||||
border-radius: 0.4rem;
|
||||
color: var(--color-bg);
|
||||
}
|
||||
|
||||
.instructions code {
|
||||
font-size: 0.875em;
|
||||
border: 0.1em solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
padding: 0.15em 0.25em;
|
||||
}
|
||||
|
||||
.link-card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
|
||||
gap: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
|
||||
const links = [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Ryan Wang's Blog",
|
||||
"url": "https://ryanc.cc/",
|
||||
"logo": "https://ryanc.cc/avatar",
|
||||
"description": "Hello Halo",
|
||||
"team": "",
|
||||
"priority": 0
|
||||
},
|
||||
{
|
||||
"id": 40,
|
||||
"name": "guqing's blog",
|
||||
"url": "https://www.guqing.xyz/",
|
||||
"logo": "https://www.guqing.xyz/avatar",
|
||||
"description": "毕生所求无它,爱与自由而已",
|
||||
"team": "",
|
||||
"priority": 0
|
||||
},
|
||||
{
|
||||
"id": 104,
|
||||
"name": "JohnNiang's Blog",
|
||||
"url": "https://johnniang.me",
|
||||
"logo": "https://johnniang.me/avatar",
|
||||
"description": "Core contributor of Halo organization.",
|
||||
"team": "",
|
||||
"priority": 0
|
||||
},
|
||||
{
|
||||
"id": 152,
|
||||
"name": "烟霞志",
|
||||
"url": "https://simplestark.com",
|
||||
"logo": "https://simplestark.com/avatar",
|
||||
"description": "空有烟霞之志,叹无水云之身。",
|
||||
"team": "",
|
||||
"priority": 0
|
||||
},
|
||||
]
|
||||
---
|
||||
|
||||
<Layout title="Links">
|
||||
<main>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2">
|
||||
|
||||
{links.map((data) => <a href={data.url} th:href="#{data.url}" target="_blank">
|
||||
<div
|
||||
class="relative rounded border border-gray-300 bg-white px-5 py-4 shadow-sm hover:shadow flex items-center space-x-3 hover:border-gray-400">
|
||||
<div class="flex-shrink-0">
|
||||
<img class="h-12 w-12 rounded-full" th:src="#{data.logo}" th:alt="#{data.name}" src={data.logo}
|
||||
alt={data.name}>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div>
|
||||
<p class="text-sm font-medium text-gray-900 truncate" th:text="#{data.name}">{data.name}</p>
|
||||
<p class="text-sm text-gray-500 truncate" th:text="#{data.description}">{data.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>)}
|
||||
</div>
|
||||
</main>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
main {
|
||||
margin: auto;
|
||||
padding: 1em;
|
||||
max-width: 70ch;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout contentClass="prose">
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${singlePage.spec.title} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<div class="page-heading">
|
||||
<h1 th:text="${singlePage.spec.title}"></h1>
|
||||
<p class="page-meta">
|
||||
<span
|
||||
th:text="${#dates.format(singlePage.spec.publishTime, 'yyyy-MM-dd')}"
|
||||
></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div th:utext="${singlePage.content.content}"></div>
|
||||
|
||||
<halo:comment
|
||||
group="content.halo.run"
|
||||
kind="SinglePage"
|
||||
th:attr="name=${singlePage.metadata.name}"></halo:comment>
|
||||
</Layout>
|
||||
+22
-10
@@ -1,14 +1,26 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import PostCard from "../components/PostCard.vue"
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const now = dayjs()
|
||||
---
|
||||
|
||||
<Layout title="Welcome to Post Page.">
|
||||
<time>{now}</time>
|
||||
<main>
|
||||
<PostCard client:visible />
|
||||
</main>
|
||||
</Layout>
|
||||
<Layout contentClass="prose">
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${post.spec.title} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<div class="page-heading">
|
||||
<h1 th:text="${post.spec.title}"></h1>
|
||||
<p class="page-meta">
|
||||
<span th:text="${#dates.format(post.spec.publishTime, 'yyyy-MM-dd')}"
|
||||
></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<th:block th:utext="${post.content.content}"></th:block>
|
||||
|
||||
<halo:comment
|
||||
group="content.halo.run"
|
||||
kind="Post"
|
||||
th:attr="name=${post.metadata.name}"
|
||||
>
|
||||
</halo:comment>
|
||||
</Layout>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${tag.spec.displayName} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<div class="page-heading">
|
||||
<h1 th:text="${tag.spec.displayName}"></h1>
|
||||
<p class="page-meta">
|
||||
<span th:text="|${posts.total} 篇文章|"></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ul class="post-feed__list" role="list">
|
||||
<li th:each="post : ${posts.items}" class="post-feed__item">
|
||||
<a class="post-feed__link" th:href="@{${post.status.permalink}}">
|
||||
<div class="post-feed__body">
|
||||
<p
|
||||
class="post-feed__date"
|
||||
th:text="${#dates.format(post.spec.publishTime, 'yyyy-MM-dd')}"
|
||||
>
|
||||
</p>
|
||||
<h2 class="post-feed__title" th:text="${post.spec.title}"></h2>
|
||||
<p class="post-feed__excerpt" th:text="${post.status.excerpt}"></p>
|
||||
</div>
|
||||
<img
|
||||
th:unless="${#strings.isEmpty(post.spec.cover)}"
|
||||
class="post-feed__image"
|
||||
th:src="${post.spec.cover}"
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div th:if="${posts.total == 0}" class="feed-empty">暂无文章。</div>
|
||||
|
||||
<nav
|
||||
th:if="${posts.totalPages gt 1}"
|
||||
class="pagination"
|
||||
aria-label="Pagination"
|
||||
>
|
||||
<a
|
||||
th:if="${posts.hasPrevious()}"
|
||||
th:href="@{${posts.prevUrl}}"
|
||||
class="pagination__prev">← 较新</a
|
||||
>
|
||||
<span
|
||||
class="pagination__info"
|
||||
th:text="|${posts.page} / ${posts.totalPages}|"></span>
|
||||
<a
|
||||
th:if="${posts.hasNext()}"
|
||||
th:href="@{${posts.nextUrl}}"
|
||||
class="pagination__next">较旧 →</a
|
||||
>
|
||||
</nav>
|
||||
</Layout>
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout pageTitle="标签">
|
||||
<Fragment slot="head">
|
||||
<title th:text="|标签 - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<div class="tag-cloud" role="list" aria-label="Tag list">
|
||||
<a
|
||||
th:each="tag : ${tags}"
|
||||
class="tag-pill"
|
||||
role="listitem"
|
||||
th:href="@{${tag.status.permalink}}"
|
||||
>
|
||||
<span th:text="${tag.spec.displayName}"></span>
|
||||
<span class="tag-pill__count" th:text="${tag.postCount}"></span>
|
||||
</a>
|
||||
</div>
|
||||
</Layout>
|
||||
@@ -0,0 +1,465 @@
|
||||
:root {
|
||||
--bg: #faf8f5;
|
||||
--bg-raised: #f2ede8;
|
||||
--ink: #1a1410;
|
||||
--ink-2: #7a7068;
|
||||
--ink-3: #b5aca2;
|
||||
--rule: #ddd8d0;
|
||||
--accent: #c2410c;
|
||||
--accent-bg: #fff4ed;
|
||||
--black: 26, 20, 16;
|
||||
--gray: 122, 112, 104;
|
||||
--gray-light: 221, 216, 208;
|
||||
--gray-dark: 44, 36, 30;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--bg: #181613;
|
||||
--bg-raised: #242018;
|
||||
--ink: #ede9e3;
|
||||
--ink-2: #9a9088;
|
||||
--ink-3: #5e5650;
|
||||
--rule: #2e2a24;
|
||||
--accent: #f47040;
|
||||
--accent-bg: #2a1a0c;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: ui-sans-serif, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: var(--bg);
|
||||
color: var(--ink);
|
||||
font-size: 17px;
|
||||
line-height: 1.75;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 820px;
|
||||
max-width: calc(100% - 2.5rem);
|
||||
margin: 0 auto;
|
||||
padding: 3rem 0 5rem;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: ui-sans-serif, sans-serif;
|
||||
margin: 0 0 0.5em;
|
||||
color: var(--ink);
|
||||
line-height: 1.2;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
h5 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
strong,
|
||||
b {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--accent);
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 1px;
|
||||
text-underline-offset: 0.2em;
|
||||
}
|
||||
a:hover {
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
}
|
||||
input {
|
||||
font-size: 16px;
|
||||
}
|
||||
table {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
img,
|
||||
video,
|
||||
iframe,
|
||||
embed,
|
||||
object {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.88em;
|
||||
padding: 0.15em 0.4em;
|
||||
background: var(--bg-raised);
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--rule);
|
||||
}
|
||||
pre {
|
||||
padding: 1.4em 1.6em;
|
||||
border-radius: 10px;
|
||||
overflow-x: auto;
|
||||
background: var(--ink);
|
||||
color: #f8f8f2;
|
||||
}
|
||||
pre > code {
|
||||
all: unset;
|
||||
font-size: 0.9em;
|
||||
color: inherit;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 0 0.75em 1.5em;
|
||||
border-left: 3px solid var(--accent);
|
||||
color: var(--ink-2);
|
||||
font-size: 1.1em;
|
||||
}
|
||||
hr {
|
||||
margin: 2.5rem 0;
|
||||
border: none;
|
||||
border-top: 1px solid var(--rule);
|
||||
}
|
||||
|
||||
/* ─── Page shell ─────────────────────────────────── */
|
||||
|
||||
.page-shell {
|
||||
display: grid;
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
.page-heading {
|
||||
padding-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--rule);
|
||||
}
|
||||
|
||||
.page-heading h1 {
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
|
||||
.page-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
margin-bottom: 0.6rem;
|
||||
color: var(--ink-3);
|
||||
font-size: 0.78rem;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
display: grid;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
/* ─── Post feed ──────────────────────────────────── */
|
||||
|
||||
.post-feed__list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.post-feed__item + .post-feed__item {
|
||||
border-top: 1px solid var(--rule);
|
||||
}
|
||||
|
||||
.post-feed__link {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 200px;
|
||||
gap: 2rem;
|
||||
align-items: start;
|
||||
padding: 2rem 0;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.post-feed__item:first-child .post-feed__link {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.post-feed__body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.55rem;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.post-feed__date {
|
||||
margin: 0;
|
||||
color: var(--ink-3);
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.post-feed__title {
|
||||
margin: 0;
|
||||
font-size: 1.35rem;
|
||||
line-height: 1.3;
|
||||
color: var(--ink);
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.post-feed__excerpt {
|
||||
margin: 0;
|
||||
color: var(--ink-2);
|
||||
font-size: 0.96rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.post-feed__image {
|
||||
display: block;
|
||||
width: 100%;
|
||||
aspect-ratio: 4 / 3;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.post-feed__link:hover .post-feed__title {
|
||||
color: var(--accent);
|
||||
}
|
||||
.post-feed__link:hover .post-feed__image {
|
||||
opacity: 0.88;
|
||||
}
|
||||
|
||||
/* ─── Taxonomy list (categories) ─────────────────── */
|
||||
|
||||
.taxonomy-list__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
padding: 0.55rem 0;
|
||||
}
|
||||
|
||||
.taxonomy-list__link {
|
||||
color: var(--ink);
|
||||
font-size: 1.05rem;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.taxonomy-list__link:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.taxonomy-list__count {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.2em 0.7em;
|
||||
border-radius: 999px;
|
||||
background: var(--bg-raised);
|
||||
border: 1px solid var(--rule);
|
||||
color: var(--ink-2);
|
||||
font-size: 0.82rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ─── Tag cloud (badges) ─────────────────────────── */
|
||||
|
||||
.tag-cloud {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.tag-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
padding: 0.35em 0.85em;
|
||||
border-radius: 6px;
|
||||
background: var(--bg-raised);
|
||||
border: 1px solid var(--rule);
|
||||
color: var(--ink-2);
|
||||
font-size: 0.88rem;
|
||||
text-decoration: none;
|
||||
transition:
|
||||
background 0.15s ease,
|
||||
color 0.15s ease,
|
||||
border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.tag-pill:hover {
|
||||
background: var(--accent-bg);
|
||||
color: var(--accent);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.tag-pill__count {
|
||||
font-size: 0.8em;
|
||||
color: var(--ink-3);
|
||||
}
|
||||
|
||||
/* ─── Archive ────────────────────────────────────── */
|
||||
|
||||
.archive-list {
|
||||
display: grid;
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
.archive-group {
|
||||
display: grid;
|
||||
grid-template-columns: 80px minmax(0, 1fr);
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.archive-group__year {
|
||||
margin: 0;
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: var(--ink-3);
|
||||
letter-spacing: -0.01em;
|
||||
padding-top: 0.2rem;
|
||||
}
|
||||
|
||||
.archive-group__items {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.archive-entry {
|
||||
display: grid;
|
||||
grid-template-columns: 80px minmax(0, 1fr);
|
||||
gap: 1rem;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
.archive-entry__date {
|
||||
color: var(--ink-3);
|
||||
font-size: 0.85rem;
|
||||
padding-top: 0.15rem;
|
||||
}
|
||||
|
||||
.archive-entry__title {
|
||||
margin: 0 0 0.2rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.archive-entry__summary {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
color: var(--ink-2);
|
||||
}
|
||||
|
||||
/* ─── Responsive ─────────────────────────────────── */
|
||||
|
||||
@media (max-width: 680px) {
|
||||
main {
|
||||
max-width: calc(100% - 2rem);
|
||||
padding: 2rem 0 4rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.post-feed__link {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1rem;
|
||||
padding: 1.5rem 0;
|
||||
}
|
||||
|
||||
.post-feed__image {
|
||||
aspect-ratio: 16 / 9;
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.taxonomy-list__item,
|
||||
.archive-group,
|
||||
.archive-entry {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.archive-group {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.taxonomy-list__item {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── Pagination ─────────────────────────────────── */
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid var(--rule);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.pagination__prev,
|
||||
.pagination__next {
|
||||
color: var(--ink-2);
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.pagination__prev:hover,
|
||||
.pagination__next:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.pagination__info {
|
||||
color: var(--ink-3);
|
||||
}
|
||||
|
||||
.archive-empty,
|
||||
.feed-empty {
|
||||
color: var(--ink-3);
|
||||
font-size: 0.95rem;
|
||||
padding: 2rem 0;
|
||||
}
|
||||
Reference in New Issue
Block a user