fix: Move to use HTML for text

Previously we had the bubbles drawn on the avatar canvas. Now it's
actually text, so is the label.
This commit is contained in:
Evan Carroll 2026-01-26 00:05:41 -06:00
parent 23374ee024
commit 66368fe274
6 changed files with 650 additions and 403 deletions

View file

@ -5,4 +5,116 @@
* This file is imported after admin.css to allow user-specific overrides.
*/
/* User-specific styles will be added here as needed */
/* =============================================================================
* Speech Bubble Component
* ============================================================================= */
.speech-bubble {
pointer-events: none;
font-family: sans-serif;
/* Padding MUST be here (not on .bubble-content) for -webkit-line-clamp to work in Chrome.
Chrome breaks line-clamp when padding is on the clamped element itself. */
background-color: var(--bubble-bg, #374151);
border: 2px solid var(--bubble-border, #4B5563);
padding: var(--padding, 8px);
border-radius: var(--border-radius, 8px);
}
.speech-bubble .bubble-content {
/* WARNING: -webkit-line-clamp breaks if padding is on this element in Chrome.
Padding must be on the parent (.speech-bubble) instead. */
display: -webkit-box;
-webkit-line-clamp: 4;
-webkit-box-orient: vertical;
overflow: hidden;
color: var(--bubble-text, #F9FAFB);
font-size: var(--font-size, 12px);
line-height: 1.5;
word-wrap: break-word;
overflow-wrap: break-word;
}
.speech-bubble .bubble-content.whisper {
font-style: italic;
}
/* Tail pointing down (bubble is above avatar) */
.speech-bubble.tail-below::after {
content: '';
position: absolute;
bottom: 0;
left: var(--tail-offset, 50%);
transform: translateX(-50%) translateY(100%);
width: 0;
height: 0;
border-left: var(--tail-size, 8px) solid transparent;
border-right: var(--tail-size, 8px) solid transparent;
border-top: var(--tail-size, 8px) solid var(--bubble-bg, #374151);
}
/* Tail border (for outline effect) */
.speech-bubble.tail-below::before {
content: '';
position: absolute;
bottom: 0;
left: var(--tail-offset, 50%);
transform: translateX(-50%) translateY(100%);
width: 0;
height: 0;
border-left: calc(var(--tail-size, 8px) + 2px) solid transparent;
border-right: calc(var(--tail-size, 8px) + 2px) solid transparent;
border-top: calc(var(--tail-size, 8px) + 2px) solid var(--bubble-border, #4B5563);
margin-left: 0;
margin-bottom: -2px;
}
/* Tail pointing up (bubble is below avatar) */
.speech-bubble.tail-above::after {
content: '';
position: absolute;
top: 0;
left: var(--tail-offset, 50%);
transform: translateX(-50%) translateY(-100%);
width: 0;
height: 0;
border-left: var(--tail-size, 8px) solid transparent;
border-right: var(--tail-size, 8px) solid transparent;
border-bottom: var(--tail-size, 8px) solid var(--bubble-bg, #374151);
}
/* Tail border (for outline effect) */
.speech-bubble.tail-above::before {
content: '';
position: absolute;
top: 0;
left: var(--tail-offset, 50%);
transform: translateX(-50%) translateY(-100%);
width: 0;
height: 0;
border-left: calc(var(--tail-size, 8px) + 2px) solid transparent;
border-right: calc(var(--tail-size, 8px) + 2px) solid transparent;
border-bottom: calc(var(--tail-size, 8px) + 2px) solid var(--bubble-border, #4B5563);
margin-top: -2px;
}
/* =============================================================================
* Username Label Component
* ============================================================================= */
.username-label {
pointer-events: none;
font-family: sans-serif;
font-size: var(--font-size, 12px);
color: #fff;
white-space: nowrap;
/* Black outline via text-shadow (matches canvas 3px stroke) */
text-shadow:
-1.5px -1.5px 0 #000,
1.5px -1.5px 0 #000,
-1.5px 1.5px 0 #000,
1.5px 1.5px 0 #000,
0px -1.5px 0 #000,
0px 1.5px 0 #000,
-1.5px 0px 0 #000,
1.5px 0px 0 #000;
}