fix(web): keep theme placeholder text dimmer than entered text - #9104
All clear
All clear
Details
Note
Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.
🔍 Agent activity — 9 tool calls
1. browse_code — apps/web/src/themePalette.ts
2. git_tools — readableThemeText|foregroundOn|themeRgbToThemeColor
💭 Let me check the signature and semantics of readableThemeText to understand how it's meant to be used.
3. browse_code — apps/web/src/themePalette.ts
4. browse_code — apps/web/src/themePalette.test.ts
💭 I notice the placeholder logic changed from computing a lightness-adjusted oklch string directly to instead mixing text and surface colors until reaching the target contrast ratio, then converting that back to a theme color format. I want to check whether this new conversion function properly handles the color space transformation without introducing rounding or format mismatches. I should check whether the test file actually imports contrastRatio to verify this, and also trace where --placeholder is consumed to see if it's used for input backgrounds against surfaceRaised.
5. browse_code — apps/web/src/themePalette.ts
6. browse_code — apps/web/src/vscodeThemeImport.test.ts
💭 I'm checking whether the test's placeholder alpha value actually gets used, since the title claims a fallback but the theme explicitly provides input.placeholderForeground—so I need to check if the import logic ignores or flattens that key.
7. git_tools — placeholder
💭 I want to check how vscodeThemeImport handles the
readableOnplaceholder, since the test uses an alpha value like "#cdd6f473" - I should look around lines 200-300 in that file.
8. browse_code — apps/web/src/vscodeThemeImport.ts
💭 I'm computing the actual rendered color of that placeholder text by flattening its alpha value over the editor background, which comes out to roughly a medium blue-gray around #6d71..., and I need to check if that has enough contrast against the dark canvas. Working through the luminance math, the contrast ratio lands at about 3.44, which fails the 4.5 threshold, so this confirms the specified color gets rejected and the fallback placeholder logic kicks in—explaining why the test is titled around a fallback scenario. Now I'm digging into how that fallback derived color gets computed via createVividThemeColors, noting it used to solve directly against the raised surface but now blends from a base text color toward that surface at a minimum contrast target—so I want to trace whether checking readability against the canvas versus the raised surface introduces any mismatch in the vivid palette. Since the raised surface tends to be lighter than the canvas in dark themes, a color meeting minimum contrast against the surface will naturally exceed it against the canvas, so that's not an issue. I'm also confirming the existing test expectations still hold—placeholder staying dimmer than the main text on the raised surface—and checking that the mixing-based approach handles direction correctly for both light and dark themes without needing explicit lighter/darker branching. I also verify the oklch output format still matches what other roles and the import tests expect. Now I'm considering whether placeholder inherits hue consistently with mutedForeground, and then flagging a real concern: placeholder text is used on input fields that may sit on the canvas/background surface rather than surfaceRaised, so I need to check whether that changes the contrast guarantees. I realize there's an edge case: if bisection can't find any mix reaching 4.6 contrast, it falls back to returning text itself, making placeholder indistinguishable from text and technically violating the "dimmer than text" expectation — though this is a rare corner case for vivid themes, not something the test seeds likely hit. The old solveOklchLightness approach instead forcibly pushed lightness to meet 4.6 regardless. Checking createManagedThemeColors at line 1137, it uses readableThemeText(surfaceRaised, text, 1, 4.6), confirming this change makes vivid theme behavior consistent with the managed theme path — that's reassuring. I'm also verifying whether readableThemeText could ever fall back to returning text itself if contrast dips below 4.6 near the surface boundary, but a 0.05 L shift from canvas likely keeps contrast comfortably above threshold in dark themes. The diff itself is minimal — one source line plus two test updates — so I want to make sure there's no other consistency issue lurking in the test file. The second test in vscodeThemeImport doesn't touch the changed code path, so it's not a UI concern. The foregroundOn helper is still referenced elsewhere, so nothing's left dead. I'm checking the third assertion in vscodeThemeImport to confirm text contrast against canvas stays higher than placeholder contrast, which should hold given the specified hex values. I'm also confirming placeholder normalization in applyContrast looks fine, and considering whether deriving placeholder from textRgb mixed toward surfaceRaised affects any consumers of that placeholder value downstream. I'm double-checking the argument order in readableThemeText calls to make sure background and foreground aren't swapped between the two call sites — they match. No real findings so far, and I'm noting the added test in themePalette.test.ts as another area to verify. For that new placeholder-contrast test, I'm mentally walking through the math across the seed themes to sanity-check it'll pass: for the light seed, surfaceRaised ends up only slightly darker than canvas, so the placeholder-to-surfaceRaised contrast should land comfortably above the 4.6 minimum since text itself is near 7:1. I'm now doing the same rough check for the dark seed to make sure the same logic holds. I'm fairly confident there are no real issues here. The last thing to verify is whether both the old and new color-conversion paths still consistently output oklch-formatted strings, since one goes through a direct oklch converter and the other through rgb-to-oklch.
9. git_tools — function themeOklchToThemeColor|function formatOklchThemeColor|function solveOklchLightness
💭 I see the actual bug now: the old
foregroundOnwould often return the base textBase lightness immediately since it already meets the 4.6 contrast threshold against surfaceRaised in dark theme, which is exactly why placeholder text ends up nearly as bright as full text. The fix mixes the value down instead, which correctly addresses the reported issue. There's a formatting conflict here — instructions say the final response should literally be "All clear" on one line, but the schema requires JSON output. I'll resolve this by keeping the JSON structure but setting the success state with title and summary both as "All clear".
Agent Credits: 90 credits
Token usage: 14 uncached input · 292,957 cache-read input · 89,914 cache-write input · 5,819 output
Agent Credits may also include non-token charges from external tools such as web research.