dev merge
This commit is contained in:
commit
04d74f8e95
38 changed files with 607 additions and 422 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import stl from './notifications.module.css';
|
||||
import { connect } from 'react-redux';
|
||||
import { Icon, Popup } from 'UI';
|
||||
import { Icon, Tooltip } from 'UI';
|
||||
import { fetchList, setViewed, clearAll } from 'Duck/notifications';
|
||||
import { setLastRead } from 'Duck/announcements';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
|
|
@ -29,7 +29,7 @@ function Notifications(props: Props) {
|
|||
}, []);
|
||||
|
||||
return useObserver(() => (
|
||||
<Popup content={`Alerts`}>
|
||||
<Tooltip title={`Alerts`}>
|
||||
<div
|
||||
className={stl.button}
|
||||
onClick={() => showModal(<AlertTriggersModal />, { right: true })}
|
||||
|
|
@ -39,7 +39,7 @@ function Notifications(props: Props) {
|
|||
</div>
|
||||
<Icon name="bell" size="18" color="gray-dark" />
|
||||
</div>
|
||||
</Popup>
|
||||
</Tooltip>
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Popup, Button } from 'UI';
|
||||
import { Popup, Button, Tooltip } from 'UI';
|
||||
import { connect } from 'react-redux';
|
||||
import cn from 'classnames';
|
||||
import { toggleChatWindow } from 'Duck/sessions';
|
||||
|
|
@ -19,7 +19,6 @@ import {
|
|||
} from 'Player/MessageDistributor/managers/AssistManager';
|
||||
import RequestLocalStream from 'Player/MessageDistributor/managers/LocalStream';
|
||||
import type { LocalStream } from 'Player/MessageDistributor/managers/LocalStream';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { toast } from 'react-toastify';
|
||||
import { confirm } from 'UI';
|
||||
import stl from './AassistActions.module.css';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { Button, PageTitle, Loader } from 'UI';
|
||||
import { Button, PageTitle, Loader, Tooltip, Popover } from 'UI';
|
||||
import { withSiteId } from 'App/routes';
|
||||
import withModal from 'App/components/Modal/withModal';
|
||||
import DashboardWidgetGrid from '../DashboardWidgetGrid';
|
||||
|
|
@ -15,7 +15,6 @@ import withPageTitle from 'HOCs/withPageTitle';
|
|||
import withReport from 'App/components/hocs/withReport';
|
||||
import DashboardOptions from '../DashboardOptions';
|
||||
import SelectDateRange from 'Shared/SelectDateRange';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import Breadcrumb from 'Shared/Breadcrumb';
|
||||
import AddMetricContainer from '../DashboardWidgetGrid/AddMetricContainer';
|
||||
import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv';
|
||||
|
|
@ -126,24 +125,25 @@ function DashboardView(props: Props) {
|
|||
<PageTitle
|
||||
title={
|
||||
// @ts-ignore
|
||||
<Tooltip delay={100} arrow title="Double click to rename">
|
||||
<Tooltip title="Double click to rename">
|
||||
{dashboard?.name}
|
||||
</Tooltip>
|
||||
}
|
||||
onDoubleClick={() => onEdit(true)}
|
||||
className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer"
|
||||
actionButton={
|
||||
<OutsideClickDetectingDiv onClickOutside={() => setShowTooltip(false)}>
|
||||
<Tooltip
|
||||
open={showTooltip}
|
||||
interactive
|
||||
useContext
|
||||
// <OutsideClickDetectingDiv onClickOutside={() => setShowTooltip(false)}>
|
||||
<Popover
|
||||
// open={showTooltip}
|
||||
// interactive
|
||||
// useContext
|
||||
// @ts-ignore
|
||||
theme="nopadding"
|
||||
hideDelay={0}
|
||||
duration={0}
|
||||
distance={20}
|
||||
html={
|
||||
// theme="nopadding"
|
||||
// hideDelay={0}
|
||||
// duration={0}
|
||||
// distance={20}
|
||||
placement="left"
|
||||
render={() => showTooltip && (
|
||||
<div style={{ padding: 0 }}>
|
||||
<AddMetricContainer
|
||||
onAction={() => setShowTooltip(false)}
|
||||
|
|
@ -151,13 +151,13 @@ function DashboardView(props: Props) {
|
|||
siteId={siteId}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
>
|
||||
<Button variant="primary" onClick={() => setShowTooltip(true)}>
|
||||
Add Metric
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</OutsideClickDetectingDiv>
|
||||
</Popover>
|
||||
// </OutsideClickDetectingDiv>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Icon, Link } from 'UI';
|
||||
import { Icon, Tooltip } from 'UI';
|
||||
import { checkForRecent } from 'App/date';
|
||||
import { Tooltip } from 'react-tippy'
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { withSiteId } from 'App/routes';
|
||||
|
||||
|
|
@ -24,9 +23,7 @@ function MetricTypeIcon({ type }: any) {
|
|||
|
||||
return (
|
||||
<Tooltip
|
||||
html={<div className="capitalize">{type}</div>}
|
||||
position="top"
|
||||
arrow
|
||||
title={<div className="capitalize">{type}</div>}
|
||||
>
|
||||
<div className="w-9 h-9 rounded-full bg-tealx-lightest flex items-center justify-center mr-2">
|
||||
<Icon name={getIcon()} size="16" color="tealx" />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { Icon } from 'UI';
|
||||
import { Icon, Tooltip } from 'UI';
|
||||
import cn from 'classnames';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
|
|
@ -65,7 +64,7 @@ function WidgetName(props: Props) {
|
|||
/>
|
||||
) : (
|
||||
// @ts-ignore
|
||||
<Tooltip delay={100} arrow title="Double click to rename" disabled={!canEdit}>
|
||||
<Tooltip title="Double click to rename" disabled={!canEdit}>
|
||||
<div
|
||||
onDoubleClick={() => setEditing(true)}
|
||||
className={
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import FunnelStepText from './FunnelStepText';
|
||||
import { Icon, Popup } from 'UI';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { Icon, Tooltip } from 'UI';
|
||||
|
||||
interface Props {
|
||||
filter: any;
|
||||
|
|
|
|||
|
|
@ -1,77 +1,83 @@
|
|||
import React, { useEffect } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { setAutoplayValues } from 'Duck/sessions'
|
||||
import React, { useEffect } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { setAutoplayValues } from 'Duck/sessions';
|
||||
import { session as sessionRoute } from 'App/routes';
|
||||
import { Link, Icon, Toggler } from 'UI';
|
||||
import { Link, Icon, Toggler, Tooltip } from 'UI';
|
||||
import { connectPlayer } from 'Player/store';
|
||||
import { Controls as PlayerControls } from 'Player';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import cn from 'classnames';
|
||||
|
||||
function Autoplay(props) {
|
||||
const { previousId, nextId, autoplay, disabled } = props
|
||||
const { previousId, nextId, autoplay, disabled } = props;
|
||||
|
||||
useEffect(() => {
|
||||
props.setAutoplayValues()
|
||||
}, [])
|
||||
props.setAutoplayValues();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<div onClick={props.toggleAutoplay} className="cursor-pointer flex items-center mr-2 hover:bg-gray-light-shade rounded-md p-2">
|
||||
<Toggler
|
||||
name="sessionsLive"
|
||||
onChange={ props.toggleAutoplay }
|
||||
checked={ autoplay }
|
||||
/>
|
||||
<div
|
||||
onClick={props.toggleAutoplay}
|
||||
className="cursor-pointer flex items-center mr-2 hover:bg-gray-light-shade rounded-md p-2"
|
||||
>
|
||||
<Toggler name="sessionsLive" onChange={props.toggleAutoplay} checked={autoplay} />
|
||||
<span className="ml-2">Auto-Play</span>
|
||||
</div>
|
||||
|
||||
<Tooltip
|
||||
delay={0}
|
||||
arrow
|
||||
animation="fade"
|
||||
position="bottom center"
|
||||
title="Play Previous Session"
|
||||
placement="bottom"
|
||||
title={<div className="whitespace-nowrap">Play Previous Session</div>}
|
||||
disabled={!previousId}
|
||||
className={cn(
|
||||
"p-1 bg-gray-bg group rounded-full color-gray-darkest font-medium",
|
||||
previousId && 'cursor-pointer',
|
||||
!disabled && nextId&& 'hover:bg-bg-blue'
|
||||
)}
|
||||
>
|
||||
<Link to={ sessionRoute(previousId) } disabled={!previousId}>
|
||||
<Icon name="prev1" className="group-hover:fill-main" color="inherit" size="16" />
|
||||
<Link to={sessionRoute(previousId)} disabled={!previousId}>
|
||||
<div
|
||||
className={cn(
|
||||
'p-1 bg-gray-bg group rounded-full color-gray-darkest font-medium',
|
||||
previousId && 'cursor-pointer',
|
||||
!disabled && nextId && 'hover:bg-bg-blue'
|
||||
)}
|
||||
>
|
||||
<Icon name="prev1" className="group-hover:fill-main" color="inherit" size="16" />
|
||||
</div>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip
|
||||
delay={0}
|
||||
arrow
|
||||
animation="fade"
|
||||
position="bottom center"
|
||||
title="Play Next Session"
|
||||
placement="bottom"
|
||||
title={<div className="whitespace-nowrap">Play Next Session</div>}
|
||||
disabled={!nextId}
|
||||
className={cn(
|
||||
"p-1 bg-gray-bg group ml-1 rounded-full color-gray-darkest font-medium",
|
||||
nextId && 'cursor-pointer',
|
||||
!disabled && nextId && 'hover:bg-bg-blue',
|
||||
)}
|
||||
>
|
||||
<Link to={ sessionRoute(nextId) } disabled={!nextId} >
|
||||
<Icon name="next1" className="group-hover:fill-main" color="inherit" size="16" />
|
||||
<Link to={sessionRoute(nextId)} disabled={!nextId}>
|
||||
<div
|
||||
className={cn(
|
||||
'p-1 bg-gray-bg group ml-1 rounded-full color-gray-darkest font-medium',
|
||||
nextId && 'cursor-pointer',
|
||||
!disabled && nextId && 'hover:bg-bg-blue'
|
||||
)}
|
||||
>
|
||||
<Icon name="next1" className="group-hover:fill-main" color="inherit" size="16" />
|
||||
</div>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const connectAutoplay = connect(state => ({
|
||||
previousId: state.getIn([ 'sessions', 'previousId' ]),
|
||||
nextId: state.getIn([ 'sessions', 'nextId' ]),
|
||||
}), { setAutoplayValues })
|
||||
const connectAutoplay = connect(
|
||||
(state) => ({
|
||||
previousId: state.getIn(['sessions', 'previousId']),
|
||||
nextId: state.getIn(['sessions', 'nextId']),
|
||||
}),
|
||||
{ setAutoplayValues }
|
||||
);
|
||||
|
||||
export default connectAutoplay(connectPlayer(state => ({
|
||||
autoplay: state.autoplay,
|
||||
}), {
|
||||
toggleAutoplay: PlayerControls.toggleAutoplay
|
||||
})(Autoplay))
|
||||
export default connectAutoplay(
|
||||
connectPlayer(
|
||||
(state) => ({
|
||||
autoplay: state.autoplay,
|
||||
}),
|
||||
{
|
||||
toggleAutoplay: PlayerControls.toggleAutoplay,
|
||||
}
|
||||
)(Autoplay)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import cn from 'classnames';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { Tooltip } from 'UI';
|
||||
|
||||
function ReportTitle() {
|
||||
const { bugReportStore } = useStore();
|
||||
|
|
@ -45,7 +45,7 @@ function ReportTitle() {
|
|||
/>
|
||||
) : (
|
||||
// @ts-ignore
|
||||
<Tooltip delay={100} arrow title="Double click to rename">
|
||||
<Tooltip title="Double click to rename">
|
||||
<div
|
||||
onDoubleClick={toggleEdit}
|
||||
className={cn(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react'
|
||||
import SectionTitle from './SectionTitle';
|
||||
import { Icon } from 'UI'
|
||||
import { Tooltip } from 'react-tippy'
|
||||
import { Icon, Tooltip } from 'UI'
|
||||
|
||||
export default function Session({ user, sessionUrl }: { user: string, sessionUrl: string }) {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Icon, ItemMenu } from 'UI';
|
||||
import { Icon, ItemMenu, Tooltip } from 'UI';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { Step as IStep } from '../../types';
|
||||
const STEP_NAMES = { CLICKRAGE: 'Multiple click', CLICK: 'Clicked', LOCATION: 'Visited' };
|
||||
|
|
@ -7,7 +7,6 @@ import { useStore } from 'App/mstore';
|
|||
import cn from 'classnames';
|
||||
import { ErrorComp, NetworkComp, NoteComp } from './SubModalItems';
|
||||
import { durationFromMs } from 'App/date';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
|
||||
const SUBSTEP = {
|
||||
network: NetworkComp,
|
||||
|
|
@ -80,7 +79,7 @@ function Step({ step, ind, isDefault }: { step: IStep; ind: number; isDefault?:
|
|||
/>
|
||||
</Tooltip>
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip title="Delete Step">
|
||||
<Tooltip title="Delete Step" className="whitespace-nowrap">
|
||||
<div onClick={() => bugReportStore.removeStep(step)}>
|
||||
<Icon name="trash" size={16} className="cursor-pointer hover:fill-gray-darkest" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Tooltip } from 'react-tippy'
|
||||
import { Tooltip } from 'UI'
|
||||
|
||||
interface Props {
|
||||
pickRadius: number;
|
||||
|
|
@ -11,7 +11,7 @@ function StepRadius({ pickRadius, setRadius }: Props) {
|
|||
<div className="w-full flex items-center gap-4">
|
||||
<div className="border-b border-dotted border-gray-medium cursor-help">
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip html={<span>Closest step to the selected timestamp ± {pickRadius}.</span>}>
|
||||
<Tooltip title={<span>Closest step to the selected timestamp ± {pickRadius}.</span>}>
|
||||
<span>± {pickRadius}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ import { countries } from 'App/constants';
|
|||
import { useStore } from 'App/mstore';
|
||||
import { browserIcon, osIcon, deviceTypeIcon } from 'App/iconNames';
|
||||
import { formatTimeOrDate } from 'App/date';
|
||||
import { Avatar, TextEllipsis, CountryFlag, Icon } from 'UI';
|
||||
import { Avatar, TextEllipsis, CountryFlag, Icon, Tooltip } from 'UI';
|
||||
import cn from 'classnames';
|
||||
import { withRequest } from 'HOCs';
|
||||
import SessionInfoItem from '../../SessionInfoItem';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import UserSessionsModal from 'Shared/UserSessionsModal';
|
||||
|
||||
|
|
@ -77,12 +76,13 @@ function UserCard({ className, request, session, width, height, similarSessions,
|
|||
</span>
|
||||
<span className="mx-1 font-bold text-xl">·</span>
|
||||
<Tooltip
|
||||
theme="light"
|
||||
// theme="light"
|
||||
delay={0}
|
||||
hideOnClick="persistent"
|
||||
arrow
|
||||
interactive
|
||||
html={
|
||||
// hideOnClick="persistent"
|
||||
// arrow
|
||||
// interactive
|
||||
className="!bg-white shadow border !color-gray-dark"
|
||||
title={
|
||||
<div className="text-left">
|
||||
<SessionInfoItem
|
||||
comp={<CountryFlag country={userCountry} />}
|
||||
|
|
@ -100,9 +100,9 @@ function UserCard({ className, request, session, width, height, similarSessions,
|
|||
{revId && <SessionInfoItem icon="info" label="Rev ID:" value={revId} isLast />}
|
||||
</div>
|
||||
}
|
||||
position="bottom center"
|
||||
hoverable
|
||||
disabled={false}
|
||||
position="bottom"
|
||||
// hoverable
|
||||
// disabled={false}
|
||||
on="hover"
|
||||
>
|
||||
<span className="color-teal cursor-pointer">More</span>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Popup, Button, Icon } from 'UI';
|
||||
import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv';
|
||||
import { Icon, Popover } from 'UI';
|
||||
import IssuesModal from './IssuesModal';
|
||||
import { fetchProjects, fetchMeta } from 'Duck/assignments';
|
||||
import stl from './issues.module.css';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
|
||||
@connect(
|
||||
(state) => ({
|
||||
|
|
@ -71,32 +69,25 @@ class Issues extends React.Component {
|
|||
return (
|
||||
<div className="relative h-full w-full p-3">
|
||||
<div className={stl.buttonWrapper}>
|
||||
<OutsideClickDetectingDiv onClickOutside={this.closeModal}>
|
||||
<Tooltip
|
||||
open={this.state.showModal}
|
||||
position="bottom"
|
||||
interactive
|
||||
trigger="click"
|
||||
unmountHTMLWhenHide
|
||||
useContext
|
||||
theme="light"
|
||||
arrow
|
||||
html={
|
||||
<div>
|
||||
<IssuesModal
|
||||
provider={provider}
|
||||
sessionId={sessionId}
|
||||
closeHandler={this.closeModal}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
<Popover
|
||||
render={({ close }) => (
|
||||
<div>
|
||||
<IssuesModal
|
||||
provider={provider}
|
||||
sessionId={sessionId}
|
||||
closeHandler={close}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="flex items-center"
|
||||
disabled={!isModalDisplayed && (metaLoading || fetchIssuesLoading || projectsLoading)}
|
||||
>
|
||||
<div className="flex items-center" onClick={this.handleOpen} disabled={!isModalDisplayed && (metaLoading || fetchIssuesLoading || projectsLoading)}>
|
||||
<Icon name={ `integrations/${ provider === 'jira' ? 'jira' : 'github'}` } size="16" />
|
||||
<span className="ml-2">Create Issue</span>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</OutsideClickDetectingDiv>
|
||||
<Icon name={`integrations/${provider === 'jira' ? 'jira' : 'github'}`} size="16" />
|
||||
<span className="ml-2">Create Issue</span>
|
||||
</div>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
import LiveTag from 'Shared/LiveTag';
|
||||
import { jumpToLive } from 'Player';
|
||||
|
||||
import { Icon } from 'UI';
|
||||
import { Icon, Tooltip } from 'UI';
|
||||
import { toggleInspectorMode } from 'Player';
|
||||
import {
|
||||
fullscreenOn,
|
||||
|
|
@ -33,7 +33,6 @@ import ControlButton from './ControlButton';
|
|||
import PlayerControls from './components/PlayerControls';
|
||||
|
||||
import styles from './controls.module.css';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import XRayButton from 'Shared/XRayButton';
|
||||
|
||||
const SKIP_INTERVALS = {
|
||||
|
|
@ -227,11 +226,7 @@ export default class Controls extends React.Component {
|
|||
|
||||
return (
|
||||
<Tooltip
|
||||
delay={0}
|
||||
position="top"
|
||||
title={label}
|
||||
interactive
|
||||
hideOnClick="persistent"
|
||||
className="mr-4"
|
||||
>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { Icon } from 'UI';
|
||||
import { Icon, Tooltip, Popover } from 'UI';
|
||||
import cn from 'classnames';
|
||||
import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv';
|
||||
import { ReduxTime } from '../Time';
|
||||
|
|
@ -49,7 +48,7 @@ function PlayerControls(props: Props) {
|
|||
const speedRef = React.useRef(null);
|
||||
const arrowBackRef = React.useRef(null);
|
||||
const arrowForwardRef = React.useRef(null);
|
||||
const skipRef = React.useRef<HTMLDivElement>()
|
||||
const skipRef = React.useRef<HTMLDivElement>();
|
||||
|
||||
React.useEffect(() => {
|
||||
const handleKeyboard = (e: KeyboardEvent) => {
|
||||
|
|
@ -77,11 +76,12 @@ function PlayerControls(props: Props) {
|
|||
setShowTooltip(!showTooltip);
|
||||
};
|
||||
const handleClickOutside = () => {
|
||||
setShowTooltip(false)
|
||||
}
|
||||
setShowTooltip(false);
|
||||
};
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
{playButton}
|
||||
<div className="mx-1" />
|
||||
{!live && (
|
||||
<div className="flex items-center font-semibold text-center" style={{ minWidth: 85 }}>
|
||||
{/* @ts-ignore */}
|
||||
|
|
@ -94,7 +94,7 @@ function PlayerControls(props: Props) {
|
|||
|
||||
<div className="rounded ml-4 bg-active-blue border border-active-blue-border flex items-stretch">
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip title="Rewind 10s" delay={0} position="top">
|
||||
<Tooltip title="Rewind 10s" position="top">
|
||||
<button
|
||||
ref={arrowBackRef}
|
||||
className="h-full hover:border-active-blue-border focus:border focus:border-blue border-borderColor-transparent"
|
||||
|
|
@ -109,17 +109,17 @@ function PlayerControls(props: Props) {
|
|||
</button>
|
||||
</Tooltip>
|
||||
<div className="p-1 border-l border-r bg-active-blue-border border-active-blue-border">
|
||||
<OutsideClickDetectingDiv onClickOutside={handleClickOutside}>
|
||||
<Tooltip
|
||||
open={showTooltip}
|
||||
interactive
|
||||
// @ts-ignore
|
||||
theme="nopadding"
|
||||
animation="none"
|
||||
duration={0}
|
||||
className="cursor-pointer select-none"
|
||||
distance={20}
|
||||
html={
|
||||
<OutsideClickDetectingDiv onClickOutside={handleClickOutside}>
|
||||
<Popover
|
||||
// open={showTooltip}
|
||||
// interactive
|
||||
// @ts-ignore
|
||||
theme="nopadding"
|
||||
animation="none"
|
||||
duration={0}
|
||||
className="cursor-pointer select-none"
|
||||
distance={20}
|
||||
render={() => (
|
||||
<div className="flex flex-col bg-white border border-borderColor-gray-light-shade text-figmaColors-text-primary rounded">
|
||||
<div className="font-semibold py-2 px-4 w-full text-left">
|
||||
Jump <span className="text-disabled-text">(Secs)</span>
|
||||
|
|
@ -141,19 +141,19 @@ function PlayerControls(props: Props) {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div onClick={toggleTooltip} ref={skipRef}>
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip disabled={showTooltip} title="Set default skip duration">
|
||||
{currentInterval}s
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
>
|
||||
<div onClick={toggleTooltip} ref={skipRef}>
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip disabled={showTooltip} title="Set default skip duration">
|
||||
{currentInterval}s
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Popover>
|
||||
</OutsideClickDetectingDiv>
|
||||
</div>
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip title="Forward 10s" delay={0} position="top">
|
||||
<Tooltip title="Forward 10s" position="top">
|
||||
<button
|
||||
ref={arrowForwardRef}
|
||||
className="h-full hover:border-active-blue-border focus:border focus:border-blue border-borderColor-transparent"
|
||||
|
|
@ -173,7 +173,7 @@ function PlayerControls(props: Props) {
|
|||
<div className="flex items-center">
|
||||
<div className="mx-2" />
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip title="Control play back speed (↑↓)" delay={0} position="top">
|
||||
<Tooltip title="Control play back speed (↑↓)" placement="top">
|
||||
<button
|
||||
ref={speedRef}
|
||||
className={cn(styles.speedButton, 'focus:border focus:border-blue')}
|
||||
|
|
@ -185,10 +185,10 @@ function PlayerControls(props: Props) {
|
|||
</Tooltip>
|
||||
<div className="mx-2" />
|
||||
<button
|
||||
className={cn(
|
||||
styles.skipIntervalButton,
|
||||
{ [styles.withCheckIcon]: skip, [styles.active]: skip },
|
||||
)}
|
||||
className={cn(styles.skipIntervalButton, {
|
||||
[styles.withCheckIcon]: skip,
|
||||
[styles.active]: skip,
|
||||
})}
|
||||
onClick={toggleSkip}
|
||||
data-disabled={disabled}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
//@ts-nocheck
|
||||
import React from 'react';
|
||||
import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/StatedScreen';
|
||||
import cn from 'classnames';
|
||||
import stl from './Marker.module.css';
|
||||
import { activeTarget } from 'Player';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { Tooltip } from 'UI';
|
||||
|
||||
interface Props {
|
||||
target: MarkedTarget;
|
||||
|
|
@ -17,23 +16,17 @@ export default function Marker({ target, active }: Props) {
|
|||
left: `${target.boundingRect.left}px`,
|
||||
width: `${target.boundingRect.width}px`,
|
||||
height: `${target.boundingRect.height}px`,
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className={cn(stl.marker, { [stl.active]: active })} style={style} onClick={() => activeTarget(target.index)}>
|
||||
<div
|
||||
className={cn(stl.marker, { [stl.active]: active })}
|
||||
style={style}
|
||||
onClick={() => activeTarget(target.index)}
|
||||
>
|
||||
<div className={stl.index}>{target.index + 1}</div>
|
||||
{/* @ts-expect-error Tooltip doesn't have children property */}
|
||||
<Tooltip
|
||||
open={active}
|
||||
arrow
|
||||
sticky
|
||||
distance={15}
|
||||
html={(
|
||||
<div>{target.count} Clicks</div>
|
||||
)}
|
||||
trigger="mouseenter"
|
||||
>
|
||||
<Tooltip open={active} delay={0} title={<div>{target.count} Clicks</div>}>
|
||||
<div className="absolute inset-0"></div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ interface Props {
|
|||
export default function SessionInfoItem(props: Props) {
|
||||
const { label, icon, value, comp, isLast = false } = props
|
||||
return (
|
||||
<div className={cn("flex items-center w-full py-2", {'border-b' : !isLast})}>
|
||||
<div className={cn("flex items-center w-full py-2 color-gray-dark", {'border-b' : !isLast})}>
|
||||
<div className="px-2 capitalize" style={{ width: '30px' }}>
|
||||
{ icon && <Icon name={icon} size="16" /> }
|
||||
{ comp && comp }
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
selectStorageListNow,
|
||||
selectStorageList,
|
||||
} from 'Player/store';
|
||||
import { JSONTree, NoContent } from 'UI';
|
||||
import { JSONTree, NoContent, Tooltip } from 'UI';
|
||||
import { formatMs } from 'App/date';
|
||||
import { diff } from 'deep-diff';
|
||||
import { jump } from 'Player';
|
||||
|
|
@ -17,7 +17,6 @@ import BottomBlock from '../BottomBlock/index';
|
|||
import DiffRow from './DiffRow';
|
||||
import cn from 'classnames';
|
||||
import stl from './storage.module.css';
|
||||
import { Tooltip } from 'react-tippy'
|
||||
|
||||
// const STATE = 'STATE';
|
||||
// const DIFF = 'DIFF';
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import React from 'react';
|
||||
import { Icon, Button } from 'UI';
|
||||
import { Icon, Tooltip } from 'UI';
|
||||
import Autoplay from './Autoplay';
|
||||
import Bookmark from 'Shared/Bookmark';
|
||||
import SharePopup from '../shared/SharePopup/SharePopup';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import Issues from './Issues/Issues';
|
||||
import NotePopup from './components/NotePopup';
|
||||
import { connectPlayer, pause } from 'Player';
|
||||
|
|
@ -46,14 +45,7 @@ function SubHeader(props) {
|
|||
}}
|
||||
>
|
||||
<Icon size="20" name="event/link" className="mr-1" />
|
||||
<Tooltip
|
||||
delay={0}
|
||||
arrow
|
||||
animation="fade"
|
||||
hideOnClick={false}
|
||||
position="bottom center"
|
||||
title={isCopied ? 'URL Copied to clipboard' : 'Click to copy'}
|
||||
>
|
||||
<Tooltip title={isCopied ? 'URL Copied to clipboard' : 'Click to copy'}>
|
||||
{location}
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { Tooltip } from 'UI';
|
||||
|
||||
const withCopy = (WrappedComponent: React.ComponentType) => {
|
||||
const ComponentWithCopy = (props: any) => {
|
||||
|
|
@ -15,7 +15,7 @@ const withCopy = (WrappedComponent: React.ComponentType) => {
|
|||
};
|
||||
return (
|
||||
<div onClick={() => copyToClipboard(value)} className="w-fit">
|
||||
<Tooltip delay={0} arrow animation="fade" hideOnClick={false} title={copied ? tooltip : 'Click to copy'}>
|
||||
<Tooltip title={copied ? tooltip : 'Click to copy'}>
|
||||
<WrappedComponent {...props} copyToClipboard={copyToClipboard} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { Tooltip } from 'UI';
|
||||
import copy from 'copy-to-clipboard';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -17,14 +17,7 @@ function CopyText(props: Props) {
|
|||
setTimeout(() => setIsCopied(false), 5000);
|
||||
};
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Tooltip
|
||||
delay={0}
|
||||
arrow
|
||||
animation="fade"
|
||||
hideOnClick={false}
|
||||
title={isCopied ? afterLabel : label}
|
||||
>
|
||||
<Tooltip delay={0} title={isCopied ? afterLabel : label}>
|
||||
<span onClick={onClick}>{children}</span>
|
||||
</Tooltip>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { Tooltip } from 'UI';
|
||||
|
||||
export const FEATURE_KEYS = {
|
||||
XRAY: 'featureViewed'
|
||||
|
|
@ -16,7 +16,7 @@ export default function GuidePopup({ children, title, description }: IProps) {
|
|||
return (
|
||||
// @ts-ignore
|
||||
<Tooltip
|
||||
html={
|
||||
title={
|
||||
<div>
|
||||
<div className="font-bold">
|
||||
{title}
|
||||
|
|
@ -26,10 +26,10 @@ export default function GuidePopup({ children, title, description }: IProps) {
|
|||
</div>
|
||||
</div>
|
||||
}
|
||||
distance={30}
|
||||
theme={'light'}
|
||||
// distance={30}
|
||||
// theme={'light'}
|
||||
open={true}
|
||||
arrow={true}
|
||||
// arrow={true}
|
||||
>
|
||||
{children}
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { MouseEvent, useState } from 'react';
|
|||
import cn from 'classnames';
|
||||
import { Icon, Input } from 'UI';
|
||||
import { List } from 'immutable';
|
||||
import { confirm, Popup } from 'UI';
|
||||
import { confirm, Tooltip } from 'UI';
|
||||
import { applySavedSearch, remove, editSavedSearch } from 'Duck/search';
|
||||
import { connect } from 'react-redux';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
|
|
@ -18,9 +18,10 @@ interface ITooltipIcon {
|
|||
function TooltipIcon(props: ITooltipIcon) {
|
||||
return (
|
||||
<div onClick={(e) => props.onClick(e)}>
|
||||
<Popup content={props.title} hideOnClick={true}>
|
||||
<Tooltip title={props.title}>
|
||||
{/* @ts-ignore */}
|
||||
<Icon size="16" name={props.name} color="main" />
|
||||
</Popup>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import { CountryFlag, Avatar, TextEllipsis, Label, Icon } from 'UI';
|
||||
import { CountryFlag, Avatar, TextEllipsis, Label, Icon, Tooltip } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { durationFormatted, formatTimeOrDate } from 'App/date';
|
||||
|
|
@ -12,7 +12,6 @@ import PlayLink from './PlayLink';
|
|||
import ErrorBars from './ErrorBars';
|
||||
import { assist as assistRoute, liveSession, sessions as sessionsRoute, isRoute } from 'App/routes';
|
||||
import { capitalize } from 'App/utils';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
|
||||
const ASSIST_ROUTE = assistRoute();
|
||||
const ASSIST_LIVE_SESSION = liveSession();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { useModal } from 'App/components/Modal';
|
||||
import React from 'react';
|
||||
import SessionSettings from 'Shared/SessionSettings';
|
||||
import { Button } from 'UI';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import { Button, Tooltip } from 'UI';
|
||||
|
||||
function SessionSettingButton(props: any) {
|
||||
const { showModal } = useModal();
|
||||
|
|
@ -13,8 +12,7 @@ function SessionSettingButton(props: any) {
|
|||
|
||||
return (
|
||||
<div className="cursor-pointer ml-4" onClick={handleClick}>
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip title="Session Settings" unmountHTMLWhenHide>
|
||||
<Tooltip title="Session Settings">
|
||||
<Button icon="sliders" variant="text" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,15 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { toast } from 'react-toastify';
|
||||
import { connectPlayer } from 'Player';
|
||||
import withRequest from 'HOCs/withRequest';
|
||||
import { Icon, Button } from 'UI';
|
||||
import { Icon, Button, Popover } from 'UI';
|
||||
import styles from './sharePopup.module.css';
|
||||
import IntegrateSlackButton from '../IntegrateSlackButton/IntegrateSlackButton';
|
||||
import SessionCopyLink from './SessionCopyLink';
|
||||
import Select from 'Shared/Select';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
import cn from 'classnames';
|
||||
import { fetchList, init } from 'Duck/integrations/slack';
|
||||
import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv';
|
||||
import { fetchList } from 'Duck/integrations/slack';
|
||||
|
||||
// @connectPlayer((state) => ({
|
||||
// time: state.time,
|
||||
// }))
|
||||
@connect(
|
||||
(state) => ({
|
||||
channels: state.getIn(['slack', 'list']),
|
||||
|
|
@ -75,84 +69,67 @@ export default class SharePopup extends React.PureComponent {
|
|||
const options = channels
|
||||
.map(({ webhookId, name }) => ({ value: webhookId, label: name }))
|
||||
.toJS();
|
||||
return (
|
||||
<OutsideClickDetectingDiv
|
||||
className={cn('relative flex items-center w-full')}
|
||||
onClickOutside={() => {
|
||||
this.setState({ isOpen: false });
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
open={isOpen}
|
||||
theme="light"
|
||||
interactive
|
||||
position="bottom"
|
||||
unmountHTMLWhenHide
|
||||
useContext
|
||||
arrow
|
||||
trigger="click"
|
||||
shown={this.handleOpen}
|
||||
className="w-full"
|
||||
// beforeHidden={this.handleClose}
|
||||
html={
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.header}>
|
||||
<div className={cn(styles.title, 'text-lg')}>Share this session link to Slack</div>
|
||||
</div>
|
||||
{options.length === 0 ? (
|
||||
<>
|
||||
<div className={styles.body}>
|
||||
<IntegrateSlackButton />
|
||||
</div>
|
||||
{showCopyLink && (
|
||||
<div className={styles.footer}>
|
||||
<SessionCopyLink />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div>
|
||||
<div className={styles.body}>
|
||||
<textarea
|
||||
name="message"
|
||||
id="message"
|
||||
cols="30"
|
||||
rows="4"
|
||||
resize="none"
|
||||
onChange={this.editMessage}
|
||||
value={comment}
|
||||
placeholder="Add Message (Optional)"
|
||||
className="p-4"
|
||||
/>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<Select
|
||||
options={options}
|
||||
defaultValue={channelId}
|
||||
onChange={this.changeChannel}
|
||||
className="mr-4"
|
||||
/>
|
||||
<div>
|
||||
<Button onClick={this.share} variant="primary">
|
||||
<div className="flex items-center">
|
||||
<Icon name="integrations/slack-bw" size="18" marginRight="10" />
|
||||
{loading ? 'Sending...' : 'Send'}
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
return (
|
||||
<Popover
|
||||
render={() => (
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.header}>
|
||||
<div className={cn(styles.title, 'text-lg')}>Share this session link to Slack</div>
|
||||
</div>
|
||||
{options.length === 0 ? (
|
||||
<>
|
||||
<div className={styles.body}>
|
||||
<IntegrateSlackButton />
|
||||
</div>
|
||||
{showCopyLink && (
|
||||
<div className={styles.footer}>
|
||||
<SessionCopyLink />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div>
|
||||
<div className={styles.body}>
|
||||
<textarea
|
||||
name="message"
|
||||
id="message"
|
||||
cols="30"
|
||||
rows="4"
|
||||
resize="none"
|
||||
onChange={this.editMessage}
|
||||
value={comment}
|
||||
placeholder="Add Message (Optional)"
|
||||
className="p-4"
|
||||
/>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<Select
|
||||
options={options}
|
||||
defaultValue={channelId}
|
||||
onChange={this.changeChannel}
|
||||
className="mr-4"
|
||||
/>
|
||||
<div>
|
||||
<Button onClick={this.share} variant="primary">
|
||||
<div className="flex items-center">
|
||||
<Icon name="integrations/slack-bw" size="18" marginRight="10" />
|
||||
{loading ? 'Sending...' : 'Send'}
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div onClick={this.onClickHandler} className="h-full w-full p-3">{trigger}</div>
|
||||
</Tooltip>
|
||||
</OutsideClickDetectingDiv>
|
||||
<div className={styles.footer}>
|
||||
<SessionCopyLink />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<div className="p-3 w-full">{trigger}</div>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import stl from './xrayButton.module.css';
|
||||
import cn from 'classnames';
|
||||
import { Popup } from 'UI';
|
||||
import { Tooltip } from 'UI';
|
||||
import GuidePopup, { FEATURE_KEYS } from 'Shared/GuidePopup';
|
||||
import { Controls as Player } from 'Player';
|
||||
import { INDEXES } from 'App/constants/zindex';
|
||||
|
|
@ -63,14 +63,14 @@ function XRayButton(props: Props) {
|
|||
></div>
|
||||
</GuidePopup>
|
||||
) : (
|
||||
<Popup content="Get a quick overview on the issues in this session." disabled={isActive}>
|
||||
<Tooltip title="Get a quick overview on the issues in this session." disabled={isActive}>
|
||||
<button
|
||||
className={cn(stl.wrapper, { [stl.default]: !isActive, [stl.active]: isActive })}
|
||||
onClick={onClick}
|
||||
>
|
||||
<span className="z-1">X-RAY</span>
|
||||
</button>
|
||||
</Popup>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Icon } from 'UI';
|
||||
import { Icon, Popover } from 'UI';
|
||||
import styles from './itemMenu.module.css';
|
||||
import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv';
|
||||
import cn from 'classnames';
|
||||
|
||||
interface Item {
|
||||
|
|
@ -58,71 +57,69 @@ export default class ItemMenu extends React.PureComponent<Props> {
|
|||
const parentStyles = label ? 'rounded px-2 py-2 hover:bg-gray-light' : '';
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<OutsideClickDetectingDiv onClickOutside={this.closeMenu}>
|
||||
<Popover
|
||||
render={() => (
|
||||
<div
|
||||
onClick={this.toggleMenu}
|
||||
className={cn(
|
||||
'flex items-center cursor-pointer select-none hover rounded-full',
|
||||
!this.props.flat ? parentStyles : '',
|
||||
{ 'bg-gray-light': !this.props.flat && displayed && label }
|
||||
)}
|
||||
className={cn(styles.menu, { [styles.menuDim]: !bold })}
|
||||
// style={{
|
||||
// top: this.props.flat ? 24 : undefined,
|
||||
// }}
|
||||
// data-displayed={displayed}
|
||||
>
|
||||
{label && (
|
||||
<span
|
||||
className={cn(
|
||||
'mr-1',
|
||||
bold ? 'font-medium color-gray-darkest' : 'color-gray-medium'
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
)}
|
||||
{this.props.flat ? null : (
|
||||
<div
|
||||
ref={(ref) => {
|
||||
this.menuBtnRef = ref;
|
||||
}}
|
||||
className={cn('rounded-full flex items-center justify-center', {
|
||||
'bg-gray-light': displayed,
|
||||
'w-10 h-10': !label,
|
||||
})}
|
||||
role="button"
|
||||
>
|
||||
<Icon name="ellipsis-v" size="16" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</OutsideClickDetectingDiv>
|
||||
<div
|
||||
className={cn(styles.menu, { [styles.menuDim]: !bold })}
|
||||
style={{
|
||||
top: this.props.flat ? 24 : undefined,
|
||||
}}
|
||||
data-displayed={displayed}
|
||||
>
|
||||
{items
|
||||
.filter(({ hidden }) => !hidden)
|
||||
.map(({ onClick, text, icon, disabled = false }) => (
|
||||
<div
|
||||
key={text}
|
||||
onClick={!disabled ? this.onClick(onClick) : () => {}}
|
||||
className={disabled ? 'cursor-not-allowed' : ''}
|
||||
role="menuitem"
|
||||
>
|
||||
<div className={cn(styles.menuItem, 'text-neutral-700', { disabled: disabled })}>
|
||||
{icon && (
|
||||
<div className={styles.iconWrapper}>
|
||||
{/* @ts-ignore */}
|
||||
<Icon name={icon} size="13" color="gray-dark" />
|
||||
</div>
|
||||
)}
|
||||
<div>{text}</div>
|
||||
{items
|
||||
.filter(({ hidden }) => !hidden)
|
||||
.map(({ onClick, text, icon, disabled = false }) => (
|
||||
<div
|
||||
key={text}
|
||||
onClick={!disabled ? this.onClick(onClick) : () => {}}
|
||||
className={disabled ? 'cursor-not-allowed' : ''}
|
||||
role="menuitem"
|
||||
>
|
||||
<div className={cn(styles.menuItem, 'text-neutral-700', { disabled: disabled })}>
|
||||
{icon && (
|
||||
<div className={styles.iconWrapper}>
|
||||
{/* @ts-ignore */}
|
||||
<Icon name={icon} size="13" color="gray-dark" />
|
||||
</div>
|
||||
)}
|
||||
<div>{text}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<div
|
||||
// onClick={this.toggleMenu}
|
||||
className={cn(
|
||||
'flex items-center cursor-pointer select-none hover rounded-full',
|
||||
!this.props.flat ? parentStyles : '',
|
||||
{ 'bg-gray-light': !this.props.flat && displayed && label }
|
||||
)}
|
||||
>
|
||||
{label && (
|
||||
<span
|
||||
className={cn('mr-1', bold ? 'font-medium color-gray-darkest' : 'color-gray-medium')}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
)}
|
||||
{this.props.flat ? null : (
|
||||
<div
|
||||
ref={(ref) => {
|
||||
this.menuBtnRef = ref;
|
||||
}}
|
||||
className={cn('rounded-full flex items-center justify-center', {
|
||||
'bg-gray-light': displayed,
|
||||
'w-10 h-10': !label,
|
||||
})}
|
||||
role="button"
|
||||
>
|
||||
<Icon name="ellipsis-v" size="16" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@
|
|||
|
||||
white-space: nowrap;
|
||||
z-index: 20;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 37px;
|
||||
/* position: absolute; */
|
||||
/* right: 0px; */
|
||||
/* top: 37px; */
|
||||
min-width: 150px;
|
||||
background-color: $white;
|
||||
border-radius: 3px;
|
||||
|
|
|
|||
86
frontend/app/components/ui/Popover/Popover.tsx
Normal file
86
frontend/app/components/ui/Popover/Popover.tsx
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import React, { cloneElement, useMemo, useState } from 'react';
|
||||
import {
|
||||
Placement,
|
||||
offset,
|
||||
flip,
|
||||
shift,
|
||||
autoUpdate,
|
||||
useFloating,
|
||||
useInteractions,
|
||||
useRole,
|
||||
useDismiss,
|
||||
useId,
|
||||
useClick,
|
||||
FloatingFocusManager,
|
||||
} from '@floating-ui/react-dom-interactions';
|
||||
import { mergeRefs } from 'react-merge-refs';
|
||||
import { INDEXES } from 'App/constants/zindex';
|
||||
|
||||
interface Props {
|
||||
render: (data: { close: () => void; labelId: string; descriptionId: string }) => React.ReactNode;
|
||||
placement?: Placement;
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
const Popover = ({ children, render, placement }: Props) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { x, y, reference, floating, strategy, context } = useFloating({
|
||||
open,
|
||||
onOpenChange: setOpen,
|
||||
middleware: [offset(5), flip(), shift()],
|
||||
placement,
|
||||
whileElementsMounted: autoUpdate,
|
||||
});
|
||||
|
||||
const id = useId();
|
||||
const labelId = `${id}-label`;
|
||||
const descriptionId = `${id}-description`;
|
||||
|
||||
const { getReferenceProps, getFloatingProps } = useInteractions([
|
||||
useClick(context),
|
||||
useRole(context),
|
||||
useDismiss(context),
|
||||
]);
|
||||
|
||||
// Preserve the consumer's ref
|
||||
const ref = useMemo(() => mergeRefs([reference, (children as any).ref]), [reference, children]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{cloneElement(children, getReferenceProps({ ref, ...children.props }))}
|
||||
{open && (
|
||||
<FloatingFocusManager
|
||||
context={context}
|
||||
modal={false}
|
||||
order={['reference', 'content']}
|
||||
returnFocus={false}
|
||||
>
|
||||
<div
|
||||
ref={floating}
|
||||
className="rounded border shadow"
|
||||
style={{
|
||||
position: strategy,
|
||||
top: y ?? 0,
|
||||
left: x ?? 0,
|
||||
zIndex: INDEXES.TOOLTIP
|
||||
}}
|
||||
aria-labelledby={labelId}
|
||||
aria-describedby={descriptionId}
|
||||
{...getFloatingProps()}
|
||||
>
|
||||
{render({
|
||||
labelId,
|
||||
descriptionId,
|
||||
close: () => {
|
||||
setOpen(false);
|
||||
},
|
||||
})}
|
||||
</div>
|
||||
</FloatingFocusManager>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Popover;
|
||||
1
frontend/app/components/ui/Popover/index.ts
Normal file
1
frontend/app/components/ui/Popover/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './Popover';
|
||||
121
frontend/app/components/ui/Tooltip/FloatingTooltip.tsx
Normal file
121
frontend/app/components/ui/Tooltip/FloatingTooltip.tsx
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import * as React from 'react';
|
||||
import { mergeRefs } from 'react-merge-refs';
|
||||
import {
|
||||
useFloating,
|
||||
autoUpdate,
|
||||
offset,
|
||||
flip,
|
||||
shift,
|
||||
useHover,
|
||||
useFocus,
|
||||
useDismiss,
|
||||
useRole,
|
||||
useInteractions,
|
||||
FloatingPortal,
|
||||
} from '@floating-ui/react-dom-interactions';
|
||||
import type { Placement } from '@floating-ui/react-dom-interactions';
|
||||
import { INDEXES } from 'App/constants/zindex';
|
||||
|
||||
export function useTooltipState({
|
||||
disabled = false,
|
||||
initialOpen = false,
|
||||
placement = 'top',
|
||||
delay,
|
||||
}: {
|
||||
disabled?: boolean;
|
||||
initialOpen?: boolean;
|
||||
placement?: Placement;
|
||||
delay?: number;
|
||||
} = {}) {
|
||||
const [open, setOpen] = React.useState(initialOpen);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (disabled) {
|
||||
setOpen(false);
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
const data = useFloating({
|
||||
placement,
|
||||
open,
|
||||
onOpenChange: setOpen,
|
||||
whileElementsMounted: autoUpdate,
|
||||
middleware: [offset(5), flip(), shift()],
|
||||
});
|
||||
|
||||
const context = data.context;
|
||||
|
||||
const hover = useHover(context, { move: false, restMs: delay, enabled: !disabled });
|
||||
const focus = useFocus(context);
|
||||
const dismiss = useDismiss(context);
|
||||
const role = useRole(context, { role: 'tooltip' });
|
||||
|
||||
const interactions = useInteractions([hover, focus, dismiss, role]);
|
||||
|
||||
return React.useMemo(
|
||||
() => ({
|
||||
open,
|
||||
setOpen,
|
||||
...interactions,
|
||||
...data,
|
||||
}),
|
||||
[open, setOpen, interactions, data]
|
||||
);
|
||||
}
|
||||
|
||||
type TooltipState = ReturnType<typeof useTooltipState>;
|
||||
|
||||
export const TooltipAnchor = React.forwardRef<
|
||||
HTMLElement,
|
||||
React.HTMLProps<HTMLElement> & {
|
||||
state: TooltipState;
|
||||
asChild?: boolean;
|
||||
}
|
||||
>(function TooltipAnchor({ children, state, asChild = false, ...props }, propRef) {
|
||||
const childrenRef = (children as any).ref;
|
||||
const ref = React.useMemo(
|
||||
() => mergeRefs([state.reference, propRef, childrenRef]),
|
||||
[state.reference, propRef, childrenRef]
|
||||
);
|
||||
|
||||
// `asChild` allows the user to pass any element as the anchor
|
||||
if (asChild && React.isValidElement(children)) {
|
||||
return React.cloneElement(
|
||||
children,
|
||||
state.getReferenceProps({ ref, ...props, ...children.props })
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button ref={ref} {...state.getReferenceProps(props)}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
||||
export const FloatingTooltip = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLProps<HTMLDivElement> & { state: TooltipState }
|
||||
>(function Tooltip({ state, ...props }, propRef) {
|
||||
const ref = React.useMemo(() => mergeRefs([state.floating, propRef]), [state.floating, propRef]);
|
||||
|
||||
return (
|
||||
<FloatingPortal>
|
||||
{state.open && (
|
||||
<div
|
||||
ref={ref}
|
||||
style={{
|
||||
position: state.strategy,
|
||||
top: state.y ?? 0,
|
||||
left: state.x ?? 0,
|
||||
visibility: state.x == null ? 'hidden' : 'visible',
|
||||
transition: 'opacity 1s',
|
||||
zIndex: INDEXES.TOOLTIP,
|
||||
...props.style,
|
||||
}}
|
||||
{...state.getFloatingProps(props)}
|
||||
/>
|
||||
)}
|
||||
</FloatingPortal>
|
||||
);
|
||||
});
|
||||
|
|
@ -1,51 +1,31 @@
|
|||
import React from 'react';
|
||||
import { Popup } from 'UI';
|
||||
import { useTooltipState, TooltipAnchor, FloatingTooltip } from './FloatingTooltip';
|
||||
import type { Placement } from '@floating-ui/react-dom-interactions';
|
||||
import cn from 'classnames';
|
||||
|
||||
interface Props {
|
||||
timeout: number
|
||||
position: string
|
||||
tooltip: string
|
||||
trigger: React.ReactNode
|
||||
title?: any;
|
||||
children: any;
|
||||
disabled?: boolean;
|
||||
open?: boolean;
|
||||
placement?: Placement;
|
||||
className?: string;
|
||||
delay?: number;
|
||||
}
|
||||
function Tooltip(props: Props) {
|
||||
const { title, disabled = false, open = false, placement, className = '', delay = 500 } = props;
|
||||
const state = useTooltipState({ disabled: disabled, placement, delay });
|
||||
return (
|
||||
<>
|
||||
<TooltipAnchor state={state}>{props.children}</TooltipAnchor>
|
||||
<FloatingTooltip
|
||||
state={state}
|
||||
className={cn('bg-gray-darkest color-white rounded py-1 px-2 animate-fade', className)}
|
||||
>
|
||||
{title}
|
||||
</FloatingTooltip>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default class Tooltip extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
timeout: 500,
|
||||
}
|
||||
state = {
|
||||
open: false,
|
||||
}
|
||||
mouseOver = false
|
||||
onMouseEnter = () => {
|
||||
this.mouseOver = true;
|
||||
setTimeout(() => {
|
||||
if (this.mouseOver) this.setState({ open: true });
|
||||
}, this.props.timeout)
|
||||
}
|
||||
onMouseLeave = () => {
|
||||
this.mouseOver = false;
|
||||
this.setState({
|
||||
open: false,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { trigger, tooltip, position } = this.props;
|
||||
const { open } = this.state;
|
||||
return (
|
||||
<Popup
|
||||
open={open}
|
||||
content={tooltip}
|
||||
disabled={!tooltip}
|
||||
position={position}
|
||||
>
|
||||
<span //TODO: no wrap component around
|
||||
onMouseEnter={ this.onMouseEnter }
|
||||
onMouseLeave={ this.onMouseLeave }
|
||||
>
|
||||
{ trigger }
|
||||
</span>
|
||||
</Popup>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default Tooltip;
|
||||
|
|
|
|||
47
frontend/app/components/ui/Tooltip/Tooltip.tsx_
Normal file
47
frontend/app/components/ui/Tooltip/Tooltip.tsx_
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import React from 'react';
|
||||
import { Popup } from 'UI';
|
||||
import { useTooltipState, TooltipAnchor, FloatingTooltip } from './FloatingTooltip';
|
||||
|
||||
interface Props {
|
||||
timeout: number;
|
||||
position: string;
|
||||
tooltip: string;
|
||||
trigger: React.ReactNode;
|
||||
}
|
||||
|
||||
export default class Tooltip extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
timeout: 500,
|
||||
};
|
||||
state = {
|
||||
open: false,
|
||||
};
|
||||
mouseOver = false;
|
||||
onMouseEnter = () => {
|
||||
this.mouseOver = true;
|
||||
setTimeout(() => {
|
||||
if (this.mouseOver) this.setState({ open: true });
|
||||
}, this.props.timeout);
|
||||
};
|
||||
onMouseLeave = () => {
|
||||
this.mouseOver = false;
|
||||
this.setState({
|
||||
open: false,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { trigger, tooltip, position } = this.props;
|
||||
const { open } = this.state;
|
||||
return (
|
||||
<Popup open={open} content={tooltip} disabled={!tooltip} position={position}>
|
||||
<span //TODO: no wrap component around
|
||||
onMouseEnter={this.onMouseEnter}
|
||||
onMouseLeave={this.onMouseLeave}
|
||||
>
|
||||
{trigger}
|
||||
</span>
|
||||
</Popup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -56,4 +56,5 @@ export { default as Toggler } from './Toggler';
|
|||
export { default as Input } from './Input';
|
||||
export { default as Form } from './Form';
|
||||
export { default as Modal } from './Modal';
|
||||
export { default as Message } from './Message';
|
||||
export { default as Message } from './Message';
|
||||
export { default as Popover } from './Popover';
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@ export const INDEXES = {
|
|||
PLAYER_REQUEST_WINDOW: 10,
|
||||
BUG_REPORT_PICKER: 19,
|
||||
BUG_REPORT: 20,
|
||||
POPUP_GUIDE_BG: 99998,
|
||||
POPUP_GUIDE_BTN: 99999,
|
||||
}
|
||||
POPUP_GUIDE_BG: 99997,
|
||||
POPUP_GUIDE_BTN: 99998,
|
||||
TOOLTIP: 99999,
|
||||
};
|
||||
|
||||
export const getHighest = () => {
|
||||
const allIndexes = Object.values(INDEXES)
|
||||
return allIndexes[allIndexes.length - 1] + 1
|
||||
}
|
||||
const allIndexes = Object.values(INDEXES);
|
||||
return allIndexes[allIndexes.length - 1] + 1;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -334,4 +334,17 @@ p {
|
|||
#ccc 2px,
|
||||
#ccc 4px
|
||||
);
|
||||
}
|
||||
|
||||
.animate-fade {
|
||||
animation: fade 0.1s cubic-bezier(0.4, 0, 0.6, 1);
|
||||
}
|
||||
|
||||
@keyframes fade {
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
"postinstall": "yarn gen:icons && yarn gen:colors"
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom-interactions": "^0.10.3",
|
||||
"@sentry/browser": "^5.21.1",
|
||||
"@svg-maps/world": "^1.0.1",
|
||||
"@svgr/webpack": "^6.2.1",
|
||||
|
|
@ -51,6 +52,7 @@
|
|||
"react-highlight": "^0.14.0",
|
||||
"react-json-view": "^1.21.3",
|
||||
"react-lazyload": "^3.2.0",
|
||||
"react-merge-refs": "^2.0.1",
|
||||
"react-redux": "^5.1.2",
|
||||
"react-router": "^5.3.3",
|
||||
"react-router-dom": "^5.3.3",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue