diff --git a/packages/app/src/app/globals.css b/packages/app/src/app/globals.css index a3823f2..16d97cc 100644 --- a/packages/app/src/app/globals.css +++ b/packages/app/src/app/globals.css @@ -16,3 +16,24 @@ body { font-family: 'Segoe UI Variable', 'Segoe UI', system-ui, -apple-system, sans-serif; background: #f5f5f5; } + +/* ── Accessible focus indicators ──────────────────────────────────────────── + Inline styles set outline:none to suppress browser defaults, but without a + replacement this breaks keyboard navigation. :focus-visible adds a visible + ring only for keyboard focus (not mouse clicks) across the entire app. + The ring colour adapts to context: blue for light-bg pages (#0066FF), + and a lighter blue for dark-bg panels (#3385FF / canvas inspector etc.). + We use !important to override inline outline:none intentionally. */ + +input:focus-visible, +textarea:focus-visible, +select:focus-visible { + outline: 2px solid #0066FF !important; + outline-offset: 2px !important; +} + +/* Canvas panels sit on a dark background — the ring matches the panel accent */ +.dark-panel input:focus-visible, +.dark-panel textarea:focus-visible { + outline-color: #3385FF !important; +} diff --git a/packages/app/src/app/onboarding/page.tsx b/packages/app/src/app/onboarding/page.tsx index a605b16..523c0d7 100644 --- a/packages/app/src/app/onboarding/page.tsx +++ b/packages/app/src/app/onboarding/page.tsx @@ -47,7 +47,7 @@ export default function OnboardingPage() { return (
(e.currentTarget.style.borderColor = '#0066FF')} diff --git a/packages/app/src/app/workspace/[wid]/page.tsx b/packages/app/src/app/workspace/[wid]/page.tsx index 7f0d7e7..829dd43 100644 --- a/packages/app/src/app/workspace/[wid]/page.tsx +++ b/packages/app/src/app/workspace/[wid]/page.tsx @@ -46,7 +46,7 @@ export default async function WorkspacePage({ params }: { params: Promise<{ wid: const projects = (projectsData ?? []) as Project[]; return ( -
+
+
+
+
@@ -61,7 +61,7 @@ export default function NewWorkspacePage() { width: '100%', boxSizing: 'border-box', padding: '10px 12px', fontSize: '0.9375rem', border: '1px solid rgba(0,0,0,0.12)', borderRadius: 8, - outline: 'none', color: '#0A0A0A', background: '#FFFFFF', + color: '#0A0A0A', background: '#FFFFFF', fontFamily: 'inherit', }} onFocus={e => (e.currentTarget.style.borderColor = '#0066FF')} diff --git a/packages/app/src/app/workspaces/page.tsx b/packages/app/src/app/workspaces/page.tsx index d75fd02..de0b113 100644 --- a/packages/app/src/app/workspaces/page.tsx +++ b/packages/app/src/app/workspaces/page.tsx @@ -37,7 +37,7 @@ export default async function WorkspacesPage() { if (workspaces.length === 0) redirect('/onboarding'); return ( -
+
diff --git a/packages/app/src/components/canvas/Canvas.tsx b/packages/app/src/components/canvas/Canvas.tsx index 997ac1c..8e243d7 100644 --- a/packages/app/src/components/canvas/Canvas.tsx +++ b/packages/app/src/components/canvas/Canvas.tsx @@ -350,6 +350,8 @@ function ZonePromptOverlay({ fontFamily: 'inherit', resize: 'none', outline: 'none', marginBottom: 8, }} + onFocus={e => (e.currentTarget.style.borderColor = '#3385FF')} + onBlur={e => (e.currentTarget.style.borderColor = 'rgba(255,255,255,0.1)')} /> {status === 'error' && (

Request failed — try again

diff --git a/packages/app/src/components/chrome/AppChrome.tsx b/packages/app/src/components/chrome/AppChrome.tsx index 1ea4bed..e682a55 100644 --- a/packages/app/src/components/chrome/AppChrome.tsx +++ b/packages/app/src/components/chrome/AppChrome.tsx @@ -110,6 +110,8 @@ export function AppChrome({ workspaceId, projectId, workspaceName, projectName } borderBottom: '1px solid rgba(255,255,255,0.06)', display: 'flex', alignItems: 'center', padding: '0 14px', gap: 0, + zIndex: 10, + position: 'relative', }}> {/* Logo */} diff --git a/packages/app/src/components/inspector/Inspector.tsx b/packages/app/src/components/inspector/Inspector.tsx index 49245ac..c890f4f 100644 --- a/packages/app/src/components/inspector/Inspector.tsx +++ b/packages/app/src/components/inspector/Inspector.tsx @@ -40,6 +40,7 @@ export function Inspector() { return (
- {/* Content */} -
+ {/* Content — minHeight:0 is required so this flex child can actually shrink and scroll */} +
{!selectedArtboardId ? (
+ scrollbarWidth: 'thin', + scrollbarColor: 'rgba(255,255,255,0.18) transparent', + } as React.CSSProperties}> {driftReport}
)} diff --git a/packages/app/src/components/navigator/ArtboardNavigator.tsx b/packages/app/src/components/navigator/ArtboardNavigator.tsx index 044066f..af5bed3 100644 --- a/packages/app/src/components/navigator/ArtboardNavigator.tsx +++ b/packages/app/src/components/navigator/ArtboardNavigator.tsx @@ -81,6 +81,7 @@ export function ArtboardNavigator() { return (