Skip to content

fix(mobile): clear the copy toast, restore semantic icons, and raise code contrast - #6818

Merged
iscekic merged 1 commit into
mainfrom
kwf/owner-visual-polish-final-20260927
Sep 29, 2026
Merged

iscekic merged 1 commit into
mainfrom
kwf/owner-visual-polish-final-20260927

Conversation

@iscekic

@iscekic iscekic commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

Changelog for users

  • Message details Copy shows an inline Copied/Could not copy message instead of a toast that covered the sheet.
  • Home choice icons for Code Reviewer, Security Agent, and PR Review now use their intended honey and gold tints like the Profile rows.
  • Formatted code blocks keep readable, distinct syntax colors in light and dark themes, including bright and tinted cards.

Changelog for maintainers

  • Message details Copy now writes to the clipboard directly and reports a boolean; it drops the shared performCopy toast path, so check callers for the old void contract.
  • Inline copy feedback resets when the sheet closes or the message switches, and a generation guard ignores a late copy.
  • Code token color now keys off the card surface: tokenSchemeForSurface and compositeOver classify the composited card instead of the app scheme.
  • The markdown palettes pass a codeTokenScheme, and CodeBlock falls back to the app scheme for tool cards that omit it.
  • tokenColorFor keeps its boolean diff-row API by delegating to tokenColorForScheme; verify both diff renderers and markdown agree.
  • Several dark token values changed; the riskiest spot is the light-theme kilo-chat olive card, whose 10% ink tint lifts the surface.

E2E proof

Long-press message-details Copy keeps the open sheet readable and actionable with no app-root toast covering it: handleMessageDetailsCopy (apps/mobile/src/components/agents/message-details-copy.ts:13-29) writes the clipboard via Clipboard.setStringAsync and returns a boolean with no toast, and MessageDetailsSheet renders the Copied / Could not copy outcome inline via testID message-details-copy-feedback (apps/mobile/src/components/agents/message-details-sheet.tsx:212, driven by useMessageDetailsCopyFeedback at line 67), asserted by message-details-sheet.mounted.test.tsx 'shows inline Copy success and failure feedback and clears it on close' (lines 392-446).

Asserted value: details-copy: inline 'Copied to clipboard' under message-details-copy-feedback. Sense check (model): Head ui-assert log line 'details-copy: inline 'Copied to clipboard' under message-details-copy-feedback' and the head screenshot showing that inline line under Copy message, versus the base run's 'testID node absent; 'Copied to clipboard' text absent'.

Base 332f0c033e07

Base after drive: the long-press Message details sheet open over the agent-chat transcript with the Copy message action visible

Base after ui-assert: the open Message details sheet showing the inline 'Copied to clipboard' line under Copy message with no app-root toast covering the sheet

Base log: ui-assert 9d6c74f84631 exited 1
$ set -euo pipefail
$ : "${KWF_EXPLORER_SIM_CLI:?}" "${KWF_LANE_VM_HARNESS:?}" "${ANDROID_SERIAL:?}"
$ TMP=$(mktemp -d)
$ node "$KWF_EXPLORER_SIM_CLI" do click 'Copy message'
$ sleep 3
$ "$KWF_LANE_VM_HARNESS/e2e/appium.sh" "$ANDROID_SERIAL" hierarchy "$TMP/h.xml" >/dev/null
$ NODE=absent
$ if grep -q 'message-details-copy-feedback' "$TMP/h.xml"; then NODE=present; fi
$ TEXT=absent
$ if grep -q 'Copied to clipboard' "$TMP/h.xml"; then TEXT=present; fi
$ echo "details-copy: testID node $NODE; 'Copied to clipboard' text $TEXT"
$ if [ "$NODE" = present ] && [ "$TEXT" = present ]; then
$ … 4 more line(s)
tapped "Copy message"
details-copy: testID node absent; 'Copied to clipboard' text absent

Head e60a7aa55e98

Head after drive: the long-press Message details sheet open over the agent-chat transcript with the Copy message action visible

Head after ui-assert: the open Message details sheet showing the inline 'Copied to clipboard' line under Copy message with no app-root toast covering the sheet

