Files
ARCADIA-Studio/harness/experiments/palette-readability-20260913/palette-foundation-independent-review-20260913.md
T

10 KiB
Raw Blame History

Independent review of palette foundation 02c2f6f

Reviewed contribution 02c2f6f46e57cf2cb00c2df789fbbad6caf973e7 against f6595ebf66e88ec42c37b5c1a3c014f5e52cb32d: four files, 369 insertions and 20 deletions. Read the complete selection remedy, readability audit, independent critique, source handoff, production consumers, and installed Iced 0.14.2 style/event/draw sources. This reviewer did not implement the candidate. No compiler, native UI, Gitea operation, or production edit was performed. Only source inspection and dependency-free color arithmetic were executed. Parent owns the separate canvas-consumer work.

Finding requiring a bounded correction

P2 — A reachable read-only input selection is excluded by a false test assumption and resolves to 2.068170:1.

crates/oa-desktop/src/style/tests.rs:158–159 says selection interaction is unavailable in Disabled text inputs and exempts their selected-value pair. Installed iced_widget-0.14.2/src/text_input.rs does not implement that assumption:

  • Mouse press/word selection/triple-click at 720–826 and dragging at 838–904 set focus/selection without checking on_input. Keyboard copy and selection likewise remain available. Mutation branches separately require on_input.
  • diff at 656–662 stops pasting when disabled; it does not clear focus or selection.
  • Draw at 501–583 checks focus/window focus for selection. Only the caret branch uses !is_disabled at 515. The Range branch always paints style.selection at 540–571.
  • Status remains Disabled whenever on_input is absent (1364–1374), including while this selectable read-only input is focused.

This is a real application consumer: hosted/view.rs:51–52,69–78,175–178 makes address, bearer-token and query inputs read-only using on_input_maybe while app.busy. A selected query can also persist when Enter submits the query and busy state changes. An initially read-only address can be selected directly. These source paths establish reachability; native observation is still pending.

Candidate style.rs:46,49 supplies INPUT_SELECTION #7B8E86 and secondary base MUTED #4B5968. Iced's default Disabled value becomes its active placeholder, i.e. MUTED (text_input.rs:1789–1795). It retains INPUT_SELECTION. Their opaque selected-text ratio is 2.068169555, whereas ordinary INK on that same selection is 4.684304944. The source editor's separate colors do not repair these ordinary inputs.

This is a candidate-state contrast gap, not a claim that the prior palette passed or a general WCAG rule forbidding inactive-control exemptions. Here the widget still offers a meaningful reading/selection/copy task, so claiming the pair is unused is factually wrong. Resolve that actual task rather than hiding it behind Disabled nomenclature.

Small repair boundary: correct the test's assumption and exercise the real read-only selected pair. A local ordinary-input adapter for the three existing conditional Hosted inputs can retain dark selected-value-capable ink while preserving on_input_maybe(None) and the read-only state; this avoids casually changing secondary base, which is also every default placeholder and secondary-button fill. Alternatively change a shared role only after reviewing its coupled consumers. Do not clear selection or disable copy merely to make the exempted state unreachable. Parent should choose the smallest coherent color/state distinction; this review makes no implementation change.

Next executable falsifier: resolve production text_input::default(theme(), Disabled) and assert selected value contrast, expecting the current source to fail near 2.06817. Add a real Iced widget-tree/render witness with no input callback, triple-click or drag a populated value, and verify the Range is painted, selected value remains readable, copying preserves text and typing publishes no mutation. A focused populated Hosted query becoming busy on Enter is the application transition witness. Keep the existing enabled-state checks. The exact widget test and native tasks have not been executed here.

Other conclusions and limited coverage gaps

The central Extended-pair approach is source-compatible with the actual public Iced APIs. Explicit Pair literals deliberately bypass Iced's text adjustment, and the tests mostly call resolved production styles rather than merely validating copied palette pairs. Primary/secondary/success/warning/danger button hover states retain base text on strong fill, and checked primary checkbox hover does the same; the candidate's white text and stronger fills cover those actual cross-state combinations. Pick-list/menu backgrounds, borders, placeholder colors and selected-menu foregrounds match the installed implementations. No additional actionable active-state pair failure was found in those reviewed consumers.

