Fix tooltip placement bugs by upgrading Popper
This commit is contained in:
parent
26b7652492
commit
3b476fb60d
15 changed files with 85 additions and 136 deletions
|
@ -5,6 +5,10 @@
|
|||
|
||||
Signal Desktop makes use of the following open source projects.
|
||||
|
||||
## @popperjs/core
|
||||
|
||||
License: MIT
|
||||
|
||||
## @sindresorhus/is
|
||||
|
||||
MIT License
|
||||
|
@ -2478,10 +2482,6 @@ Signal Desktop makes use of the following open source projects.
|
|||
|
||||
License: MIT
|
||||
|
||||
## popper.js
|
||||
|
||||
License: MIT
|
||||
|
||||
## protobufjs
|
||||
|
||||
This license applies to all parts of protobuf.js except those files
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
"fs-xattr": "0.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@popperjs/core": "2.9.2",
|
||||
"@signalapp/signal-client": "0.8.1",
|
||||
"@sindresorhus/is": "0.8.0",
|
||||
"@types/pino": "6.3.6",
|
||||
|
@ -123,7 +124,6 @@
|
|||
"pify": "3.0.0",
|
||||
"pino": "6.11.1",
|
||||
"pino-multi-stream": "5.3.0",
|
||||
"popper.js": "1.15.0",
|
||||
"protobufjs": "6.10.2",
|
||||
"proxy-agent": "4.0.1",
|
||||
"quill": "1.3.7",
|
||||
|
@ -135,7 +135,7 @@
|
|||
"react-dropzone": "10.1.7",
|
||||
"react-hot-loader": "4.12.11",
|
||||
"react-measure": "2.3.0",
|
||||
"react-popper": "1.3.7",
|
||||
"react-popper": "2.2.5",
|
||||
"react-quill": "2.0.0-beta.2",
|
||||
"react-redux": "7.1.0",
|
||||
"react-router-dom": "5.0.1",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2019-2020 Signal Messenger, LLC
|
||||
// Copyright 2019-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
|
@ -260,7 +260,12 @@ export const StickerFrame = React.memo(
|
|||
previewActive &&
|
||||
previewPopperRoot
|
||||
? createPortal(
|
||||
<Popper placement="bottom">
|
||||
<Popper
|
||||
placement="bottom"
|
||||
modifiers={[
|
||||
{ name: 'offset', options: { offset: [undefined, 8] } },
|
||||
]}
|
||||
>
|
||||
{({ ref, style, arrowProps, placement }) => (
|
||||
<StickerPreview
|
||||
ref={ref}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2019-2020 Signal Messenger, LLC
|
||||
// Copyright 2019-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
@import '../mixins';
|
||||
|
@ -39,26 +39,6 @@
|
|||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
composes: base;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.top {
|
||||
composes: base;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.left {
|
||||
composes: base;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.right {
|
||||
composes: base;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright 2019-2020 Signal Messenger, LLC
|
||||
// Copyright 2019-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
import { PopperArrowProps } from 'react-popper';
|
||||
import { Placement } from 'popper.js';
|
||||
import { Placement } from '@popperjs/core';
|
||||
import * as styles from './StickerPreview.scss';
|
||||
import { MessageBubble } from './MessageBubble';
|
||||
import { MessageSticker, Props as MessageStickerProps } from './MessageSticker';
|
||||
|
@ -26,22 +26,6 @@ const renderMessages = (
|
|||
</>
|
||||
);
|
||||
|
||||
const getBaseClass = (placement?: Placement) => {
|
||||
if (placement === 'top') {
|
||||
return styles.top;
|
||||
}
|
||||
|
||||
if (placement === 'right') {
|
||||
return styles.right;
|
||||
}
|
||||
|
||||
if (placement === 'left') {
|
||||
return styles.left;
|
||||
}
|
||||
|
||||
return styles.bottom;
|
||||
};
|
||||
|
||||
const getArrowClass = (placement?: Placement) => {
|
||||
if (placement === 'top') {
|
||||
return styles.arrowBottom;
|
||||
|
@ -64,7 +48,7 @@ export const StickerPreview = React.memo(
|
|||
const i18n = useI18n();
|
||||
|
||||
return (
|
||||
<div className={getBaseClass(placement)} ref={ref} style={style}>
|
||||
<div className={styles.base} ref={ref} style={style}>
|
||||
{arrowProps ? (
|
||||
<div
|
||||
ref={arrowProps.ref}
|
||||
|
|
|
@ -4989,7 +4989,6 @@ button.module-image__border-overlay:focus {
|
|||
height: 56px;
|
||||
border-radius: 30px;
|
||||
position: relative;
|
||||
margin: 4px 0;
|
||||
z-index: 2;
|
||||
|
||||
animation: {
|
||||
|
@ -9908,8 +9907,6 @@ $contact-modal-padding: 18px;
|
|||
}
|
||||
|
||||
&[data-placement='top'] {
|
||||
margin-bottom: 12px;
|
||||
|
||||
.module-tooltip-arrow {
|
||||
bottom: 0;
|
||||
}
|
||||
|
@ -9921,8 +9918,6 @@ $contact-modal-padding: 18px;
|
|||
}
|
||||
|
||||
&[data-placement='right'] {
|
||||
margin-left: 12px;
|
||||
|
||||
.module-tooltip-arrow {
|
||||
left: 0;
|
||||
}
|
||||
|
@ -9934,8 +9929,6 @@ $contact-modal-padding: 18px;
|
|||
}
|
||||
|
||||
&[data-placement='bottom'] {
|
||||
margin-top: 12px;
|
||||
|
||||
.module-tooltip-arrow {
|
||||
top: 0;
|
||||
}
|
||||
|
@ -9947,8 +9940,6 @@ $contact-modal-padding: 18px;
|
|||
}
|
||||
|
||||
&[data-placement='left'] {
|
||||
margin-right: 12px;
|
||||
|
||||
.module-tooltip-arrow {
|
||||
right: 0;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ export const MediaQualitySelector = ({
|
|||
</Reference>
|
||||
{menuShowing && popperRoot
|
||||
? createPortal(
|
||||
<Popper placement="top-start" positionFixed>
|
||||
<Popper placement="top-start" strategy="fixed">
|
||||
{({ ref, style, placement }) => (
|
||||
<div
|
||||
className="MediaQualitySelector__popper"
|
||||
|
|
|
@ -7,6 +7,7 @@ import { noop } from 'lodash';
|
|||
import { Manager, Reference, Popper } from 'react-popper';
|
||||
import { Theme, themeClassName } from '../util/theme';
|
||||
import { multiRef } from '../util/multiRef';
|
||||
import { offsetDistanceModifier } from '../util/popperUtil';
|
||||
|
||||
type EventWrapperPropsType = {
|
||||
children: React.ReactNode;
|
||||
|
@ -96,7 +97,7 @@ export const Tooltip: React.FC<PropsType> = ({
|
|||
</TooltipEventWrapper>
|
||||
)}
|
||||
</Reference>
|
||||
<Popper placement={direction}>
|
||||
<Popper placement={direction} modifiers={[offsetDistanceModifier(12)]}>
|
||||
{({ arrowProps, placement, ref, style }) =>
|
||||
showTooltip && (
|
||||
<div
|
||||
|
|
|
@ -63,6 +63,7 @@ import { createRefMerger } from '../_util';
|
|||
import { emojiToData } from '../emoji/lib';
|
||||
import { SmartReactionPicker } from '../../state/smart/ReactionPicker';
|
||||
import { getCustomColorStyle } from '../../util/getCustomColorStyle';
|
||||
import { offsetDistanceModifier } from '../../util/popperUtil';
|
||||
|
||||
type Trigger = {
|
||||
handleContextClick: (event: React.MouseEvent<HTMLDivElement>) => void;
|
||||
|
@ -1429,7 +1430,7 @@ export class Message extends React.Component<Props, State> {
|
|||
{reactionPickerRoot &&
|
||||
createPortal(
|
||||
// eslint-disable-next-line consistent-return
|
||||
<Popper placement="top">
|
||||
<Popper placement="top" modifiers={[offsetDistanceModifier(4)]}>
|
||||
{({ ref, style }) => (
|
||||
<SmartReactionPicker
|
||||
ref={ref}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2019-2020 Signal Messenger, LLC
|
||||
// Copyright 2019-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
|
@ -129,7 +129,7 @@ export const EmojiButton = React.memo(
|
|||
</Reference>
|
||||
{open && popperRoot
|
||||
? createPortal(
|
||||
<Popper placement="top-start" positionFixed>
|
||||
<Popper placement="top-start" strategy="fixed">
|
||||
{({ ref, style }) => (
|
||||
<EmojiPicker
|
||||
ref={ref}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2019-2020 Signal Messenger, LLC
|
||||
// Copyright 2019-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
|
@ -10,6 +10,7 @@ import { StickerPicker } from './StickerPicker';
|
|||
import { countStickers } from './lib';
|
||||
import { StickerPackType, StickerType } from '../../state/ducks/stickers';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
import { offsetDistanceModifier } from '../../util/popperUtil';
|
||||
|
||||
export type OwnProps = {
|
||||
readonly i18n: LocalizerType;
|
||||
|
@ -202,7 +203,11 @@ export const StickerButton = React.memo(
|
|||
)}
|
||||
</Reference>
|
||||
{!open && !showIntroduction && installedPack ? (
|
||||
<Popper placement={position} key={installedPack.id}>
|
||||
<Popper
|
||||
placement={position}
|
||||
key={installedPack.id}
|
||||
modifiers={[offsetDistanceModifier(6)]}
|
||||
>
|
||||
{({ ref, style, placement, arrowProps }) => (
|
||||
<button
|
||||
type="button"
|
||||
|
@ -239,7 +244,7 @@ export const StickerButton = React.memo(
|
|||
</Popper>
|
||||
) : null}
|
||||
{!open && showIntroduction ? (
|
||||
<Popper placement={position}>
|
||||
<Popper placement={position} modifiers={[offsetDistanceModifier(6)]}>
|
||||
{({ ref, style, placement, arrowProps }) => (
|
||||
<button
|
||||
type="button"
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
import { Emoji } from '../../components/emoji/Emoji';
|
||||
import { EmojiPickDataType } from '../../components/emoji/EmojiPicker';
|
||||
import { getBlotTextPartitions, matchBlotTextPartitions } from '../util';
|
||||
import { sameWidthModifier } from '../../util/popperUtil';
|
||||
|
||||
const Keyboard = Quill.import('modules/keyboard');
|
||||
|
||||
|
@ -265,25 +266,7 @@ export class EmojiCompletion {
|
|||
}
|
||||
|
||||
const element = createPortal(
|
||||
<Popper
|
||||
placement="top"
|
||||
modifiers={{
|
||||
width: {
|
||||
enabled: true,
|
||||
fn: oldData => {
|
||||
const data = oldData;
|
||||
const { width, left } = data.offsets.reference;
|
||||
|
||||
data.styles.width = `${width}px`;
|
||||
data.offsets.popper.width = width;
|
||||
data.offsets.popper.left = left;
|
||||
|
||||
return data;
|
||||
},
|
||||
order: 840,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Popper placement="top-start" modifiers={[sameWidthModifier]}>
|
||||
{({ ref, style }) => (
|
||||
<div
|
||||
ref={ref}
|
||||
|
|
|
@ -14,6 +14,7 @@ import { Avatar } from '../../components/Avatar';
|
|||
import { LocalizerType } from '../../types/Util';
|
||||
import { MemberRepository } from '../memberRepository';
|
||||
import { matchBlotTextPartitions } from '../util';
|
||||
import { sameWidthModifier } from '../../util/popperUtil';
|
||||
|
||||
export type MentionCompletionOptions = {
|
||||
i18n: LocalizerType;
|
||||
|
@ -218,25 +219,7 @@ export class MentionCompletion {
|
|||
}
|
||||
|
||||
const element = createPortal(
|
||||
<Popper
|
||||
placement="top"
|
||||
modifiers={{
|
||||
width: {
|
||||
enabled: true,
|
||||
fn: oldData => {
|
||||
const data = oldData;
|
||||
const { width, left } = data.offsets.reference;
|
||||
|
||||
data.styles.width = `${width}px`;
|
||||
data.offsets.popper.width = width;
|
||||
data.offsets.popper.left = left;
|
||||
|
||||
return data;
|
||||
},
|
||||
order: 840,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Popper placement="top-start" modifiers={[sameWidthModifier]}>
|
||||
{({ ref, style }) => (
|
||||
<div
|
||||
ref={ref}
|
||||
|
|
33
ts/util/popperUtil.ts
Normal file
33
ts/util/popperUtil.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { Modifier } from '@popperjs/core';
|
||||
import type { OffsetModifier } from '@popperjs/core/lib/modifiers/offset';
|
||||
|
||||
/**
|
||||
* Shorthand for the [offset modifier][0] when you just wanna set the distance.
|
||||
*
|
||||
* [0]: https://popper.js.org/docs/v2/modifiers/offset/
|
||||
*/
|
||||
export const offsetDistanceModifier = (
|
||||
distance: number
|
||||
): Partial<OffsetModifier> => ({
|
||||
name: 'offset',
|
||||
options: { offset: [undefined, distance] },
|
||||
});
|
||||
|
||||
/**
|
||||
* Make the popper element the same width as the reference, even when you resize.
|
||||
*
|
||||
* Should probably be used with the "top-start", "top-end", "bottom-start", or
|
||||
* "bottom-end" placement.
|
||||
*/
|
||||
export const sameWidthModifier: Modifier<'sameWidth', unknown> = {
|
||||
name: 'sameWidth',
|
||||
enabled: true,
|
||||
phase: 'write',
|
||||
fn({ state }) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
state.elements.popper.style.width = `${state.rects.reference.width}px`;
|
||||
},
|
||||
};
|
49
yarn.lock
49
yarn.lock
|
@ -1580,6 +1580,11 @@
|
|||
"@nodelib/fs.scandir" "2.1.3"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@popperjs/core@2.9.2":
|
||||
version "2.9.2"
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
|
||||
integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
|
||||
|
||||
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
|
||||
|
@ -6542,18 +6547,6 @@ deep-equal@^1.0.1:
|
|||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
|
||||
|
||||
deep-equal@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
|
||||
integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==
|
||||
dependencies:
|
||||
is-arguments "^1.0.4"
|
||||
is-date-object "^1.0.1"
|
||||
is-regex "^1.0.4"
|
||||
object-is "^1.0.1"
|
||||
object-keys "^1.1.1"
|
||||
regexp.prototype.flags "^1.2.0"
|
||||
|
||||
deep-extend@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
||||
|
@ -10398,11 +10391,6 @@ is-alphanumerical@^1.0.0:
|
|||
is-alphabetical "^1.0.0"
|
||||
is-decimal "^1.0.0"
|
||||
|
||||
is-arguments@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3"
|
||||
integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==
|
||||
|
||||
is-arrayish@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
|
@ -12966,11 +12954,6 @@ object-inspect@^1.7.0, object-inspect@^1.8.0:
|
|||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
|
||||
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
|
||||
|
||||
object-is@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4"
|
||||
integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==
|
||||
|
||||
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||
|
@ -13914,7 +13897,7 @@ polished@^3.3.1:
|
|||
dependencies:
|
||||
"@babel/runtime" "^7.4.5"
|
||||
|
||||
popper.js@1.15.0, popper.js@^1.14.4, popper.js@^1.14.7:
|
||||
popper.js@^1.14.4, popper.js@^1.14.7:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.15.0.tgz#5560b99bbad7647e9faa475c6b8056621f5a4ff2"
|
||||
integrity sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA==
|
||||
|
@ -14749,6 +14732,11 @@ react-fast-compare@2.0.4:
|
|||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||
|
||||
react-fast-compare@^3.0.1:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
|
||||
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
|
||||
|
||||
react-focus-lock@^1.18.3:
|
||||
version "1.19.1"
|
||||
resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-1.19.1.tgz#2f3429793edaefe2d077121f973ce5a3c7a0651a"
|
||||
|
@ -14845,17 +14833,12 @@ react-popper-tooltip@^2.8.3:
|
|||
"@babel/runtime" "^7.4.5"
|
||||
react-popper "^1.3.3"
|
||||
|
||||
react-popper@1.3.7:
|
||||
version "1.3.7"
|
||||
resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.7.tgz#f6a3471362ef1f0d10a4963673789de1baca2324"
|
||||
integrity sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww==
|
||||
react-popper@2.2.5:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.2.5.tgz#1214ef3cec86330a171671a4fbcbeeb65ee58e96"
|
||||
integrity sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.1.2"
|
||||
create-react-context "^0.3.0"
|
||||
deep-equal "^1.1.1"
|
||||
popper.js "^1.14.4"
|
||||
prop-types "^15.6.1"
|
||||
typed-styles "^0.0.7"
|
||||
react-fast-compare "^3.0.1"
|
||||
warning "^4.0.2"
|
||||
|
||||
react-popper@^1.3.3:
|
||||
|
|
Loading…
Reference in a new issue