feat: back-to-top, footer, about page, responsive design, etc.

(cherry picked from commit 21319d339305c77311d42aa18501d425a5a2619c)
This commit is contained in:
saicaca 2023-09-29 11:58:14 +08:00
parent 124843848f
commit 8ed0aa071f
14 changed files with 127 additions and 20 deletions

View File

@ -85,12 +85,12 @@ function formatDate(date: Date) {
></div> ></div>
</div> </div>
<!-- post title --> <!-- post title -->
<div class="max-w-[65%] w-[65%] transition text-left font-bold"> <div class="max-w-[65%] w-[65%] text-left font-bold
<div class="group-hover:ml-1 transition-all group-hover:text-[var(--primary)] group-hover:translate-x-1 transition-all group-hover:text-[var(--primary)]
text-black/80 dark:text-white/80 pr-8 whitespace-nowrap overflow-ellipsis overflow-hidden"> text-black/80 dark:text-white/80 pr-8 whitespace-nowrap overflow-ellipsis overflow-hidden"
>
{post.data.title} {post.data.title}
</div> </div>
</div>
<!-- tag list --> <!-- tag list -->
<div class="w-[15%] text-left text-sm transition <div class="w-[15%] text-left text-sm transition
whitespace-nowrap overflow-ellipsis overflow-hidden whitespace-nowrap overflow-ellipsis overflow-hidden

View File

@ -0,0 +1,11 @@
---
---
<div class="card-base max-w-[var(--page-width)] min-h-[72px] rounded-b-none mx-auto flex items-center px-6">
<div class="text-black/50 dark:text-white/50 text-sm">
© 2023 Author. All Rights Reserved.
<br>
Powered by Vivia
</div>
</div>

View File

@ -65,6 +65,8 @@ color_set({
--deep-text: oklch(0.25 0.02 var(--hue)) --deep-text: oklch(0.25 0.02 var(--hue))
--line-divider: black(0.08) white(0.08)
--line-color: black(0.1) white(0.1) --line-color: black(0.1) white(0.1)
--meta-divider: black(0.2) white(0.2) --meta-divider: black(0.2) white(0.2)
--selection-bg: oklch(0.90 0.05 var(--hue)) oklch(0.40 0.08 var(--hue)) --selection-bg: oklch(0.90 0.05 var(--hue)) oklch(0.40 0.08 var(--hue))
@ -88,5 +90,8 @@ color_set({
h1, h2, h3, h4, h5, h6, p, a, span, li, ul, ol, blockquote, code, pre, table, th, td, strong { h1, h2, h3, h4, h5, h6, p, a, span, li, ul, ol, blockquote, code, pre, table, th, td, strong {
@apply transition; @apply transition;
} }
.card-shadow {
@apply drop-shadow-[0_2px_4px_rgba(0,0,0,0.005)]
}
} }
</style> </style>

View File

@ -15,7 +15,7 @@ const className = Astro.props.class;
<div> <div>
<a href="/"><Button light class="font-bold px-5">Home</Button></a> <a href="/"><Button light class="font-bold px-5">Home</Button></a>
<a href="/archive"><Button light class="font-bold px-5">Archive</Button></a> <a href="/archive"><Button light class="font-bold px-5">Archive</Button></a>
<Button light class="font-bold px-5">About</Button> <a href="/about"><Button light class="font-bold px-5">About</Button></a>
</div> </div>
<div> <div>
<Button id="scheme-switch" iconName="material-symbols:wb-sunny-outline-rounded" iconSize={20} isIcon light></Button> <Button id="scheme-switch" iconName="material-symbols:wb-sunny-outline-rounded" iconSize={20} isIcon light></Button>

View File

@ -30,14 +30,14 @@ const coverWidth = "30%";
const { remarkPluginFrontmatter } = await entry.render(); const { remarkPluginFrontmatter } = await entry.render();
--- ---
<div class:list={["card-base flex w-full rounded-[var(--radius-large)] overflow-hidden relative", className]}> <div class:list={["card-base flex flex-col-reverse lg:flex-col w-full rounded-[var(--radius-large)] overflow-hidden relative", className]}>
<div class:list={[" px-10 pt-7 pb-6 relative", {'w-full': !hasCover, "w-[calc(100%_-_var(--coverWidth))]": hasCover}]}> <div class:list={[" px-10 pt-4 lg:pt-7 pb-6 relative", {'w-full': !hasCover, "w-full lg:w-[calc(100%_-_var(--coverWidth))]": hasCover}]}>
<a href={url} <a href={url}
class="transition w-full block font-bold mb-3 text-4xl class="transition w-full block font-bold mb-3 text-4xl
text-black/90 dark:text-white/90 text-black/90 dark:text-white/90
hover:text-[var(--primary)] dark:hover:text-[var(--primary)] hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)] before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
before:absolute before:top-[38px] before:left-5 before:absolute before:top-[26px] lg:before:top-[38px] before:left-5
"> ">
{title} {title}
</a> </a>
@ -58,7 +58,10 @@ const { remarkPluginFrontmatter } = await entry.render();
</div> </div>
{hasCover && <a href={url} {hasCover && <a href={url}
class=`group w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden`> class:list={["group",
"max-h-[20vh] lg:max-h-none mx-4 mt-4 lg:mx-0 lg:mt-0",
"lg:w-[var(--coverWidth)] relative lg:absolute lg:top-3 lg:bottom-3 lg:right-3 rounded-xl overflow-hidden"
]} >
<div class="absolute z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition"></div> <div class="absolute z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition"></div>
<div class="absolute z-20 w-full h-full flex items-center justify-center "> <div class="absolute z-20 w-full h-full flex items-center justify-center ">
<Icon name="material-symbols:chevron-right-rounded" <Icon name="material-symbols:chevron-right-rounded"

View File

@ -0,0 +1,59 @@
---
import { Icon } from 'astro-icon/components';
import Button from "./Button.astro";
---
<!-- There can't be a filter on parent element, or it will break `fixed` -->
<div class="back-to-top-wrapper" transition:persist>
<div id="back-to-top-btn" class="back-to-top-btn hide flex items-center rounded-2xl overflow-hidden" onclick="topFunction()">
<Button card height="60px" width="60px">
<Icon name="material-symbols:keyboard-arrow-up-rounded" class="mx-auto"></Icon>
</Button>
</div>
</div>
<style lang="stylus">
.back-to-top-wrapper
width: 60px
height: 60px
position: absolute
right: -84px
top: 0
.back-to-top-btn
color: var(--primary)
font-size: 36px
font-weight: bold
border: none
position: fixed
bottom: 240px
opacity: 1
cursor: pointer
i
font-size: 28px
&.hide
transform: scale(0.9)
opacity: 0
pointer-events: none
</style>
<script is:raw>
function topFunction() {
window.scroll({ top: 0, behavior: 'smooth' });
}
function scrollFunction() {
let btn = document.getElementById('back-to-top-btn');
if (document.body.scrollTop > 600 || document.documentElement.scrollTop > 600) {
btn.classList.remove('hide')
} else {
btn.classList.add('hide')
}
}
window.onscroll = function() {
scrollFunction();
}
</script>

View File

@ -45,10 +45,10 @@ import { Icon } from 'astro-icon/components';
'bg-none': light, 'bg-none': light,
'hover:bg-[var(--btn-plain-bg-hover)]': light, 'hover:bg-[var(--btn-plain-bg-hover)]': light,
'active:bg-[var(--btn-plain-bg-active)]': light, 'active:bg-[var(--btn-plain-bg-active)]': light,
'text-neutral-900': light, 'text-black/75': light,
'hover:text-[var(--primary)]': light, 'hover:text-[var(--primary)]': light,
'dark:text-neutral-300': light || regular, 'dark:text-white/75': light || regular,
'dark:hover:text-[var(--primary)]': light, 'dark:hover:text-[var(--primary)]': light,
'bg-[var(--btn-regular-bg)]': regular, 'bg-[var(--btn-regular-bg)]': regular,

View File

@ -11,7 +11,7 @@ const vConf = getConfig();
--- ---
<div class="card-base" transition:persist> <div class="card-base" transition:persist>
<ImageBox src={vConf.profile.avatar} class="w-full rounded-2xl mb-3"></ImageBox> <ImageBox src={vConf.profile.avatar} class="w-[240px] mt-4 mx-auto lg:w-full lg:mt-0 rounded-2xl mb-3"></ImageBox>
<div class="font-bold text-lg text-center mb-1 dark:text-neutral-50 transition">{vConf.profile.author}</div> <div class="font-bold text-lg text-center mb-1 dark:text-neutral-50 transition">{vConf.profile.author}</div>
<div class="h-1 w-5 bg-[var(--primary)] mx-auto rounded-full mb-3 transition"></div> <div class="h-1 w-5 bg-[var(--primary)] mx-auto rounded-full mb-3 transition"></div>
<div class="text-center text-neutral-400 mb-2 transition">{vConf.profile.subtitle}</div> <div class="text-center text-neutral-400 mb-2 transition">{vConf.profile.subtitle}</div>

View File

View File

@ -75,7 +75,7 @@ if (!banner || typeof banner !== 'string' || banner.trim() === '') {
<title>{title}</title> <title>{title}</title>
</head> </head>
<body class="bg-[oklch(0.95_0.01_var(--hue))] dark:bg-[oklch(0.16_0.014_var(--hue))] min-h-screen transition"> <body class="bg-[oklch(0.95_0.01_var(--hue))] dark:bg-[oklch(0.16_0.014_var(--hue))] min-h-screen transition ">
<GlobalStyles> <GlobalStyles>
<div class="absolute w-full" <div class="absolute w-full"
class:list={{'banner-home': isHomePage, 'banner-else': !isHomePage}} class:list={{'banner-home': isHomePage, 'banner-else': !isHomePage}}

View File

@ -3,6 +3,8 @@ import Layout from "./Layout.astro";
import Navbar from "../components/Navbar.astro"; import Navbar from "../components/Navbar.astro";
import SideBar from "../components/widget/SideBar.astro"; import SideBar from "../components/widget/SideBar.astro";
import {pathsEqual} from "../utils/url-utils"; import {pathsEqual} from "../utils/url-utils";
import Footer from "../components/Footer.astro";
import BackToTop from "../components/control/BackToTop.astro";
interface Props { interface Props {
title: string; title: string;
@ -18,7 +20,7 @@ const sidebarWidth = "280px";
--- ---
<Layout title={title} banner={banner}> <Layout title={title} banner={banner}>
<div class=`max-w-[1200px] grid grid-cols-[280px_auto] grid-auto-rows-[auto] mx-auto gap-4 relative` <div class=`max-w-[1200px] min-h-screen grid grid-cols-[280px_auto] grid-rows-[auto_auto_1fr_auto] lg:grid-rows-[auto_1fr_auto] mx-auto gap-4 relative overflow-hidden `
transition:animate="none" transition:animate="none"
> >
<div id="top-row" class="col-span-2 grid-rows-1" class:list={{ <div id="top-row" class="col-span-2 grid-rows-1" class:list={{
@ -27,14 +29,21 @@ const sidebarWidth = "280px";
> >
<Navbar transition:animate="fade" transition:persist></Navbar> <Navbar transition:animate="fade" transition:persist></Navbar>
</div> </div>
<SideBar class="max-w-[280px] col-span-1 grid-rows-2" transition:persist></SideBar> <SideBar class="row-start-3 row-end-4 col-span-2 lg:row-start-2 lg:row-end-3 lg:col-span-1 lg:max-w-[280px] overflow-hidden" transition:persist></SideBar>
<div class="grid-rows-2 grid-cols-2 overflow-hidden" transition:animate="slide"> <div class="row-start-2 row-end-3 col-span-2 lg:col-span-1 overflow-hidden" transition:animate="slide">
<!-- the overflow-hidden here prevent long text break the layout--> <!-- the overflow-hidden here prevent long text break the layout-->
<slot></slot> <slot></slot>
</div> </div>
<div class="grid-rows-3 col-span-2 mt-4" transition:persist>
<Footer></Footer>
</div>
<BackToTop></BackToTop>
</div> </div>
</Layout> </Layout>
<style> <style>

20
src/pages/about.astro Normal file
View File

@ -0,0 +1,20 @@
---
import MainGridLayout from "../layouts/MainGridLayout.astro";
import { getEntry } from 'astro:content'
const aboutPost = await getEntry('spec', 'about')
const { Content } = await aboutPost.render()
---
<MainGridLayout>
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative min-h-[120px]">
<div class="card-base z-10 px-9 py-6 relative w-full ">
<div class="prose dark:prose-invert max-w-none prose-h1:text-3xl">
<Content />
</div>
</div>
</div>
</MainGridLayout>

View File

@ -30,13 +30,13 @@ const { remarkPluginFrontmatter } = await entry.render();
]}> ]}>
<div class="flex flex-row text-black/30 dark:text-white/30 gap-5 mb-3 transition"> <div class="flex flex-row text-black/30 dark:text-white/30 gap-5 mb-3 transition">
<div class="flex flex-row items-center"> <div class="flex flex-row items-center">
<div class="transition h-6 w-6 rounded-md bg-black/5 dark:bg-white/5 text-black/50 dark:text-white/50 flex items-center justify-center mr-2"> <div class="transition h-6 w-6 rounded-md bg-black/5 dark:bg-white/10 text-black/50 dark:text-white/50 flex items-center justify-center mr-2">
<Icon name="material-symbols:notes-rounded"></Icon> <Icon name="material-symbols:notes-rounded"></Icon>
</div> </div>
<div class="text-sm">{remarkPluginFrontmatter.words} words</div> <div class="text-sm">{remarkPluginFrontmatter.words} words</div>
</div> </div>
<div class="flex flex-row items-center"> <div class="flex flex-row items-center">
<div class="transition h-6 w-6 rounded-md bg-black/5 dark:bg-white/5 text-black/50 dark:text-white/50 flex items-center justify-center mr-2"> <div class="transition h-6 w-6 rounded-md bg-black/5 dark:bg-white/10 text-black/50 dark:text-white/50 flex items-center justify-center mr-2">
<Icon name="material-symbols:schedule-outline-rounded"></Icon> <Icon name="material-symbols:schedule-outline-rounded"></Icon>
</div> </div>
<div class="text-sm">{remarkPluginFrontmatter.minutes} minutes</div> <div class="text-sm">{remarkPluginFrontmatter.minutes} minutes</div>
@ -59,7 +59,7 @@ const { remarkPluginFrontmatter } = await entry.render();
categories={entry.data.categories} categories={entry.data.categories}
></PostMetadata> ></PostMetadata>
<div class="border-b-black/8 dark:border-b-white/8 border-dashed border-b-[1px] mb-5"></div> <div class="border-[var(--line-divider)] border-dashed border-b-[1px] mb-5"></div>
<div class="prose dark:prose-invert max-w-none prose-h1:text-3xl"> <div class="prose dark:prose-invert max-w-none prose-h1:text-3xl">
<Content /> <Content />

View File

@ -1,5 +1,5 @@
appearance: appearance:
hue: 290 hue: 250
banner: banner:
url: https://saicaca.github.io/vivia-preview/assets/banner.jpg url: https://saicaca.github.io/vivia-preview/assets/banner.jpg