slight rework of emoji
This commit is contained in:
parent
1bb14f059e
commit
3a8799f581
|
@ -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>")?;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue