[MM-62649] Switch DeveloperModeIndicator over to floating-ui (#3294)
* [MM-62649] Switch DeveloperModeIndicator over to floating-ui * Fix test
This commit is contained in:
42
package-lock.json
generated
42
package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "11.11.4",
|
"@emotion/react": "11.11.4",
|
||||||
|
"@floating-ui/react": "0.26.28",
|
||||||
"@mattermost/compass-icons": "0.1.45",
|
"@mattermost/compass-icons": "0.1.45",
|
||||||
"auto-launch": "5.0.6",
|
"auto-launch": "5.0.6",
|
||||||
"bootstrap": "4.6.1",
|
"bootstrap": "4.6.1",
|
||||||
@@ -2568,10 +2569,39 @@
|
|||||||
"@floating-ui/utils": "^0.2.0"
|
"@floating-ui/utils": "^0.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@floating-ui/react": {
|
||||||
|
"version": "0.26.28",
|
||||||
|
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz",
|
||||||
|
"integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/react-dom": "^2.1.2",
|
||||||
|
"@floating-ui/utils": "^0.2.8",
|
||||||
|
"tabbable": "^6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8.0",
|
||||||
|
"react-dom": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/react-dom": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/dom": "^1.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8.0",
|
||||||
|
"react-dom": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@floating-ui/utils": {
|
"node_modules/@floating-ui/utils": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.9",
|
||||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
|
||||||
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
|
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@formatjs/ecma402-abstract": {
|
"node_modules/@formatjs/ecma402-abstract": {
|
||||||
"version": "1.18.2",
|
"version": "1.18.2",
|
||||||
@@ -16229,6 +16259,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tabbable": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "0.1.10",
|
"version": "0.1.10",
|
||||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz",
|
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz",
|
||||||
|
@@ -160,6 +160,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "11.11.4",
|
"@emotion/react": "11.11.4",
|
||||||
|
"@floating-ui/react": "0.26.28",
|
||||||
"@mattermost/compass-icons": "0.1.45",
|
"@mattermost/compass-icons": "0.1.45",
|
||||||
"auto-launch": "5.0.6",
|
"auto-launch": "5.0.6",
|
||||||
"bootstrap": "4.6.1",
|
"bootstrap": "4.6.1",
|
||||||
|
@@ -15,6 +15,8 @@ jest.mock('electron', () => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.mock('electron-is-dev', () => false);
|
||||||
|
|
||||||
describe('main/developerMode', () => {
|
describe('main/developerMode', () => {
|
||||||
it('should toggle values correctly', () => {
|
it('should toggle values correctly', () => {
|
||||||
const developerMode = new DeveloperMode('file.json');
|
const developerMode = new DeveloperMode('file.json');
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import {ipcMain} from 'electron';
|
import {ipcMain} from 'electron';
|
||||||
|
import isDev from 'electron-is-dev';
|
||||||
import {EventEmitter} from 'events';
|
import {EventEmitter} from 'events';
|
||||||
|
|
||||||
import {DEVELOPER_MODE_UPDATED, IS_DEVELOPER_MODE_ENABLED, UPDATE_PATHS} from 'common/communication';
|
import {DEVELOPER_MODE_UPDATED, IS_DEVELOPER_MODE_ENABLED, UPDATE_PATHS} from 'common/communication';
|
||||||
@@ -20,7 +21,7 @@ export class DeveloperMode extends EventEmitter {
|
|||||||
ipcMain.handle(IS_DEVELOPER_MODE_ENABLED, this.enabled);
|
ipcMain.handle(IS_DEVELOPER_MODE_ENABLED, this.enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
enabled = () => process.env.MM_DESKTOP_DEVELOPER_MODE === 'true';
|
enabled = () => process.env.MM_DESKTOP_DEVELOPER_MODE === 'true' || isDev;
|
||||||
|
|
||||||
toggle = (setting: keyof DeveloperSettings) => {
|
toggle = (setting: keyof DeveloperSettings) => {
|
||||||
if (!this.enabled()) {
|
if (!this.enabled()) {
|
||||||
|
@@ -22,6 +22,8 @@ jest.mock('electron-context-menu', () => {
|
|||||||
return () => jest.fn();
|
return () => jest.fn();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
jest.mock('electron-is-dev', () => false);
|
||||||
|
|
||||||
jest.mock('electron', () => {
|
jest.mock('electron', () => {
|
||||||
class NotificationMock {
|
class NotificationMock {
|
||||||
static isSupported = jest.fn();
|
static isSupported = jest.fn();
|
||||||
|
@@ -3,34 +3,33 @@
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
// eslint-disable-next-line no-restricted-imports
|
|
||||||
import {OverlayTrigger, Tooltip} from 'react-bootstrap';
|
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
import 'renderer/css/components/DeveloperModeIndicator.scss';
|
import 'renderer/css/components/DeveloperModeIndicator.scss';
|
||||||
|
|
||||||
|
import WithTooltip from './WithTooltip';
|
||||||
|
|
||||||
export default function DeveloperModeIndicator({developerMode, darkMode}: {developerMode: boolean; darkMode: boolean}) {
|
export default function DeveloperModeIndicator({developerMode, darkMode}: {developerMode: boolean; darkMode: boolean}) {
|
||||||
if (!developerMode) {
|
if (!developerMode) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OverlayTrigger
|
<WithTooltip
|
||||||
placement='left'
|
title={
|
||||||
overlay={
|
<FormattedMessage
|
||||||
<Tooltip id='DeveloperModeIndicator__tooltip'>
|
id='renderer.components.developerModeIndicator.tooltip'
|
||||||
<FormattedMessage
|
defaultMessage='Developer mode is enabled. You should only have this enabled if a Mattermost developer has instructed you to.'
|
||||||
id='renderer.components.developerModeIndicator.tooltip'
|
/>
|
||||||
defaultMessage='Developer mode is enabled. You should only have this enabled if a Mattermost developer has instructed you to.'
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
}
|
||||||
|
isVertical={false}
|
||||||
|
className='DeveloperModeIndicator__tooltip'
|
||||||
>
|
>
|
||||||
<div className={classNames('DeveloperModeIndicator', {darkMode})}>
|
<div className={classNames('DeveloperModeIndicator', {darkMode})}>
|
||||||
<i className='icon-flask-outline'/>
|
<i className='icon-flask-outline'/>
|
||||||
<span className='DeveloperModeIndicator__badge'/>
|
<span className='DeveloperModeIndicator__badge'/>
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
</WithTooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
204
src/renderer/components/WithTooltip/index.tsx
Normal file
204
src/renderer/components/WithTooltip/index.tsx
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import type {Placement} from '@floating-ui/react';
|
||||||
|
import {
|
||||||
|
useFloating,
|
||||||
|
autoUpdate,
|
||||||
|
offset,
|
||||||
|
useHover,
|
||||||
|
useFocus,
|
||||||
|
useDismiss,
|
||||||
|
useRole,
|
||||||
|
useInteractions,
|
||||||
|
arrow,
|
||||||
|
FloatingPortal,
|
||||||
|
useTransitionStyles,
|
||||||
|
FloatingArrow,
|
||||||
|
flip,
|
||||||
|
useMergeRefs,
|
||||||
|
} from '@floating-ui/react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import React, {useRef, useState, useMemo, cloneElement, isValidElement} from 'react';
|
||||||
|
import type {ReactElement, ReactNode} from 'react';
|
||||||
|
import type {MessageDescriptor} from 'react-intl';
|
||||||
|
import {defineMessage} from 'react-intl';
|
||||||
|
|
||||||
|
import {Constants} from 'renderer/constants';
|
||||||
|
|
||||||
|
import TooltipContent from './tooltip_content';
|
||||||
|
|
||||||
|
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',
|
||||||
|
defaultMessage: 'Alt',
|
||||||
|
}),
|
||||||
|
cmd: '⌘',
|
||||||
|
ctrl: defineMessage({
|
||||||
|
id: 'shortcuts.generic.ctrl',
|
||||||
|
defaultMessage: 'Ctrl',
|
||||||
|
}),
|
||||||
|
option: '⌥',
|
||||||
|
shift: defineMessage({
|
||||||
|
id: 'shortcuts.generic.shift',
|
||||||
|
defaultMessage: 'Shift',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string | ReactNode | MessageDescriptor;
|
||||||
|
emoji?: string;
|
||||||
|
isEmojiLarge?: boolean;
|
||||||
|
hint?: string | ReactNode | MessageDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the tooltip should be vertical or horizontal, by default it is vertical
|
||||||
|
* This doesn't always guarantee the tooltip will be vertical, it just determines the initial placement and fallback placements
|
||||||
|
*/
|
||||||
|
isVertical?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Do not use this except for special cases
|
||||||
|
* Callback when the tooltip appears
|
||||||
|
*/
|
||||||
|
onOpen?: () => void;
|
||||||
|
children: ReactElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function WithTooltip({
|
||||||
|
children,
|
||||||
|
title,
|
||||||
|
isEmojiLarge = false,
|
||||||
|
hint,
|
||||||
|
isVertical = true,
|
||||||
|
delayClose = false,
|
||||||
|
className,
|
||||||
|
onOpen,
|
||||||
|
disabled,
|
||||||
|
}: Props) {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const arrowRef = useRef(null);
|
||||||
|
|
||||||
|
function handleChange(open: boolean) {
|
||||||
|
setOpen(open);
|
||||||
|
|
||||||
|
if (onOpen && open) {
|
||||||
|
onOpen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const placements = useMemo<{initial: Placement; fallback: Placement[]}>(() => {
|
||||||
|
let initial: Placement;
|
||||||
|
let fallback: Placement[];
|
||||||
|
if (isVertical) {
|
||||||
|
initial = 'top';
|
||||||
|
fallback = ['bottom', 'right', 'left'];
|
||||||
|
} else {
|
||||||
|
initial = 'right';
|
||||||
|
fallback = ['left', 'top', 'bottom'];
|
||||||
|
}
|
||||||
|
return {initial, fallback};
|
||||||
|
}, [isVertical]);
|
||||||
|
|
||||||
|
const {refs: {setReference, setFloating}, floatingStyles, context: floatingContext} = useFloating({
|
||||||
|
open: disabled ? false : open,
|
||||||
|
onOpenChange: handleChange,
|
||||||
|
whileElementsMounted: autoUpdate,
|
||||||
|
placement: 'left',
|
||||||
|
middleware: [
|
||||||
|
offset(Constants.OverlayArrow.OFFSET),
|
||||||
|
flip({
|
||||||
|
fallbackPlacements: placements.fallback,
|
||||||
|
}),
|
||||||
|
arrow({
|
||||||
|
element: arrowRef,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const {isMounted, styles: transitionStyles} = useTransitionStyles(floatingContext, TRANSITION_STYLE_PROPS);
|
||||||
|
|
||||||
|
const hover = useHover(floatingContext, {
|
||||||
|
restMs: Constants.OverlaysTimings.CURSOR_REST_TIME_BEFORE_OPEN,
|
||||||
|
delay: {
|
||||||
|
open: Constants.OverlaysTimings.CURSOR_MOUSEOVER_TO_OPEN,
|
||||||
|
close: delayClose ? Constants.OverlaysTimings.CURSOR_MOUSEOUT_TO_CLOSE_WITH_DELAY : Constants.OverlaysTimings.CURSOR_MOUSEOUT_TO_CLOSE,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const focus = useFocus(floatingContext);
|
||||||
|
const dismiss = useDismiss(floatingContext);
|
||||||
|
const role = useRole(floatingContext, {role: 'tooltip'});
|
||||||
|
|
||||||
|
const {getReferenceProps, getFloatingProps} = useInteractions([hover, focus, dismiss, role]);
|
||||||
|
|
||||||
|
if (!isValidElement(children)) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('Children must be a valid React element for WithTooltip');
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergedRefs = useMergeRefs([setReference, (children as any)?.ref]);
|
||||||
|
|
||||||
|
const trigger = cloneElement(
|
||||||
|
children,
|
||||||
|
getReferenceProps({
|
||||||
|
ref: mergedRefs,
|
||||||
|
...children.props,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{trigger}
|
||||||
|
|
||||||
|
{isMounted && (
|
||||||
|
<FloatingPortal id={Constants.RootHtmlPortalId}>
|
||||||
|
<div
|
||||||
|
ref={setFloating}
|
||||||
|
className={classNames('tooltipContainer', className)}
|
||||||
|
style={{...floatingStyles, ...transitionStyles}}
|
||||||
|
{...getFloatingProps()}
|
||||||
|
>
|
||||||
|
<TooltipContent
|
||||||
|
title={title}
|
||||||
|
isEmojiLarge={isEmojiLarge}
|
||||||
|
hint={hint}
|
||||||
|
/>
|
||||||
|
<FloatingArrow
|
||||||
|
ref={arrowRef}
|
||||||
|
context={floatingContext}
|
||||||
|
width={Constants.OverlayArrow.WIDTH}
|
||||||
|
height={Constants.OverlayArrow.HEIGHT}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FloatingPortal>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const TRANSITION_STYLE_PROPS = {
|
||||||
|
duration: {
|
||||||
|
open: Constants.OverlaysTimings.FADE_IN_DURATION,
|
||||||
|
close: Constants.OverlaysTimings.FADE_OUT_DURATION,
|
||||||
|
},
|
||||||
|
initial: Constants.OverlayTransitionStyles.START,
|
||||||
|
};
|
32
src/renderer/components/WithTooltip/tooltip_content.tsx
Normal file
32
src/renderer/components/WithTooltip/tooltip_content.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import type {ReactNode} from 'react';
|
||||||
|
import React, {memo} from 'react';
|
||||||
|
import type {MessageDescriptor} from 'react-intl';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string | ReactNode | MessageDescriptor;
|
||||||
|
isEmojiLarge?: boolean;
|
||||||
|
hint?: string | ReactNode | MessageDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
function TooltipContent(props: Props) {
|
||||||
|
return (
|
||||||
|
<div className='tooltipContent'>
|
||||||
|
<span
|
||||||
|
className={classNames('tooltipContentTitleContainer', {
|
||||||
|
isEmojiLarge: props.isEmojiLarge,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<span className='tooltipContentTitle'>{props.title}</span>
|
||||||
|
</span>
|
||||||
|
{props.hint && (
|
||||||
|
<span className='tooltipContentHint'>{props.hint}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(TooltipContent);
|
68
src/renderer/components/WithTooltip/with_tooltip.scss
Normal file
68
src/renderer/components/WithTooltip/with_tooltip.scss
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
@use '../../css/variables';
|
||||||
|
|
||||||
|
.tooltipContainer {
|
||||||
|
z-index: variables.$z-index-tooltip;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -97,4 +97,28 @@ export const Constants = {
|
|||||||
flv: 'video',
|
flv: 'video',
|
||||||
webm: 'video',
|
webm: 'video',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the ID of the root portal container that is used to render modals and other components
|
||||||
|
* that need to be rendered outside of the main app container.
|
||||||
|
*/
|
||||||
|
RootHtmlPortalId: 'root-portal',
|
||||||
|
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
|
||||||
|
},
|
||||||
|
OverlayTransitionStyles: {
|
||||||
|
START: {
|
||||||
|
opacity: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
OverlayArrow: {
|
||||||
|
WIDTH: 10, // in px
|
||||||
|
HEIGHT: 6, // in px
|
||||||
|
OFFSET: 8, // in px
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
2
src/renderer/css/_variables.scss
Normal file
2
src/renderer/css/_variables.scss
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Since they can be used on any modal, menu or popover for now they are highest
|
||||||
|
$z-index-tooltip: 1350;
|
@@ -47,8 +47,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#DeveloperModeIndicator__tooltip {
|
.DeveloperModeIndicator__tooltip.tooltipContainer {
|
||||||
> .tooltip-inner {
|
max-width: none;
|
||||||
max-width: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -6,5 +6,6 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app" />
|
<div id="app" />
|
||||||
|
<div id='root-portal' />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Reference in New Issue
Block a user