| @@ -1,6 +1,8 @@ | ||
| 1 | -import React from 'react' | |
| 1 | +import React, { useId } from 'react' | |
| 2 | 2 | import classnames from 'classnames' |
| 3 | +import { __ } from '@wordpress/i18n' | |
| 4 | +import { trimTrailingChar } from '../../utils/text' | |
| 3 | 5 | import type { ReactNode } from 'react' |
| 4 | 6 | |
| 5 | 7 | export interface TooltipProps { |
| 6 | 8 | block?: boolean |
| @@ -9,17 +11,45 @@ | ||
| 9 | 11 | end?: boolean |
| 10 | 12 | icon?: ReactNode |
| 11 | 13 | children: ReactNode |
| 12 | 14 | className?: classnames.Argument |
| 15 | + label?: string | |
| 13 | 16 | } |
| 14 | 17 | |
| 15 | -export const Tooltip: React.FC<TooltipProps> = ({ block, inline, start, end, icon, className, children }) => | |
| 16 | - <div className={classnames( | |
| 17 | - 'tooltip', | |
| 18 | - { 'tooltip-block': block, 'tooltip-inline': inline, 'tooltip-start': start, 'tooltip-end': end }, | |
| 19 | - className | |
| 20 | - )}> | |
| 21 | - {icon ?? <span className="dashicons dashicons-editor-help"></span>} | |
| 22 | - <div className="tooltip-content"> | |
| 23 | - {children} | |
| 18 | +export const Tooltip: React.FC<TooltipProps> = ({ | |
| 19 | + block, inline, start, end, | |
| 20 | + icon, | |
| 21 | + className, | |
| 22 | + children, | |
| 23 | + label | |
| 24 | +}) => { | |
| 25 | + const tooltipId = useId() | |
| 26 | + return ( | |
| 27 | + <div className={classnames( | |
| 28 | + 'tooltip help-tooltip', | |
| 29 | + { 'tooltip-block': block, 'tooltip-inline': inline, 'tooltip-start': start, 'tooltip-end': end }, | |
| 30 | + className | |
| 31 | + )}> | |
| 32 | + <button | |
| 33 | + type="button" | |
| 34 | + className="tooltip-trigger" | |
| 35 | + aria-label={label ?? __('More information', 'code-snippets')} | |
| 36 | + aria-describedby={tooltipId} | |
| 37 | + > | |
| 38 | + {icon ?? <span className="dashicons dashicons-editor-help" aria-hidden="true"></span>} | |
| 39 | + </button> | |
| 40 | + <div role="tooltip" className="tooltip-content" id={tooltipId}> | |
| 41 | + {children} | |
| 42 | + </div> | |
| 24 | 43 | </div> |
| 25 | - </div> | |
| 44 | + ) | |
| 45 | +} | |
| 46 | + | |
| 47 | +export const ErrorTooltip: React.FC<{ message: string }> = ({ message }) => | |
| 48 | + <Tooltip | |
| 49 | + block | |
| 50 | + end | |
| 51 | + label={__('Error', 'code-snippets')} | |
| 52 | + icon={<span className="dashicons dashicons-warning" aria-hidden="true"></span>} | |
| 53 | + > | |
| 54 | + {`${trimTrailingChar(message, '.!?')}. ${__('Please try again.', 'code-snippets')}`} | |
| 55 | + </Tooltip> | |