Mutual Checker: Icons in blog cards; icon tooltips
resolved
Right now this doesn't completely work; I don't understand the CSS that's causing a specific friend's URL to vanish completely (presumably because it's long and has no hyphen) and I'm not making any progress. I require a CSS wizard.
Description
This adds mutual icons to the blog cards that appear when hovering over a blog avatar in most places, which I find really useful. (I would like to add an "is following you" icon type as well.)
This also adds on-hover tooltips to mutual icons; see #890.
Testing steps
Right now this doesn't completely work; I don't understand the CSS that's causing a specific friend's URL to vanish completely (presumably because it's long and has no hyphen) and I'm not making any progress. I require a CSS wizard.
Figured out a way around this!
We can prepend the icon to the parent of the parent of blogCardLink, I've tried this at several node levels and this prevents the link from overflowing to blank.
blogCardLink.parentElement.parentElement.prepend(icon.cloneNode(true));
We would then have to change the display of the parent to flex and also set the height of the SVG.
const styleElement = buildStyle(`
${keyToCss('popoverHolder')} ${keyToCss('blogCardBlogLink')} {
display: flex;
}
${keyToCss('popoverHolder')} ${keyToCss('blogCardBlogLink')} svg.xkit-mutual-icon {
height: 1.5em;
}
`);
I've tried and verified that it produces this:

There's probably a more graceful way to get the icon out of the link's parent's parent, but the proof-of-concept works!
Hmm, it does indeed! Targeting the anchor element is probably the cleanest way to implement that, and allows for easily stealing the right color.
pageModifications.register(`${keyToCss('blogCardBlogLink')} > a`, processBlogCardLinks);
const clonedIcon = icon.cloneNode(true);
clonedIcon.setAttribute('fill', blogCardLink.style.color);
blogCardLink.before(clonedIcon);
Edit: Ah, this breaks one day a year.
Edit: Ah, this breaks one day a year.
Not if we curry processBlogCardLinks!
const processBlogCardLinks = aprilFools => blogCardLinks =>
// other stuff
!aprilFools && clonedIcon.setAttribute('fill', blogCardLink.style.color);
pageModifications.register(`${keyToCss('blogCardBlogLink')} > a`, processBlogCardLinks(aprilFools));

Generally in this codebase we just define preference variables in the module scope, relying on main() having been called and having set them before any other functions in the module, but that does work here too!
Ah, then would setting aprilFools to let and moving it out of main to the top work?
Note: a network request can be skipped the first time you mouse over a blog avatar that you do not follow by using the blogData react props helper function from #910 to get the following status of a blog card:
+ import { blogData, timelineObject } from '../util/react_props.js';
const getIsFollowing = async (blogName, element) => {
- const { blog } = await timelineObject(element) ?? {};
+ const blog = await blogData(element) ?? (await timelineObject(element))?.blog;
if (following[blogName] === undefined) {
if (blogName === blog?.name) {
This really isn't very many network requests IMO, so super minor.
- [x] do this
(Mention me here and I'll bother fixing the merge conflicts in this PR.)
I feel like there should be a better way to do this, but... I kind of have to rewrite a bunch of stuff to get this to merge correctly, so I could either make all of those changes in the merge commit (obviously stupid) or just sort of merge commit garbage and make a rather random diff in the next commit? Eh, oh well.
Works, and I have no more code nits, but I'm not happy about the vertical alignment of the icon in blog cards...
It looks like the <svg>'s bounding box is just... wrong? It's bigger than the actual icon. Needs to be cleaned up in a vector editor; I'd do it in Figma right now, but it's 11:57pm so I really shouldn't. (Goodnight.)
oh my GODDDD it's not the SVG's bounding box that's the problem at all it's just the fucking text having position: relative; top: 3px; that's causing the alignment problem!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
wait no. the real problem is... that the SVG element... resizes incorrectly when a height is set explicitly? It behaves differently when setting width: 1.4em even though the viewbox is square.
I hate this.
There's something in the back of my mind about having encountered this before and maybe fixed it but I can't recall what the details were... and it's annoying to investigate because the element only appears on hover. Might be time to override removeChild to make it easier to examine again, sigh.
It's pretty easy to inspect, actually. Just open up the debugger, have it focused so that F8 will pause execution, hover the thing, pause execution. On Firefox at least the inspector still works completely and changes to CSS are reflected visually.
I have a fix almost ready to push, but now I'm trying to fix normal icons too... the alignment has been bothering me for forever, but if I do it too good it looks like part of the icon gets cut off, which I am trying to mitigate now.
Actually nevermind, the in-post icons are fine actually. I thought I saw an elevated level perfection in the fixed blog card alignment, but it was illusory.
Nevermind on that nevermind. I have seen a clean 18px square mutual icon and I like it a lot.
It's pretty easy to inspect, actually. Just open up the debugger, have it focused so that F8 will pause execution, hover the thing, pause execution. On Firefox at least the inspector still works completely and changes to CSS are reflected visually.
Oh, fun, I figured out why when I tried that it never worked: I use the debugger popped out in another window, which of course prevents you from simultaneously focusing it and mousing over the page to make the popup appear. I solved this with a userscript, though I actually picked a hotkey combination that also does something on Tumblr, so maybe change it, hypothetical viewer who wants to use this:
document.addEventListener('keydown', event => {
if (event.code === 'KeyP' && event.shiftKey) {
event.stopPropagation();
debugger;
}
}, { useCapture: true });
Anyway, I still find this method inconvenient, as you can't (or I haven't figured out how to) navigate to an element by right clicking it, and sure I've gotten pretty good at keyboard-navigating through the redpop DOM, but it seems silly to have to :D
The element inspector also has a button that lets you pick an element to inspect via left-click. It's the one shaped like a pointer.
Yeah, and it doesn't work when, oh no wait, yes it does 🤦
Me: "are you sure it doesn't look worse this way" Also me: *using Palettes for Tumblr with both a font-face and font-size override* ¯\_(ツ)_/¯
~~Edit: Oh, rem, I mean that certainly explains that~~ nope it's flexbox
Side-by-side for fun:
Before (master) |
After (this branch) |
|---|---|
...hm, maybe the improvement was an illusion after all. I can't spot a difference here. (I spot it in the element inspector, though!)
Right, so: the blog text in the post header has a normal font size of 14px (0.875rem) and a line height of 18px (1.125rem). We add the SVG inline and size it to match the line height of 18px (1.125rem), which it does. However...
The blog text in the blog card has a normal font size of 16px (1rem), a line height of 24px (1.5rem), and is shifted downward from its regular position in a flex container by 3px (hardcoded), for Reasons I guess.
Because we insert the blog card SVG as the child of a flex container, it will get shrunk unless we override that. Your PR sets a width of 24px (1.5rem), but I observe an actual 18.531px width in practice. That's basically the same as setting flex: none; and not overriding the 1.125rem value. But this only vertically aligns correctly with the default font size, as it's basically a coincidence.
Setting the icon height to actually match the 1.5rem line height and shifting it downward by 3px with position: relative presumably makes the vertical alignment consistent with any font size value, but that's obviously way too big and also clips.
Presumably the perfect CSS makes the icon the right size (maybe 18px, maybe closer to 18*16/14 = 20.57px so it's proportional to the font, whatever), positions it so it aligns with a 1.5rem-height box (no matter the font size), then shifts it down by 3px. ~~Not sure this is actually doable declaratively, since text isn't centered vertically in its line.~~
This is one way to do that but it's... stupid?
${keyToCss('blogCardBlogLink')} svg.xkit-mutual-icon {
- width: 1.5rem;
+ position: relative;
+ top: calc(3px + 0.15rem);
+ flex: none;
+ align-self: start;
}
Wait no, me stupid, this works.
${keyToCss('blogCardBlogLink')} svg.xkit-mutual-icon {
- width: 1.5rem;
+ position: relative;
+ top: 3px;
+ flex: none;
+ align-self: start;
+ height: 1.5rem;
}
| smol |
|---|
Unfortunately because of the overflow: hidden on the blog name wrapper, the line-height-aligned icon gets snipped off at the bottom at the default font size. (Forgot to take a screenshot; whoops!) HOWEVER because the effect is only visual, and the SVG box is perfectly aligned with the text box, we can just use border-box sizing and some top/bottom padding to reduce the content box to the text size, which fixes the visual issue.
Also tested and still aligned at weird-but-not-crazy base font sizes (12px to 22px).
the line-height-aligned icon gets snipped off at the bottom at the default font size.
Interesting, I'm not able to reproduce this!
I require a CSS wizard.
Spoiler alert: I required a CSS wizard.