Polish workbench keyboard focus
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-06-20 02:18:33 +02:00
parent 053917d6fc
commit 5814afb3b5
8 changed files with 109 additions and 8 deletions
+6 -4
View File
@@ -489,6 +489,7 @@ function App(): JSX.Element {
className={item.key === activeWorkspace ? 'nav-item nav-item-active' : 'nav-item'}
onClick={() => setActiveWorkspace(item.key)}
aria-current={item.key === activeWorkspace ? 'page' : undefined}
aria-label={`Open ${item.label} workspace: ${item.description}`}
data-testid={`workspace-nav-${item.key}`}
>
<span>{item.label}</span>
@@ -515,6 +516,7 @@ function App(): JSX.Element {
className={item.key === activeWorkspace ? 'command-chip command-chip-active' : 'command-chip'}
onClick={() => setActiveWorkspace(item.key)}
aria-pressed={item.key === activeWorkspace}
aria-label={`Switch to ${item.label} workspace`}
>
{item.label}
</button>
@@ -544,16 +546,16 @@ function App(): JSX.Element {
</p>
</div>
<div className="quick-action-grid">
<button type="button" onClick={() => setActiveWorkspace('data')}>
<button type="button" onClick={() => setActiveWorkspace('data')} aria-label="Open data setup workspace">
Open data setup
</button>
<button type="button" onClick={() => setActiveWorkspace('map')}>
<button type="button" onClick={() => setActiveWorkspace('map')} aria-label="Inspect map workspace">
Inspect map
</button>
<button type="button" onClick={() => setActiveWorkspace('analysis')}>
<button type="button" onClick={() => setActiveWorkspace('analysis')} aria-label="Review QA/QC workspace">
Review QA/QC
</button>
<button type="button" onClick={() => setActiveWorkspace('exports')}>
<button type="button" onClick={() => setActiveWorkspace('exports')} aria-label="Manage exports workspace">
Manage exports
</button>
</div>
@@ -86,6 +86,8 @@ export function WorkbenchInspector({
)
const latestQualityCheck = qualityChecks[0] ?? null
const latestPersistedExport = exports[0] ?? null
const activeTabId = `inspector-tab-${activeTab}`
const activePanelId = `inspector-panel-${activeTab}`
const tabs: Array<{ key: InspectorTab; label: string }> = [
{ key: 'context', label: 'Context' },
@@ -111,6 +113,8 @@ export function WorkbenchInspector({
onClick={() => setActiveTab(tab.key)}
role="tab"
aria-selected={activeTab === tab.key}
aria-controls={`inspector-panel-${tab.key}`}
id={`inspector-tab-${tab.key}`}
data-testid={`inspector-tab-${tab.key}`}
>
{tab.label}
@@ -119,7 +123,7 @@ export function WorkbenchInspector({
</div>
{activeTab === 'context' ? (
<div className="inspector-tab-panel">
<div className="inspector-tab-panel" role="tabpanel" id={activePanelId} aria-labelledby={activeTabId}>
<div className="inspector-card">
<h3>Project context</h3>
<InspectorField label="Project" value={selectedProject?.name} />
@@ -157,7 +161,7 @@ export function WorkbenchInspector({
) : null}
{activeTab === 'dataset' ? (
<div className="inspector-tab-panel">
<div className="inspector-tab-panel" role="tabpanel" id={activePanelId} aria-labelledby={activeTabId}>
<div className="inspector-action-bar">
<button type="button" className="secondary-action" onClick={onOpenDataWorkspace}>
Data catalog
@@ -174,7 +178,7 @@ export function WorkbenchInspector({
) : null}
{activeTab === 'quality' ? (
<div className="inspector-tab-panel">
<div className="inspector-tab-panel" role="tabpanel" id={activePanelId} aria-labelledby={activeTabId}>
<div className="inspector-card">
<h3>Latest QA/QC</h3>
<InspectorField label="Check type" value={latestQualityCheck?.check_type} />
@@ -205,7 +209,7 @@ export function WorkbenchInspector({
) : null}
{activeTab === 'ai' ? (
<div className="inspector-tab-panel">
<div className="inspector-tab-panel" role="tabpanel" id={activePanelId} aria-labelledby={activeTabId}>
<div className="inspector-card">
<h3>Detection run</h3>
<InspectorField label="Selected run" value={selectedDetectionRunId} />
+16
View File
@@ -13,6 +13,8 @@
--accent: #0f766e;
--accent-strong: #115e59;
--accent-soft: #e3f4ef;
--focus-ring: #0f766e;
--focus-ring-soft: rgba(15, 118, 110, 0.2);
--warning: #b45309;
--danger: #991b1b;
--shadow: 0 12px 32px rgba(33, 48, 41, 0.08);
@@ -82,6 +84,20 @@ button:disabled {
opacity: 0.52;
}
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.nav-item:focus-visible,
.command-chip:focus-visible,
.inspector-tab:focus-visible,
.dataset-action-button:focus-visible {
outline: 3px solid var(--focus-ring);
outline-offset: 2px;
border-color: var(--focus-ring);
box-shadow: 0 0 0 5px var(--focus-ring-soft);
}
input,
select,
textarea {