diff --git a/.changeset/tough-ears-drive.md b/.changeset/tough-ears-drive.md new file mode 100644 index 00000000000..7cb54e4143e --- /dev/null +++ b/.changeset/tough-ears-drive.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +ActionList.Item: fix inline descriptions being referenced via `aria-labelledby` instead of `aria-describedby` diff --git a/packages/react/src/ActionList/ActionList.test.tsx b/packages/react/src/ActionList/ActionList.test.tsx index 6def3de94f5..49e44022c7f 100644 --- a/packages/react/src/ActionList/ActionList.test.tsx +++ b/packages/react/src/ActionList/ActionList.test.tsx @@ -203,6 +203,42 @@ describe('ActionList', () => { expect(descriptions[2]).not.toHaveAttribute('title') }) + it('references inline description via aria-describedby', () => { + const {container} = HTMLRender( + + + Item label + Inline description + + , + ) + + const item = container.querySelector('[role="option"]')! + const descriptionEl = container.querySelector('[data-component="ActionList.Description"]')! + const descriptionId = descriptionEl.getAttribute('id')! + + expect(item.getAttribute('aria-describedby')).toContain(descriptionId) + expect(item.getAttribute('aria-labelledby')).not.toContain(descriptionId) + }) + + it('references block description via aria-describedby', () => { + const {container} = HTMLRender( + + + Item label + Block description + + , + ) + + const item = container.querySelector('[role="option"]')! + const descriptionEl = container.querySelector('[data-component="ActionList.Description"]')! + const descriptionId = descriptionEl.getAttribute('id')! + + expect(item.getAttribute('aria-describedby')).toContain(descriptionId) + expect(item.getAttribute('aria-labelledby')).not.toContain(descriptionId) + }) + it('should support size prop on LinkItem', () => { const {container} = HTMLRender( diff --git a/packages/react/src/ActionList/Item.tsx b/packages/react/src/ActionList/Item.tsx index e6625ca0cdf..765fd27d7c5 100644 --- a/packages/react/src/ActionList/Item.tsx +++ b/packages/react/src/ActionList/Item.tsx @@ -232,16 +232,16 @@ const UnwrappedItem = ( const ariaLabelledBy = React.useMemo(() => { const parts = [labelId] if (hasTrailingVisualSlot) parts.push(trailingVisualId) - if (hasDescriptionSlot && descriptionVariant === 'inline') parts.push(inlineDescriptionId) return parts.join(' ') - }, [labelId, hasTrailingVisualSlot, trailingVisualId, hasDescriptionSlot, descriptionVariant, inlineDescriptionId]) + }, [labelId, hasTrailingVisualSlot, trailingVisualId]) const ariaDescribedBy = React.useMemo(() => { const parts: string[] = [] if (hasDescriptionSlot && descriptionVariant === 'block') parts.push(blockDescriptionId) + if (hasDescriptionSlot && descriptionVariant === 'inline') parts.push(inlineDescriptionId) if (inactiveWarningId) parts.push(inactiveWarningId) return parts.length > 0 ? parts.join(' ') : undefined - }, [hasDescriptionSlot, descriptionVariant, blockDescriptionId, inactiveWarningId]) + }, [hasDescriptionSlot, descriptionVariant, blockDescriptionId, inlineDescriptionId, inactiveWarningId]) const menuItemProps = React.useMemo( () => ({