Compare commits

..

No commits in common. "f6cc226e0386d77c7f2ffcb8222d3933f75cc4ef" and "73f8046888f94c024fe95a6ca5da79c77e2f9dee" have entirely different histories.

11 changed files with 81 additions and 186 deletions

View file

@ -1,11 +1,8 @@
--- ---
import ArticleMenu from './ArticleMenu.astro';
import { AstroComponentFactory } from 'astro/dist/runtime/server'; import { AstroComponentFactory } from 'astro/dist/runtime/server';
export interface Props { export interface Props {
PostContent: AstroComponentFactory; PostContent: AstroComponentFactory;
slug: string;
title: string; title: string;
description: string; description: string;
readingTime: number; readingTime: number;
@ -15,9 +12,8 @@ export interface Props {
} }
const { const {
PostContent, slug, PostContent, title, description,
title, description, readingTime, date, image,
readingTime, date,
preview = false, preview = false,
} = Astro.props; } = Astro.props;
@ -36,28 +32,13 @@ const locale = 'ru';
{readingTime.toFixed(1)} min read {readingTime.toFixed(1)} min read
</span> </span>
</address> </address>
{
!preview ?
<ArticleMenu slug={slug} title={title} /> :
""
}
</header> </header>
{ {
!preview ? !preview ?
<article> <article>
<PostContent /> <PostContent />
</article> : </article> :
<div class="description"> <div>
{description} {description}
</div> </div>
} }
<style lang="less">
address {
margin-top: 0.25rem;
}
.description {
margin-top: 0.25rem;
}
</style>

View file

@ -1,6 +1,7 @@
--- ---
import Article from './Article.astro'; import Article from './Article.astro';
import ArticleMenu from './ArticleMenu.astro'; import SimpleMenu from '../layouts/SimpleMenu.astro';
import MenuItem from './MenuItem.astro';
import postRenderer from '../post-renderer.mjs'; import postRenderer from '../post-renderer.mjs';
import { postType } from '../post-renderer.mjs'; import { postType } from '../post-renderer.mjs';
@ -14,6 +15,7 @@ const {
PostContent, title, description, PostContent, title, description,
readingTime, date, image, readingTime, date, image,
} = await postRenderer(post); } = await postRenderer(post);
const link = `/blog/${post.slug}`;
--- ---
<div class="card card-elevated" id={post.slug}> <div class="card card-elevated" id={post.slug}>
@ -26,7 +28,41 @@ const {
image={image} image={image}
preview={true} preview={true}
/> />
<ArticleMenu slug={post.slug} title={title} isCard /> <SimpleMenu jcc="end">
<MenuItem
name={/*Comments*/""}
link={`/blog/comments#${post.slug}`}
icon="&#xf075;"
atLeft={false}
/>
<MenuItem
name={/*Copy Link*/""}
link="javascript:void(0)"
icon="&#xf0c5;"
atLeft={false}>
<span slot="js-dataset"
data-btn="copylink"
data-url={link}>
</span>
</MenuItem>
<MenuItem
name={/*Share*/""}
link="javascript:void(0)"
icon="&#xf1e0;"
atLeft={false}>
<span slot="js-dataset"
data-btn="share"
data-title={title}
data-url={link}>
</span>
</MenuItem>
<MenuItem
name="Read"
link={link}
icon="&#xf105;"
atLeft={false}
/>
</SimpleMenu>
</div> </div>
<style> <style>

View file

@ -1,78 +0,0 @@
---
import SimpleMenu from '../layouts/SimpleMenu.astro';
import MenuItem from './MenuItem.astro';
export interface Props {
slug: string;
title: string;
isCard?: boolean;
}
const { slug, title, isCard = false } = Astro.props;
const link = `/blog/${slug}`;
---
<SimpleMenu jc={isCard ? "end" : "start"} largeGap={!isCard}>
<MenuItem
name="Comments"
link={`${link}#comments`}
icon="&#xf075;"
iconAfter={isCard}
hideLabel={isCard}
/>
<MenuItem
name="Copy link"
link="javascript:void(0)"
icon="&#xf0c5;"
classes={["btn-copy"]}
dataset={{"data-url": link}}
iconAfter={isCard}
hideLabel={isCard}
/>
<MenuItem
name="Share"
link="javascript:void(0)"
icon="&#xf1e0;"
classes={["btn-share"]}
dataset={{"data-url": link, "data-title": title}}
iconAfter={isCard}
hideLabel={isCard}
/>
{
isCard ?
<MenuItem
name="Read"
link={link}
icon="&#xf105;"
iconAfter={true}
/> :
""
}
</SimpleMenu>
<script>
const handlerCopy = (ev: Event) => {
const elem = ev.currentTarget as HTMLAnchorElement
navigator.clipboard.writeText(
location.origin + elem.dataset.url
)
}
const handlerShare = (ev: Event) => {
const elem = ev.currentTarget as HTMLAnchorElement
navigator.share({
title: elem.dataset.title,
url: elem.dataset.url,
})
}
const btnsCopy = document.querySelectorAll('.btn-copy')
for (let btn of btnsCopy) {
btn.addEventListener('click', handlerCopy)
}
const btnsShare = document.querySelectorAll('.btn-share')
for (let btn of btnsShare) {
btn.addEventListener('click', handlerShare)
}
</script>

View file

@ -1,4 +1,5 @@
--- ---
import SimpleMenu from '../layouts/SimpleMenu.astro';
import Icon from './Icon.astro'; import Icon from './Icon.astro';
export interface Props { export interface Props {

View file

@ -6,89 +6,51 @@ export interface Props {
link: string; link: string;
icon: string; icon: string;
tblank?: boolean; tblank?: boolean;
iconAfter?: boolean; atLeft?: boolean;
hideLabel?: boolean;
classes?: Array<string>; classes?: Array<string>;
dataset?: Object; datajs?: string;
} }
const { const {
name, link, icon, name, link, icon,
tblank = false, tblank = false,
iconAfter = false, atLeft = true,
hideLabel = false,
classes = [], classes = [],
dataset = {}, datajs = "",
} = Astro.props; } = Astro.props;
--- ---
<li class:list={{"icon-after": iconAfter, "hide-label": hideLabel}}> <li>
<a href={link} target={tblank ? "_blank" : "_self"} class:list={classes} {...dataset}> <slot name="js-dataset"></slot>
<a href={link} target={tblank ? "_blank" : "_self"} class:list={classes} data-js={datajs}>
<span class="icon-wrapper"> <span class="icon-wrapper">
<Icon code={icon} /> <Icon code={icon} />
</span> </span>
<span class="name">{name}</span> {name}
</a> </a>
</li> </li>
<style lang="less"> <style lang="less" define:vars={{fxd: atLeft ? "row" : "row-reverse"}}>
@icon-size: 1.5rem; a {
display: flex;
flex-direction: var(--fxd);
align-items: center;
li { font-size: 1.15rem;
a {
display: flex;
flex-direction: row;
align-items: center;
column-gap: 0.125rem;
font-size: 1.15rem;
}
&:hover {
.icon-wrapper {
color: var(--fg);
}
}
}
li.icon-after {
a {
flex-direction: row-reverse;
}
}
li.hide-label {
a {
flex-direction: column;
align-items: center;
}
.name {
display: none;
}
position: relative;
&:hover {
.name {
display: block;
width: max-content;
padding: 0.2rem;
position: absolute;
bottom: @icon-size + 0.25rem;
z-index: 10;
font-size: 0.9rem;
color: #eee;
background: rgba(0, 0, 0, .7);
border-radius: 0.2rem;
}
}
} }
.icon-wrapper { .icon-wrapper {
width: @icon-size; margin-right: 0.2rem;
font-size: @icon-size; width: 1.5rem;
font-size: 1.5rem;
color: var(--fg-sec); color: var(--fg-sec);
} }
li:hover {
.icon-wrapper {
color: var(--fg);
}
}
</style> </style>

View file

@ -6,18 +6,19 @@ import MenuItem from "../components/MenuItem.astro";
export interface Props { export interface Props {
title: string; title: string;
description: string; description: string;
mainpage?: boolean; article?: boolean;
} }
const { title, description, mainpage = false } = Astro.props; const { title, description, article = false } = Astro.props;
--- ---
<Layout title={"Blog | " + title} description={description}> <Layout title={"Blog | " + title} description={description}>
<slot name="metadata" slot="metadata" /> <slot name="metadata" slot="metadata" />
<NavMenu> <NavMenu>
{ {
mainpage ? !article ?
<MenuItem name="Home" icon="&#xf104;" link="/" /> : <MenuItem name="Home" icon="&#xf104;" link="/" />
<MenuItem name="Articles" icon="&#xf1ea;" link="/blog" /> :
<MenuItem name="Articles" icon="&#xf104;" link="/blog" /> <MenuItem name="Articles" icon="&#xf104;" link="/blog" />
} }
<MenuItem name="Shorts" icon="&#xf0e7;" link="/blog/shorts" /> <MenuItem name="Shorts" icon="&#xf0e7;" link="/blog/shorts" />

View file

@ -52,6 +52,7 @@ const { title, description } = Astro.props;
margin: auto; margin: auto;
padding: @main-padding; padding: @main-padding;
max-width: @max-width; max-width: @max-width;
width: 100%;
} }
article { article {

View file

@ -59,7 +59,6 @@ const { id } = Astro.props;
border-radius: var(--bdrs); border-radius: var(--bdrs);
background: var(--bg); background: var(--bg);
box-shadow: 0 0 1rem #161616;
} }
.controls { .controls {

View file

@ -1,17 +1,16 @@
--- ---
export interface Props { export interface Props {
jc: "start" | "center" | "end" | "space-around" | "space-between"; jcc: "start" | "center" | "end" | "space-around" | "space-between";
largeGap?: boolean;
} }
const { jc, largeGap = false } = Astro.props; const { jcc } = Astro.props;
--- ---
<ul style={{columnGap: largeGap ? "0.5rem" : "0.125rem"}}> <ul>
<slot /> <slot />
</ul> </ul>
<style lang="less" define:vars={{jc: jc}}> <style lang="less" define:vars={{jcc: jcc}}>
ul { ul {
list-style: none; list-style: none;
margin: 0; margin: 0;
@ -19,6 +18,6 @@ const { jc, largeGap = false } = Astro.props;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: var(--jc); justify-content: var(--jcc);
} }
</style> </style>

View file

@ -3,9 +3,7 @@ import BlogLayout from "../../layouts/BlogLayout.astro";
import Article from "../../components/Article.astro"; import Article from "../../components/Article.astro";
import { getCollection } from "astro:content"; import { getCollection } from "astro:content";
import postRenderer from "../../post-renderer.mjs"; import postRenderer from "../../post-renderer.mjs";
import { postType } from "../../post-renderer.mjs";
export async function getStaticPaths() { export async function getStaticPaths() {
const posts = await getCollection("blog"); const posts = await getCollection("blog");
@ -17,14 +15,14 @@ export async function getStaticPaths() {
})); }));
} }
const post: postType = Astro.props.post; const { post } = Astro.props;
const { const {
PostContent, title, description, PostContent, title, description,
readingTime, date, image, readingTime, date, image,
} = await postRenderer(post); } = await postRenderer(post);
--- ---
<BlogLayout title={title} description={description}> <BlogLayout title={title} description={description} article={true}>
<Fragment slot="metadata"> <Fragment slot="metadata">
<meta property="og:type" content="article" /> <meta property="og:type" content="article" />
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
@ -39,7 +37,6 @@ const {
</Fragment> </Fragment>
<Article <Article
PostContent={PostContent} PostContent={PostContent}
slug={post.slug}
title={title} title={title}
description={description} description={description}
readingTime={readingTime} readingTime={readingTime}
@ -51,10 +48,6 @@ const {
<style lang="less" is:global> <style lang="less" is:global>
@import "/src/styles/max_width.less"; @import "/src/styles/max_width.less";
main {
width: 100%;
}
article { article {
margin: 0; margin: 0;

View file

@ -28,7 +28,7 @@ const description =
"The simpliest things!"; "The simpliest things!";
--- ---
<BlogLayout title="Homepage" description={description} mainpage> <BlogLayout title="Homepage" description={description}>
<Fragment slot="metadata"> <Fragment slot="metadata">
<meta name="robots" content="noindex, follow" /> <meta name="robots" content="noindex, follow" />
</Fragment> </Fragment>