overleaf/services/web/frontend/js/features/symbol-palette/components/symbol-palette-item.js
Alf Eaton 0360d01aeb Add Symbol Palette component, data and stories (#4027)
GitOrigin-RevId: b00128bc087e2ebe9911fa19b7e62fd4bb492226
2021-05-14 02:09:50 +00:00

68 lines
1.8 KiB
JavaScript

import React, { useEffect, useRef } from 'react'
import { OverlayTrigger, Tooltip } from 'react-bootstrap'
import PropTypes from 'prop-types'
export default function SymbolPaletteItem({
focused,
handleSelect,
handleKeyDown,
symbol,
}) {
const buttonRef = useRef(null)
// call focus() on this item when appropriate
useEffect(() => {
if (
focused &&
buttonRef.current &&
document.activeElement?.closest('.symbol-palette-items')
) {
buttonRef.current.focus()
}
}, [focused])
return (
<OverlayTrigger
placement="top"
trigger={['hover', 'focus']}
overlay={
<Tooltip id={`tooltip-symbol-${symbol.codepoint}`}>
<div className="symbol-palette-item-description">
{symbol.description}
</div>
<div className="symbol-palette-item-command" aria-hidden="true">
{symbol.command}
</div>
{symbol.notes && (
<div className="symbol-palette-item-notes">{symbol.notes}</div>
)}
</Tooltip>
}
>
<button
key={symbol.codepoint}
className="symbol-palette-item"
onClick={() => handleSelect(symbol)}
onKeyDown={handleKeyDown}
tabIndex={focused ? 0 : -1}
ref={buttonRef}
role="option"
aria-selected={focused}
>
<span aria-hidden="true">{symbol.character}</span>
</button>
</OverlayTrigger>
)
}
SymbolPaletteItem.propTypes = {
symbol: PropTypes.shape({
codepoint: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
command: PropTypes.string.isRequired,
character: PropTypes.string.isRequired,
notes: PropTypes.string,
}),
handleKeyDown: PropTypes.func.isRequired,
handleSelect: PropTypes.func.isRequired,
focused: PropTypes.bool,
}