uttrflow / uttrflow/uttrflow-swift

AI suggestion ghost text takes Uttrflow's appearance, not the field's, so it is invisible on a white page in Dark Mode

Open
#533 0 comments 0 reactions 0 assignees View on GitHub
accessibility area:ai-suggestions bug P1
Dominant language
Swift
Stars
4
Forks
17
Avg merge
3h 32m
Merged PRs (30d)
277

Description

## What happens

The ghost text's colour follows Uttrflow's own appearance, not the field it is drawn over.

- `SuggestionView` draws the ghost as `.foregroundStyle(.primary.opacity(presentation.opacity))` with no background (`Sources/Uttrflow/Suggestion/SuggestionView.swift:56-59`, rows at `:78`, the dot at `:41`).
- The panel is transparent (`isOpaque = false`, `backgroundColor = .clear`, `SuggestionPanelController.swift:164-165`) and never sets its own `appearance`. So `.primary` resolves from `NSApplication.shared.appearance`, which `AppDelegate.applyAppearance` sets from Uttrflow's Light/Dark/System setting (`Sources/Uttrflow/AppDelegate.swift:1762-1769`).
- `ghostOpacity` is 0.45 (`Sources/UttrflowUX/SuggestionPresentation.swift:62`).

Worked out for the common mismatches:

| Mac or Uttrflow appearance | Field background | Ghost colour | Contrast |
|---|---|---|---|
| Dark | white web page or document | white at 45% = white | 1.0 : 1 (invisible) |
| Light | dark editor or terminal (#1E1E1E) | black at 45% over #1E1E1E ≈ #111111 | ≈ 1.1 : 1 (invisible) |
| Light | white | ≈ #8C8C8C | ≈ 3.4 : 1 |
| Dark | #1E1E1E | ≈ #838383 | ≈ 4.4 : 1 |

Most web pages and many documents stay white in Dark Mode, and many terminals are dark in Light Mode. So the mismatch is common, and in it Tab is still armed for a suggestion nobody can see.

(This is not one of the overlay stacking, screen-edge or staleness bugs already being fixed.)

## Why it matters

An invisible suggestion that still takes Tab looks to the user like Tab randomly inserting text. Low-vision users are hit hardest.

## How to reproduce

Set the Mac to Dark Mode, turn AI suggestions on, and type a remembered line into a text field on a white web page. Nothing visible appears, but Tab inserts a completion.

## Acceptance criteria

- The ghost reads against the field it sits on. For example, sample the field's text colour from `AXAttributedStringForRange` (`AXForegroundColor`, which `FocusedFieldReader.typeStyle` already fetches) and draw at a share of that, or give the ghost a subtle backing that guarantees contrast.
- Where the colour cannot be known, the choice is at least made from the screen content's luminance, not from Uttrflow's appearance setting.
- A test in `Tests/UttrflowUXTests` covers the colour decision for light-on-dark and dark-on-light.

Contributor guide

Open the contributing guide

Research direction

Start with SuggestionView.swift, SuggestionPanelController.swift, AppDelegate.swift, and FocusedFieldReader.typeStyle to trace how the ghost colour and appearance are chosen. Add the colour decision coverage under Tests/UttrflowUXTests for light-on-dark and dark-on-light cases; done means suggestions remain readable when the field and Uttrflow appearances differ.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, swift
Domain
accessibility, desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.