diff --git a/apps/vr-tests-react-components/src/stories/Tooltip/Tooltip.stories.tsx b/apps/vr-tests-react-components/src/stories/Tooltip/Tooltip.stories.tsx index ce840bb11acef..25733bfbd31fc 100644 --- a/apps/vr-tests-react-components/src/stories/Tooltip/Tooltip.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Tooltip/Tooltip.stories.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import type { Meta } from '@storybook/react-webpack5'; import { Tooltip } from '@fluentui/react-tooltip'; +import { TextBoldRegular } from '@fluentui/react-icons'; import { useStyles } from './utils'; import { DARK_MODE, getStoryVariant, HIGH_CONTRAST, TestWrapperDecorator } from '../../utilities'; @@ -29,6 +30,21 @@ export const BasicDarkMode = getStoryVariant(Basic, DARK_MODE); export const BasicHighContrast = getStoryVariant(Basic, HIGH_CONTRAST); +export const SecondaryContent = () => ( +
+ + + +
+); +SecondaryContent.storyName = 'secondary content'; + +export const SecondaryContentDarkMode = getStoryVariant(SecondaryContent, DARK_MODE); + +export const SecondaryContentHighContrast = getStoryVariant(SecondaryContent, HIGH_CONTRAST); + export const Inverted = () => (
diff --git a/change/@fluentui-react-tooltip-d906f048-c7cf-41ab-bb86-27edec248fed.json b/change/@fluentui-react-tooltip-d906f048-c7cf-41ab-bb86-27edec248fed.json new file mode 100644 index 0000000000000..8def9b2b399ea --- /dev/null +++ b/change/@fluentui-react-tooltip-d906f048-c7cf-41ab-bb86-27edec248fed.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "feat: add secondary content to Tooltip", + "packageName": "@fluentui/react-tooltip", + "email": "petrduda@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-headless-components-preview/library/src/components/Tooltip/Tooltip.test.tsx b/packages/react-components/react-headless-components-preview/library/src/components/Tooltip/Tooltip.test.tsx index 5137f1b26b42c..6e42a086bd6a9 100644 --- a/packages/react-components/react-headless-components-preview/library/src/components/Tooltip/Tooltip.test.tsx +++ b/packages/react-components/react-headless-components-preview/library/src/components/Tooltip/Tooltip.test.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; +import { renderToStaticMarkup } from 'react-dom/server'; import { render, screen } from '@testing-library/react'; -import { resetIdsForTests } from '@fluentui/react-utilities'; +import { resetIdsForTests, SSRProvider } from '@fluentui/react-utilities'; import { isConformant } from '../../testing/isConformant'; import type { IsConformantOptions } from '@fluentui/react-conformance'; import { Tooltip } from './Tooltip'; @@ -100,6 +101,80 @@ describe('Tooltip', () => { expect(target).toHaveAttribute('aria-describedby', tooltip.id); }); + it('renders secondary content', () => { + render( + + + , + ); + + const tooltip = screen.getByRole('tooltip'); + const target = screen.getByRole('button'); + expect(tooltip).toHaveTextContent('BoldCtrl+B'); + expect(tooltip.querySelector('span')).toHaveTextContent('Ctrl+B'); + expect(target).toHaveAttribute('aria-label', 'Bold Ctrl+B'); + expect(target).not.toHaveAttribute('aria-labelledby'); + }); + + it('includes secondary content in a rich accessible label', () => { + render( + Bold} secondaryContent="Ctrl+B" relationship="label"> + + , + ); + + const tooltip = screen.getByRole('tooltip'); + const target = screen.getByRole('button'); + const secondaryContent = tooltip.querySelector(':scope > span'); + + expect(target).toHaveAttribute('aria-labelledby', tooltip.id); + expect(secondaryContent).not.toHaveAttribute('aria-hidden'); + }); + + it('keeps a string label with secondary content when the trigger popup is expanded', () => { + render( + + + , + ); + + expect(screen.queryByRole('tooltip')).toBeNull(); + expect(screen.getByRole('button')).toHaveAttribute('aria-label', 'Bold Ctrl+B'); + }); + + it('keeps a generic secondary content label when the trigger popup is expanded', () => { + render( + Ctrl+B} relationship="label" visible> + + , + ); + + const tooltip = document.querySelector('[role="tooltip"]'); + const target = screen.getByRole('button'); + + expect(tooltip).not.toBeNull(); + expect(target).not.toHaveAttribute('aria-label'); + expect(target).toHaveAttribute('aria-labelledby', tooltip?.id); + expect(tooltip).toHaveTextContent('BoldCtrl+B'); + }); + + it('keeps the primary string label during SSR with generic secondary content', () => { + const html = renderToStaticMarkup( + + Ctrl+B} relationship="label"> +