Compare commits

..

3 commits

11 changed files with 186 additions and 81 deletions

View file

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

View file

@ -1,7 +1,6 @@
---
import Article from './Article.astro';
import SimpleMenu from '../layouts/SimpleMenu.astro';
import MenuItem from './MenuItem.astro';
import ArticleMenu from './ArticleMenu.astro';
import postRenderer from '../post-renderer.mjs';
import { postType } from '../post-renderer.mjs';
@ -15,7 +14,6 @@ const {
PostContent, title, description,
readingTime, date, image,
} = await postRenderer(post);
const link = `/blog/${post.slug}`;
---
<div class="card card-elevated" id={post.slug}>
@ -28,41 +26,7 @@ const link = `/blog/${post.slug}`;
image={image}
preview={true}
/>
<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>
<ArticleMenu slug={post.slug} title={title} isCard />
</div>
<style>

View file

@ -0,0 +1,78 @@
---
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,5 +1,4 @@
---
import SimpleMenu from '../layouts/SimpleMenu.astro';
import Icon from './Icon.astro';
export interface Props {

View file

@ -6,51 +6,89 @@ export interface Props {
link: string;
icon: string;
tblank?: boolean;
atLeft?: boolean;
iconAfter?: boolean;
hideLabel?: boolean;
classes?: Array<string>;
datajs?: string;
dataset?: Object;
}
const {
name, link, icon,
tblank = false,
atLeft = true,
iconAfter = false,
hideLabel = false,
classes = [],
datajs = "",
dataset = {},
} = Astro.props;
---
<li>
<slot name="js-dataset"></slot>
<a href={link} target={tblank ? "_blank" : "_self"} class:list={classes} data-js={datajs}>
<li class:list={{"icon-after": iconAfter, "hide-label": hideLabel}}>
<a href={link} target={tblank ? "_blank" : "_self"} class:list={classes} {...dataset}>
<span class="icon-wrapper">
<Icon code={icon} />
</span>
{name}
<span class="name">{name}</span>
</a>
</li>
<style lang="less" define:vars={{fxd: atLeft ? "row" : "row-reverse"}}>
a {
display: flex;
flex-direction: var(--fxd);
align-items: center;
<style lang="less">
@icon-size: 1.5rem;
font-size: 1.15rem;
li {
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 {
margin-right: 0.2rem;
width: 1.5rem;
font-size: 1.5rem;
width: @icon-size;
font-size: @icon-size;
color: var(--fg-sec);
}
li:hover {
.icon-wrapper {
color: var(--fg);
}
}
</style>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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