Skip to content

Conversation

@dreamwasp
Copy link
Contributor

@dreamwasp dreamwasp commented Nov 20, 2025

Overview

Adds props to InfoTip for customizing the button's aria-label and aria-labelledby attribute. Also adds automatic focus management - when you open an InfoTip, focus moves to the content container. This removed aria-live since it's no longer needed.

PR Checklist

  • Related to designs: N/A
  • Related to JIRA ticket: GMT-216
  • I have run this code to verify it works
  • This PR includes unit tests for the code change
  • This PR includes testing instructions for the code change
  • The alpha package of this PR is passing end-to-end tests in all relevant Codecademy repositories

Testing Instructions

Auto-focus + keyboard nav (verify tab order makes sense!):

Floating without links:

  1. Go to Default story with placement: "floating"
  2. Tab to to InfoTip button + press enter - focus should automatically move to the popover content
  3. Press Tab - should wrap back to button (no getting stuck in empty popover)
  4. Also works with VO on click.

Floating with links:

  1. Go to WithLinksOrButtons story
  2. Open with keyboard - focus auto-moves to popover content
  3. Tab through the links - should move naturally
  4. After last link, Tab wraps back to InfoTip button
  5. Shift+Tab from button - should exit backward to previous page element (no trap)

Inline without links:

  1. Go to Default story (default inline placement)
  2. Open with keyboard - focus auto-moves to tip content
  3. Tab - moves to next element in document (normal flow)

Inline with links:

  1. Make a quick test with inline placement + links
  2. Open it - focus auto-moves to content
  3. Tab through - should follow normal document flow with the links

GridForm + ConnectedForm

  1. Head to the infotip section of GridForm or ConnectedForm + check it out

Screen reader check:

  1. Use VO/NVDA to verify custom aria-role, label, and labelledby get announced
  2. Make sure the auto-focus to content is smooth and announced properly

Finish and do a celebratory dance 🎉

PR Links and Envs

Repository PR Link
Monolith Monolith PR
Mono Mono PR

@nx-cloud
Copy link

nx-cloud bot commented Nov 20, 2025

View your CI Pipeline Execution ↗ for commit a880b53


☁️ Nx Cloud last updated this comment at 2026-01-28 20:14:14 UTC

@dreamwasp dreamwasp changed the title fix(InfoTip): Remove ariaa-live and implement focus mgmt fix(InfoTip): Remove aria-live and implement focus mgmt Nov 20, 2025
@dreamwasp dreamwasp changed the title fix(InfoTip): Remove aria-live and implement focus mgmt fix(InfoTip)!: Remove aria-live and implement focus mgmt Jan 15, 2026
Copy link
Contributor

@LinKCoding LinKCoding left a comment

Choose a reason for hiding this comment

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

Overall, looks great!
It's much cleaner than the delayed announcement and the duplicate screenreader text.
Works great in VO and the focus control is 🔥

Left some nits, but not blocking and up to you if you'd want to implement.


## Custom Accessible Labeling

Provide either `ariaLabel` or `ariaLabelledby` to ensure screen reader users understand the purpose of the InfoTip button.
Copy link
Contributor

Choose a reason for hiding this comment

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

Note: the phrasing here is stronger than the current JSDoc:

Its recommended to provide either ariaLabel or ariaLabelledby.

where "recommended" to me feels a bit more optional.

export type InfoTipProps = TipBaseProps & {
alignment?: TipBaseAlignment;
/**
* Accessible label for the InfoTip button. Its recommended to provide either `ariaLabel` or `ariaLabelledby`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: "Its" => "It's"
Also nit: Feels appropriate to remove "recommended", but would defer to an a11y expert if there's any opinion there.

*/
ariaLabel?: string;
/**
* ID of an element that labels the InfoTip button. Its recommended to provide either `ariaLabel` or `ariaLabelledby`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: "Its" => "It's"

Copy link
Contributor

@LinKCoding LinKCoding left a comment

Choose a reason for hiding this comment

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

Looks great!
Left a quick note for your consideration~

Comment on lines 7 to 10
export type InfoTipPropsWithoutAria = Omit<
InfoTipProps,
'ariaLabel' | 'ariaLabelledby'
> & {
Copy link
Contributor

Choose a reason for hiding this comment

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

This Omit makes me think that InfoTipPropsWithAriaLabel and InfoTipPropsWithAriaLabelledby can share an InfoTipsBaseProps (that get exported and used here)

and then the aria-* specific props be part of a discriminated union.

Food for thought :)

@codecov
Copy link

codecov bot commented Jan 26, 2026

Codecov Report

❌ Patch coverage is 98.75000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.04%. Comparing base (dba147a) to head (a880b53).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/gamut/src/Tip/InfoTip/index.tsx 94.73% 1 Missing ⚠️
packages/gamut/src/Tip/InfoTip/type-utils.ts 94.44% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3215      +/-   ##
==========================================
- Coverage   89.65%   89.04%   -0.62%     
==========================================
  Files         353      236     -117     
  Lines        5065     4298     -767     
  Branches     1606     1446     -160     
==========================================
- Hits         4541     3827     -714     
+ Misses        516      463      -53     
  Partials        8        8              
Flag Coverage Δ
main ?
pull-request 89.04% <98.75%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@LinKCoding LinKCoding left a comment

Choose a reason for hiding this comment

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

Looked over Radio, CheckBox with InfoTip
and GridForm (which had a Radio with InfoTip)
and the VO announces the label now too! 🔥

@codecademydev
Copy link
Collaborator

📬 Published Alpha Packages:

@codecademy/[email protected]
@codecademy/[email protected]
@codecademy/[email protected]

@github-actions
Copy link
Contributor

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.

6 participants