Head log: ui-assert 9d6c74f84631 exited 0
$ set -euo pipefail
$ : "${KWF_EXPLORER_SIM_CLI:?}" "${KWF_LANE_VM_HARNESS:?}" "${ANDROID_SERIAL:?}"
$ TMP=$(mktemp -d)
$ node "$KWF_EXPLORER_SIM_CLI" do click 'Copy message'
$ sleep 3
$ "$KWF_LANE_VM_HARNESS/e2e/appium.sh" "$ANDROID_SERIAL" hierarchy "$TMP/h.xml" >/dev/null
$ NODE=absent
$ if grep -q 'message-details-copy-feedback' "$TMP/h.xml"; then NODE=present; fi
$ TEXT=absent
$ if grep -q 'Copied to clipboard' "$TMP/h.xml"; then TEXT=present; fi
$ echo "details-copy: testID node $NODE; 'Copied to clipboard' text $TEXT"
$ if [ "$NODE" = present ] && [ "$TEXT" = present ]; then
$ … 4 more line(s)
tapped "Copy message"
details-copy: testID node present; 'Copied to clipboard' text present
details-copy: inline 'Copied to clipboard' under message-details-copy-feedback

Home ProductChoices restore the semantic icon treatment matching the Profile rows: ConfigureRow hue=honey for Code Reviewer and Security Agent and hue=gold for PR Review (apps/mobile/src/components/home/product-choices.tsx:37,47,61) resolve through the shared hue->rowTint->IconTile tokens (apps/mobile/src/components/ui/configure-row.tsx:102-112, apps/mobile/src/lib/agent-color.ts:159-212, apps/mobile/src/components/ui/icon-tile.tsx:34) with no one-off hard-coded colors, asserted as ['honey','honey','gold'] in product-choices.mounted.test.tsx:88, and profile-screen.tsx:181,194,225 already carries the same honey/honey/gold treatment.

Asserted value: home hue: Code Reviewer, Security Agent and PR Review tiles saturated (honey/honey/gold). Sense check (model): Head log line 'home hue: Code Reviewer, Security Agent and PR Review tiles saturated (honey/honey/gold)' with head ui-assert exiting 0, against base saturation 0.30 neutral, and the head screenshot shows the honey/gold-tinted tiles on the Home Explore rows.

Base 332f0c033e07

Base after drive: the Home Explore product-choice rows in light theme showing Code Reviewer, Security Agent and PR Review

Base after ui-assert: the Home Explore rows with the honey-tinted Code Reviewer and Security Agent icon tiles and the gold-tinted PR Review icon tile, matching the Profile rows

