-
+
{Icons.more({ size: 18 })}
@@ -168,6 +169,8 @@ export function MobileDetail({
{/* Tabs */}
setTab(t.id)}
+ onKeyDown={(e) => {
+ const idx = TABS.findIndex((x) => x.id === t.id);
+ let nextIdx: number | null = null;
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") {
+ nextIdx = (idx + 1) % TABS.length;
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
+ nextIdx = (idx - 1 + TABS.length) % TABS.length;
+ } else if (e.key === "Home") {
+ nextIdx = 0;
+ } else if (e.key === "End") {
+ nextIdx = TABS.length - 1;
+ }
+ if (nextIdx !== null) {
+ e.preventDefault();
+ setTab(TABS[nextIdx]!.id);
+ setTimeout(() => {
+ const btns = document.querySelectorAll('[role="tab"]');
+ (btns[nextIdx!] as HTMLButtonElement | null)?.focus();
+ }, 0);
+ }
+ }}
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
style={{
padding: "8px 14px",
borderRadius: 999,
@@ -215,6 +243,7 @@ export function MobileDetail({
type="button"
onClick={onChat}
data-testid="mobile-chat-cta"
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2"
style={{
width: "100%",
height: 52,
diff --git a/canvas/src/components/mobile/MobileHome.tsx b/canvas/src/components/mobile/MobileHome.tsx
index 271fa511f..2569ada91 100644
--- a/canvas/src/components/mobile/MobileHome.tsx
+++ b/canvas/src/components/mobile/MobileHome.tsx
@@ -183,6 +183,7 @@ export function MobileHome({
type="button"
onClick={onSpawn}
aria-label="Spawn new agent"
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2"
style={{
position: "absolute",
right: 24,
diff --git a/canvas/src/components/mobile/MobileMe.tsx b/canvas/src/components/mobile/MobileMe.tsx
index c1735083d..ca859e9be 100644
--- a/canvas/src/components/mobile/MobileMe.tsx
+++ b/canvas/src/components/mobile/MobileMe.tsx
@@ -83,6 +83,7 @@ export function MobileMe({
type="button"
onClick={() => setAccent(c)}
aria-label={`Set accent ${c}`}
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
style={{
width: 36,
height: 36,
@@ -173,6 +174,7 @@ function SegmentedRow({
key={o.id}
type="button"
onClick={() => onChange(o.id)}
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
style={{
flex: 1,
padding: "10px 8px",
diff --git a/canvas/src/components/mobile/MobileSpawn.tsx b/canvas/src/components/mobile/MobileSpawn.tsx
index 7ee62e89d..fd66c783f 100644
--- a/canvas/src/components/mobile/MobileSpawn.tsx
+++ b/canvas/src/components/mobile/MobileSpawn.tsx
@@ -148,6 +148,7 @@ export function MobileSpawn({ dark, onClose }: { dark: boolean; onClose: () => v
type="button"
onClick={onClose}
aria-label="Close"
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
style={{
width: 32,
height: 32,
@@ -214,6 +215,7 @@ export function MobileSpawn({ dark, onClose }: { dark: boolean; onClose: () => v
setTplId(t.id);
setTier(tCode);
}}
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
style={{
background: on
? dark
@@ -286,7 +288,7 @@ export function MobileSpawn({ dark, onClose }: { dark: boolean; onClose: () => v
justifyContent: "center",
}}
>
- {Icons.check({ size: 10, sw: 2.5 })}
+ {Icons.check({ size: 10, sw: 2.5 })}
)}
@@ -330,6 +332,7 @@ export function MobileSpawn({ dark, onClose }: { dark: boolean; onClose: () => v
key={t}
type="button"
onClick={() => setTier(t)}
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
style={{
flex: 1,
padding: "10px 8px",
@@ -377,6 +380,7 @@ export function MobileSpawn({ dark, onClose }: { dark: boolean; onClose: () => v
type="button"
onClick={handleSpawn}
disabled={busy || !tplId || templates.length === 0}
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2"
style={{
width: "100%",
height: 52,
diff --git a/canvas/src/components/mobile/components.tsx b/canvas/src/components/mobile/components.tsx
index 592604a52..4d06ca210 100644
--- a/canvas/src/components/mobile/components.tsx
+++ b/canvas/src/components/mobile/components.tsx
@@ -291,6 +291,7 @@ export function AgentCard({
data-testid="workspace-card"
aria-label={`${agent.name}, status: ${agent.status}, tier ${agent.tier}${agent.remote ? ", remote" : ""}`}
onClick={onClick}
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
style={{
display: "block",
width: "100%",
@@ -444,6 +445,7 @@ export function FilterChips({
type="button"
aria-checked={on}
onClick={() => onChange(o.id)}
+ className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
style={{
display: "inline-flex",
alignItems: "center",