Skip to content

Commit 7115498

Browse files
committed
Added message perma links with copy button
1 parent b397668 commit 7115498

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

app/assets/stylesheets/components/messages.css

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,35 @@
7979
color: var(--color-text-muted);
8080
}
8181

82+
.message-number {
83+
color: var(--color-text-link);
84+
text-decoration: none;
85+
font-weight: var(--font-weight-semibold);
86+
margin-right: var(--spacing-2);
87+
}
88+
89+
.message-number:hover {
90+
text-decoration: underline;
91+
}
92+
93+
.message-copy {
94+
border: none;
95+
background: none;
96+
color: var(--color-text-link);
97+
cursor: pointer;
98+
padding: 0;
99+
display: inline-flex;
100+
align-items: center;
101+
}
102+
103+
.message-copy:hover {
104+
text-decoration: underline;
105+
}
106+
107+
.message-copy.copied {
108+
color: var(--color-success);
109+
}
110+
82111
.reply-indicator {
83112
color: var(--color-purple);
84113
font-style: italic;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Controller } from "@hotwired/stimulus"
2+
3+
// Copies a provided URL to the clipboard.
4+
export default class extends Controller {
5+
static values = { url: String }
6+
7+
async copy(event) {
8+
event.preventDefault()
9+
const text = this.urlValue
10+
if (!text) return
11+
12+
try {
13+
await navigator.clipboard.writeText(text)
14+
} catch (_err) {
15+
this.fallbackCopy(text)
16+
}
17+
18+
this.showFeedback()
19+
}
20+
21+
fallbackCopy(text) {
22+
const textarea = document.createElement("textarea")
23+
textarea.value = text
24+
textarea.setAttribute("readonly", "")
25+
textarea.style.position = "absolute"
26+
textarea.style.left = "-9999px"
27+
document.body.appendChild(textarea)
28+
textarea.select()
29+
document.execCommand("copy")
30+
textarea.remove()
31+
}
32+
33+
showFeedback() {
34+
this.element.classList.add("copied")
35+
setTimeout(() => this.element.classList.remove("copied"), 1200)
36+
}
37+
}

app/views/topics/_message.html.slim

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@
1212
.message-header
1313
.message-author
1414
.author-row
15-
span.message-number = "##{display_number}"
15+
= link_to "##{display_number}", "#message-#{message.id}", class: "message-number"
16+
= button_tag type: "button",
17+
class: "message-copy",
18+
data: { controller: "clipboard", action: "click->clipboard#copy", "clipboard-url-value": topic_url(@topic, anchor: "message-#{message.id}") },
19+
title: "Copy message link",
20+
"aria-label": "Copy message link" do
21+
i.fa-regular.fa-copy
1622
= image_tag message.sender.gravatar_url(size: 42), class: "message-avatar", alt: message.sender.name
1723
.author-details
1824
.author-name = message.sender.name

0 commit comments

Comments
 (0)