Default ordinary text_editor consumers also exist outside the highlighted Source page: descriptions/conditions, semantic-review text, and Hosted read-only source. Their active/focused colors resolve to the ordinary input BG/INK/INPUT_SELECTION combination and therefore have the same passing source arithmetic. They are not all source-styled, which is appropriate. However, the new suite tests ordinary text_input and custom Source text_editor, not default ordinary text_editor; adding that resolved-style case is useful protection against future divergence in the two Iced defaults. This is a coverage improvement, not a demonstrated present failure.

Default scrollbars are another actual shared-role consumer (scrollable.rs:2345–2429, many panes in views.rs). Ordinary thumb MUTED on white rail is 7.172088:1; hover uses primary strong and drag uses TEAL. No present contrast issue was found. The suite omits them. If the foundation is described as covering all default controls, add their resolved states or scope that claim. Auto-scroll overlay alpha/shadow remains a separate composite/native visual check.

The canvas-surface test copies five painter fill constants and the six-percent tint expression. It tests actual INK/MUTED/BOUNDARY/kind outputs, but duplicated fills can become stale if a painter changes. Treat it as a palette baseline, not proof that every actual Scene/canvas paint pair is covered. The separate canvas-consumer work and actual paint witness should verify the real consumer surface/foreground pair. A production palette abstraction solely to avoid a handful of test literals is unnecessary without broader need.

Unused stock button::background/subtle and non-primary checkbox styles have further pair couplings (for example pressed background buttons retain base text over background.strong). Search found no application consumers of those styles. This review does not require exhaustive unused-Iced-style support or count those hypothetical combinations as current application defects.

Syntax, selection lifecycle, disabled state and focus

The diff changes only formatter colors, leaving lexer classes, byte spans, multiline splitting, highlighter settings, source snapshot identity, font mapping, and source edit/persistence/history machinery unchanged. The sole Source .style adapter preserves inherited status-dependent border geometry while assigning its white surface, dark fallback/placeholder/caret and separate selection fill. It does not track selection, introduce range-state caches, recolor only selected text, or trigger selection-specific tokenization. No newly introduced stale-highlight or source mutation path was found.

The S2 colors are very dark and closely matched in luminance; readable ordinary/selected glyph arithmetic does not prove token categories remain easy to scan. Native source reading/editing at the actual font/DPI remains necessary, particularly comments, punctuation, number/string distinctions, error diagnostics and multiline selections. Existing empty/newline-only selection geometry and blur-hidden range paint remain unchanged and must not be claimed repaired.

The Source adapter makes Active and Disabled background/value/placeholder colors identical; its current production Source call always supplies on_action, so Disabled is not a newly reachable ordinary application state there. The test covers Disabled colors but does not prove a distinct read-only cue. Record that limitation if this adapter is reused later; no speculative production change is required now.

Selected navigation correctly preserves inherited disabled text alpha instead of restoring opaque INK. Its 2-unit outline provides a non-fill selection cue. It is not a keyboard-focus implementation. Default source/input focus still changes a one-unit border's color (ordinary BOUNDARY to primary strong), with no extra geometry; it is visible against the surface, but source ratios alone do not prove the focused field can always be located on the user's display. This behavior is inherited, explicitly scoped in the handoff, and not a new blocker to the palette experiment. Native focus transfer should remain a separate acceptance observation. Disabled button alpha tests correctly avoid pretending an opaque contrast equation establishes composited appearance.

Identity and handoff

Local candidate payload hashes match the source handoff:

File SHA-256
style.rs 924e6a92bc28c9f07936c8ab0bc41b6f097956ef4c0e24a571d7fa6fb6591382
style/tests.rs 4a3f7486bfa85129d1504f7a0990e28325bd704770f814f255d5044996246dcd
highlight.rs 8222e2deed5d60ea522241ccb2c653caf50ecc1d4404d633f54e0193c5f622e9
views.rs 1c0b1197d3bf3d3f7aaaea2cf8a89bf4f7e2634e65345f81693fc91df151b9c3
installed Iced text_input.rs 7cd64b0f79c6000f2985cc290642698a814be5dcd7b7a56ae463b13ffe5c3b47
installed Iced text_editor.rs cecf8686c90aa92066d55075beba545dfb7dd5a44bad0c1519fcb110a56070e1

Color arithmetic used the final byte colors, sRGB decoding at 0.04045, luminance weights 0.2126/0.7152/0.0722 and the unrounded luminance contrast ratio. It did not model antialiasing, alpha compositing, gamut, monitor calibration or run the Rust test suite. Recommendation: address the reachable read-only input selection and retain the bounded candidate for combined gates/native evaluation. No palette/display acceptance or issue closure is established by this review.