Fix "in contacts" tooltip exceeding desired boundary
See [#4907][0]. [0]: https://github.com/signalapp/Signal-Desktop/pull/4907
This commit is contained in:
parent
54974b377a
commit
2cd02855fc
5 changed files with 65 additions and 4 deletions
|
@ -9,15 +9,26 @@ import { LocalizerType } from '../types/Util';
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
tooltipContainerRef?: React.RefObject<HTMLElement>;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InContactsIcon = (props: PropsType): JSX.Element => {
|
export const InContactsIcon = (props: PropsType): JSX.Element => {
|
||||||
const { className, i18n } = props;
|
const { className, i18n, tooltipContainerRef } = props;
|
||||||
|
|
||||||
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
|
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
|
||||||
return (
|
return (
|
||||||
<Tooltip content={i18n('contactInAddressBook')}>
|
<Tooltip
|
||||||
|
content={i18n('contactInAddressBook')}
|
||||||
|
popperModifiers={[
|
||||||
|
{
|
||||||
|
name: 'preventOverflow',
|
||||||
|
options: {
|
||||||
|
boundary: tooltipContainerRef?.current || undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
aria-label={i18n('contactInAddressBook')}
|
aria-label={i18n('contactInAddressBook')}
|
||||||
className={classNames('module-in-contacts-icon__icon', className)}
|
className={classNames('module-in-contacts-icon__icon', className)}
|
||||||
|
|
|
@ -81,6 +81,26 @@ story.add('Sticky', () => (
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
story.add('With Applied Popper Modifiers', () => {
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
{...createProps({
|
||||||
|
direction: TooltipPlacement.Bottom,
|
||||||
|
})}
|
||||||
|
popperModifiers={[
|
||||||
|
{
|
||||||
|
name: 'offset',
|
||||||
|
options: {
|
||||||
|
offset: [80, 80],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{Trigger}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
story.add('Dark Theme', () => (
|
story.add('Dark Theme', () => (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
{...createProps({
|
{...createProps({
|
||||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { noop } from 'lodash';
|
import { noop } from 'lodash';
|
||||||
import { Manager, Reference, Popper } from 'react-popper';
|
import { Manager, Reference, Popper } from 'react-popper';
|
||||||
|
import type { StrictModifiers } from '@popperjs/core';
|
||||||
import { Theme, themeClassName } from '../util/theme';
|
import { Theme, themeClassName } from '../util/theme';
|
||||||
import { refMerger } from '../util/refMerger';
|
import { refMerger } from '../util/refMerger';
|
||||||
import { offsetDistanceModifier } from '../util/popperUtil';
|
import { offsetDistanceModifier } from '../util/popperUtil';
|
||||||
|
@ -70,6 +71,7 @@ export type PropsType = {
|
||||||
content: string | JSX.Element;
|
content: string | JSX.Element;
|
||||||
className?: string;
|
className?: string;
|
||||||
direction?: TooltipPlacement;
|
direction?: TooltipPlacement;
|
||||||
|
popperModifiers?: Array<StrictModifiers>;
|
||||||
sticky?: boolean;
|
sticky?: boolean;
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
};
|
};
|
||||||
|
@ -81,6 +83,7 @@ export const Tooltip: React.FC<PropsType> = ({
|
||||||
direction,
|
direction,
|
||||||
sticky,
|
sticky,
|
||||||
theme,
|
theme,
|
||||||
|
popperModifiers = [],
|
||||||
}) => {
|
}) => {
|
||||||
const [isHovering, setIsHovering] = React.useState(false);
|
const [isHovering, setIsHovering] = React.useState(false);
|
||||||
|
|
||||||
|
@ -99,7 +102,10 @@ export const Tooltip: React.FC<PropsType> = ({
|
||||||
</TooltipEventWrapper>
|
</TooltipEventWrapper>
|
||||||
)}
|
)}
|
||||||
</Reference>
|
</Reference>
|
||||||
<Popper placement={direction} modifiers={[offsetDistanceModifier(12)]}>
|
<Popper
|
||||||
|
placement={direction}
|
||||||
|
modifiers={[offsetDistanceModifier(12), ...popperModifiers]}
|
||||||
|
>
|
||||||
{({ arrowProps, placement, ref, style }) =>
|
{({ arrowProps, placement, ref, style }) =>
|
||||||
showTooltip && (
|
showTooltip && (
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -113,12 +113,15 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
private menuTriggerRef: React.RefObject<any>;
|
private menuTriggerRef: React.RefObject<any>;
|
||||||
|
|
||||||
|
public headerRef: React.RefObject<HTMLDivElement>;
|
||||||
|
|
||||||
public constructor(props: PropsType) {
|
public constructor(props: PropsType) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = { isNarrow: false, modalState: ModalState.NothingOpen };
|
this.state = { isNarrow: false, modalState: ModalState.NothingOpen };
|
||||||
|
|
||||||
this.menuTriggerRef = React.createRef();
|
this.menuTriggerRef = React.createRef();
|
||||||
|
this.headerRef = React.createRef();
|
||||||
this.showMenuBound = this.showMenu.bind(this);
|
this.showMenuBound = this.showMenu.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,6 +166,7 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
<InContactsIcon
|
<InContactsIcon
|
||||||
className="module-ConversationHeader__header__info__title__in-contacts-icon"
|
className="module-ConversationHeader__header__info__title__in-contacts-icon"
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
|
tooltipContainerRef={this.headerRef}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
@ -596,7 +600,11 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className="module-ConversationHeader__header">{contents}</div>;
|
return (
|
||||||
|
<div className="module-ConversationHeader__header" ref={this.headerRef}>
|
||||||
|
{contents}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(): ReactNode {
|
public render(): ReactNode {
|
||||||
|
|
|
@ -12792,6 +12792,22 @@
|
||||||
"updated": "2020-05-20T20:10:43.540Z",
|
"updated": "2020-05-20T20:10:43.540Z",
|
||||||
"reasonDetail": "Used to reference popup menu"
|
"reasonDetail": "Used to reference popup menu"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"rule": "React-createRef",
|
||||||
|
"path": "ts/components/conversation/ConversationHeader.js",
|
||||||
|
"line": " this.headerRef = react_1.default.createRef();",
|
||||||
|
"reasonCategory": "usageTrusted",
|
||||||
|
"updated": "2021-01-18T22:24:05.937Z",
|
||||||
|
"reasonDetail": "Used to reference popup menu boundaries element"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "React-createRef",
|
||||||
|
"path": "ts/components/conversation/ConversationHeader.tsx",
|
||||||
|
"line": " this.headerRef = React.createRef();",
|
||||||
|
"reasonCategory": "usageTrusted",
|
||||||
|
"updated": "2021-01-18T22:24:05.937Z",
|
||||||
|
"reasonDetail": "Used to reference popup menu boundaries element"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"rule": "React-useRef",
|
"rule": "React-useRef",
|
||||||
"path": "ts/components/conversation/ConversationHero.tsx",
|
"path": "ts/components/conversation/ConversationHero.tsx",
|
||||||
|
|
Loading…
Reference in a new issue