Skip to content

Improve accessibility with semantic buttons, ARIA labels, and color contrast updates#593

Merged
jrhoads merged 5 commits intomasterfrom
accessibility
Apr 16, 2026
Merged

Improve accessibility with semantic buttons, ARIA labels, and color contrast updates#593
jrhoads merged 5 commits intomasterfrom
accessibility

Conversation

@jrhoads
Copy link
Copy Markdown
Contributor

@jrhoads jrhoads commented Mar 27, 2026

Purpose

The purpose of this pull request is to improve the accessibility (a11y) and visual consistency of the application. This includes updating color contrasts to meet standards, adding descriptive ARIA labels to interactive elements, and converting non-semantic interactive tags into semantic buttons.

Approach

Key Modifications

  • Accessibility Enhancements:
    • Added aria-label to social links in the footer, search buttons, help icons, and filter items.
    • Converted the <a> tag filter toggle in FilterItem to a semantic <button>.
    • Converted the clear-search <span> in the Header to a semantic <Button> component.
  • Styling and Branding:
    • Updated the "secondary" brand color from #A3ACB2 to a darker #243b54 for better contrast and visibility.
    • Introduced CSS variables (e.g., --datacite-color-primary) for consistent theming across components like FacetListItem and WorkMetadata.
    • Adjusted the positioning and styling of the search clear button for better alignment.
  • UI Consistency:
    • Standardized link colors in the navigation and metadata sections.
    • Added a hover state for generic buttons.

Important Technical Details

  • Semantic HTML: Elements that trigger actions without navigating (like toggling filters or clearing search) were moved from <a> or <span> to <button> to ensure correct screen reader behavior and keyboard focus.
  • CSS Variables: The introduction of :root variables allows for easier theme management in the future.
  • Z-Index and Positioning: The search clear button layout was adjusted in styles.css to accommodate its transition to a button element.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Reviewer, please remember our guidelines:

  • Be humble in the language and feedback you give, ask don't tell.
  • Consider using positive language as opposed to neutral when offering feedback. This is to avoid the negative bias that can occur with neutral language appearing negative.
  • Offer suggestions on how to improve code e.g. simplification or expanding clarity.
  • Ensure you give reasons for the changes you are proposing.

Summary by CodeRabbit

  • New Features

    • Introduced themeable color system with CSS custom properties for consistent brand color management across the app.
  • Accessibility Improvements

    • Enhanced semantic HTML structure for interactive controls.
    • Added accessibility labels to search and filter buttons.
    • Improved keyboard navigation with visible focus indicators.
  • Style

    • Updated button colors and hover states for improved visual consistency.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

Warning

Rate limit exceeded

@jrhoads has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 34 minutes and 58 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 34 minutes and 58 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 88add194-6c51-4745-a7e9-4ff7e0d3328d

📥 Commits

Reviewing files that changed from the base of the PR and between d14df3d and 271bd48.

📒 Files selected for processing (1)
  • src/components/Header/Search.tsx

Walkthrough

This PR introduces a CSS custom property for primary colors, converts non-semantic HTML elements to buttons with ARIA labels for accessibility, and updates styling across multiple components. The color system migrates from hard-coded hex values to a centralized --datacite-color-primary variable while maintaining backward-compatible fallbacks.

Changes