Base log: ui-assert 953f34f3b7a3 exited 1
$ set -euo pipefail
$ : "${KWF_LANE_VM_HARNESS:?}" "${ANDROID_SERIAL:?}"
$ TMP=$(mktemp -d)
$ "$KWF_LANE_VM_HARNESS/e2e/appium.sh" "$ANDROID_SERIAL" hierarchy "$TMP/h.xml" >/dev/null
$ adb -s "$ANDROID_SERIAL" exec-out screencap -p > "$TMP/shot.png"
$ cat > "$TMP/probe.cjs" <<'NODE'
$ const fs = require('fs');
$ const sharp = require(process.env.KWF_LANE_VM_HARNESS + '/node_modules/sharp');
$ (async () => {
$   const xml = fs.readFileSync(process.argv[2], 'utf8');
$   const img = await sharp(process.argv[3]).raw().toColourspace('srgb').toBuffer({ resolveWithObject: true });
$   const data = img.data;
$ … 43 more line(s)
home hue: Code Reviewer tile saturation 0.30 rgb(20,18,14)
home hue: Security Agent tile saturation 0.26 rgb(23,22,17)
home hue: PR Review tile saturation 0.30 rgb(20,18,14)
home hue: a product-choice tile is neutral, not its semantic hue

Head e60a7aa55e98

Head after drive: the Home Explore product-choice rows in light theme showing Code Reviewer, Security Agent and PR Review

Head after ui-assert: the Home Explore rows with the honey-tinted Code Reviewer and Security Agent icon tiles and the gold-tinted PR Review icon tile, matching the Profile rows

Head log: ui-assert 953f34f3b7a3 exited 0
$ set -euo pipefail
$ : "${KWF_LANE_VM_HARNESS:?}" "${ANDROID_SERIAL:?}"
$ TMP=$(mktemp -d)
$ "$KWF_LANE_VM_HARNESS/e2e/appium.sh" "$ANDROID_SERIAL" hierarchy "$TMP/h.xml" >/dev/null
$ adb -s "$ANDROID_SERIAL" exec-out screencap -p > "$TMP/shot.png"
$ cat > "$TMP/probe.cjs" <<'NODE'
$ const fs = require('fs');
$ const sharp = require(process.env.KWF_LANE_VM_HARNESS + '/node_modules/sharp');
$ (async () => {
$   const xml = fs.readFileSync(process.argv[2], 'utf8');
$   const img = await sharp(process.argv[3]).raw().toColourspace('srgb').toBuffer({ resolveWithObject: true });
$   const data = img.data;
$ … 43 more line(s)
home hue: Code Reviewer tile saturation 0.77 rgb(124,108,28)
home hue: Security Agent tile saturation 0.77 rgb(124,108,29)
home hue: PR Review tile saturation 0.77 rgb(122,124,28)
home hue: Code Reviewer, Security Agent and PR Review tiles saturated (honey/honey/gold)

Formatted code blocks derive syntax token colors from the real code-card surface and stay legible and distinct in both themes: tokenSchemeForSurface/compositeOver (apps/mobile/src/lib/pr-review/diff/syntax-colors.ts:108-164) classify the composited card, markdown-palette passes codeTokenScheme for the kilo-chat/user/assistant cards (apps/mobile/src/components/agents/markdown-palette.ts:64,77,86), markdown-renderer forwards it (markdown-renderer.ts:219), and CodeBlock/highlightRunChildren apply tokenColorForScheme (code-block.tsx:182,389; code-block-chunk-content.tsx:32,51; highlight-runs.tsx:49), with syntax-colors.test.ts asserting every onLight/onDark token clears the 4.5:1 MIN_TEXT_RATIO on the bright lime card and the tinted olive #616B28 kilo-chat card (lines 21,26-28,167-178).

Asserted value: code contrast: JSON tokens clear 4.5:1 on the bright user card. Sense check (model): Head ui-assert exited 0 with 'code contrast: JSON tokens clear 4.5:1 on the bright user card' (dark #1e6639 token at 4.72:1), while base exited 1 with 'code contrast: JSON tokens below 4.5:1 on the bright card' (#5fcb8e at 1.37:1), on the lime-card JSON code-block screenshots.

Base 332f0c033e07

Base after drive: the dark-theme agent-chat user bubble showing the JSON fenced code block on the bright lime card

Base after ui-assert: the JSON code block with dark, legible, distinct tokens on the bright lime user card

Base log: ui-assert 27c3ae0c6e60 exited 1
$ set -euo pipefail
$ : "${KWF_LANE_VM_HARNESS:?}" "${ANDROID_SERIAL:?}"
$ TMP=$(mktemp -d)
$ adb -s "$ANDROID_SERIAL" exec-out screencap -p > "$TMP/shot.png"
$ cat > "$TMP/probe.cjs" <<'NODE'
$ const sharp = require(process.env.KWF_LANE_VM_HARNESS + '/node_modules/sharp');
$ const CARD = [0xd3, 0xdc, 0x6f];
$ const MIN_RATIO = 4.5;
$ function lin(v) { v /= 255; return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4); }
$ function lum(r, g, b) { return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b); }
$ function cardDiff(r, g, b) { return Math.max(Math.abs(r - CARD[0]), Math.abs(g - CARD[1]), Math.abs(b - CARD[2])); }
$ function hex(c) { return '#' + [c.r, c.g, c.b].map(v => v.toString(16).padStart(2, '0')).join(''); }
$ … 76 more line(s)
code contrast: top ink families #1a1a10 5230px 11.87:1, #5fcb8e 3803px 1.37:1, #66cc8c 955px 1.35:1, #0e0e10 797px 13.07:1, #86d184 603px 1.24:1, #77ce88 499px 1.30:1
code contrast: substantial token families 2 (>= 1997 px of 16643) on bright card 0.662
code contrast: worst token ink #5fcb8e (3803 px) 0.471 vs bright card 0.662 = 1.37:1
code contrast: JSON tokens below 4.5:1 on the bright card

Head e60a7aa55e98

Head after drive: the dark-theme agent-chat user bubble showing the JSON fenced code block on the bright lime card

Head after ui-assert: the JSON code block with dark, legible, distinct tokens on the bright lime user card

Head log: ui-assert 27c3ae0c6e60 exited 0
$ set -euo pipefail
$ : "${KWF_LANE_VM_HARNESS:?}" "${ANDROID_SERIAL:?}"
$ TMP=$(mktemp -d)
$ adb -s "$ANDROID_SERIAL" exec-out screencap -p > "$TMP/shot.png"
$ cat > "$TMP/probe.cjs" <<'NODE'
$ const sharp = require(process.env.KWF_LANE_VM_HARNESS + '/node_modules/sharp');
$ const CARD = [0xd3, 0xdc, 0x6f];
$ const MIN_RATIO = 4.5;
$ function lin(v) { v /= 255; return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4); }
$ function lum(r, g, b) { return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b); }
$ function cardDiff(r, g, b) { return Math.max(Math.abs(r - CARD[0]), Math.abs(g - CARD[1]), Math.abs(b - CARD[2])); }
$ function hex(c) { return '#' + [c.r, c.g, c.b].map(v => v.toString(16).padStart(2, '0')).join(''); }
$ … 76 more line(s)
code contrast: top ink families #1a1a10 5038px 11.87:1, #1e6639 3847px 4.72:1, #0e0e10 797px 13.07:1, #89ac59 505px 1.76:1, #256b3b 432px 4.39:1, #95b45d 354px 1.59:1
code contrast: substantial token families 2 (>= 1990 px of 16587) on bright card 0.662
code contrast: worst token ink #1e6639 (3847 px) 0.101 vs bright card 0.662 = 4.72:1
code contrast: JSON tokens clear 4.5:1 on the bright user card
Owner request

Mobile visual defects across light and dark themes: (1) a toast currently covers a long-press menu; place it so the menu stays readable and actionable. (2) Home page choice icons and the matching profile item icon lack their semantic colors; restore the intended colored icon treatment, not one-off hard-coded colors. (3) formatted code blocks have low syntax contrast, including pale JSON tokens on a bright card; adjust the shared code block/syntax colors for legibility in both themes while retaining distinct token types. Inspect the existing theme tokens and shared components. Verify each visible surface on a real device, including an open long-press menu with a toast. Open a PR for review; do not merge it. Use Android-native device proof for all three surfaces.

@iscekic iscekic self-assigned this Sep 28, 2026
@iscekic
iscekic marked this pull request as ready for review September 28, 2026 19:49
@kilo-code-bot

kilo-code-bot Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (15 files)
  • apps/mobile/src/components/agents/code-block-chunk-content.tsx
  • apps/mobile/src/components/agents/code-block.tsx
  • apps/mobile/src/components/agents/markdown-palette.ts
  • apps/mobile/src/components/agents/markdown-renderer.ts
  • apps/mobile/src/components/agents/message-details-copy.ts
  • apps/mobile/src/components/agents/message-details-sheet.mounted.test.tsx
  • apps/mobile/src/components/agents/message-details-sheet.test.ts
  • apps/mobile/src/components/agents/message-details-sheet.tsx
  • apps/mobile/src/components/home/product-choices.mounted.test.tsx
  • apps/mobile/src/components/home/product-choices.tsx
  • apps/mobile/src/components/pr-review/diff/diff-line.tsx
  • apps/mobile/src/components/pr-review/diff/highlight-runs.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-side-by-side-row.tsx
  • apps/mobile/src/lib/pr-review/diff/syntax-colors.test.ts
  • apps/mobile/src/lib/pr-review/diff/syntax-colors.ts

Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants