Skip to content

Make Agency work on iPhone and add dark mode - #20

Open
jcpsimmons wants to merge 2 commits into
browser-use:mainfrom
jcpsimmons:codex/agency-iphone-dark-mode
Open

jcpsimmons wants to merge 2 commits into
browser-use:mainfrom
jcpsimmons:codex/agency-iphone-dark-mode

Conversation

@jcpsimmons

@jcpsimmons jcpsimmons commented Sep 14, 2026

Copy link
Copy Markdown

Agency's desktop navigation and crowded feedback controls leave too little room to review cards on a phone. This change gives the queue a clear reading layout at iPhone widths and adds a persistent System / Light / Dark appearance choice.

  • Full-width queue tabs, native mobile topic/sort pickers, labelled actions, and a feedback field with room to type. Return adds a line on touch screens; Send submits.
  • Device safe-area padding and visual-viewport sizing keep controls accessible around the keyboard and in landscape. Short screens retain topic and sort controls when the keyboard is closed.
  • A restrained blue palette and local font stack carry through cards, Settings, and Activity. Theme choice applies before paint and updates browser chrome; expanded card details survive theme switches.
  • Legacy card surfaces adapt foreground and background together. Stored card HTML, action prompts, approval handling, and job state are unchanged. Image assets keep their original colors.
  • Activity chart labels retain readable sizes, with horizontal scrolling for longer histories.

Validation: production build passes; frontend TypeScript check passes; ESLint reports zero errors and the existing move effect dependency warning. Browser checks cover 320, 375, 390, and 430px portrait widths, 844px landscape, and 1280px desktop; saved themes against the opposite OS preference; Settings; filter/sort behavior; expanded details; multiline feedback and exact approval payloads using intercepted synthetic API responses. A visual-viewport-only keyboard simulation keeps Send in view. Live completed cards and Activity were checked read-only. Physical iPhone Safari validation remains a useful follow-up.

The screenshots below contain fictional sample data only.

Light, 390px Dark, 390px
Phone layout in light mode Phone layout in dark mode

Summary by cubic

Makes the Agency queue usable on iPhone screens and adds a persistent System / Light / Dark appearance choice that applies before paint.

Mobile layout

  • Queue tabs span full width; topic and sort use native pickers on phones.
  • Feedback sits above decision controls with room to type; Return adds a line on touch screens, Send submits.
  • Safe-area padding and visual-viewport sizing keep controls reachable around the keyboard and in landscape.

Theme

  • The choice is saved in this browser and applies across cards, Settings, and Activity.
  • Legacy card surfaces adapt foreground and background together; stored card HTML, action prompts, approval handling, and job state are unchanged.
  • Image assets keep their original colors; card authors can use --ink, --ink-2, --panel, --panel-2, and --accent for theme-aware content.
  • Long activity histories scroll horizontally; physical iPhone Safari validation remains a useful follow-up.

Written for commit c8ea1e7. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/appearance.tsx">

<violation number="1" location="app/appearance.tsx:35">
P1: On iOS Safari versions that only expose `MediaQueryList.addListener`, `useAppearance` throws while subscribing to system-theme changes. Add an `addListener`/`removeListener` fallback so those iPhones can mount the app reliably.</violation>
</file>

<file name="app/agency.tsx">

<violation number="1" location="app/agency.tsx:183">
P3: Open actions no longer show the required visible ↗ marker because the replacement presentation path dropped the old pseudo-element rule. Preserve that rule in the new presentation styles so every Open button retains the documented external-link affordance.</violation>
</file>

<file name="lib/card-presentation.ts">

<violation number="1" location="lib/card-presentation.ts:5">
P2: When a legacy card uses a colored `main` or `article` surface, light mode removes it while dark mode remaps it to `var(--panel-2)`. Preserve the stored light background by removing this unconditional transparent override, while keeping the dark surface rule.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread app/appearance.tsx

