From 368bccad215f138fbfef895fd01b6a4b9bc59389 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 2 Oct 2026 23:30:50 -0400 Subject: [PATCH] U: High Contrast interface theme Co-Authored-By: Claude Opus 5.5 --- ROADMAP.md | 1 + crates/ui-egui/src/menus.rs | 2 +- crates/ui-egui/src/theme.rs | 37 ++++++++++++++++++++++++++++++++++++- docs/parity.md | 8 ++++---- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 58e5c1f..1501400 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -50,6 +50,7 @@ DesignCraft aims at full Adobe InDesign parity — and to be better: faster, ope - Editorial notes (`note.new/edit/delete/convertToText/list`, Notes panel): anchored in text, flagged on screen, never printed or exported. - File ▸ Print Booklet (`file.printBooklet`): saddle-stitch or 2-up consecutive printer spreads as PDF, padded with blanks, with a gap between pages. - Edit ▸ Transparency Blend Space (`edit.transparencyBlendSpace`; RGB for web/mobile documents; IDML TransparencyPreference) — stored; compositing is still RGB on screen and in PDF. +- High Contrast interface theme (fifth Interface Color Theme: black chrome, white text, yellow selection). - Drag and drop text editing: drag selected text to move it (Alt copies) with its formatting (`text.release`). - Image Import Options: place any page of a multi-page PDF (`file.place {pdfPage}`; the app asks which page), shown on screen and embedded as that page in PDF export. - Define Lists: named numbered lists that continue across stories in page order (`list.define`, paragraph `listName` / `startAt`), round-tripped through IDML; `null` in `type.para` / `type.char` now removes an override. diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 6a0c4ed..170b814 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -84,7 +84,7 @@ pub const UI_COMMANDS: &[(&str, &str, Option<&str>, &str)] = &[ None, "{name: Essentials|Advanced|Book|Digital Publishing|Interactive for PDF|Printing and Proofing|Typography}", ), - ("window.brightness", "Interface Color Theme", None, "{brightness: dark|mediumDark|mediumLight|light}"), + ("window.brightness", "Interface Color Theme", None, "{brightness: dark|mediumDark|mediumLight|light|highContrast}"), ]; /// Menu bar: (menu, entries). Entries: `cmd:`, `ui:`, `-` separator, `>Submenu` … `<`. diff --git a/crates/ui-egui/src/theme.rs b/crates/ui-egui/src/theme.rs index fbde8c5..a4c014f 100644 --- a/crates/ui-egui/src/theme.rs +++ b/crates/ui-egui/src/theme.rs @@ -12,16 +12,19 @@ pub enum Brightness { MediumDark, MediumLight, Light, + /// Accessibility: black chrome, white text, yellow selection and focus. + HighContrast, } impl Brightness { - pub const ALL: [Brightness; 4] = [Brightness::Dark, Brightness::MediumDark, Brightness::MediumLight, Brightness::Light]; + pub const ALL: [Brightness; 5] = [Brightness::Dark, Brightness::MediumDark, Brightness::MediumLight, Brightness::Light, Brightness::HighContrast]; pub fn label(self) -> &'static str { match self { Brightness::Dark => "Dark", Brightness::MediumDark => "Medium Dark", Brightness::MediumLight => "Medium Light", Brightness::Light => "Light", + Brightness::HighContrast => "High Contrast", } } pub fn id(self) -> &'static str { @@ -30,6 +33,7 @@ impl Brightness { Brightness::MediumDark => "mediumDark", Brightness::MediumLight => "mediumLight", Brightness::Light => "light", + Brightness::HighContrast => "highContrast", } } pub fn parse(s: &str) -> Option { @@ -206,6 +210,37 @@ impl Tokens { tab_strip: hex(0xe2e2e2), ..dark }, + Brightness::HighContrast => Tokens { + app_bar: hex(0x000000), + panel: hex(0x000000), + panel_darker: hex(0x000000), + input: hex(0x000000), + input_border: hex(0xffffff), + divider: hex(0xffffff), + text: hex(0xffffff), + text_strong: hex(0xffffff), + text_dim: hex(0xe6e6e6), + text_disabled: hex(0xa0a0a0), + icon: hex(0xffffff), + hover: hex(0x3d3d00), + tool_active: hex(0x5c5c00), + accent: hex(0xffeb3b), + accent_strong: hex(0xffd600), + row_selected: hex(0x5c5c00), + pasteboard: hex(0x1a1a1a), + ruler: hex(0x000000), + ruler_tick: hex(0xffffff), + tab_inactive: hex(0x000000), + button: hex(0x000000), + border: hex(0xffffff), + field_border: hex(0xffffff), + well: hex(0x5c5c00), + well_rim: hex(0xffeb3b), + ruler_text: hex(0xffffff), + section_divider: hex(0xffffff), + tab_strip: hex(0x000000), + ..dark + }, } } } diff --git a/docs/parity.md b/docs/parity.md index 1f21c63..1b60b89 100644 --- a/docs/parity.md +++ b/docs/parity.md @@ -5,13 +5,13 @@ The summary is generated by `cargo xtask parity` from the table at the bottom of Each row of the InDesign feature catalogue is scored **D** (done), **P** (partial: works but lacks options or UI) or **M** (missing), weighted by priority (**P0** core = 3, **P1** = 2, **P2** = 1). Out-of-scope rows (Adobe cloud services, plug-ins, Typekit, Flash) are excluded. -**Weighted breadth parity: 86%** over 275 features. +**Weighted breadth parity: 87%** over 275 features. | Priority | Features | Done | Partial | Missing | Parity | |---|---|---|---|---|---| | P0 | 102 | 99 | 3 | 0 | 99% | | P1 | 97 | 75 | 21 | 1 | 88% | -| P2 | 76 | 19 | 13 | 44 | 34% | +| P2 | 76 | 20 | 13 | 43 | 35% | | Area | Parity | |---|---| @@ -33,7 +33,7 @@ Each row of the InDesign feature catalogue is scored **D** (done), **P** (partia | XML & automation | 50% | | View & navigation | 82% | | Undo, history, saving | 100% | -| Accessibility | 50% | +| Accessibility | 70% | Open P0 items: Preferences, Vector/page formats (PDF/AI/SVG/EPS place), Export to PDF (print). @@ -315,4 +315,4 @@ Open P0 items: Preferences, Vector/page formats (PDF/AI/SVG/EPS place), Export t | Accessibility | Tagged PDF export | P2 | P | | Accessibility | Alt text | P2 | D | | Accessibility | Keyboard navigation of UI | P1 | P | -| Accessibility | High contrast | P2 | M | +| Accessibility | High contrast | P2 | D |