slight rework of emoji

This commit is contained in:
liquidex 2024-02-20 21:50:24 +01:00
parent 1bb14f059e
commit 3a8799f581
3 changed files with 118 additions and 32 deletions

View file

@ -492,8 +492,10 @@ where
.copied(); .copied();
if let Some(branch) = branch_id.map(|id| self.treehouse.tree.branch(id)) if let Some(branch) = branch_id.map(|id| self.treehouse.tree.branch(id))
{ {
self.writer.write_str("<a href=\"#")?; self.writer.write_str("<a href=\"")?;
escape_html(&mut self.writer, &branch.html_id)?; escape_html(&mut self.writer, &self.config.site)?;
self.writer.write_str("/b?")?;
escape_html(&mut self.writer, &branch.attributes.id)?;
self.writer.write_str("\">")?; self.writer.write_str("\">")?;
} }
self.writer.write_str("<img is=\"th-emoji\" title=\":")?; self.writer.write_str("<img is=\"th-emoji\" title=\":")?;
@ -502,6 +504,8 @@ where
escape_html(&mut self.writer, &self.config.site)?; escape_html(&mut self.writer, &self.config.site)?;
self.writer.write_str("/static/emoji/")?; self.writer.write_str("/static/emoji/")?;
escape_html(&mut self.writer, filename)?; escape_html(&mut self.writer, filename)?;
self.writer.write_str("\" alt=\"")?;
escape_html(&mut self.writer, name)?;
self.writer.write_str("\">")?; self.writer.write_str("\">")?;
if branch_id.is_some() { if branch_id.is_some() {
self.writer.write_str("</a>")?; self.writer.write_str("</a>")?;

View file

@ -459,19 +459,12 @@ img[is="th-emoji"] {
/* And also style emoji tooltips. */ /* And also style emoji tooltips. */
.emoji-wrapper { th-emoji-tooltip {
--transition-duration: 0.2s;
position: relative;
}
.emoji-tooltip {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
position: absolute; position: fixed;
left: 50%;
transform: translateX(-50%) translateY(-10%) scale(0.8); transform: translateX(-50%) translateY(-10%) scale(0.8);
width: max-content; width: max-content;
z-index: 100; z-index: 100;
@ -490,24 +483,24 @@ img[is="th-emoji"] {
pointer-events: none; pointer-events: none;
} }
.emoji-wrapper:hover .emoji-tooltip { th-emoji-tooltip.transitioned-in {
opacity: 100%; opacity: 100%;
filter: blur(0px); filter: blur(0px);
transform: translateX(-50%) scale(1.0); transform: translateX(-50%) scale(1.0);
} }
.emoji-tooltip img { th-emoji-tooltip img {
display: block; display: block;
max-width: 64px; max-width: 64px;
max-height: 64px; max-height: 64px;
} }
.emoji-tooltip p { th-emoji-tooltip p {
--recursive-wght: 550; --recursive-wght: 550;
color: var(--text-color); color: var(--text-color);
font-size: 0.75em; font-size: 0.9em;
margin: 0; margin: 0;
padding-top: 4px; padding-top: 6px;
line-height: 1; line-height: 1;
} }

View file

@ -1,29 +1,118 @@
// Emoji zoom-in functionality. // Emoji zoom-in functionality.
class Emoji extends HTMLImageElement { class EmojiTooltip extends HTMLElement {
constructor() { constructor(emoji, { onClosed }) {
super(); super();
this.wrapper = document.createElement("span"); this.emoji = emoji;
this.wrapper.className = "emoji-wrapper"; this.onClosed = onClosed;
this.replaceWith(this.wrapper); }
this.wrapper.appendChild(this);
this.enlarged = new Image(); connectedCallback() {
this.enlarged.src = this.src; this.role = "tooltip";
this.titleElement = document.createElement("p"); this.image = new Image();
this.titleElement.innerText = this.title; this.image.src = this.emoji.src;
this.tooltip = document.createElement("div"); this.description = document.createElement("p");
this.tooltip.className = "emoji-tooltip"; this.description.textContent = `${this.emoji.emojiName}`;
this.tooltip.appendChild(this.enlarged);
this.tooltip.appendChild(this.titleElement);
this.wrapper.appendChild(this.tooltip); let emojiBoundingBox = this.emoji.getBoundingClientRect();
this.style.left = `${emojiBoundingBox.left + emojiBoundingBox.width / 2}px`;
this.style.top = `calc(${emojiBoundingBox.top}px + 1.5em)`;
this.alt = this.title; this.fullyOpaque = false;
this.addEventListener("transitionend", event => {
if (event.propertyName == "opacity") {
this.fullyOpaque = !this.fullyOpaque;
if (!this.fullyOpaque) {
this.onClosed();
}
}
});
// Timeout is zero because we just want to execute this later, to be definitely sure
// the transition plays out.
setTimeout(() => this.classList.add("transitioned-in"), 0);
this.appendChild(this.image);
this.appendChild(this.description);
}
close() {
this.classList.remove("transitioned-in");
}
}
customElements.define("th-emoji-tooltip", EmojiTooltip);
let emojiTooltips = null;
addEventListener("wheel", event => emojiTooltips.closeTooltips(event));
class EmojiTooltips extends HTMLElement {
constructor() {
super();
this.tooltips = new Set();
this.abortController = new AbortController();
}
connectedCallback() {
emojiTooltips = this;
}
disconnectedCallback() {
this.abortController.abort();
}
openTooltip(emoji) {
let tooltip = new EmojiTooltip(emoji, {
onClosed: () => {
this.removeChild(tooltip);
this.tooltips.delete(tooltip);
},
});
this.appendChild(tooltip);
this.tooltips.add(tooltip);
return tooltip;
}
closeTooltip(tooltip) {
tooltip.close();
}
closeTooltips() {
for (let tooltip of this.tooltips) {
console.log("close", this);
tooltip.close();
}
}
}
customElements.define("th-emoji-tooltips", EmojiTooltips);
class Emoji extends HTMLImageElement {
connectedCallback() {
this.emojiName = this.title;
// title makes the browser add a tooltip. We replace browser tooltips with our own,
// so remove the title.
this.title = ""; this.title = "";
this.addEventListener("mouseenter", () => this.openTooltip());
this.addEventListener("mouseleave", () => this.closeTooltip());
this.addEventListener("scroll", () => this.closeTooltip());
}
openTooltip() {
this.tooltip = emojiTooltips.openTooltip(this);
}
closeTooltip() {
emojiTooltips.closeTooltip(this.tooltip);
this.tooltip = null;
} }
} }