function subscribeSystem(callback: () => void) {
const query = window.matchMedia("(prefers-color-scheme: dark)");
query.addEventListener("change", callback);

@cubic-dev-ai cubic-dev-ai Bot Sep 14, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: On iOS Safari versions that only expose MediaQueryList.addListener, useAppearance throws while subscribing to system-theme changes. Add an addListener/removeListener fallback so those iPhones can mount the app reliably.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/appearance.tsx, line 35:

<comment>On iOS Safari versions that only expose `MediaQueryList.addListener`, `useAppearance` throws while subscribing to system-theme changes. Add an `addListener`/`removeListener` fallback so those iPhones can mount the app reliably.</comment>

<file context>
@@ -0,0 +1,91 @@
+
+function subscribeSystem(callback: () => void) {
+  const query = window.matchMedia("(prefers-color-scheme: dark)");
+  query.addEventListener("change", callback);
+  return () => query.removeEventListener("change", callback);
+}
</file context>
Fix with cubic

Comment thread lib/card-presentation.ts
export const cardPresentation = `
:host{display:block;color:var(--ink);font-family:var(--font);color-scheme:inherit}
*{box-sizing:border-box}
main,article{width:100%;max-width:80ch!important;margin-inline:auto!important;padding:24px!important;background:transparent!important;color:var(--ink)!important;font-family:var(--font)!important}

@cubic-dev-ai cubic-dev-ai Bot Sep 14, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a legacy card uses a colored main or article surface, light mode removes it while dark mode remaps it to var(--panel-2). Preserve the stored light background by removing this unconditional transparent override, while keeping the dark surface rule.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/card-presentation.ts, line 5:

<comment>When a legacy card uses a colored `main` or `article` surface, light mode removes it while dark mode remaps it to `var(--panel-2)`. Preserve the stored light background by removing this unconditional transparent override, while keeping the dark surface rule.</comment>

<file context>
@@ -0,0 +1,43 @@
+export const cardPresentation = `
+:host{display:block;color:var(--ink);font-family:var(--font);color-scheme:inherit}
+*{box-sizing:border-box}
+main,article{width:100%;max-width:80ch!important;margin-inline:auto!important;padding:24px!important;background:transparent!important;color:var(--ink)!important;font-family:var(--font)!important}
+h1{font-family:var(--font)!important;font-size:clamp(25px,4vw,34px)!important;line-height:1.16!important;font-weight:650!important;letter-spacing:-.035em!important;margin:8px 0 18px!important;text-wrap:balance}
+h2,h3{font-family:var(--font)!important;line-height:1.3}
</file context>
Fix with cubic

Comment thread app/agency.tsx
? new Map(Array.from(root.querySelectorAll("details"), (detail) => [detail.querySelector("summary")?.textContent, detail.open]))
: new Map();
root.innerHTML = `<style>:host{display:block;font-family:inherit}*{box-sizing:border-box}[data-radar-action]{min-height:44px;cursor:pointer}[data-radar-action="open"]{display:inline-flex!important;align-items:center;gap:.38em}[data-radar-action="open"]::after{content:"↗";font-size:.8em;line-height:1;opacity:.68;transform:translateY(-.08em)}</style>${idea.cardHtml}`;
root.innerHTML = idea.cardHtml;

@cubic-dev-ai cubic-dev-ai Bot Sep 14, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Open actions no longer show the required visible ↗ marker because the replacement presentation path dropped the old pseudo-element rule. Preserve that rule in the new presentation styles so every Open button retains the documented external-link affordance.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/agency.tsx, line 183:

<comment>Open actions no longer show the required visible ↗ marker because the replacement presentation path dropped the old pseudo-element rule. Preserve that rule in the new presentation styles so every Open button retains the documented external-link affordance.</comment>

<file context>
@@ -177,7 +180,8 @@ function AgentCard({ idea, actionable, onAction, onInteraction }: { idea: Idea;
       ? new Map(Array.from(root.querySelectorAll("details"), (detail) => [detail.querySelector("summary")?.textContent, detail.open]))
       : new Map();
-    root.innerHTML = `<style>:host{display:block;font-family:inherit}*{box-sizing:border-box}[data-radar-action]{min-height:44px;cursor:pointer}[data-radar-action="open"]{display:inline-flex!important;align-items:center;gap:.38em}[data-radar-action="open"]::after{content:"↗";font-size:.8em;line-height:1;opacity:.68;transform:translateY(-.08em)}</style>${idea.cardHtml}`;
+    root.innerHTML = idea.cardHtml;
+    applyCardPresentation(root);
     root.querySelectorAll('[data-radar-action="change"], [data-radar-action="no"]').forEach((button) => button.remove());
</file context>
Suggested change
root.innerHTML = idea.cardHtml;
root.innerHTML = `${idea.cardHtml}<style>[data-radar-action="open"]::after{content:"↗";font-size:.8em;line-height:1;opacity:.68;transform:translateY(-.08em)}</style>`;
Fix with cubic

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant