v3: the invite tree spaces every row the same — a child sat 0.2rem under its parent but siblings 0.4rem apart, since each row's spacing was split into top and bottom padding and a last child dropped its bottom half. Every row now has one gap above it (--invite-tree-gap), the connectors run through it from the same variable, and the user link is a block, so a theme's line height can't push the avatar off the connector's center.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
48
src/App.css
48
src/App.css
@@ -5729,7 +5729,13 @@ body.has-player .chat-fab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ── Invite tree ── */
|
/* ── Invite tree ── */
|
||||||
|
/* Every row but the very first has the same gap above it, a child's as a
|
||||||
|
sibling's: the gap is the node's top padding, so the connectors can run
|
||||||
|
through it. --invite-tree-avatar-center is where a row's avatar is centered,
|
||||||
|
from the top of its node. */
|
||||||
.invite-tree {
|
.invite-tree {
|
||||||
|
--invite-tree-gap: 0.5rem;
|
||||||
|
--invite-tree-avatar-center: calc(var(--invite-tree-gap) + 12px);
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -5737,60 +5743,54 @@ body.has-player .chat-fab {
|
|||||||
|
|
||||||
.invite-tree-node {
|
.invite-tree-node {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0.2rem 0;
|
padding-top: var(--invite-tree-gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
.invite-tree-node:last-child {
|
.invite-tree-node:first-child:not(.invite-tree-node .invite-tree-node) {
|
||||||
padding-bottom: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Child list: indented so connector lines have room on the left.
|
/* A child list is indented so that the vertical connector, at its left edge,
|
||||||
The vertical line sits at the list's left:0, centered under the parent
|
is centered under the parent's 24px avatar (12px center - 1px half-line). */
|
||||||
avatar (avatar center 12px - 1px half-line = 11px). */
|
|
||||||
.invite-tree-node > .invite-tree {
|
.invite-tree-node > .invite-tree {
|
||||||
margin-left: 11px;
|
margin-left: 11px;
|
||||||
padding-left: calc(12px + 0.5rem);
|
padding-left: calc(12px + 0.5rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connectors are owned per child node (not by the list) so they always anchor
|
/* Each child draws its own connectors, so they anchor to its avatar however
|
||||||
to that child's own avatar center, regardless of how deep its subtree is.
|
deep its subtree is. The vertical one drops from the row above to its
|
||||||
--avatar-center = node top padding (0.2rem) + half the 24px avatar (12px). */
|
avatar center, and on through its subtree when a sibling follows. */
|
||||||
.invite-tree-node > .invite-tree > .invite-tree-node {
|
.invite-tree-node .invite-tree-node::before {
|
||||||
--avatar-center: calc(0.2rem + 12px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Vertical segment: drops from the top of the child node to its avatar center,
|
|
||||||
joining the line coming down from the parent / previous sibling. */
|
|
||||||
.invite-tree-node > .invite-tree > .invite-tree-node::before {
|
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: calc(-12px - 0.5rem);
|
left: calc(-12px - 0.5rem);
|
||||||
top: 0;
|
top: 0;
|
||||||
height: var(--avatar-center);
|
height: var(--invite-tree-avatar-center);
|
||||||
width: 2px;
|
width: 2px;
|
||||||
background: var(--color-border-subtle);
|
background: var(--color-border-subtle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Non-last children extend the vertical segment through their full height
|
.invite-tree-node .invite-tree-node:not(:last-child)::before {
|
||||||
(including any subtree) so it reaches the next sibling. */
|
|
||||||
.invite-tree-node > .invite-tree > .invite-tree-node:not(:last-child)::before {
|
|
||||||
height: auto;
|
height: auto;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Horizontal connector: from the vertical line to the child's avatar. */
|
/* The horizontal one runs from the vertical line to the avatar. */
|
||||||
.invite-tree-node > .invite-tree > .invite-tree-node::after {
|
.invite-tree-node .invite-tree-node::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: calc(-12px - 0.5rem);
|
left: calc(-12px - 0.5rem);
|
||||||
top: calc(var(--avatar-center) - 1px); /* straddle center with the 2px bar */
|
top: calc(var(--invite-tree-avatar-center) - 1px);
|
||||||
width: calc(12px + 0.5rem);
|
width: calc(12px + 0.5rem);
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background: var(--color-border-subtle);
|
background: var(--color-border-subtle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A block, not inline: in a line box, the theme's line height would add space
|
||||||
|
under the avatar and move it off --invite-tree-avatar-center. */
|
||||||
.invite-tree-user {
|
.invite-tree-user {
|
||||||
display: inline-flex;
|
display: flex;
|
||||||
|
width: fit-content;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
|
|||||||
Reference in New Issue
Block a user