fix(web): render UI icons as SVG instead of font glyphs

UI chrome (dropdown carets, undo/redo, checkmarks, close/menu/osnap,
layer/file-menu icons) and ribbon tool icons were drawn as Unicode
glyphs. Desktop fills missing glyphs via system-font fallback, but the
web build bundles only Fira Sans with no fallback, so they rendered as
empty tofu boxes (issue #116).

Add a shared src/ui/icons.rs (SVG-backed, tintable) plus bundled assets,
and switch every glyph site and IconKind::Glyph tool def to SVG.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-18 12:29:32 +03:00
commit 864dd6cef7
81 changed files with 782 additions and 372 deletions

View file

@ -76,7 +76,7 @@ impl StatusBar {
// Which pills the user has chosen to show on the bar.
config: &'a StatusBarConfig,
) -> Element<'a, Message> {
let menu_btn = button(text("≡").size(14).color(ICON_COLOR))
let menu_btn = button(crate::ui::icons::tinted(crate::ui::icons::MENU, 14.0, ICON_COLOR))
.on_press(Message::Command("MENU".into()))
.style(|_: &Theme, _| button::Style {
background: Some(Background::Color(Color::TRANSPARENT)),
@ -285,7 +285,7 @@ fn format_coords(p: glam::Vec3) -> String {
// ── Customization handle ──────────────────────────────────────────────────
fn customize_btn() -> Element<'static, Message> {
button(text("≡").size(14).color(ICON_COLOR))
button(crate::ui::icons::tinted(crate::ui::icons::MENU, 14.0, ICON_COLOR))
.on_press(Message::ToggleStatusBarMenu)
.style(|_: &Theme, status| button::Style {
background: Some(Background::Color(match status {
@ -466,8 +466,15 @@ fn osnap_btn(active: bool, snap_enabled: bool, open: bool) -> Element<'static, M
OSNAP_OFF_TEXT
};
let left = button(text("⚡ OSNAP").size(10).color(text_color))
.on_press(Message::ToggleSnapEnabled)
let left = button(
row![
crate::ui::icons::tinted(crate::ui::icons::BOLT, 11.0, text_color),
text("OSNAP").size(10).color(text_color),
]
.spacing(3)
.align_y(iced::Center),
)
.on_press(Message::ToggleSnapEnabled)
.style(move |_: &Theme, status| button::Style {
background: Some(Background::Color(match status {
button::Status::Hovered => {
@ -495,7 +502,7 @@ fn osnap_btn(active: bool, snap_enabled: bool, open: bool) -> Element<'static, M
})
.padding([2, 6]);
let right = button(text("▾").size(9).color(text_color))
let right = button(crate::ui::icons::arrow_down(9.0, text_color))
.on_press(Message::ToggleSnapPopup)
.style(move |_: &Theme, status| button::Style {
background: Some(Background::Color(match status {
@ -607,12 +614,16 @@ fn space_tab<'a>(
.padding([2, 6])
.width(Length::Fixed(90.0));
let cancel_btn = button(text("✕").size(10).color(Color {
r: 0.65,
g: 0.65,
b: 0.65,
a: 1.0,
}))
let cancel_btn = button(crate::ui::icons::tinted(
crate::ui::icons::CLOSE,
10.0,
Color {
r: 0.65,
g: 0.65,
b: 0.65,
a: 1.0,
},
))
.on_press(Message::LayoutRenameCancel)
.style(|_: &Theme, _| button::Style {
background: Some(Background::Color(Color::TRANSPARENT)),