Implement mastodon comments
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
main > p:not(.nodropcap):first-of-type:first-letter {
|
||||
main > article > p:not(.nodropcap):first-of-type:first-letter {
|
||||
float: left;
|
||||
font-size: 4rem;
|
||||
padding: .5rem .5rem .5rem .5rem;
|
||||
|
@ -24,7 +24,7 @@
|
||||
--icon-filter: none;
|
||||
|
||||
/* Corners */
|
||||
--corner-radius: .3rem;
|
||||
--border-radius: .3rem;
|
||||
|
||||
/* Space & Size */
|
||||
--syntax-tab-size: 2;
|
||||
@ -32,6 +32,7 @@
|
||||
--single-gap: 1rem;
|
||||
--double-gap: 2rem;
|
||||
--triple-gap: 3rem;
|
||||
--quad-gap: 4rem;
|
||||
|
||||
/* Transitions */
|
||||
--transition-normal: all .3s;
|
||||
@ -49,11 +50,28 @@
|
||||
--weight-heavy: 500;
|
||||
--weight-normal: 300;
|
||||
|
||||
/* Links */
|
||||
--link-decoration-thickness: .1rem;
|
||||
|
||||
/* Borders */
|
||||
--border-nav: 1px solid var(--text-color);
|
||||
--border-nav-currentpage: 20px solid var(--contrast-color);
|
||||
--border-nav-hover: 20px solid var(--text-color);
|
||||
--border-thin: 1px solid var(--color-gray-20);
|
||||
|
||||
/* Shadow */
|
||||
--box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
|
||||
/* Components */
|
||||
--wc-card-background-color: var(--card-color);
|
||||
--wc-card-border-radius: var(--border-radius);
|
||||
--wc-card-box-shadow: var(--box-shadow);
|
||||
--wc-link-color: var(--text-color);
|
||||
--wc-link-decoration-color: var(--contrast-color);
|
||||
--wc-link-decoration-thickness: var(--link-decoration-thickness);
|
||||
--wc-comment-text-margin: auto auto auto 4rem;
|
||||
--wc-profile-pic-size: 3rem;
|
||||
--wc-profile-pic-border-radius: 10rem;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@ -64,7 +82,7 @@
|
||||
--contrast-color: #04c49e;
|
||||
|
||||
/* --text-color is assigned to --color-gray-_ above */
|
||||
--text-color-link: var(--contrast-color);
|
||||
--text-color-link: var(--text-color);
|
||||
|
||||
--background-color: #15202b;
|
||||
--logo-filter: none;
|
||||
@ -96,6 +114,7 @@ body {
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
font-family: var(--font-family);
|
||||
font-size: 13px;
|
||||
font-variant-Ligatures: normal;
|
||||
font-weight: var(--weight-normal);
|
||||
margin: 0 auto;
|
||||
@ -109,7 +128,7 @@ body {
|
||||
}
|
||||
a {
|
||||
text-decoration-color: var(--contrast-color);
|
||||
text-decoration-thickness: .1rem;
|
||||
text-decoration-thickness: var(--link-decoration-thickness);
|
||||
transition: var(--transition-normal);
|
||||
}
|
||||
/* https://www.a11yproject.com/posts/how-to-hide-content/ */
|
||||
@ -123,8 +142,18 @@ a {
|
||||
width: 1px;
|
||||
}
|
||||
footer {
|
||||
margin-top: var(--triple-gap);
|
||||
padding: var(--single-gap);
|
||||
border-top: var(--border-thin);
|
||||
}
|
||||
footer .copyright-notice {
|
||||
padding-right: var(--single-gap);
|
||||
}
|
||||
footer .webring {
|
||||
display: inline-block;
|
||||
padding-right: var(--single-gap);
|
||||
}
|
||||
footer p {
|
||||
font-size: var(--font-s);
|
||||
}
|
||||
h1, h2, h3 {
|
||||
color: var(--text-color);
|
||||
@ -140,7 +169,7 @@ h1 {
|
||||
h2 {
|
||||
font-size: var(--font-xl);
|
||||
font-weight: var(--weight-extraheavy);
|
||||
margin-top: var(--double-gap);
|
||||
margin: var(--quad-gap) auto 0 auto;
|
||||
}
|
||||
h3 {
|
||||
font-size: var(--font-l);
|
||||
@ -167,7 +196,7 @@ p, li {
|
||||
}
|
||||
figure {
|
||||
margin: 0;
|
||||
padding: var(--single-gap) 0 var(--single-gap) 0;
|
||||
padding: var(--single-gap) 0 0 0;
|
||||
width: 100%;
|
||||
}
|
||||
figure > a > img {
|
||||
@ -182,6 +211,17 @@ figcaption {
|
||||
.page-block {
|
||||
margin-bottom: var(--triple-gap);
|
||||
}
|
||||
.big-link {
|
||||
width: 100%;
|
||||
padding: var(--half-gap);
|
||||
border: var(--border-nav);
|
||||
border-radius: var(--border-radius);
|
||||
margin: var(--single-gap) auto var(--single-gap) auto;
|
||||
transition: var(--transition-normal);
|
||||
}
|
||||
.big-link:hover {
|
||||
border-color: var(--contrast-color);
|
||||
}
|
||||
a[href]:not(.icon-button) {
|
||||
color: var(--text-color-link);
|
||||
}
|
||||
@ -194,9 +234,8 @@ a[href]:active:not(.icon-button) {
|
||||
}
|
||||
.links-nextprev {
|
||||
list-style: none;
|
||||
border-top: var(--border-thin);
|
||||
padding: var(--triple-gap) 0 var(--single-gap) 0;
|
||||
margin-top: var(--triple-gap);
|
||||
padding: 0 0 var(--single-gap) 0;
|
||||
margin-top: var(--single-gap);
|
||||
}
|
||||
|
||||
table {
|
||||
@ -207,6 +246,27 @@ table th {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
/* Comments */
|
||||
.comment-ingress {
|
||||
margin-bottom: var(--double-gap);
|
||||
}
|
||||
#comment-section h2 {
|
||||
margin: var(--quad-gap) auto 0 auto;
|
||||
}
|
||||
wc-comment::part(author-link) {
|
||||
font-size: var(--font-n);
|
||||
font-weight: var(--weight-extraheavy);
|
||||
text-decoration: none;
|
||||
}
|
||||
wc-comment::part(main) {
|
||||
margin-bottom: var(--double-gap);
|
||||
}
|
||||
wc-comment::part(publish-date) {
|
||||
font-weight: var(--weight-heavy);
|
||||
font-size: var(--font-s);
|
||||
margin-top: -.25rem;
|
||||
}
|
||||
|
||||
/* Code Fences */
|
||||
pre,
|
||||
code {
|
||||
@ -233,7 +293,6 @@ code {
|
||||
/* Header */
|
||||
header {
|
||||
align-items: end;
|
||||
border-bottom: var(--border-thin);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1em .5em;
|
||||
@ -331,17 +390,17 @@ nav ul {
|
||||
.postlist-item {
|
||||
align-items: flex-start;
|
||||
background-color: var(--card-color);
|
||||
border-radius: var(--corner-radius);
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 1em;
|
||||
margin-bottom: var(--double-gap);
|
||||
padding: var(--single-gap) 1.1rem var(--single-gap) 1.1rem;
|
||||
width: 100%;
|
||||
}
|
||||
.post-image-container {
|
||||
border-radius: var(--corner-radius);
|
||||
border-radius: var(--border-radius);
|
||||
margin-right: var(--single-gap);
|
||||
max-height: 15rem;
|
||||
overflow: hidden;
|
||||
@ -421,9 +480,14 @@ a.post-tag:hover {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
/* Article / Post */
|
||||
.post h2 {
|
||||
font-size: var(--font-l);
|
||||
}
|
||||
|
||||
/* Post Metadata */
|
||||
.post-metadata {
|
||||
margin-bottom: var(--triple-gap);
|
||||
margin-bottom: var(--double-gap);
|
||||
margin-top: var(--single-gap);
|
||||
padding: 0 0 0 .4rem;
|
||||
}
|
||||
@ -481,7 +545,7 @@ h2 + .header-anchor {
|
||||
margin-bottom: var(--single-gap);
|
||||
}
|
||||
h3, .post-copy a h3 {
|
||||
font-size: 1rem;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
@ -494,6 +558,11 @@ h2 + .header-anchor {
|
||||
margin-top: var(--single-gap);
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer .webring {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Nav */
|
||||
.nav {
|
||||
flex-flow: row wrap;
|
||||
|
4
public/js/main.js
Normal file
4
public/js/main.js
Normal file
@ -0,0 +1,4 @@
|
||||
import './webComponents/card.js';
|
||||
import './webComponents/profilePic.js';
|
||||
import './webComponents/speechBubble.js';
|
||||
import './webComponents/comment.js';
|
33
public/js/webComponents/card.js
Normal file
33
public/js/webComponents/card.js
Normal file
@ -0,0 +1,33 @@
|
||||
const template = document.createElement('template');
|
||||
|
||||
template.innerHTML = `
|
||||
<style>
|
||||
#card {
|
||||
align-items: flex-start;
|
||||
background-color: var(--wc-card-background-color);
|
||||
border-radius: var(--wc-card-border-radius);
|
||||
box-shadow: var(--wc-card-box-shadow);
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 1em;
|
||||
padding: var(--single-gap) 1.1rem var(--single-gap) 1.1rem;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="card" part="main">
|
||||
<slot></slot>
|
||||
</div>
|
||||
`
|
||||
|
||||
class card extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._shadowRoot = this.attachShadow({ 'mode': 'open' });
|
||||
this._shadowRoot.appendChild(template.content.cloneNode(true));
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('wc-card', card);
|
76
public/js/webComponents/comment.js
Normal file
76
public/js/webComponents/comment.js
Normal file
@ -0,0 +1,76 @@
|
||||
const template = document.createElement('template');
|
||||
|
||||
template.innerHTML = `
|
||||
<style>
|
||||
a {
|
||||
color: var(--wc-link-color);
|
||||
text-decoration-color: var(--wc-link-decoration-color);
|
||||
text-decoration-thickness: var(--wc-link-decoration-thickness);
|
||||
}
|
||||
#comment {
|
||||
margin: var(--wc-comment-text-margin);
|
||||
}
|
||||
#comment p {
|
||||
margin: 0 auto 0 auto;
|
||||
}
|
||||
#meta {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
}
|
||||
#meta-text {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
#meta-text p {
|
||||
margin: 0 1rem 0 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<article id="commentContainer" class="blog-comment" part="main">
|
||||
<div id="meta" part="meta">
|
||||
<div>
|
||||
<wc-profile-pic url="" />
|
||||
</div>
|
||||
<div id="meta-text" part="meta-text">
|
||||
<p id="author" part="author">
|
||||
<a id="author-link" part="author-link"></a><span> says:</span>
|
||||
</p>
|
||||
<p id="publish-date" part="publish-date"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="comment" part="content">
|
||||
</div>
|
||||
</article>
|
||||
`
|
||||
|
||||
class comment extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._shadowRoot = this.attachShadow({ 'mode': 'open' });
|
||||
this._shadowRoot.appendChild(template.content.cloneNode(true));
|
||||
this.$comment = this._shadowRoot.querySelector('#commentContainer');
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['author_name', 'author_url', 'avatar_url', 'comment_content', 'publish_date'];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldVal, newVal) {
|
||||
if (oldVal != newVal) {
|
||||
this[name] = newVal;
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
this.$comment.querySelector('#author-link').innerHTML = this.author_name;
|
||||
this.$comment.querySelector('#author-link').href = this.author_url;
|
||||
this.$comment.querySelector('wc-profile-pic').setAttribute('url', this.avatar_url)
|
||||
this.$comment.querySelector('#comment').innerHTML = this.comment_content;
|
||||
this.$comment.querySelector('#publish-date').innerHTML = this.publish_date;
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('wc-comment', comment);
|
40
public/js/webComponents/profilePic.js
Normal file
40
public/js/webComponents/profilePic.js
Normal file
@ -0,0 +1,40 @@
|
||||
const template = document.createElement('template');
|
||||
|
||||
template.innerHTML = `
|
||||
<style>
|
||||
#profilePic {
|
||||
border-radius: var(--wc-profile-pic-border-radius);
|
||||
width: var(--wc-profile-pic-size);
|
||||
height: var(--wc-profile-pic-size);
|
||||
}
|
||||
</style>
|
||||
|
||||
<img src="" id="profilePic"/>
|
||||
`
|
||||
|
||||
class profilePic extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._shadowRoot = this.attachShadow({ 'mode': 'open' });
|
||||
this._shadowRoot.appendChild(template.content.cloneNode(true));
|
||||
this.$profilePic = this._shadowRoot.querySelector('#profilePic');
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['url'];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldVal, newVal) {
|
||||
if (oldVal != newVal) {
|
||||
this[name] = newVal;
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
this.url ? this.$profilePic.src = this.url : null;
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('wc-profile-pic', profilePic);
|
Reference in New Issue
Block a user