Feat : Introduced Delay Options for Tooltip (#5766)
Fixes https://github.com/twentyhq/twenty/issues/5727 --------- Co-authored-by: Rushikesh Tarapure <rushikeshtarapure@gofynd.com> Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
committed by
GitHub
parent
86f95c0870
commit
bc8c895b0e
@ -1,6 +1,5 @@
|
|||||||
import { Tooltip } from 'react-tooltip';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { Avatar } from 'twenty-ui';
|
import { AppTooltip, Avatar } from 'twenty-ui';
|
||||||
|
|
||||||
import { Comment } from '@/activities/types/Comment';
|
import { Comment } from '@/activities/types/Comment';
|
||||||
import {
|
import {
|
||||||
@ -42,21 +41,6 @@ const StyledDate = styled.div`
|
|||||||
margin-left: ${({ theme }) => theme.spacing(1)};
|
margin-left: ${({ theme }) => theme.spacing(1)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTooltip = styled(Tooltip)`
|
|
||||||
background-color: ${({ theme }) => theme.background.primary};
|
|
||||||
|
|
||||||
box-shadow: 0px 2px 4px 3px
|
|
||||||
${({ theme }) => theme.background.transparent.light};
|
|
||||||
|
|
||||||
box-shadow: 2px 4px 16px 6px
|
|
||||||
${({ theme }) => theme.background.transparent.light};
|
|
||||||
|
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
|
||||||
|
|
||||||
opacity: 1;
|
|
||||||
padding: 8px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
type CommentHeaderProps = {
|
type CommentHeaderProps = {
|
||||||
comment: Pick<Comment, 'id' | 'author' | 'createdAt'>;
|
comment: Pick<Comment, 'id' | 'author' | 'createdAt'>;
|
||||||
actionBar?: React.ReactNode;
|
actionBar?: React.ReactNode;
|
||||||
@ -87,7 +71,7 @@ export const CommentHeader = ({ comment, actionBar }: CommentHeaderProps) => {
|
|||||||
<StyledDate id={`id-${commentId}`}>
|
<StyledDate id={`id-${commentId}`}>
|
||||||
{beautifiedCreatedAt}
|
{beautifiedCreatedAt}
|
||||||
</StyledDate>
|
</StyledDate>
|
||||||
<StyledTooltip
|
<AppTooltip
|
||||||
anchorSelect={`#id-${commentId}`}
|
anchorSelect={`#id-${commentId}`}
|
||||||
content={exactCreatedAt}
|
content={exactCreatedAt}
|
||||||
clickable
|
clickable
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
import { Tooltip } from 'react-tooltip';
|
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { Avatar, IconCheckbox, IconNotes } from 'twenty-ui';
|
import { AppTooltip, Avatar, IconCheckbox, IconNotes } from 'twenty-ui';
|
||||||
|
|
||||||
import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
|
import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
|
||||||
import { timelineActivityWithoutTargetsFamilyState } from '@/activities/timeline/states/timelineActivityWithoutTargetsFamilyState';
|
import { timelineActivityWithoutTargetsFamilyState } from '@/activities/timeline/states/timelineActivityWithoutTargetsFamilyState';
|
||||||
@ -109,21 +108,6 @@ const StyledVerticalLine = styled.div`
|
|||||||
width: 2px;
|
width: 2px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTooltip = styled(Tooltip)`
|
|
||||||
background-color: ${({ theme }) => theme.background.primary};
|
|
||||||
|
|
||||||
box-shadow: 0px 2px 4px 3px
|
|
||||||
${({ theme }) => theme.background.transparent.light};
|
|
||||||
|
|
||||||
box-shadow: 2px 4px 16px 6px
|
|
||||||
${({ theme }) => theme.background.transparent.light};
|
|
||||||
|
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
|
||||||
|
|
||||||
opacity: 1;
|
|
||||||
padding: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledTimelineItemContainer = styled.div<{ isGap?: boolean }>`
|
const StyledTimelineItemContainer = styled.div<{ isGap?: boolean }>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
@ -217,7 +201,7 @@ export const TimelineActivity = ({
|
|||||||
<StyledItemTitleDate id={`id-${activityForTimeline.id}`}>
|
<StyledItemTitleDate id={`id-${activityForTimeline.id}`}>
|
||||||
{beautifiedCreatedAt}
|
{beautifiedCreatedAt}
|
||||||
</StyledItemTitleDate>
|
</StyledItemTitleDate>
|
||||||
<StyledTooltip
|
<AppTooltip
|
||||||
anchorSelect={`#id-${activityForTimeline.id}`}
|
anchorSelect={`#id-${activityForTimeline.id}`}
|
||||||
content={exactCreatedAt}
|
content={exactCreatedAt}
|
||||||
clickable
|
clickable
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
import React, { ReactElement, useContext } from 'react';
|
import React, { ReactElement, useContext } from 'react';
|
||||||
import { Tooltip } from 'react-tooltip';
|
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { IconComponent } from 'twenty-ui';
|
import { AppTooltip, IconComponent } from 'twenty-ui';
|
||||||
|
|
||||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||||
import { useFieldFocus } from '@/object-record/record-field/hooks/useFieldFocus';
|
import { useFieldFocus } from '@/object-record/record-field/hooks/useFieldFocus';
|
||||||
@ -55,17 +54,6 @@ const StyledInlineCellBaseContainer = styled.div`
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTooltip = styled(Tooltip)`
|
|
||||||
background-color: ${({ theme }) => theme.background.primary};
|
|
||||||
box-shadow: ${({ theme }) => theme.boxShadow.light};
|
|
||||||
|
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
|
||||||
|
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
|
||||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
|
||||||
padding: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const StyledSkeletonDiv = styled.div`
|
export const StyledSkeletonDiv = styled.div`
|
||||||
height: 24px;
|
height: 24px;
|
||||||
`;
|
`;
|
||||||
@ -141,7 +129,7 @@ export const RecordInlineCellContainer = ({
|
|||||||
)}
|
)}
|
||||||
{/* TODO: Displaying Tooltips on the board is causing performance issues https://react-tooltip.com/docs/examples/render */}
|
{/* TODO: Displaying Tooltips on the board is causing performance issues https://react-tooltip.com/docs/examples/render */}
|
||||||
{!showLabel && !fieldDefinition?.disableTooltip && (
|
{!showLabel && !fieldDefinition?.disableTooltip && (
|
||||||
<StyledTooltip
|
<AppTooltip
|
||||||
anchorSelect={`#${labelId}`}
|
anchorSelect={`#${labelId}`}
|
||||||
content={label}
|
content={label}
|
||||||
clickable
|
clickable
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
import { ChangeEvent, ReactNode, useRef } from 'react';
|
import { ChangeEvent, ReactNode, useRef } from 'react';
|
||||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
||||||
import { Tooltip } from 'react-tooltip';
|
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { Avatar, AvatarType } from 'twenty-ui';
|
import { AppTooltip, Avatar, AvatarType } from 'twenty-ui';
|
||||||
import { v4 as uuidV4 } from 'uuid';
|
import { v4 as uuidV4 } from 'uuid';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -55,17 +54,6 @@ const StyledTitle = styled.div`
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTooltip = styled(Tooltip)`
|
|
||||||
background-color: ${({ theme }) => theme.background.primary};
|
|
||||||
box-shadow: ${({ theme }) => theme.boxShadow.light};
|
|
||||||
|
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
|
||||||
|
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
|
||||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
|
||||||
padding: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledAvatarWrapper = styled.div`
|
const StyledAvatarWrapper = styled.div`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`;
|
`;
|
||||||
@ -153,7 +141,7 @@ export const ShowPageSummaryCard = ({
|
|||||||
Added {beautifiedCreatedAt}
|
Added {beautifiedCreatedAt}
|
||||||
</StyledDate>
|
</StyledDate>
|
||||||
)}
|
)}
|
||||||
<StyledTooltip
|
<AppTooltip
|
||||||
anchorSelect={`#${dateElementId}`}
|
anchorSelect={`#${dateElementId}`}
|
||||||
content={exactCreatedAt}
|
content={exactCreatedAt}
|
||||||
clickable
|
clickable
|
||||||
|
|||||||
@ -10,6 +10,12 @@ export enum TooltipPosition {
|
|||||||
Bottom = 'bottom',
|
Bottom = 'bottom',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum TooltipDelay {
|
||||||
|
noDelay = '0ms',
|
||||||
|
shortDelay = '300ms',
|
||||||
|
mediumDelay = '500ms',
|
||||||
|
}
|
||||||
|
|
||||||
const StyledAppTooltip = styled(Tooltip)`
|
const StyledAppTooltip = styled(Tooltip)`
|
||||||
backdrop-filter: ${({ theme }) => theme.blur.strong};
|
backdrop-filter: ${({ theme }) => theme.blur.strong};
|
||||||
background-color: ${({ theme }) => RGBA(theme.color.gray80, 0.8)};
|
background-color: ${({ theme }) => RGBA(theme.color.gray80, 0.8)};
|
||||||
@ -36,38 +42,51 @@ export type AppTooltipProps = {
|
|||||||
anchorSelect?: string;
|
anchorSelect?: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
delayHide?: number;
|
|
||||||
offset?: number;
|
offset?: number;
|
||||||
noArrow?: boolean;
|
noArrow?: boolean;
|
||||||
isOpen?: boolean;
|
isOpen?: boolean;
|
||||||
place?: PlacesType;
|
place?: PlacesType;
|
||||||
|
delay?: TooltipDelay;
|
||||||
positionStrategy?: PositionStrategy;
|
positionStrategy?: PositionStrategy;
|
||||||
|
clickable?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AppTooltip = ({
|
export const AppTooltip = ({
|
||||||
anchorSelect,
|
anchorSelect,
|
||||||
className,
|
className,
|
||||||
content,
|
content,
|
||||||
delayHide,
|
|
||||||
isOpen,
|
isOpen,
|
||||||
noArrow,
|
noArrow,
|
||||||
offset,
|
offset,
|
||||||
|
delay = TooltipDelay.mediumDelay,
|
||||||
place,
|
place,
|
||||||
positionStrategy,
|
positionStrategy,
|
||||||
children,
|
children,
|
||||||
}: AppTooltipProps) => (
|
clickable,
|
||||||
<StyledAppTooltip
|
}: AppTooltipProps) => {
|
||||||
{...{
|
const delayInMs =
|
||||||
anchorSelect,
|
delay === TooltipDelay.noDelay
|
||||||
className,
|
? 0
|
||||||
content,
|
: delay === TooltipDelay.shortDelay
|
||||||
delayHide,
|
? 300
|
||||||
isOpen,
|
: 500;
|
||||||
noArrow,
|
|
||||||
offset,
|
return (
|
||||||
place,
|
<StyledAppTooltip
|
||||||
positionStrategy,
|
{...{
|
||||||
children,
|
anchorSelect,
|
||||||
}}
|
className,
|
||||||
/>
|
content,
|
||||||
);
|
delayShow: delayInMs,
|
||||||
|
delayHide: delayInMs,
|
||||||
|
isOpen,
|
||||||
|
noArrow,
|
||||||
|
offset,
|
||||||
|
place,
|
||||||
|
positionStrategy,
|
||||||
|
children,
|
||||||
|
clickable,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { styled } from '@linaria/react';
|
|||||||
|
|
||||||
import { THEME_COMMON } from '@ui/theme';
|
import { THEME_COMMON } from '@ui/theme';
|
||||||
|
|
||||||
import { AppTooltip } from './AppTooltip';
|
import { AppTooltip, TooltipDelay } from './AppTooltip';
|
||||||
|
|
||||||
const spacing4 = THEME_COMMON.spacing(4);
|
const spacing4 = THEME_COMMON.spacing(4);
|
||||||
|
|
||||||
@ -87,12 +87,12 @@ export const OverflowingTextWithTooltip = ({
|
|||||||
<AppTooltip
|
<AppTooltip
|
||||||
anchorSelect={`#${textElementId}`}
|
anchorSelect={`#${textElementId}`}
|
||||||
content={mutliline ? undefined : text ?? ''}
|
content={mutliline ? undefined : text ?? ''}
|
||||||
delayHide={1}
|
|
||||||
offset={5}
|
offset={5}
|
||||||
isOpen
|
isOpen
|
||||||
noArrow
|
noArrow
|
||||||
place="bottom"
|
place="bottom"
|
||||||
positionStrategy="absolute"
|
positionStrategy="absolute"
|
||||||
|
delay={TooltipDelay.mediumDelay}
|
||||||
>
|
>
|
||||||
{mutliline ? <pre>{text}</pre> : ''}
|
{mutliline ? <pre>{text}</pre> : ''}
|
||||||
</AppTooltip>
|
</AppTooltip>
|
||||||
|
|||||||
@ -6,7 +6,11 @@ import {
|
|||||||
ComponentDecorator,
|
ComponentDecorator,
|
||||||
} from '@ui/testing';
|
} from '@ui/testing';
|
||||||
|
|
||||||
import { AppTooltip as Tooltip, TooltipPosition } from '../AppTooltip';
|
import {
|
||||||
|
AppTooltip as Tooltip,
|
||||||
|
TooltipDelay,
|
||||||
|
TooltipPosition,
|
||||||
|
} from '../AppTooltip';
|
||||||
|
|
||||||
const meta: Meta<typeof Tooltip> = {
|
const meta: Meta<typeof Tooltip> = {
|
||||||
title: 'UI/Display/Tooltip',
|
title: 'UI/Display/Tooltip',
|
||||||
@ -19,6 +23,7 @@ type Story = StoryObj<typeof Tooltip>;
|
|||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
place: TooltipPosition.Bottom,
|
place: TooltipPosition.Bottom,
|
||||||
|
delay: TooltipDelay.mediumDelay,
|
||||||
content: 'Tooltip Test',
|
content: 'Tooltip Test',
|
||||||
isOpen: true,
|
isOpen: true,
|
||||||
anchorSelect: '#hover-text',
|
anchorSelect: '#hover-text',
|
||||||
@ -28,12 +33,54 @@ export const Default: Story = {
|
|||||||
anchorSelect,
|
anchorSelect,
|
||||||
className,
|
className,
|
||||||
content,
|
content,
|
||||||
delayHide,
|
delay,
|
||||||
isOpen,
|
isOpen,
|
||||||
noArrow,
|
noArrow,
|
||||||
offset,
|
offset,
|
||||||
place,
|
place,
|
||||||
positionStrategy,
|
positionStrategy,
|
||||||
|
clickable,
|
||||||
|
}) => (
|
||||||
|
<>
|
||||||
|
<p id="hover-text" data-testid="tooltip">
|
||||||
|
Hover me!
|
||||||
|
</p>
|
||||||
|
<Tooltip
|
||||||
|
{...{
|
||||||
|
anchorSelect,
|
||||||
|
className,
|
||||||
|
content,
|
||||||
|
delay,
|
||||||
|
isOpen,
|
||||||
|
noArrow,
|
||||||
|
offset,
|
||||||
|
place,
|
||||||
|
positionStrategy,
|
||||||
|
clickable,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Hoverable: Story = {
|
||||||
|
args: {
|
||||||
|
place: TooltipPosition.Bottom,
|
||||||
|
delay: TooltipDelay.mediumDelay,
|
||||||
|
content: 'Tooltip Test',
|
||||||
|
isOpen: true,
|
||||||
|
anchorSelect: '#hover-text',
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
render: ({
|
||||||
|
anchorSelect,
|
||||||
|
className,
|
||||||
|
content,
|
||||||
|
delay,
|
||||||
|
noArrow,
|
||||||
|
offset,
|
||||||
|
place,
|
||||||
|
positionStrategy,
|
||||||
}) => (
|
}) => (
|
||||||
<>
|
<>
|
||||||
<p id="hover-text" data-testid="tooltip">
|
<p id="hover-text" data-testid="tooltip">
|
||||||
@ -44,8 +91,7 @@ export const Default: Story = {
|
|||||||
anchorSelect,
|
anchorSelect,
|
||||||
className,
|
className,
|
||||||
content,
|
content,
|
||||||
delayHide,
|
delay,
|
||||||
isOpen,
|
|
||||||
noArrow,
|
noArrow,
|
||||||
offset,
|
offset,
|
||||||
place,
|
place,
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { PullRequestIcon } from '@/app/_components/ui/icons/SvgIcons';
|
|||||||
import { Theme } from '@/app/_components/ui/theme/theme';
|
import { Theme } from '@/app/_components/ui/theme/theme';
|
||||||
import { formatIntoRelativeDate } from '@/shared-utils/formatIntoRelativeDate';
|
import { formatIntoRelativeDate } from '@/shared-utils/formatIntoRelativeDate';
|
||||||
|
|
||||||
|
// TODO: use twenty-ui Tooltip
|
||||||
const StyledTooltip = styled(Tooltip)``;
|
const StyledTooltip = styled(Tooltip)``;
|
||||||
|
|
||||||
const Item = styled.div`
|
const Item = styled.div`
|
||||||
|
|||||||
Reference in New Issue
Block a user