[MM-62390] Combine the floating and transition styles into one in WithTooltip and other related minor improvements (#29730)

Этот коммит содержится в:
M-ZubairAhmed
2025-01-07 18:40:01 +05:30
коммит произвёл GitHub
родитель 06ce7b4a5a
Коммит e0e24aaa6f
19 изменённых файлов: 158 добавлений и 162 удалений

Просмотреть файл

@@ -64,7 +64,6 @@ export function SendPostOptions({disabled, onSelect, channelId}: Props) {
return (
<Menu.Container
menuButtonTooltip={{
id: 'send_post_option_schedule_post',
text: formatMessage({
id: 'create_post_button.option.schedule_message',
defaultMessage: 'Schedule message',

Просмотреть файл

@@ -195,7 +195,8 @@ export default class AnnouncementBar extends React.PureComponent<Props, State> {
barContent = (
<WithTooltip
title={this.props.tooltipMsg ? this.props.tooltipMsg : message}
tooltipContentContainerClassName='announcementBarTooltip'
className='announcementBarTooltip'
delayClose={true}
>
{barContent}

Просмотреть файл

@@ -1,5 +1,5 @@
.announcementBarTooltip {
min-width: 50vw;
max-width: 100vw;
max-width: 90vw;
pointer-events: auto;
}

Просмотреть файл

@@ -82,7 +82,6 @@ function BookmarksMenu({
id: 'channelBookmarksPlusMenuDropdown',
}}
menuButtonTooltip={addBookmarkTooltipText ? {
id: 'channelBookmarksPlusMenuButtonTooltip',
text: addBookmarkTooltipText,
} : undefined}
>

Просмотреть файл

@@ -352,7 +352,6 @@ exports[`components/dot_menu/DotMenu should match snapshot, on Center 1`] = `
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "PostDotMenu-ButtonTooltip-post_id_1",
"text": "More",
}
}

Просмотреть файл

@@ -507,7 +507,6 @@ export class DotMenuClass extends React.PureComponent<Props, State> {
onToggle: this.handleMenuToggle,
}}
menuButtonTooltip={{
id: `PostDotMenu-ButtonTooltip-${this.props.post.id}`,
text: formatMessage({id: 'post_info.dot_menu.tooltip.more', defaultMessage: 'More'}),
class: 'hidden-xs',
}}

Просмотреть файл

@@ -44,7 +44,6 @@ type MenuButtonProps = {
}
type MenuButtonTooltipProps = {
id: string;
isVertical?: boolean;
class?: string;
text: string;

Просмотреть файл

@@ -85,13 +85,7 @@ export function ProfilePopoverController<TriggerComponentType = HTMLSpanElement>
middleware: [autoPlacement()],
});
const {isMounted, styles: transitionStyles} = useTransitionStyles(floatingContext, {
duration: {
open: OverlaysTimings.FADE_IN_DURATION,
close: OverlaysTimings.FADE_OUT_DURATION,
},
initial: OverlayTransitionStyles.START,
});
const {isMounted, styles: transitionStyles} = useTransitionStyles(floatingContext, TRANSITION_STYLE_PROPS);
const clickInteractions = useClick(floatingContext);
const dismissInteraction = useDismiss(floatingContext);
@@ -154,3 +148,11 @@ export function ProfilePopoverController<TriggerComponentType = HTMLSpanElement>
</>
);
}
const TRANSITION_STYLE_PROPS = {
duration: {
open: OverlaysTimings.FADE_IN_DURATION,
close: OverlaysTimings.FADE_OUT_DURATION,
},
initial: OverlayTransitionStyles.START,
};

Просмотреть файл

@@ -25,7 +25,6 @@ exports[`components/sidebar/sidebar_category/sidebar_category_sorting_menu shoul
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarCategorySortingMenu-ButtonTooltip-category_id",
"text": "Category options",
}
}

Просмотреть файл

@@ -47,7 +47,6 @@ const SidebarCategoryGenericMenu = ({
children: <DotsVerticalIcon size={16}/>,
}}
menuButtonTooltip={{
id: `SidebarCategoryMenu-ButtonTooltip-${id}`,
text: formatMessage({id: 'sidebar_left.sidebar_category_menu.editCategory', defaultMessage: 'Category options'}),
class: 'hidden-xs',
}}

Просмотреть файл

@@ -198,7 +198,6 @@ const SidebarCategorySortingMenu = ({
children: <DotsVerticalIcon size={16}/>,
}}
menuButtonTooltip={{
id: `SidebarCategorySortingMenu-ButtonTooltip-${category.id}`,
text: formatMessage({id: 'sidebar_left.sidebar_category_menu.editCategory', defaultMessage: 'Category options'}),
class: 'hidden-xs',
}}

Просмотреть файл

@@ -22,7 +22,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should match sn
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}
@@ -168,7 +167,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should match sn
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}
@@ -314,7 +312,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should match sn
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}
@@ -460,7 +457,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should show cor
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}
@@ -574,7 +570,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should show cor
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}
@@ -703,7 +698,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should show cor
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}
@@ -849,7 +843,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should show cor
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}
@@ -995,7 +988,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should show cor
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}
@@ -1141,7 +1133,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should show cor
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}
@@ -1287,7 +1278,6 @@ exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should show cor
menuButtonTooltip={
Object {
"class": "hidden-xs",
"id": "SidebarChannelMenu-ButtonTooltip-channel_id",
"text": "Channel options",
}
}

