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:
parent
23374ee024
commit
66368fe274
6 changed files with 650 additions and 403 deletions
74
crates/chattyness-user-ui/src/components/username_label.rs
Normal file
74
crates/chattyness-user-ui/src/components/username_label.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
//! HTML-based username label component.
|
||||
//!
|
||||
//! Renders display names as HTML/CSS elements instead of canvas,
|
||||
//! allowing independent updates without triggering avatar redraws.
|
||||
|
||||
use leptos::prelude::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::avatar_canvas::AvatarBoundsStore;
|
||||
|
||||
/// Base text size multiplier. Text at 100% slider = base_sizes * 1.4
|
||||
const BASE_TEXT_SCALE: f64 = 1.4;
|
||||
|
||||
/// Individual username label component.
|
||||
///
|
||||
/// Renders as HTML/CSS for efficient updates independent of avatar canvas.
|
||||
/// Reads avatar position from the shared bounds store written by AvatarCanvas.
|
||||
#[component]
|
||||
pub fn UsernameLabel(
|
||||
/// The user ID this label belongs to (for reading bounds from store).
|
||||
user_id: Uuid,
|
||||
/// The display name to show.
|
||||
display_name: String,
|
||||
/// Shared store containing avatar bounds (written by AvatarCanvas).
|
||||
avatar_bounds_store: AvatarBoundsStore,
|
||||
/// Text size multiplier.
|
||||
#[prop(default = 1.0.into())]
|
||||
text_em_size: Signal<f64>,
|
||||
/// Optional opacity for fading members.
|
||||
#[prop(default = 1.0)]
|
||||
opacity: f64,
|
||||
) -> impl IntoView {
|
||||
// Compute style based on avatar bounds
|
||||
let style = Memo::new(move |_| {
|
||||
let te = text_em_size.get();
|
||||
let text_scale = te * BASE_TEXT_SCALE;
|
||||
let font_size = 12.0 * text_scale;
|
||||
|
||||
let avatar_bounds = avatar_bounds_store
|
||||
.get()
|
||||
.get(&user_id)
|
||||
.copied()
|
||||
.unwrap_or_default();
|
||||
|
||||
// If bounds are all zero, avatar hasn't rendered yet
|
||||
if avatar_bounds.content_center_x == 0.0 && avatar_bounds.content_top_y == 0.0 {
|
||||
return "display: none;".to_string();
|
||||
}
|
||||
|
||||
let x = avatar_bounds.content_center_x;
|
||||
let y = avatar_bounds.content_bottom_y + 15.0 * text_scale;
|
||||
|
||||
format!(
|
||||
"position: absolute; \
|
||||
left: {}px; \
|
||||
top: {}px; \
|
||||
transform: translateX(-50%); \
|
||||
--font-size: {}px; \
|
||||
opacity: {}; \
|
||||
z-index: 99998;",
|
||||
x, y, font_size, opacity
|
||||
)
|
||||
});
|
||||
|
||||
view! {
|
||||
<div
|
||||
class="username-label"
|
||||
style=style
|
||||
data-user-id=user_id.to_string()
|
||||
>
|
||||
{display_name}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue