Skip to content

fix(a11y): add aria-label to icon buttons in dialogs, sidebar, and documents (QUA-189)#1527

Open
hungdqdesign wants to merge 89 commits intopaperclipai:masterfrom
hungdqdesign:fix/dialog-sidebar-aria-label-qua-189
Open

fix(a11y): add aria-label to icon buttons in dialogs, sidebar, and documents (QUA-189)#1527
hungdqdesign wants to merge 89 commits intopaperclipai:masterfrom
hungdqdesign:fix/dialog-sidebar-aria-label-qua-189

Conversation

@hungdqdesign
Copy link

Summary

  • PropertiesPanel.tsx: Close button → aria-label="Close properties panel"
  • NewGoalDialog.tsx: Expand/Minimize button → aria-label (dynamic), Close button → aria-label="Close"
  • NewProjectDialog.tsx: Expand/Minimize button → aria-label (dynamic), Close button → aria-label="Close"
  • Sidebar.tsx: Search button → aria-label="Search"
  • NewAgentDialog.tsx: Close button → aria-label="Close"
  • IssuesList.tsx: Add issue to group → aria-label="Add issue to {group.label}"
  • CompanySkills.tsx: Add skill button → aria-label="Add skill"
  • IssueDetail.tsx: More options PopoverTrigger → aria-label="More options"
  • IssueDocumentsSection.tsx: Copy document + Document actions buttons → add aria-label alongside existing title

Fixes

Resolves QUA-189 — [A11Y] Dialog và Sidebar icon buttons thiếu aria-label (Batch 13)

WCAG criteria addressed:

  • SC 4.1.2 (Name, Role, Value) — Level AA
  • All icon-only buttons now have programmatic accessible names

Test Plan

  • Verify screen reader announces each button correctly
  • Verify hover tooltips (title) still work where applicable
  • No regression for mouse/keyboard interaction

🤖 Generated with Claude Code

