From 694479bcdb3f8197fb40a52c4d7839846d68bafc Mon Sep 17 00:00:00 2001 From: daudix Date: Wed, 23 Oct 2024 04:35:15 +0300 Subject: [PATCH] Improved comments (see changelog) --- CHANGELOG.md | 5 ++ content/blog/the-quill-of-duck/index.md | 4 + sass/_alerts.scss | 2 - sass/_article-list.scss | 4 - sass/_article.scss | 2 - sass/_buttons.scss | 13 +++ sass/_comments.scss | 102 ++++++++++++++++++------ sass/_emoji.scss | 7 +- sass/_icon.scss | 2 + sass/_media.scss | 2 +- sass/_nav.scss | 4 - sass/_pre-container.scss | 2 - sass/_statements.scss | 2 - static/comments.js | 62 ++++++++++---- templates/article.html | 57 +------------ templates/partials/comments.html | 61 ++++++++++++++ templates/partials/nav.html | 5 +- 17 files changed, 215 insertions(+), 121 deletions(-) create mode 100644 templates/partials/comments.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ece298..b9b36c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,12 +16,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add missing translation strings for author separator and conjunctions. - Add shortcode for Mastodon post embedding. - Add support for Fuse.js search (#101). +- Add support for preview cards in comments. - Add the ability to set video attributes via shortcode. ### Changed - **[BREAKING]** Rename `nav-bg` CSS variable to `glass-bg`. - **[BREAKING]** Rename the visually hidden `hidden` class to `visually-hidden`. `hidden` is now used to completely hide the elements, including screen readers. +- Add default width/height to the `icon` class. +- Improve the look of threads in comments. - Make `emoji` class available outside of comments. - Make the code and styling for article cards much cleaner. - Make the shortcodes code much cleaner. @@ -35,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fix article cards missing a focus outline. +- Fix hover state of custom emojis in comments. +- Fix hover state of the "Load Comments" button. - Fix navbar mods having broken border radius. ## [5.4.0](https://codeberg.org/daudix/duckquill/compare/v5.3.2...v5.4.0) diff --git a/content/blog/the-quill-of-duck/index.md b/content/blog/the-quill-of-duck/index.md index cc0b0d6..826c15a 100644 --- a/content/blog/the-quill-of-duck/index.md +++ b/content/blog/the-quill-of-duck/index.md @@ -31,6 +31,10 @@ disclaimer = """ # user = "cassidy" # id = "112774854109302186" # +# Thread with preview cards +# host = "mastodon.blaede.family" +# user = "cassidy" +# id = "110669429936617026" # Post on GoToSocial # # host = "alpha.polymaths.social" diff --git a/sass/_alerts.scss b/sass/_alerts.scss index 685dd8f..ac6eb92 100644 --- a/sass/_alerts.scss +++ b/sass/_alerts.scss @@ -81,8 +81,6 @@ blockquote { .icon { vertical-align: -0.125em; margin-inline-end: 0.25rem; - width: 1rem; - height: 1rem; } } } diff --git a/sass/_article-list.scss b/sass/_article-list.scss index e476cdc..7bf1bdc 100644 --- a/sass/_article-list.scss +++ b/sass/_article-list.scss @@ -330,8 +330,6 @@ .icon { vertical-align: -0.125em; margin-inline-end: 0.25rem; - width: 1rem; - height: 1rem; } } @@ -371,8 +369,6 @@ .icon { transition: var(--transition); - width: 1rem; - height: 1rem; :root[dir*="rtl"] & { transform: scaleX(-1); diff --git a/sass/_article.scss b/sass/_article.scss index 2123740..e610c5d 100644 --- a/sass/_article.scss +++ b/sass/_article.scss @@ -96,8 +96,6 @@ .icon { transition: var(--transition); - width: 1rem; - height: 1rem; } } diff --git a/sass/_buttons.scss b/sass/_buttons.scss index 76e1c91..7a1cf83 100644 --- a/sass/_buttons.scss +++ b/sass/_buttons.scss @@ -13,6 +13,19 @@ button.inline-button { appearance: none; cursor: pointer; border: none; + + &:disabled { + cursor: not-allowed; + + &:hover { + background-color: var(--fg-muted-1); + color: var(--fg-muted-5); + } + + &:active { + transform: none; + } + } } a.inline-button, diff --git a/sass/_comments.scss b/sass/_comments.scss index 18474fd..f536481 100644 --- a/sass/_comments.scss +++ b/sass/_comments.scss @@ -25,30 +25,21 @@ gap: 0.25rem; margin-block-start: 2rem; - #load-comments { + #load-comments:disabled { --shimmer: rgb(from var(--accent-color) r g b / calc(var(--color-opacity) * 2)); + animation: loading-shimmer var(--transition-long) ease-in-out alternate infinite; + transition: none; background-image: linear-gradient(to right, var(--fg-muted-1) 50%, var(--shimmer) 75%, var(--fg-muted-1) 100%); background-size: 200%; background-color: transparent; - &:disabled { - animation: loading-shimmer var(--transition-long) ease-in-out alternate infinite; - transition: none; - cursor: not-allowed; + &:hover { + background-color: transparent; + } - &:hover { - background-color: transparent; - color: var(--fg-muted-5); - } - - &:active { - transform: none; - } - - @keyframes loading-shimmer { - to { - background-position-x: -200%; - } + @keyframes loading-shimmer { + to { + background-position-x: -200%; } } } @@ -84,6 +75,16 @@ border-radius: 0.25rem; border-inline-start: 0.25rem solid var(--fg-muted-2); padding-inline-start: 1rem; + + &:has(+ .comment-reply) { + border-end-start-radius: 0; + } + + & + .comment-reply { + margin-block-start: -2rem; + border-start-start-radius: 0; + padding-block-start: 2rem; + } } .avatar-link { @@ -140,7 +141,7 @@ &.op { background-color: var(--accent-color-alpha); - padding-inline-start: 0.625rem; + padding-inline-start: 0.4375rem; color: var(--accent-color); &:hover { @@ -153,17 +154,18 @@ } &::before { - --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath d='m1 7 3 3 7-8' style='fill:none;stroke:%23000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none'/%3E%3C/svg%3E"); + // --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath d='m1 7 3 3 7-8' style='fill:none;stroke:%23000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none'/%3E%3C/svg%3E"); + --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M5.21 1.27A3.7 3.7 0 0 1 8 0c1.113 0 2.11.492 2.79 1.27a3.68 3.68 0 0 1 2.866 1.074A3.68 3.68 0 0 1 14.73 5.21C15.54 5.914 16 6.93 16 8s-.46 2.086-1.27 2.79a3.68 3.68 0 0 1-1.074 2.866 3.68 3.68 0 0 1-2.867 1.074C10.086 15.54 9.07 16 8 16s-2.086-.46-2.79-1.27a3.68 3.68 0 0 1-2.866-1.074A3.68 3.68 0 0 1 1.27 10.79 3.7 3.7 0 0 1 0 8c0-1.113.492-2.11 1.27-2.79a3.68 3.68 0 0 1 1.074-2.866A3.68 3.68 0 0 1 5.21 1.27m5.75 5.242a.613.613 0 0 0-.437-.98.61.61 0 0 0-.562.265L7.305 9.512 5.973 8.18a.616.616 0 0 0-.868.87l1.844 1.845a.61.61 0 0 0 .485.18.63.63 0 0 0 .453-.255zm0 0'/%3E%3C/svg%3E"); -webkit-mask-image: var(--icon); display: inline-block; - vertical-align: -0.0625rem; + vertical-align: -0.1875rem; mask-image: var(--icon); mask-size: cover; transition: var(--transition); margin-inline-end: 0.25rem; background-color: var(--accent-color); - width: 0.75rem; - height: 0.75rem; + width: 1rem; + height: 1rem; content: ""; } @@ -245,6 +247,57 @@ } } + .card { + transition: var(--transition); + margin-block-start: 1rem; + box-shadow: var(--edge-highlight); + border-radius: var(--rounded-corner); + background-color: var(--fg-muted-1); + width: min(calc(var(--container-width) / 2), 100%); + overflow: hidden; + font-weight: normal; + text-decoration: none; + + &:hover { + background-color: var(--fg-muted-2); + } + + &:active { + transform: var(--active); + } + + figure { + display: flex; + flex-direction: row; + margin: 0; + + img { + margin: 0; + box-shadow: none; + border-radius: 0; + width: min(calc(var(--container-width) / 4), 50%); + } + + figcaption { + display: flex; + flex-direction: column; + justify-content: center; + gap: 0.5rem; + padding: 1rem; + color: var(--fg-color); + font-size: var(--font-size-medium); + text-align: start; + + p { + margin-block-start: 0.25rem; + margin-block-end: 0; + color: var(--fg-muted-5); + font-size: var(--font-size-small); + } + } + } + } + footer { display: flex; grid-area: interactions; @@ -257,6 +310,7 @@ border-radius: 999px; background-color: transparent; padding: 0.5rem 0.75rem; + padding-inline-start: 0.625rem; line-height: 1; font-variant-numeric: tabular-nums; text-decoration: none; @@ -265,8 +319,6 @@ vertical-align: -0.125em; transition: var(--transition-longer); margin-inline-end: 0.25rem; - width: 1rem; - height: 1rem; } &:hover { diff --git a/sass/_emoji.scss b/sass/_emoji.scss index d7194ad..73840c0 100644 --- a/sass/_emoji.scss +++ b/sass/_emoji.scss @@ -1,9 +1,12 @@ .emoji { - all: unset; display: inline-block; - vertical-align: middle; + vertical-align: bottom; transition: var(--transition); cursor: zoom-in; + margin: 0; + box-shadow: none; + border-radius: 0; + background-color: transparent; width: 1.5em; height: 1.5em; diff --git a/sass/_icon.scss b/sass/_icon.scss index 0ccbd84..77e40fd 100644 --- a/sass/_icon.scss +++ b/sass/_icon.scss @@ -2,6 +2,8 @@ i.icon { display: inline-block; mask-size: cover; background-color: currentColor; + width: 1rem; + height: 1rem; font-style: normal; font-variant: normal; line-height: 0; diff --git a/sass/_media.scss b/sass/_media.scss index 8db5d7e..d8d6f70 100644 --- a/sass/_media.scss +++ b/sass/_media.scss @@ -104,7 +104,7 @@ video { img { transition: var(--transition-longer); - &:not(.no-hover, .full-bleed, [src*="#no-hover"], [src*="#full-bleed"]) { + &:not(.no-hover, .full-bleed, [src*="#no-hover"], [src*="#full-bleed"], .emoji) { cursor: zoom-in; &:hover { diff --git a/sass/_nav.scss b/sass/_nav.scss index 83e4ecd..15dbf76 100644 --- a/sass/_nav.scss +++ b/sass/_nav.scss @@ -123,8 +123,6 @@ mask-image: var(--icon); transition: var(--transition); margin-inline-end: 0.25rem; - width: 1rem; - height: 1rem; } } @@ -169,8 +167,6 @@ .icon { vertical-align: -0.125em; transition: var(--transition); - width: 1rem; - height: 1rem; } } diff --git a/sass/_pre-container.scss b/sass/_pre-container.scss index becf6b4..d0628b8 100644 --- a/sass/_pre-container.scss +++ b/sass/_pre-container.scss @@ -55,8 +55,6 @@ -webkit-mask-image: var(--icon); mask-image: var(--icon); transition: var(--transition); - width: 1rem; - height: 1rem; :root[dir*="rtl"] & { transform: scaleX(-1); diff --git a/sass/_statements.scss b/sass/_statements.scss index b9679eb..fcb2087 100644 --- a/sass/_statements.scss +++ b/sass/_statements.scss @@ -25,8 +25,6 @@ .icon { margin-inline-end: 0.375rem; - width: 1rem; - height: 1rem; } } diff --git a/static/comments.js b/static/comments.js index 99d752c..e0b5ba0 100644 --- a/static/comments.js +++ b/static/comments.js @@ -105,6 +105,12 @@ function loadComments() { status.content = emojify(status.content, status.emojis); + let comment = document.createElement("article"); + comment.id = `comment-${status.id}`; + comment.className = isReply ? "comment comment-reply" : "comment"; + comment.setAttribute("itemprop", "comment"); + comment.setAttribute("itemtype", "http://schema.org/Comment"); + let avatarSource = document.createElement("source"); avatarSource.setAttribute( "srcset", @@ -143,6 +149,7 @@ function loadComments() { `${viewProfileText} @${status.account.username}@${instance}` ); avatar.appendChild(avatarPicture); + comment.appendChild(avatar); let instanceBadge = document.createElement("a"); instanceBadge.className = "instance"; @@ -164,6 +171,7 @@ function loadComments() { header.className = "author"; header.appendChild(display); header.appendChild(instanceBadge); + comment.appendChild(header); let permalink = document.createElement("a"); permalink.setAttribute("href", status.url); @@ -181,10 +189,12 @@ function loadComments() { timestamp.setAttribute("datetime", status.created_at); timestamp.appendChild(permalink); permalink.classList.add("external"); + comment.appendChild(timestamp); let main = document.createElement("main"); main.setAttribute("itemprop", "text"); main.innerHTML = status.content; + comment.appendChild(main); let attachments = status.media_attachments; let SUPPORTED_MEDIA = ["image", "video", "gifv", "audio"]; @@ -267,6 +277,8 @@ function loadComments() { media.appendChild(mediaLink); } }); + + comment.appendChild(media); } let interactions = document.createElement("footer"); @@ -292,25 +304,41 @@ function loadComments() { faves.appendChild(favesIcon); faves.insertAdjacentHTML('beforeend', ` ${status.favourites_count}`); interactions.appendChild(faves); - - let comment = document.createElement("article"); - comment.id = `comment-${status.id}`; - comment.className = isReply ? "comment comment-reply" : "comment"; - comment.setAttribute("itemprop", "comment"); - comment.setAttribute("itemtype", "http://schema.org/Comment"); - comment.appendChild(avatar); - comment.appendChild(header); - comment.appendChild(timestamp); - comment.appendChild(main); - if ( - attachments && - Array.isArray(attachments) && - attachments.length > 0 - ) { - comment.appendChild(media); - } comment.appendChild(interactions); + if (status.card != null) { + let cardFigure = document.createElement("figure"); + + if (status.card.image != null) { + let cardImg = document.createElement("img"); + cardImg.setAttribute("src", status.card.image); + cardImg.classList.add("no-hover"); + cardFigure.appendChild(cardImg); + } + + let cardCaption = document.createElement("figcaption"); + + let cardTitle = document.createElement("strong"); + cardTitle.innerHTML = status.card.title; + cardCaption.appendChild(cardTitle); + + if (status.card.description != null && status.card.description.length > 0) { + let cardDescription = document.createElement("p"); + cardDescription.innerHTML = status.card.description; + cardCaption.appendChild(cardDescription); + } + + cardFigure.appendChild(cardCaption); + + let card = document.createElement("a"); + card.className = "card"; + card.setAttribute("href", status.card.url); + card.setAttribute("rel", relAttributes); + card.appendChild(cardFigure); + + comment.appendChild(card); + } + if (op === true) { comment.classList.add("op"); diff --git a/templates/article.html b/templates/article.html index 1d2da16..19f813d 100644 --- a/templates/article.html +++ b/templates/article.html @@ -135,62 +135,7 @@ {%- if page.extra.comments.id -%} - {%- if page.extra.comments.host -%} - {%- set host = page.extra.comments.host -%} - {%- else -%} - {%- set host = config.extra.comments.host -%} - {%- endif -%} - - {%- if page.extra.comments.user -%} - {%- set user = page.extra.comments.user -%} - {%- else %} - {%- set user = config.extra.comments.user -%} - {%- endif -%} - - {%- set id = page.extra.comments.id -%} - - {%- set date_locale = macros_translate::translate(key="date_locale", default="en-US", language_strings=language_strings) | replace(from="_", to="-") -%} - - - - - - - - - - - - - - - -
- {%- if config.extra.comments.show_qr -%} - - {%- endif -%} -

{{ macros_translate::translate(key="comments", default="Comments", language_strings=language_strings) }}

-

{{ macros_translate::translate(key="comments_description", default="You can comment on this blog post by publicly replying to this post using a Mastodon or other ActivityPub/Fediverse account. Known non-private replies are displayed below.", language_strings=language_strings) }}

-
- - - {{- macros_translate::translate(key="open_post", default="Open Post", language_strings=language_strings) -}} - -
-
- -
-
+ {%- include "partials/comments.html" -%} {%- endif -%} {%- if page.lower or page.higher -%} diff --git a/templates/partials/comments.html b/templates/partials/comments.html new file mode 100644 index 0000000..15cb307 --- /dev/null +++ b/templates/partials/comments.html @@ -0,0 +1,61 @@ +{%- if page.extra.comments.host -%} + {%- set host = page.extra.comments.host -%} +{%- else -%} + {%- set host = config.extra.comments.host -%} +{%- endif -%} + +{%- if page.extra.comments.user -%} + {%- set user = page.extra.comments.user -%} +{%- else %} + {%- set user = config.extra.comments.user -%} +{%- endif -%} + +{%- set id = page.extra.comments.id -%} + +{%- set date_locale = macros_translate::translate(key="date_locale", default="en-US", language_strings=language_strings) | replace(from="_", to="-") -%} + + + + + + + + + + + + + + + +{%- if page.extra.comments.uri -%} + {%- set uri = page.extra.comments.uri -%} + +{%- endif -%} + +
+ {%- if config.extra.comments.show_qr -%} + + {%- endif -%} +

{{ macros_translate::translate(key="comments", default="Comments", language_strings=language_strings) }}

+

{{ macros_translate::translate(key="comments_description", default="You can comment on this blog post by publicly replying to this post using a Mastodon or other ActivityPub/Fediverse account. Known non-private replies are displayed below.", language_strings=language_strings) }}

+
+ + + {{- macros_translate::translate(key="open_post", default="Open Post", language_strings=language_strings) -}} + +
+
+ +
+
diff --git a/templates/partials/nav.html b/templates/partials/nav.html index 951d6a7..12c1858 100644 --- a/templates/partials/nav.html +++ b/templates/partials/nav.html @@ -20,10 +20,7 @@ {%- if link.menu and link.menu | length > 0 -%}
  • - - - {{- macros_translate::translate(key=link.name, default=link.name, language_strings=language_strings) -}} - + {{- macros_translate::translate(key=link.name, default=link.name, language_strings=language_strings) -}}
      {%- for link in link.menu -%} {%- if link.url is matching('https?://') %}