Просмотреть файл

@@ -297,7 +297,6 @@ const SidebarChannelMenu = ({
children: <DotsVerticalIcon size={16}/>,
}}
menuButtonTooltip={{
id: `SidebarChannelMenu-ButtonTooltip-${channel.id}`,
class: 'hidden-xs',
text: formatMessage({id: 'sidebar_left.sidebar_channel_menu.editChannel', defaultMessage: 'Channel options'}),
}}

Просмотреть файл

@@ -1,8 +1,9 @@
@use 'utils/variables';
#user-group-popover .popover-content {
padding: 0;
}
.user-group-popover-floating-overlay {
// 99 being the z-index of the global header
z-index: 1060;
z-index: variables.$z-index-user-group-popover;
}

Просмотреть файл

@@ -24,21 +24,17 @@ import type {ReactElement, ReactNode} from 'react';
import type {MessageDescriptor} from 'react-intl';
import {defineMessage} from 'react-intl';
import {Constants} from 'utils/constants';
import {OverlayArrow, OverlaysTimings, OverlayTransitionStyles, RootHtmlPortalId} from 'utils/constants';
import TooltipContent from './tooltip_content';
import type {ShortcutDefinition} from './tooltip_shortcut';
import './tooltip.scss';
const ARROW_WIDTH = 10; // in px
const ARROW_HEIGHT = 6; // in px
const ARROW_OFFSET = 8; // in px
const TOOLTIP_REST_TIME_BEFORE_OPEN = 400; // in ms
const TOOLTIP_APPEAR_DURATION = 250; // in ms
const TOOLTIP_DISAPPEAR_DURATION = 200; // in ms
import './with_tooltip.scss';
/**
* Shortcut keys map to translations that can be used in the tooltip
* when shortcut definition is provided
*/
export const ShortcutKeys = {
alt: defineMessage({
id: 'shortcuts.generic.alt',
@@ -68,7 +64,17 @@ interface Props {
* This doesn't always guarantee the tooltip will be vertical, it just determines the initial placement and fallback placements
*/
isVertical?: boolean;
tooltipContentContainerClassName?: string;
/**
* If closing of the tooltip should be delayed,
* Useful if tooltips contains links that need to be clicked
*/
delayClose?: boolean;
/**
* Additional class name to be added to the tooltip container
*/
className?: string;
disabled?: boolean;
/**
@@ -79,7 +85,7 @@ interface Props {
children: ReactElement;
}
function WithTooltip({
export default function WithTooltip({
children,
title,
emoji,
@@ -87,7 +93,8 @@ function WithTooltip({
hint,
shortcut,
isVertical = true,
tooltipContentContainerClassName,
delayClose = false,
className,
onOpen,
disabled,
}: Props) {
@@ -116,13 +123,13 @@ function WithTooltip({
return {initial, fallback};
}, [isVertical]);
const {refs: {setReference, setFloating}, floatingStyles, context} = useFloating({
const {refs: {setReference, setFloating}, floatingStyles, context: floatingContext} = useFloating({
open: disabled ? false : open,
onOpenChange: handleChange,
whileElementsMounted: autoUpdate,
placement: placements.initial,
middleware: [
offset(ARROW_OFFSET),
offset(OverlayArrow.OFFSET),
flip({
fallbackPlacements: placements.fallback,
}),
@@ -132,75 +139,61 @@ function WithTooltip({
],
});
const hover = useHover(context, {
restMs: TOOLTIP_REST_TIME_BEFORE_OPEN,
const {isMounted, styles: transitionStyles} = useTransitionStyles(floatingContext, TRANSITION_STYLE_PROPS);
const hover = useHover(floatingContext, {
restMs: OverlaysTimings.CURSOR_REST_TIME_BEFORE_OPEN,
delay: {
open: Constants.OVERLAY_TIME_DELAY,
open: OverlaysTimings.CURSOR_MOUSEOVER_TO_OPEN,
close: delayClose ? OverlaysTimings.CURSOR_MOUSEOUT_TO_CLOSE_WITH_DELAY : OverlaysTimings.CURSOR_MOUSEOUT_TO_CLOSE,
},
});
const focus = useFocus(context);
const dismiss = useDismiss(context);
const role = useRole(context, {role: 'tooltip'});
const focus = useFocus(floatingContext);
const dismiss = useDismiss(floatingContext);
const role = useRole(floatingContext, {role: 'tooltip'});
const {getReferenceProps, getFloatingProps} = useInteractions([hover, focus, dismiss, role]);
const {isMounted, styles: transitionStyles} = useTransitionStyles(context, {
duration: {
open: TOOLTIP_APPEAR_DURATION,
close: TOOLTIP_DISAPPEAR_DURATION,
},
initial: {
opacity: 0,
},
common: {
opacity: 1,
},
});
if (!isValidElement(children)) {
// eslint-disable-next-line no-console
console.error('Children must be a valid React element for WithTooltip');
}
const mergedRefs = useMergeRefs([(children as any)?.ref, setReference]);
const mergedRefs = useMergeRefs([setReference, (children as any)?.ref]);
const trigger = cloneElement(children, {
...getReferenceProps({
const trigger = cloneElement(
children,
getReferenceProps({
ref: mergedRefs,
...children.props,
}),
});
);
return (
<>
{trigger}
{isMounted && (
<FloatingPortal
id='root-portal' // This is the global portal container id
>
<FloatingPortal id={RootHtmlPortalId}>
<div
className='tooltipContainer'
ref={setFloating}
style={floatingStyles}
className={classNames('tooltipContainer', className)}
style={{...floatingStyles, ...transitionStyles}}
{...getFloatingProps()}
>
<div
className={classNames('tooltipContentContainer', tooltipContentContainerClassName)}
style={transitionStyles}
>
<TooltipContent
title={title}
emoji={emoji}
isEmojiLarge={isEmojiLarge}
hint={hint}
shortcut={shortcut}
/>
<FloatingArrow
ref={arrowRef}
context={context}
width={ARROW_WIDTH}
height={ARROW_HEIGHT}
/>
</div>
<TooltipContent
title={title}
emoji={emoji}
isEmojiLarge={isEmojiLarge}
hint={hint}
shortcut={shortcut}
/>
<FloatingArrow
ref={arrowRef}
context={floatingContext}
width={OverlayArrow.WIDTH}
height={OverlayArrow.HEIGHT}
/>
</div>
</FloatingPortal>
)}
@@ -208,4 +201,10 @@ function WithTooltip({
);
}
export default WithTooltip;
const TRANSITION_STYLE_PROPS = {
duration: {
open: OverlaysTimings.FADE_IN_DURATION,
close: OverlaysTimings.FADE_OUT_DURATION,
},
initial: OverlayTransitionStyles.START,
};

Просмотреть файл

@@ -1,70 +0,0 @@
.tooltipContainer {
z-index: 1070;
> .tooltipContentContainer {
z-index: 1070;
max-width: 220px;
padding: 4px 8px;
border-radius: 4px;
background: rgba(0, 0, 0, 1);
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.12);
line-height: 18px;
pointer-events: none;
text-align: center;
word-break: break-word;
> .tooltipContent {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: "Open Sans", sans-serif;
> .tooltipContentTitleContainer {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 6px;
&.isEmojiLarge {
flex-direction: column;
gap: 2px;
> .tooltipContentEmoji {
padding-top: 1px;
}
}
> .tooltipContentEmoji {
display: flex;
align-items: center;
justify-content: center;
}
> .tooltipContentTitle {
color: #ffffff;
font-size: 12px;
font-weight: 600;
line-height: 15px;
}
}
> .tooltipContentShortcut {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 4px 0;
gap: 2px;
}
> .tooltipContentHint {
color: rgba(255, 255, 255, 0.64);
font-size: 11px;
font-weight: 600;
line-height: 16px;
}
}
}
}

Просмотреть файл

@@ -0,0 +1,68 @@
@use 'utils/variables';
.tooltipContainer {
z-index: variables.$z-index-popover;
max-width: 220px;
padding: 4px 8px;
border-radius: 4px;
background: rgba(0, 0, 0, 1);
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.12);
line-height: 18px;
pointer-events: none;
text-align: center;
word-break: break-word;
> .tooltipContent {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: "Open Sans", sans-serif;
> .tooltipContentTitleContainer {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 6px;
&.isEmojiLarge {
flex-direction: column;
gap: 2px;
> .tooltipContentEmoji {
padding-top: 1px;
}
}
> .tooltipContentEmoji {
display: flex;
align-items: center;
justify-content: center;
}
> .tooltipContentTitle {
color: #ffffff;
font-size: 12px;
font-weight: 600;
line-height: 15px;
}
}
> .tooltipContentShortcut {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 4px 0;
gap: 2px;
}
> .tooltipContentHint {
color: rgba(255, 255, 255, 0.64);
font-size: 11px;
font-weight: 600;
line-height: 16px;
}
}
}

Просмотреть файл

@@ -36,3 +36,9 @@ $elevation-3: var(--elevation-3);
$elevation-4: var(--elevation-4);
$elevation-5: var(--elevation-5);
$elevation-6: var(--elevation-6);
// Z-Index
// Central place to manage z-index values for the app, providing a consistent way to manage stacking order.
$z-index-popover: 1070;
$z-index-user-group-popover: 1060;
$z-index-global-header: 99;

Просмотреть файл

@@ -2240,6 +2240,9 @@ export const RootHtmlPortalId = 'root-portal';
export const OverlaysTimings = {
CURSOR_REST_TIME_BEFORE_OPEN: 400, // in ms
CURSOR_MOUSEOVER_TO_OPEN: 400, // in ms
CURSOR_MOUSEOUT_TO_CLOSE: 0,
CURSOR_MOUSEOUT_TO_CLOSE_WITH_DELAY: 200, // in ms
FADE_IN_DURATION: 250, // in ms
FADE_OUT_DURATION: 150, // in ms
};
@@ -2250,5 +2253,10 @@ export const OverlayTransitionStyles = {
},
};
export default Constants;
export const OverlayArrow = {
WIDTH: 10, // in px
HEIGHT: 6, // in px
OFFSET: 8, // in px
};
export default Constants;