diff --git a/packages/desktop-client/src/components/NotesButton.tsx b/packages/desktop-client/src/components/NotesButton.tsx index 366f7c2ea99..bbb1e14b67e 100644 --- a/packages/desktop-client/src/components/NotesButton.tsx +++ b/packages/desktop-client/src/components/NotesButton.tsx @@ -15,7 +15,7 @@ import { remarkBreaks, sequentialNewlinesPlugin } from '../util/markdown'; import Button from './common/Button'; import Text from './common/Text'; import View from './common/View'; -import { Tooltip, useTooltip } from './tooltips'; +import { Tooltip, type TooltipPosition, useTooltip } from './tooltips'; const remarkPlugins = [sequentialNewlinesPlugin, remarkGfm, remarkBreaks]; @@ -86,7 +86,7 @@ const markdownStyles = css({ type NotesTooltipProps = { editable?: boolean; defaultNotes?: string; - position?: string; + position?: TooltipPosition; onClose?: (notes: string) => void; }; function NotesTooltip({ @@ -138,7 +138,7 @@ type NotesButtonProps = { width?: number; height?: number; defaultColor?: string; - tooltipPosition?: string; + tooltipPosition?: TooltipPosition; style?: CSSProperties; }; export default function NotesButton({ diff --git a/packages/desktop-client/src/components/tooltips.js b/packages/desktop-client/src/components/tooltips.tsx similarity index 83% rename from packages/desktop-client/src/components/tooltips.js rename to packages/desktop-client/src/components/tooltips.tsx index 99039766883..b86a9128a25 100644 --- a/packages/desktop-client/src/components/tooltips.js +++ b/packages/desktop-client/src/components/tooltips.tsx @@ -1,18 +1,28 @@ -import React, { Component, createContext, createRef, useState } from 'react'; +import { + Component, + createContext, + createRef, + useState, + type RefObject, + type ReactNode, + type MouseEventHandler, + type MouseEvent, + type ContextType, +} from 'react'; import ReactDOM from 'react-dom'; import { css } from 'glamor'; -import { styles, theme } from '../style'; +import { type CSSProperties, styles, theme } from '../style'; -export const IntersectionBoundary = createContext(); +export const IntersectionBoundary = createContext>(null); export function useTooltip() { - const [isOpen, setIsOpen] = useState(false); + const [isOpen, setIsOpen] = useState(false); return { - getOpenEvents: (events = {}) => ({ - onClick: e => { + getOpenEvents: (events: { onClick?: MouseEventHandler } = {}) => ({ + onClick: (e: MouseEvent) => { e.stopPropagation(); events.onClick?.(e); setIsOpen(true); @@ -24,14 +34,56 @@ export function useTooltip() { }; } -export class Tooltip extends Component { +export type TooltipPosition = + | 'top' + | 'top-left' + | 'top-right' + | 'bottom' + | 'bottom-left' + | 'bottom-right' + | 'bottom-stretch' + | 'top-stretch' + | 'bottom-center' + | 'top-center' + | 'left-center' + | 'right'; + +type TooltipProps = { + position?: TooltipPosition; + onClose?: () => void; + forceLayout?: boolean; + forceTop?: number; + ignoreBoundary?: boolean; + targetRect?: DOMRect; + offset?: number; + style?: CSSProperties; + width?: number; + children: ReactNode; + targetHeight?: number; +}; +type MutableDomRect = { + top: number; + left: number; + width: number; + height: number; +}; + +export class Tooltip extends Component { static contextType = IntersectionBoundary; - state = { position: null }; + position: TooltipPosition; + contentRef: RefObject; + cleanup: () => void; + target: HTMLDivElement; + context: ContextType = this.context; // assign type to context without using declare. constructor(props) { super(props); this.position = props.position || 'bottom-right'; - this.contentRef = createRef(); + this.contentRef = createRef(); + } + + isHTMLElement(element: unknown): element is HTMLElement { + return element instanceof HTMLElement; } setup() { @@ -107,7 +159,7 @@ export class Tooltip extends Component { } } - getContainer() { + getContainer(): HTMLElement { const { ignoreBoundary = false } = this.props; if (!ignoreBoundary && this.context) { @@ -123,6 +175,7 @@ export class Tooltip extends Component { if ( container.parentNode && + this.isHTMLElement(container.parentNode) && container.parentNode.style.overflow === 'auto' ) { return container.parentNode; @@ -138,9 +191,18 @@ export class Tooltip extends Component { } const box = contentEl.getBoundingClientRect(); + const anchorEl = this.target.parentNode; - let anchorRect = targetRect || anchorEl.getBoundingClientRect(); + let anchorRect: MutableDomRect | undefined = + targetRect || + (this.isHTMLElement(anchorEl) + ? anchorEl?.getBoundingClientRect() + : undefined); + + if (!anchorRect) { + return; + } // Copy it so we can mutate it anchorRect = { @@ -238,6 +300,7 @@ export class Tooltip extends Component { bottom: 'inherit', left: 'inherit', right: 'inherit', + width: undefined as string | undefined, }; if ( diff --git a/upcoming-release-notes/2073.md b/upcoming-release-notes/2073.md new file mode 100644 index 00000000000..ec82b1108c5 --- /dev/null +++ b/upcoming-release-notes/2073.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [IzStriker] +--- + +Migrate tooltips.js to typescript