Cohort / File(s) Summary
Color System Refactoring
src/components/DataCiteButton/DataCiteButton.tsx, src/components/FacetList/FacetListItem.module.scss, src/components/WorkMetadata/WorkMetadata.module.scss, src/styles.css
Migrated hard-coded color values (#A3ACB2, #88939a) to CSS custom property --datacite-color-primary with appropriate fallbacks, enabling centralized theme color management across components.
Accessibility Enhancements
src/components/FilterItem/FilterItem.tsx, src/components/Header/Search.tsx, src/components/SearchBox/SearchBox.tsx
Converted non-semantic elements (anchors, spans) to <button> elements with explicit ARIA labels (aria-label, aria-pressed), improving screen reader support and keyboard navigation.
Search Control Refinements
src/components/Header/Search.tsx, src/styles.css
Repositioned submit button within input group, converted clear control to interactive button with updated styling (right: 80px, text color #243b54), and refactored query parameter logic to use function argument instead of component state.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes in the pull request: semantic buttons, ARIA labels, and color contrast updates are the primary focus across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch accessibility

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cypress
Copy link
Copy Markdown

cypress bot commented Mar 27, 2026

akita    Run #1994

Run Properties:  status check passed Passed #1994  •  git commit 286dbf848a ℹ️: Merge 271bd4860af558f7f155c06a211d5a66d01f97a2 into 021008fa7ba33510382ef285441e...
Project akita
Branch Review accessibility
Run status status check passed Passed #1994
Run duration 01m 47s
Commit git commit 286dbf848a ℹ️: Merge 271bd4860af558f7f155c06a211d5a66d01f97a2 into 021008fa7ba33510382ef285441e...
Committer Joseph Rhoads
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 3
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 47
View all changes introduced in this branch ↗︎

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/SearchBox/SearchBox.tsx (1)

51-68: ⚠️ Potential issue | 🟠 Major

Clear action is still non-semantic and not keyboard-accessible.

The submit button labeling is good, but the clear control remains a clickable <span>. Use a real button so it is focusable and keyboard operable.

🔧 Suggested fix
       {searchInput !== '' && (
-        <span
+        <Button
           id="search-clear-facets"
+          type="button"
           title="Clear"
-          aria-label="Clear"
+          aria-label="Clear search input"
+          className="p-0 border-0 bg-transparent"
           onClick={onSearchClear}
         >
           <FontAwesomeIcon icon={faTimes} />
-        </span>
+        </Button>
       )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/SearchBox/SearchBox.tsx` around lines 51 - 68, The clear
control is implemented as a non-semantic, non-keyboard-accessible <span> (id
"search-clear-facets") inside SearchBox; replace it with a proper button element
so it is focusable and keyboard operable, keep the existing title/aria-label
("Clear"), move the onClick handler to the button (use the existing
onSearchClear callback), and preserve the FontAwesomeIcon and conditional
rendering (searchInput !== '') and any className/style to maintain appearance
and behavior.
🧹 Nitpick comments (2)
src/styles.css (1)

691-694: Include :focus-visible with hover styles for keyboard parity.

This keeps visual feedback consistent for keyboard users, not just mouse hover.

♿ Suggested refinement
-.button:hover {
+.button:hover,
+.button:focus-visible {
     background-color: `#0071b2`;
     color: `#fff`;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/styles.css` around lines 691 - 694, The :hover rule for .button only
targets mouse users; add a matching :focus-visible selector to provide
equivalent keyboard focus styling. Update the CSS where .button:hover is defined
so that .button:focus-visible receives the same background-color and color, and
ensure any outline or box-shadow for focus is preserved or set explicitly to
maintain accessibility; reference the .button:hover selector and the
.button:focus-visible state when applying the change.
src/components/DataCiteButton/DataCiteButton.tsx (1)

17-20: Consider using the global CSS variable as the single source of truth.

#243b54 is now duplicated in TS and global CSS. Referencing the existing CSS variable here reduces drift risk.

♻️ Suggested refactor
 const COLORS = {
   primary: '#037AAD',
-  secondary: '#243b54',
+  secondary: 'var(--datacite-color-primary, `#243b54`)',
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/DataCiteButton/DataCiteButton.tsx` around lines 17 - 20, The
COLORS constant in DataCiteButton.tsx duplicates the palette from global CSS
(COLORS { primary, secondary } contains '#243b54'); replace the hardcoded
secondary color with the global CSS custom property instead (use the CSS var in
the component styles or set COLORS.secondary =
'var(--your-global-secondary-var)') so the component reads the single source of
truth; update any usage of COLORS.secondary in DataCiteButton to use that CSS
variable name (or remove COLORS entirely and reference the CSS var directly in
the component's style/class).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/FilterItem/FilterItem.tsx`:
- Around line 43-50: This button is a toggle so add an aria-pressed boolean to
announce its state; update the button in FilterItem to include aria-pressed={/*
boolean active state */} by using the existing state checker (e.g., an
isActive(id) or by deriving a truthy value from activeIcon(id) or the
component's active prop) and keep the onClick calling toggleFilter(id); ensure
the attribute uses the same id/name context (name, id, activeIcon, toggleFilter)
so screen readers receive true/false for the pressed state.

In `@src/components/Header/Search.tsx`:
- Around line 60-63: The clear button currently calls setSearchInput('') and
search('') but the search function reads the module state searchInput (not the
query argument), causing an empty ?query= to be serialized; update the search
function (search) to prefer the passed-in query parameter (use the function
parameter if defined, falling back to searchInput) and when the resolved query
is an empty string or null remove the query param from the URL instead of
serializing ?query=; ensure the onClick handler (which calls setSearchInput('')
and search('')) continues to work with this change.

---

Outside diff comments:
In `@src/components/SearchBox/SearchBox.tsx`:
- Around line 51-68: The clear control is implemented as a non-semantic,
non-keyboard-accessible <span> (id "search-clear-facets") inside SearchBox;
replace it with a proper button element so it is focusable and keyboard
operable, keep the existing title/aria-label ("Clear"), move the onClick handler
to the button (use the existing onSearchClear callback), and preserve the
FontAwesomeIcon and conditional rendering (searchInput !== '') and any
className/style to maintain appearance and behavior.

---

Nitpick comments:
In `@src/components/DataCiteButton/DataCiteButton.tsx`:
- Around line 17-20: The COLORS constant in DataCiteButton.tsx duplicates the
palette from global CSS (COLORS { primary, secondary } contains '#243b54');
replace the hardcoded secondary color with the global CSS custom property
instead (use the CSS var in the component styles or set COLORS.secondary =
'var(--your-global-secondary-var)') so the component reads the single source of
truth; update any usage of COLORS.secondary in DataCiteButton to use that CSS
variable name (or remove COLORS entirely and reference the CSS var directly in
the component's style/class).

In `@src/styles.css`:
- Around line 691-694: The :hover rule for .button only targets mouse users; add
a matching :focus-visible selector to provide equivalent keyboard focus styling.
Update the CSS where .button:hover is defined so that .button:focus-visible
receives the same background-color and color, and ensure any outline or
box-shadow for focus is preserved or set explicitly to maintain accessibility;
reference the .button:hover selector and the .button:focus-visible state when
applying the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: abd0ee27-dfc2-47ef-b811-e61b8a0e7b3e

📥 Commits

Reviewing files that changed from the base of the PR and between 561cc8a and 9bf1b34.

📒 Files selected for processing (9)
  • src/components/DataCiteButton/DataCiteButton.tsx
  • src/components/FacetList/FacetListItem.module.scss
  • src/components/FilterItem/FilterItem.tsx
  • src/components/Footer/Footer.tsx
  • src/components/Header/Search.tsx
  • src/components/HelpIcon/HelpIcon.tsx
  • src/components/SearchBox/SearchBox.tsx
  • src/components/WorkMetadata/WorkMetadata.module.scss
  • src/styles.css

Comment thread src/components/FilterItem/FilterItem.tsx
Comment thread src/components/Header/Search.tsx
cursor bot pushed a commit that referenced this pull request Apr 3, 2026
- Use semantic button for facet search clear control (SearchBox)
- Fix Header search() to use passed query and drop empty query param
- Add aria-pressed to filter toggle button
- Align DataCiteButton secondary color with CSS variable
- Add :focus-visible parity for .button and facet clear focus ring

Co-authored-by: Joseph Rhoads <jrhoads@users.noreply.github.com>
jrhoads and others added 4 commits April 16, 2026 13:52
- Use semantic button for facet search clear control (SearchBox)
- Fix Header search() to use passed query and drop empty query param
- Add aria-pressed to filter toggle button
- Align DataCiteButton secondary color with CSS variable
- Add :focus-visible parity for .button and facet clear focus ring

Co-authored-by: Joseph Rhoads <jrhoads@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/Header/Search.tsx`:
- Line 38: The current router.push call in Search.tsx builds
`${base}?${params.toString()}` which yields a trailing '?' when
params.toString() is empty; update the logic around router.push (the code using
base and params.toString()) to check if params.toString() is non-empty and push
`${base}?${params.toString()}` only in that case, otherwise push just base
(e.g., compute the URL conditionally before calling router.push).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bab434dc-8d43-43a7-a5f3-6b6beda737a8

📥 Commits

Reviewing files that changed from the base of the PR and between 3dd47bd and d14df3d.

📒 Files selected for processing (7)
  • src/components/DataCiteButton/DataCiteButton.tsx
  • src/components/FacetList/FacetListItem.module.scss
  • src/components/FilterItem/FilterItem.tsx
  • src/components/Header/Search.tsx
  • src/components/SearchBox/SearchBox.tsx
  • src/components/WorkMetadata/WorkMetadata.module.scss
  • src/styles.css
✅ Files skipped from review due to trivial changes (4)
  • src/components/WorkMetadata/WorkMetadata.module.scss
  • src/components/FacetList/FacetListItem.module.scss
  • src/components/FilterItem/FilterItem.tsx
  • src/components/DataCiteButton/DataCiteButton.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/styles.css
  • src/components/SearchBox/SearchBox.tsx

Comment thread src/components/Header/Search.tsx Outdated
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@jrhoads jrhoads requested review from a team, ashwinisukale and bklaing2 April 16, 2026 12:29
@jrhoads jrhoads merged commit 5112662 into master Apr 16, 2026
13 checks passed
@jrhoads jrhoads deleted the accessibility branch April 16, 2026 13:51
@cypress
Copy link
Copy Markdown

cypress bot commented Apr 16, 2026

akita    Run #1996

Run Properties:  status check passed Passed #1996  •  git commit 51126628eb: Merge pull request #593 from datacite/accessibility
Project akita
Branch Review 1.47.0
Run status status check passed Passed #1996
Run duration 01m 45s
Commit git commit 51126628eb: Merge pull request #593 from datacite/accessibility
Committer Joseph Rhoads
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 3
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 47
View all changes introduced in this branch ↗︎

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.

3 participants