hungdqdesign and others added 30 commits March 21, 2026 00:24
… and add missing models (paperclipai#1357)

Cursor CLI now rejects "auto" as a model selection with "Cannot use this
model: auto". Change the default to "composer-2" and add "composer-2" +
"composer-2-fast" to the fallback model list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…awbot.vn

Add allowedHosts: "all" to vite server config so that requests from
custom domain behind Cloudflare are not blocked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Break the monolithic AgentDetail page into focused, maintainable modules:
- AgentDetail.tsx: slim orchestrator (593 LOC, down from 3988)
- agent-detail/OverviewTab.tsx: dashboard with charts, issues, costs
- agent-detail/InstructionsTab.tsx: instructions bundle editor
- agent-detail/ConfigurationTab.tsx: agent config form + permissions + keys
- agent-detail/SkillsTab.tsx: skill management
- agent-detail/RunsTab.tsx: run list + run detail (lazy loaded via React.lazy)
- agent-detail/LogViewer.tsx: live transcript/log viewer
- agent-detail/KeysTab.tsx: API key management
- agent-detail/WorkspaceOperations.tsx: workspace operation UI
- agent-detail/utils.ts: shared utilities and types

RunsTab is lazy-loaded for better initial page performance.
No functional changes — pure extraction refactor.

QUA-123

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…calls

When /agents/:id/wakeup is called directly (not via the checkout route),
the contextSnapshot lacks issueId/projectId/workspaceId, causing the run
to fall back to agent_home instead of the project workspace.

Now enqueueWakeup auto-detects the agent's in-progress checked-out issue
and enriches the context with issueId, projectId, and projectWorkspaceId.
Also persists resolved projectId to contextSnapshot when only issueId was
provided.

Fixes paperclipai#1387

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… locks (QUA-12)

release() now clears executionRunId, executionAgentNameKey, and
executionLockedAt alongside checkoutRunId. Previously these fields
persisted after release, causing permanent stale locks that blocked
re-checkout by other agents.

Adds unit tests verifying all execution fields are nulled on release.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nsert (#QUA-91)

Gemini adapter output sometimes contains null bytes (0x00) which PostgreSQL
rejects in TEXT and JSONB columns. Add stripNullBytes() sanitization at the
DB write layer (setRunStatus + appendRunEvent) to protect against any adapter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rclipai#1361)

On Windows with WIN1252 system locale, child process stdout/stderr
default to the system encoding, causing crashes when adapter output
contains Unicode characters. Add setEncoding("utf8") on streams
immediately after spawn, matching the pattern used in codex-local.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…paperclipai#1465)

Users running adapters like codex_local with non-standard models (e.g.
grok-4.20-beta) were blocked by the hardcoded model dropdown. Now:

- ModelDropdown shows a "Use <custom>" option when search doesn't match
  any known model
- InlineEntitySelector gains allowCustomValue prop for the same behavior
- NewIssueDialog model override selector enables custom values
- Custom model values display correctly in trigger buttons

Closes paperclipai#1465

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nsert (#QUA-91)

Gemini adapter output sometimes contains null bytes (0x00) which PostgreSQL
rejects in TEXT and JSONB columns. Add stripNullBytes() sanitization at the
DB write layer (setRunStatus + appendRunEvent) to protect against any adapter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rclipai#1361)

On Windows with WIN1252 system locale, child process stdout/stderr
default to the system encoding, causing crashes when adapter output
contains Unicode characters. Add setEncoding("utf8") on streams
immediately after spawn, matching the pattern used in codex-local.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… and add missing models (paperclipai#1357)

Cursor CLI now rejects "auto" as a model selection with "Cannot use this
model: auto". Change the default to "composer-2" and add "composer-2" +
"composer-2-fast" to the fallback model list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…awbot.vn

Add allowedHosts: "all" to vite server config so that requests from
custom domain behind Cloudflare are not blocked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…i#1403)

cancelActiveForAgentInternal now matches cancelRunInternal's escalation
pattern: SIGTERM → grace period → SIGKILL. The runningProcesses entry
is deferred until after the grace window to prevent orphaned processes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…aperclipai#1461)

The codex adapter's getQuotaWindows spawns the codex CLI in its class
constructor. If codex is not installed, spawn emits ENOENT which can
crash the server when the Costs → Providers page is loaded.

Wrap each adapter.getQuotaWindows() call in try-catch to handle both
synchronous throws and async rejections gracefully.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s equivalents

- packages/db: replaced `cp -r` with `fs.cpSync(..., {recursive: true})`
- cli: replaced `chmod +x` with a Node.js platform check that only
  runs chmodSync on darwin/linux, skipping Windows entirely

Closes paperclipai#1462
Closes paperclipai#1463

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…paperclipai#1165)

enqueueWakeup can throw (budget blocked, agent state conflict, etc).
Without a try-catch inside the tickTimers loop, one failing agent
aborts the entire tick — silently stopping all scheduled heartbeats.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… local_trusted mode

When a bearer token is present but fails validation (expired JWT, invalid key),
the default local_trusted board actor was not cleared, allowing unauthenticated
requests to inherit full board-level access. This enabled agents with expired
auth to perform destructive operations like deleting other agents.

Now clears the actor to { type: "none" } when a bearer token is present before
validation, so only successful verification restores the proper actor type.

Fixes paperclipai#1314

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…pai#1451)

jwtConfig() only read PAPERCLIP_AGENT_JWT_SECRET, but server startup
(index.ts) accepts BETTER_AUTH_SECRET as a fallback. When only
BETTER_AUTH_SECRET is set (common in local dev), all agent runs failed
to get PAPERCLIP_API_KEY injected. Align the fallback chain so local
agents authenticate correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…th EPERM

On Windows without Developer Mode, symlink creation fails with EPERM.
The new symlinkOrCopy helper catches EPERM and falls back to
fs.cp(source, target, {recursive: true}), allowing skills to be
installed without requiring elevated privileges.

Closes paperclipai#1464

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…perclipai#1464)

On Windows without Developer Mode, symlink creation fails with EPERM.
Add a three-tier fallback: symlink → junction → recursive copy.
This ensures skills installation works for all Windows users without
requiring elevated permissions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hungdqdesign and others added 27 commits March 22, 2026 07:40
- Filter tabs: All | Active | Planned | Achieved
- Default filter: active (most useful view)
- Persist preference to localStorage key goals:statusFilter
- Empty state when filtered results = 0
- Pattern matches Routines page filter bar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nt Tasks (QUA-162)

Section headers for Recent Activity and Recent Tasks lacked navigation links,
creating dead-ends for users who want to see the full list. Added subtle
"View all →" links pointing to /activity and /issues respectively.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
assertAdapterConfigConstraints now checks that the configured model
exists in the adapter's known model list for all adapter types, not
just opencode_local. Returns a clear 422 error with available models
when a mismatch is detected.

Also expanded the PATCH handler guard to call validation for all
adapter types, preventing silent misconfiguration that causes agents
to fail at runtime.

Closes paperclipai#1388

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
buildWakeText hardcoded ~/.openclaw/workspace/ as the claimed API key
location. When an agent has a different workspace (e.g. workspace-nora),
the path was wrong and the agent couldn't find its token.

Now accepts an optional workspacePath from agent config or paperclip
workspace context, falling back to the original default only when
neither is available.

Closes paperclipai#1371

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts:
#	server/src/__tests__/heartbeat-context-content-trust.test.ts
…-tabs

refactor(ui): split AgentDetail.tsx into tab-based modules
fix(ui): allow custom model input for adapters
…i#1390)

A queued heartbeat run that never started (startedAt IS NULL) is now
treated as stale in isTerminalOrMissingHeartbeatRun(), allowing checkout
to supersede its executionRunId lock. Also added a final fallback in
checkout() that clears stale executionRunId locks regardless of issue
status, preventing permanent 409 conflicts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… (QUA-165)

- aria-label={expanded ? "Collapse" : "Expand"} for screen reader context
- aria-expanded={expanded} to announce state changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e (QUA-166, QUA-167)

- Projects page: add status filter bar (All / Backlog / Planned / In Progress / Completed)
  with count badges and localStorage persistence (key: projects:statusFilter)
- ApprovalCard: show Loader2 spinner + "Approving..."/"Rejecting..." label while
  mutation is pending, so users get clear feedback on action progress

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cuments (QUA-189)

- PropertiesPanel: Close button aria-label="Close properties panel"
- NewGoalDialog: Expand/Minimize + Close buttons aria-label
- NewProjectDialog: Expand/Minimize + Close buttons aria-label
- Sidebar: Search button aria-label="Search"
- NewAgentDialog: Close button aria-label="Close"
- IssuesList: Add-issue-to-group button aria-label with group name
- CompanySkills: Add skill button aria-label="Add skill"
- IssueDetail: More options PopoverTrigger button aria-label="More options"
- IssueDocumentsSection: Copy + Document actions buttons add aria-label alongside title

WCAG 2.1 SC 4.1.2 (Name, Role, Value) — Level AA

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 22, 2026

Too many files changed for review. (111 files found, 100 file limit)

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