diff --git a/packages/components/tooltip/README.mdx b/packages/components/tooltip/README.mdx index 993634be9a..e53d41f635 100644 --- a/packages/components/tooltip/README.mdx +++ b/packages/components/tooltip/README.mdx @@ -50,3 +50,5 @@ import { Tooltip } from '@contentful/f36-tooltip'; Hover me ``` + +- When using `ReactElement` as the content, it's recommended to use the `ScreenReaderOnly` component when displaying critical information. diff --git a/packages/components/tooltip/src/Tooltip.test.tsx b/packages/components/tooltip/src/Tooltip.test.tsx index 461770ada0..7b3b1b89ff 100644 --- a/packages/components/tooltip/src/Tooltip.test.tsx +++ b/packages/components/tooltip/src/Tooltip.test.tsx @@ -4,6 +4,7 @@ import userEvent from '@testing-library/user-event'; import { axe } from '@/scripts/test/axeHelper'; import { Tooltip } from './Tooltip'; +import { Paragraph } from '@contentful/f36-typography'; jest.mock('@contentful/f36-core', () => { const actual = jest.requireActual('@contentful/f36-core'); @@ -126,4 +127,26 @@ describe('Tooltip', () => { expect(results).toHaveNoViolations(); }); + + it('render a React Element as children', async () => { + const user = userEvent.setup(); + + const { container } = render( + Ich bin ein Paragraph} + > + Hover me + , + ); + await user.hover(screen.getByText('Hover me')); + + const results = await axe(container); + + expect(results).toHaveNoViolations(); + expect(screen.getByRole('tooltip').textContent).toBe( + 'Ich bin ein Paragraph', + ); + }); }); diff --git a/packages/components/tooltip/src/Tooltip.tsx b/packages/components/tooltip/src/Tooltip.tsx index 2cfd3704cb..090c890ec4 100644 --- a/packages/components/tooltip/src/Tooltip.tsx +++ b/packages/components/tooltip/src/Tooltip.tsx @@ -18,6 +18,28 @@ import { getStyles } from './Tooltip.styles'; export type TooltipPlacement = Placement; +type TextContentTooltip = { + /** + * Content of the tooltip + */ + content?: string; + /** + * Accesible label property, only required when using ReactElement as content + */ + label?: string; +}; + +type RichContentTooltip = { + /** + * Content of the tooltip + */ + content?: React.ReactElement; + /** + * Accesible label property, only required when using ReactElement as content + */ + label: string; +}; + export interface TooltipProps extends CommonProps { /** * Child nodes to be rendered in the component and that will show the tooltip when they are hovered @@ -27,10 +49,6 @@ export interface TooltipProps extends CommonProps { * HTML element used to wrap the target of the tooltip */ as?: React.ElementType; - /** - * Content of the tooltip - */ - content?: string; /** * A unique id of the tooltip */ @@ -101,6 +119,7 @@ export const Tooltip = ({ className, as: HtmlTag = 'span', content, + label, id, isVisible = false, hideDelay = 0, @@ -117,7 +136,7 @@ export const Tooltip = ({ usePortal = false, isDisabled = false, ...otherProps -}: TooltipProps) => { +}: TooltipProps & (TextContentTooltip | RichContentTooltip)) => { const styles = getStyles(); const [show, setShow] = useState(isVisible); const tooltipId = useId(id, 'tooltip'); @@ -210,7 +229,7 @@ export const Tooltip = ({ }} {...attributes.popper} > - {content} + {content} { ); }; + +export const WithReactElement = () => { + return ( + <> + + With React Elements as children + + + + +

I'm a React Element

+
+ } + > + Hover me + + + + ); +}; diff --git a/packages/forma-36-codemod/transforms/v4-tooltip.js b/packages/forma-36-codemod/transforms/v4-tooltip.js index 92a3a7feb3..1d12240595 100644 --- a/packages/forma-36-codemod/transforms/v4-tooltip.js +++ b/packages/forma-36-codemod/transforms/v4-tooltip.js @@ -1,19 +1,7 @@ const { modifyPropsCodemod } = require('./common/modify-props-codemod'); -const { hasProperty, getProperty } = require('../utils'); module.exports = modifyPropsCodemod({ componentName: 'Tooltip', - beforeRename: (attributes) => { - if ( - hasProperty(attributes, { propertyName: 'content' }) && - typeof getProperty(attributes, { propertyName: 'content' } !== 'string') - ) { - console.error( - 'Value of property "content" on Tooltip component should be a string.', - ); - } - return attributes; - }, renameMap: { place: 'placement', containerElement: 'as',