diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 75f7a5fa..6e1aa660 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,6 +25,7 @@ jobs: app-name: figcraft app-title: FigCraft craft-fonts-ref: 43913056ce82a3fdad0ef69f6b88d1dc922a8104 + web-craft-fonts: true has-server: true version: ${{ inputs.version }} secrets: diff --git a/crates/text/build.rs b/crates/text/build.rs index f5f5096b..6d59a993 100644 --- a/crates/text/build.rs +++ b/crates/text/build.rs @@ -65,8 +65,8 @@ fn craft_fonts(dir: &std::path::Path, manifest_rel: &str) -> Result String { ); crate::widgets::select_all_on_focus(ui, &r, &filter); if r.has_focus() { - ui.painter().rect_stroke(field, CornerRadius::same(5), Stroke::new(1.0, t.accent), egui::StrokeKind::Inside); + ui.painter().rect_stroke(field, CornerRadius::same(5), Stroke::new(1.0, crate::theme::ACCENT), egui::StrokeKind::Inside); if ui.input(|i| i.key_pressed(egui::Key::Escape)) { filter.clear(); } diff --git a/crates/ui-egui/src/comments.rs b/crates/ui-egui/src/comments.rs index 2706bd8a..d33c81ee 100644 --- a/crates/ui-egui/src/comments.rs +++ b/crates/ui-egui/src/comments.rs @@ -189,10 +189,10 @@ pub fn cluster(points: &[Pos2], r: f32) -> Vec> { } /// A message's text with its @mentions of `people` picked out, wrapped at `width`. -pub fn rich_text(text: &str, people: &[&str], color: Color32, width: f32) -> LayoutJob { +pub fn rich_text(text: &str, people: &[&str], color: Color32, mention_color: Color32, width: f32) -> LayoutJob { let mut job = LayoutJob::default(); let plain = TextFormat { font_id: regular(12.0), color, ..Default::default() }; - let mention = TextFormat { font_id: semibold(12.0), color: ACCENT, ..Default::default() }; + let mention = TextFormat { font_id: semibold(12.0), color: mention_color, ..Default::default() }; let mut at = 0; for r in mention_ranges(text, people) { job.append(text.get(at..r.start).unwrap_or(""), 0.0, plain.clone()); @@ -729,7 +729,7 @@ fn message( ui.add_space(indent); let mut names: Vec<&str> = cx.people.iter().map(String::as_str).collect(); names.push(cx.me); - ui.add(egui::Label::new(rich_text(&m.text, &names, t.text, ui.available_width())).wrap()); + ui.add(egui::Label::new(rich_text(&m.text, &names, t.text, t.accent_text, ui.available_width())).wrap()); }); } } @@ -1062,7 +1062,8 @@ pub fn panel(app: &mut FigApp, ui: &mut Ui) { ui.add_space(16.0); ui.label(egui::RichText::new(tr(app.ui.comments.filter.label())).font(regular(11.0)).color(t.text_secondary)); ui.add_space(4.0); - if ui.add(egui::Label::new(egui::RichText::new(tr("Show open")).font(regular(11.0)).color(ACCENT)).sense(Sense::click())).clicked() { + if ui.add(egui::Label::new(egui::RichText::new(tr("Show open")).font(regular(11.0)).color(t.accent_text)).sense(Sense::click())).clicked() + { app.ui.comments.filter = Filter::Open; } }); diff --git a/crates/ui-egui/src/dev_mode.rs b/crates/ui-egui/src/dev_mode.rs index d3456088..0b429820 100644 --- a/crates/ui-egui/src/dev_mode.rs +++ b/crates/ui-egui/src/dev_mode.rs @@ -628,7 +628,7 @@ pub fn dev_resources_section(app: &mut FigApp, ui: &mut Ui, doc: &Document, id: } icons::paint(ui.painter(), Rect::from_center_size(pos2(r.min.x + PAD + 7.0, r.center().y), vec2(14.0, 14.0)), Icon::Link, t.icon_secondary); let x = r.min.x + PAD + 22.0; - ui.painter().text(pos2(x, r.center().y - 7.0), Align2::LEFT_CENTER, widgets::elide(ui, name, text_w), semibold(11.0), ACCENT); + ui.painter().text(pos2(x, r.center().y - 7.0), Align2::LEFT_CENTER, widgets::elide(ui, name, text_w), semibold(11.0), t.accent_text); let below = match item.from.and_then(|f| doc.node(f)) { Some(m) => trf("From {name}", &[("name", &m.name)]), None => url.clone(), diff --git a/crates/ui-egui/src/home.rs b/crates/ui-egui/src/home.rs index 34f35100..700390a9 100644 --- a/crates/ui-egui/src/home.rs +++ b/crates/ui-egui/src/home.rs @@ -324,7 +324,7 @@ fn action_card(ui: &mut Ui, t: &Tokens, icon: Icon, title: &str, sub: &str) -> b } card_frame(ui, t, r, &resp); let ir = Rect::from_min_size(pos2(r.min.x + 16.0, r.center().y - 16.0), vec2(32.0, 32.0)); - ui.painter().rect_filled(ir, CornerRadius::same(6), ACCENT); + ui.painter().rect_filled(ir, CornerRadius::same(6), t.accent); icons::paint(ui.painter(), ir.shrink(8.0), icon, t.accent_on); ui.painter().text(pos2(r.min.x + 60.0, r.center().y - 8.0), Align2::LEFT_CENTER, title_shown, semibold(12.0), t.text); ui.painter().text(pos2(r.min.x + 60.0, r.center().y + 9.0), Align2::LEFT_CENTER, sub_shown, regular(11.0), t.text_secondary); diff --git a/crates/ui-egui/src/home_recents.rs b/crates/ui-egui/src/home_recents.rs index 708fb4db..81d68240 100644 --- a/crates/ui-egui/src/home_recents.rs +++ b/crates/ui-egui/src/home_recents.rs @@ -738,7 +738,7 @@ fn file_icon(ui: &Ui, t: &Tokens, center: egui::Pos2, path: &str) { let r = Rect::from_center_size(center, vec2(16.0, 16.0)); match FileKind::of(Path::new(path)) { FileKind::FigCraft | FileKind::Fig => { - ui.painter().rect_filled(r, CornerRadius::same(4), ACCENT); + ui.painter().rect_filled(r, CornerRadius::same(4), t.accent); icons::paint(ui.painter(), r.shrink(3.0), Icon::Logo, t.accent_on); } kind => { diff --git a/crates/ui-egui/src/home_recents_tests.rs b/crates/ui-egui/src/home_recents_tests.rs index 1c3235dd..e49866ab 100644 --- a/crates/ui-egui/src/home_recents_tests.rs +++ b/crates/ui-egui/src/home_recents_tests.rs @@ -256,9 +256,11 @@ fn rects_of(s: &[Shape], c: egui::Color32) -> usize { s.iter().filter(|s| matches!(s, Shape::Rect(r) if r.fill == c)).count() } -/// Images drawn (meshes with a texture of their own). +/// Preview images in the main content area, excluding the branded sidebar icon. fn images(s: &[Shape]) -> usize { - s.iter().filter(|s| matches!(s, Shape::Mesh(m) if m.texture_id != egui::TextureId::default())).count() + s.iter() + .filter(|s| matches!(s, Shape::Mesh(m) if m.texture_id != egui::TextureId::default() && m.vertices.iter().any(|v| v.pos.x > 240.0))) + .count() } #[test] diff --git a/crates/ui-egui/src/layers.rs b/crates/ui-egui/src/layers.rs index 32f66f80..26b63a5b 100644 --- a/crates/ui-egui/src/layers.rs +++ b/crates/ui-egui/src/layers.rs @@ -332,7 +332,7 @@ fn pages_edge(app: &mut FigApp, ui: &mut Ui, shown: f32) { if active { ui.ctx().set_cursor_icon(egui::CursorIcon::ResizeVertical); } - let (width, colour) = if active { (2.0, t.accent) } else { (1.0, t.border) }; + let (width, colour) = if active { (2.0, ACCENT) } else { (1.0, t.border) }; ui.painter().line_segment([line.left_center(), line.right_center()], Stroke::new(width, colour)); let asked = if resp.double_clicked() { Some(None) @@ -642,7 +642,7 @@ fn search_field(app: &mut FigApp, ui: &mut Ui, t: &Tokens, w: f32, id: Id) { ); crate::widgets::select_all_on_focus(ui, &r, &app.ui.layer_filter); if r.has_focus() { - ui.painter().rect_stroke(field, CornerRadius::same(5), Stroke::new(1.0, t.accent), egui::StrokeKind::Inside); + ui.painter().rect_stroke(field, CornerRadius::same(5), Stroke::new(1.0, ACCENT), egui::StrokeKind::Inside); } if (r.has_focus() || r.lost_focus()) && ui.input(|i| i.key_pressed(egui::Key::Escape)) { app.ui.layer_search = false; diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index 450317b4..c3824253 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -1032,7 +1032,7 @@ impl FigApp { let resp = ui.interact(rect, id, egui::Sense::click_and_drag()); if resp.hovered() || resp.dragged() { ui.ctx().set_cursor_icon(egui::CursorIcon::ResizeHorizontal); - ui.painter().vline(x, rows, egui::Stroke::new(2.0, theme::Tokens::get(ui.ctx()).accent)); + ui.painter().vline(x, rows, egui::Stroke::new(2.0, theme::ACCENT)); } if resp.double_clicked() { return Some(PANEL_DEFAULT); @@ -1716,11 +1716,11 @@ pub(crate) fn drop_overlay(ctx: &egui::Context, rect: egui::Rect, label: &str) { let painter = ctx.layer_painter(egui::LayerId::new(egui::Order::Foreground, egui::Id::new("drop_overlay"))); let area = rect.shrink(4.0); painter.rect_filled(area, egui::CornerRadius::same(8), t.accent.gamma_multiply(0.12)); - painter.rect_stroke(area, egui::CornerRadius::same(8), egui::Stroke::new(2.0, t.accent), egui::StrokeKind::Inside); + painter.rect_stroke(area, egui::CornerRadius::same(8), egui::Stroke::new(2.0, theme::ACCENT), egui::StrokeKind::Inside); let galley = painter.layout_no_wrap(label.to_owned(), theme::semibold(14.0), t.text); let pill = egui::Rect::from_center_size(area.center(), galley.size() + egui::vec2(32.0, 16.0)); painter.rect_filled(pill, egui::CornerRadius::same(8), t.panel); - painter.rect_stroke(pill, egui::CornerRadius::same(8), egui::Stroke::new(1.0, t.accent), egui::StrokeKind::Inside); + painter.rect_stroke(pill, egui::CornerRadius::same(8), egui::Stroke::new(1.0, theme::ACCENT), egui::StrokeKind::Inside); painter.galley(pill.center() - galley.size() / 2.0, galley, t.text); // Hovering sends no pointer events on every platform: keep the overlay current. ctx.request_repaint(); diff --git a/crates/ui-egui/src/present.rs b/crates/ui-egui/src/present.rs index 786f5c5a..9c0f1608 100644 --- a/crates/ui-egui/src/present.rs +++ b/crates/ui-egui/src/present.rs @@ -2223,7 +2223,7 @@ fn top_bar(p: &mut Presenter, ui: &mut Ui, bar: Rect, now: f64, chrome: Chrome) } let on = (*act == BarAction::Comments && p.view.comments) || (*act == BarAction::Inspect && p.view.inspect); if on { - ui.painter().rect_filled(br, CornerRadius::same(5), ACCENT); + ui.painter().rect_filled(br, CornerRadius::same(5), t.accent); } else if resp.hovered() { ui.painter().rect_filled(br, CornerRadius::same(5), hover); } diff --git a/crates/ui-egui/src/proto_panel.rs b/crates/ui-egui/src/proto_panel.rs index 710bab99..86085b8f 100644 --- a/crates/ui-egui/src/proto_panel.rs +++ b/crates/ui-egui/src/proto_panel.rs @@ -763,7 +763,7 @@ fn trigger_rows(app: &mut FigApp, ui: &mut Ui, node: NodeId, k: usize, it: &Inte let id = capture_id().with("field"); ui.painter().rect_filled(r, CornerRadius::same(5), t.field); if cap { - ui.painter().rect_stroke(r, CornerRadius::same(5), Stroke::new(1.0, t.accent), StrokeKind::Inside); + ui.painter().rect_stroke(r, CornerRadius::same(5), Stroke::new(1.0, ACCENT), StrokeKind::Inside); ui.memory_mut(|m| m.request_focus(id)); let _ = ui.interact(r, id, Sense::focusable_noninteractive()); let pressed = ui.input(|i| { diff --git a/crates/ui-egui/src/right.rs b/crates/ui-egui/src/right.rs index e6d2b8b9..2dc71192 100644 --- a/crates/ui-egui/src/right.rs +++ b/crates/ui-egui/src/right.rs @@ -11,7 +11,7 @@ use crate::i18n::{tr, trf, trn}; use crate::icons::{self, Icon}; use crate::list_drag::{ListDrag, move_flags, remove_flags}; use crate::style_picker::{self, StyleSlot}; -use crate::theme::{ACCENT, Tokens, regular, semibold}; +use crate::theme::{Tokens, regular, semibold}; use crate::widgets::{self, Edit, FIELD_H, FieldEdit, Lead, PAD}; use crate::{FigApp, RightTab}; @@ -88,7 +88,7 @@ pub fn right_panel(app: &mut FigApp, ui: &mut Ui) { let sw = (label.size().x + 24.0).max(56.0); let share = Rect::from_min_size(pos2(top.max.x - 14.0 - sw, top.center().y - 16.0), vec2(sw, 32.0)); let sresp = ui.interact(share, ui.id().with("share"), Sense::click()).tip(tr("Share: live session, export")); - ui.painter().rect_filled(share, CornerRadius::same(6), if sresp.hovered() { t.accent_hover } else { ACCENT }); + ui.painter().rect_filled(share, CornerRadius::same(6), if sresp.hovered() { t.accent_hover } else { t.accent }); ui.painter().galley(share.center() - label.size() / 2.0, label, t.accent_on); crate::live::share_popover(app, &sresp); // Play presents; its chevron opens the play menu (present, or preview in a pane). @@ -286,11 +286,11 @@ pub fn menu_row(ui: &mut Ui, label: &str, shortcut: &str, art_w: f32, art: impl if hovered { ui.painter().rect_filled(r, CornerRadius::same(5), t.menu_hover); } - let col = if hovered { Color32::WHITE } else { t.text }; + let col = t.menu_text; ui.painter().galley(pos2(r.min.x + MENU_PAD, r.center().y - text.size().y / 2.0), text, col); if let Some(k) = keys { let at = pos2(r.max.x - MENU_PAD - k.size().x, r.center().y - k.size().y / 2.0); - ui.painter().galley(at, k, if hovered { Color32::WHITE } else { t.text_secondary }); + ui.painter().galley(at, k, if hovered { t.menu_text } else { t.menu_dim }); } art(ui.painter(), r, col); resp diff --git a/crates/ui-egui/src/style_picker.rs b/crates/ui-egui/src/style_picker.rs index 966ea482..29c9c5a9 100644 --- a/crates/ui-egui/src/style_picker.rs +++ b/crates/ui-egui/src/style_picker.rs @@ -482,7 +482,7 @@ fn style_grid(ui: &mut Ui, list: &[(&Style, Key)], applied: Option<&Key>, editab None => preview(ui, r, s, StyleSlot::Fill), } if applied == Some(key) { - ui.painter().rect_stroke(r.expand(2.0), CornerRadius::same(5), Stroke::new(2.0, t.accent), egui::StrokeKind::Inside); + ui.painter().rect_stroke(r.expand(2.0), CornerRadius::same(5), Stroke::new(2.0, crate::theme::ACCENT), egui::StrokeKind::Inside); } else if resp.hovered() && !text { ui.painter().rect_stroke(r.expand(2.0), CornerRadius::same(4), Stroke::new(1.0, t.menu_text), egui::StrokeKind::Inside); } diff --git a/crates/ui-egui/src/theme.rs b/crates/ui-egui/src/theme.rs index 517f9089..01b9e7f5 100644 --- a/crates/ui-egui/src/theme.rs +++ b/crates/ui-egui/src/theme.rs @@ -45,14 +45,17 @@ pub struct Tokens { pub focus: Color32, } -/// FigCraft's brand green, shared with the original app icon. -pub const ACCENT: Color32 = Color32::from_rgb(0x02, 0xDA, 0x96); +/// FigCraft's brand green for solid surfaces. +pub const BRAND: Color32 = Color32::from_rgb(0x02, 0xDA, 0x96); +/// Contrast-safe green for thin selection outlines and white-on-green labels. +/// It reaches 4.5:1 on white and 3:1 on the dark canvas. +pub const ACCENT: Color32 = Color32::from_rgb(0x00, 0x87, 0x5F); /// Ink on the bright green brand surface (white would not have enough contrast). pub const ACCENT_ON: Color32 = Color32::from_rgb(0x07, 0x35, 0x2A); pub const COMPONENT: Color32 = Color32::from_rgb(0x97, 0x47, 0xFF); /// Handoff status badges (white text on these, in both themes). -pub const DEV_READY: Color32 = Color32::from_rgb(0x14, 0xAE, 0x5C); -pub const DEV_CHANGED: Color32 = Color32::from_rgb(0xD9, 0x7A, 0x06); +pub const DEV_READY: Color32 = Color32::from_rgb(0x08, 0x7D, 0x4F); +pub const DEV_CHANGED: Color32 = Color32::from_rgb(0xA7, 0x5B, 0x00); pub const DEV_COMPLETED: Color32 = Color32::from_rgb(0x6E, 0x6E, 0x73); impl Tokens { @@ -74,7 +77,7 @@ impl Tokens { pressed: Color32::from_rgb(0xE6, 0xE6, 0xE6), field: Color32::from_rgb(0xF5, 0xF5, 0xF5), field_hover_border: Color32::from_rgb(0xE6, 0xE6, 0xE6), - accent: ACCENT, + accent: BRAND, accent_hover: Color32::from_rgb(0x00, 0xAD, 0x78), accent_on: ACCENT_ON, // Darker green keeps links and labels legible on white and selected rows. @@ -84,7 +87,7 @@ impl Tokens { component: COMPONENT, component_row: Color32::from_rgb(0xF1, 0xE9, 0xFF), danger: Color32::from_rgb(0xF2, 0x48, 0x22), - success: Color32::from_rgb(0x14, 0xAE, 0x5C), + success: DEV_READY, warning: Color32::from_rgb(0xFF, 0xCD, 0x29), guide: Color32::from_rgb(0xF2, 0x48, 0x22), tab_bar: Color32::from_rgb(0xE8, 0xE8, 0xE8), @@ -92,7 +95,7 @@ impl Tokens { shadow: Color32::from_black_alpha(40), menu: Color32::from_rgb(0x1E, 0x1E, 0x1E), menu_text: Color32::from_rgb(0xFF, 0xFF, 0xFF), - menu_hover: Color32::from_rgb(0x00, 0x6B, 0x4C), + menu_hover: ACCENT, menu_dim: Color32::from_rgb(0x9A, 0x9A, 0x9A), focus: Color32::from_rgb(0x00, 0x7A, 0x56), } @@ -115,7 +118,7 @@ impl Tokens { pressed: Color32::from_rgb(0x44, 0x44, 0x44), field: Color32::from_rgb(0x38, 0x38, 0x38), field_hover_border: Color32::from_rgb(0x4D, 0x4D, 0x4D), - accent: ACCENT, + accent: BRAND, accent_hover: Color32::from_rgb(0x52, 0xE9, 0xB7), accent_on: ACCENT_ON, accent_text: Color32::from_rgb(0x52, 0xE9, 0xB7), @@ -124,7 +127,7 @@ impl Tokens { component: Color32::from_rgb(0xD2, 0x7C, 0xFF), component_row: Color32::from_rgb(0x3E, 0x30, 0x52), danger: Color32::from_rgb(0xF2, 0x48, 0x22), - success: Color32::from_rgb(0x14, 0xAE, 0x5C), + success: DEV_READY, warning: Color32::from_rgb(0xFF, 0xCD, 0x29), guide: Color32::from_rgb(0xF2, 0x48, 0x22), tab_bar: Color32::from_rgb(0x1E, 0x1E, 0x1E), @@ -132,9 +135,9 @@ impl Tokens { shadow: Color32::from_black_alpha(90), menu: Color32::from_rgb(0x1E, 0x1E, 0x1E), menu_text: Color32::from_rgb(0xFF, 0xFF, 0xFF), - menu_hover: Color32::from_rgb(0x00, 0x6B, 0x4C), + menu_hover: ACCENT, menu_dim: Color32::from_rgb(0x9A, 0x9A, 0x9A), - focus: ACCENT, + focus: BRAND, } } @@ -192,7 +195,7 @@ fn visuals(t: Tokens) -> Visuals { v.window_corner_radius = egui::CornerRadius::same(13); v.menu_corner_radius = egui::CornerRadius::same(13); v.selection.bg_fill = t.accent.gamma_multiply(0.3); - v.selection.stroke = Stroke::new(1.0, t.accent); + v.selection.stroke = Stroke::new(1.0, ACCENT); v.hyperlink_color = t.accent_text; for w in [&mut v.widgets.inactive, &mut v.widgets.hovered, &mut v.widgets.active, &mut v.widgets.open, &mut v.widgets.noninteractive] { w.corner_radius = egui::CornerRadius::same(5); @@ -208,10 +211,10 @@ fn visuals(t: Tokens) -> Visuals { v.widgets.hovered.bg_stroke = Stroke::new(1.0, t.field_hover_border); v.widgets.active.bg_fill = t.pressed; v.widgets.active.weak_bg_fill = t.pressed; - v.widgets.active.bg_stroke = Stroke::new(1.0, t.accent); + v.widgets.active.bg_stroke = Stroke::new(1.0, ACCENT); v.popup_shadow = egui::Shadow { offset: [0, 4], blur: 16, spread: 0, color: t.shadow }; v.window_shadow = egui::Shadow { offset: [0, 8], blur: 24, spread: 0, color: t.shadow }; - v.text_cursor.stroke = Stroke::new(1.0, t.accent); + v.text_cursor.stroke = Stroke::new(1.0, ACCENT); v } @@ -261,9 +264,9 @@ pub fn install_fonts(ctx: &Context, system: bool, cjk: u8) { fonts.families.insert(FontFamily::Name("semibold".into()), semi); // Keep the logo's typeface independent of UI text. System Archivo is used when available; // releases with craft-fonts embed it so the wordmark does not depend on installation. - let archivo = find("Archivo", "SemiBold") - .map(FontData::from_static) - .or_else(|| system.then(|| figcraft_text::find_face("Archivo", "SemiBold")).flatten().map(|face| font_data(&face))); + let archivo = find("Archivo", "SemiBold").map(FontData::from_static).or_else(|| { + system.then(|| figcraft_text::find_face("Archivo", "SemiBold")).flatten().filter(|face| face.family == "Archivo").map(|face| font_data(&face)) + }); let mut brand = Vec::new(); if let Some(data) = archivo { fonts.font_data.insert("archivo".into(), Arc::new(data)); @@ -368,7 +371,7 @@ pub fn paint_wordmark(painter: &egui::Painter, left_center: egui::Pos2, size: f3 let fig = painter.layout_no_wrap("Fig".into(), font.clone(), t.text); let fig_width = fig.size().x; painter.galley(egui::pos2(left_center.x, left_center.y - fig.size().y / 2.0), fig, t.text); - painter.text(egui::pos2(left_center.x + fig_width, left_center.y), egui::Align2::LEFT_CENTER, "Craft", font, t.accent); + painter.text(egui::pos2(left_center.x + fig_width, left_center.y), egui::Align2::LEFT_CENTER, "Craft", font, t.accent_text); } /// Paint the owner's original chameleon icon from the existing app asset. @@ -379,7 +382,7 @@ pub fn paint_app_icon(ui: &egui::Ui, rect: egui::Rect) { Some(egui::ColorImage::from_rgba_unmultiplied([rgba.width() as usize, rgba.height() as usize], rgba.as_raw())) }); let Some(image) = image else { - ui.painter().rect_filled(rect, egui::CornerRadius::same(5), ACCENT); + ui.painter().rect_filled(rect, egui::CornerRadius::same(5), BRAND); crate::icons::paint(ui.painter(), rect.shrink(rect.width() * 0.22), crate::icons::Icon::Logo, ACCENT_ON); return; }; diff --git a/crates/ui-egui/src/toolbar.rs b/crates/ui-egui/src/toolbar.rs index 1902ad89..58409b97 100644 --- a/crates/ui-egui/src/toolbar.rs +++ b/crates/ui-egui/src/toolbar.rs @@ -9,7 +9,7 @@ use crate::FigApp; use crate::a11y::{self, Nav, Region, Tip}; use crate::i18n::{tr, tr_noop, trf}; use crate::icons::{self, Icon}; -use crate::theme::{ACCENT, Tokens, regular}; +use crate::theme::{Tokens, regular}; struct Group { key: &'static str, @@ -145,7 +145,7 @@ fn main_toolbar(app: &mut FigApp, ui: &mut Ui, canvas: Rect, t: &Tokens) { // The Actions button reads on while its panel is open; clicking it again closes it. let actions_open = id == "actions" && app.ui.palette.is_some(); if actions_open { - ui.painter().rect_filled(r, CornerRadius::same(5), ACCENT); + ui.painter().rect_filled(r, CornerRadius::same(5), t.accent); } else if resp.hovered() { ui.painter().rect_filled(r, CornerRadius::same(5), t.hover); } @@ -372,7 +372,7 @@ fn tool_cell(ui: &mut Ui, t: &Tokens, r: Rect, id: impl egui::AsIdSalt, icon: Ic }); a11y::toggle(&resp, tip, active); let bg = if active { - ACCENT + t.accent } else if resp.hovered() { t.hover } else { @@ -395,7 +395,7 @@ fn done_button(ui: &mut Ui, t: &Tokens, x: f32, cy: f32, tip: &str) -> bool { divider(ui, t, x, cy); let done = Rect::from_min_size(pos2(x + 12.0, cy - 14.0), vec2(DONE_W, 28.0)); let resp = ui.interact(done, ui.id().with("tool_done"), Sense::click()).tip(tip); - ui.painter().rect_filled(done, CornerRadius::same(6), if resp.hovered() { t.accent_hover } else { ACCENT }); + ui.painter().rect_filled(done, CornerRadius::same(6), if resp.hovered() { t.accent_hover } else { t.accent }); ui.painter().text(done.center(), Align2::CENTER_CENTER, tr("Done"), crate::theme::semibold(11.5), t.accent_on); resp.clicked() } diff --git a/crates/ui-egui/src/typography.rs b/crates/ui-egui/src/typography.rs index 7740a9e0..06185d0c 100644 --- a/crates/ui-egui/src/typography.rs +++ b/crates/ui-egui/src/typography.rs @@ -587,7 +587,7 @@ fn decoration_details(app: &mut FigApp, ui: &mut Ui, styles: &[TextStyle], apply if !auto && ui .add( - egui::Label::new(egui::RichText::new(tr("Auto")).font(regular(11.0)).color(Tokens::get(ui.ctx()).accent)) + egui::Label::new(egui::RichText::new(tr("Auto")).font(regular(11.0)).color(Tokens::get(ui.ctx()).accent_text)) .sense(Sense::click()), ) .on_hover_text(tip) @@ -713,7 +713,7 @@ fn variable_axes(app: &mut FigApp, ui: &mut Ui, ids: &[NodeId], styles: &[TextSt } if styles.iter().any(|s| !s.variations.is_empty()) { ui.add_space(8.0); - let r = ui.add(egui::Label::new(egui::RichText::new(tr("Reset to style")).font(regular(11.0)).color(t.accent)).sense(Sense::click())); + let r = ui.add(egui::Label::new(egui::RichText::new(tr("Reset to style")).font(regular(11.0)).color(t.accent_text)).sense(Sense::click())); if r.on_hover_text(tr("Back to the values the font style implies")).clicked() { app.run("text.setVariations", json!({"ids": ids, "variations": {}, "replace": true})); } @@ -789,7 +789,7 @@ fn axis_slider(ui: &mut Ui, id: Id, axis: &figcraft_text::Axis, value: Option, supported: match on { Some(true) => { ui.painter().rect_filled(b, CornerRadius::same(3), t.accent); - icons::paint(ui.painter(), b.shrink(1.5), Icon::Check, Color32::WHITE); + icons::paint(ui.painter(), b.shrink(1.5), Icon::Check, t.accent_on); } Some(false) => { ui.painter().rect_stroke(b, CornerRadius::same(3), Stroke::new(1.0, t.border_strong), StrokeKind::Inside); } None => { ui.painter().rect_filled(b, CornerRadius::same(3), t.accent); - ui.painter().line_segment([pos2(b.min.x + 3.5, b.center().y), pos2(b.max.x - 3.5, b.center().y)], Stroke::new(1.5, Color32::WHITE)); + ui.painter().line_segment([pos2(b.min.x + 3.5, b.center().y), pos2(b.max.x - 3.5, b.center().y)], Stroke::new(1.5, t.accent_on)); } } let col = if supported { t.text } else { t.text_tertiary }; @@ -1025,7 +1025,7 @@ fn lead_field(ui: &mut Ui, id: Id, glyph: LeadGlyph, value: &str, width: f32, ti crate::a11y::text(&resp, tip, value); ui.painter().rect_filled(rect, CornerRadius::same(5), t.field); if editing.is_some() { - ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, t.accent), StrokeKind::Inside); + ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, crate::theme::ACCENT), StrokeKind::Inside); } else if resp.hovered() { ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, t.field_hover_border), StrokeKind::Inside); } @@ -1274,7 +1274,7 @@ pub(crate) fn font_picker(ui: &mut Ui, current: Option<&str>, just_opened: bool) if hovered { ui.painter().rect_filled(rect, CornerRadius::same(5), t.accent); } - let col = if hovered { Color32::WHITE } else { t.text }; + let col = if hovered { t.accent_on } else { t.text }; if current.is_some_and(|c| c.eq_ignore_ascii_case(f)) { icons::paint( ui.painter(), diff --git a/crates/ui-egui/src/widgets.rs b/crates/ui-egui/src/widgets.rs index ea7f4de3..ca7504ae 100644 --- a/crates/ui-egui/src/widgets.rs +++ b/crates/ui-egui/src/widgets.rs @@ -217,7 +217,7 @@ fn number_field_impl( let hovered = field_resp.hovered() || lead_resp.hovered() || editing.is_some(); ui.painter().rect_filled(rect, CornerRadius::same(5), t.field); if editing.is_some() { - ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, t.accent), StrokeKind::Inside); + ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, crate::theme::ACCENT), StrokeKind::Inside); } else if hovered { ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, t.field_hover_border), StrokeKind::Inside); } @@ -507,7 +507,7 @@ fn text_field_in(ui: &mut Ui, id: Id, value: &str, rect: Rect, placeholder: &str a11y::text(&resp, name, value); ui.painter().rect_filled(rect, CornerRadius::same(5), t.field); if editing.is_some() { - ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, t.accent), StrokeKind::Inside); + ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, crate::theme::ACCENT), StrokeKind::Inside); } else if resp.hovered() { ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, t.field_hover_border), StrokeKind::Inside); } @@ -570,7 +570,7 @@ pub fn text_input(ui: &mut Ui, id: Id, text: &mut String, width: f32, hint: &str ui.painter().rect_filled(rect, CornerRadius::same(5), t.field); let r = field_editor(ui, rect, id, text, hint); if r.has_focus() { - ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, t.accent), StrokeKind::Inside); + ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, crate::theme::ACCENT), StrokeKind::Inside); } else if ui.rect_contains_pointer(rect) { ui.painter().rect_stroke(rect, CornerRadius::same(5), Stroke::new(1.0, t.field_hover_border), StrokeKind::Inside); } @@ -992,7 +992,7 @@ pub fn radio(ui: &mut Ui, on: bool, label: &str) -> bool { ui.painter().circle_filled(c, 7.0, t.accent); ui.painter().circle_filled(c, 2.5, t.accent_on); } else { - ui.painter().circle_stroke(c, 6.5, Stroke::new(1.0, if resp.hovered() { t.accent } else { t.border_strong })); + ui.painter().circle_stroke(c, 6.5, Stroke::new(1.0, if resp.hovered() { crate::theme::ACCENT } else { t.border_strong })); } ui.painter().text(pos2(rect.min.x + 22.0, rect.center().y), Align2::LEFT_CENTER, label, regular(11.0), t.text); resp.clicked() @@ -1046,7 +1046,7 @@ pub fn text_field_inline(ui: &mut Ui, id: Id, value: &str, rect: Rect, font: egu match buf { Some(mut text) => { ui.painter().rect_filled(rect.expand(2.0), CornerRadius::same(4), t.panel); - ui.painter().rect_stroke(rect.expand(2.0), CornerRadius::same(4), Stroke::new(1.0, t.accent), StrokeKind::Inside); + ui.painter().rect_stroke(rect.expand(2.0), CornerRadius::same(4), Stroke::new(1.0, crate::theme::ACCENT), StrokeKind::Inside); let mut child = ui.new_child(egui::UiBuilder::new().max_rect(rect)); let r = crate::bidi::single_line(&mut child, te_id, &mut text, font, rect.width()); a11y::own_focus(&r);