Compact context menus on desktop (#1726)
This commit is contained in:
parent
9c789cdcb8
commit
c81ed0eb61
@ -11,17 +11,13 @@
|
|||||||
background: #181f27;
|
background: #181f27;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Menu .bubble {
|
.Menu {
|
||||||
--color-background: #232a34;
|
--color-text: white;
|
||||||
--color-chat-hover: #2f363e;
|
--color-background-compact-menu: #212121DD;
|
||||||
--color-item-active: #2f363e;
|
--color-background-compact-menu-hover: #00000066;
|
||||||
--color-text: #fff;
|
.bubble {
|
||||||
box-shadow: 0 0.25rem 0.5rem 0.125rem rgba(16, 16, 16, 0.3);
|
box-shadow: 0 0.25rem 0.5rem 0.125rem rgba(16, 16, 16, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact menu items
|
|
||||||
.MenuItem {
|
|
||||||
padding: 0.75rem 1rem !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.single-column {
|
&.single-column {
|
||||||
|
|||||||
@ -2,14 +2,18 @@
|
|||||||
|
|
||||||
.participant-menu {
|
.participant-menu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
--color-text: white;
|
||||||
|
--color-background-compact-menu: #212121DD;
|
||||||
|
--color-background-compact-menu-hover: #00000066;
|
||||||
|
|
||||||
.bubble {
|
.bubble {
|
||||||
background: none;
|
background: none !important;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
color: #ffffff;
|
color: var(--color-text);
|
||||||
|
|
||||||
.group {
|
.group {
|
||||||
box-shadow: 0 0.25rem 0.5rem 0.125rem rgba(16, 16, 16, 0.3);
|
box-shadow: 0 0.25rem 0.5rem 0.125rem rgba(16, 16, 16, 0.3);
|
||||||
@ -20,6 +24,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.compact {
|
||||||
|
.group {
|
||||||
|
background: var(--color-background-compact-menu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.volume-control {
|
.volume-control {
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
|
|
||||||
|
|||||||
@ -69,6 +69,16 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.MenuItem.compact .archived-badge {
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.MenuItem.compact .Switcher {
|
||||||
|
transform: scale(0.75);
|
||||||
|
}
|
||||||
|
|
||||||
[dir="rtl"] .archived-badge {
|
[dir="rtl"] .archived-badge {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
|||||||
@ -43,6 +43,7 @@ const BotCommandMenu: FC<OwnProps> = ({
|
|||||||
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
||||||
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
||||||
noCloseOnBackdrop={!IS_TOUCH_ENV}
|
noCloseOnBackdrop={!IS_TOUCH_ENV}
|
||||||
|
noCompact
|
||||||
>
|
>
|
||||||
{botCommands.map((botCommand) => (
|
{botCommands.map((botCommand) => (
|
||||||
<BotCommand
|
<BotCommand
|
||||||
|
|||||||
@ -56,6 +56,7 @@ const BotKeyboardMenu: FC<OwnProps & StateProps> = ({
|
|||||||
onCloseAnimationEnd={handleClose}
|
onCloseAnimationEnd={handleClose}
|
||||||
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
||||||
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
||||||
|
noCompact
|
||||||
>
|
>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
{message.keyboardButtons.map((row) => (
|
{message.keyboardButtons.map((row) => (
|
||||||
|
|||||||
@ -86,6 +86,7 @@ const SendAsMenu: FC<OwnProps> = ({
|
|||||||
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
||||||
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
||||||
noCloseOnBackdrop={!IS_TOUCH_ENV}
|
noCloseOnBackdrop={!IS_TOUCH_ENV}
|
||||||
|
noCompact
|
||||||
>
|
>
|
||||||
<div className="send-as-title" dir="auto">{lang('SendMessageAsTitle')}</div>
|
<div className="send-as-title" dir="auto">{lang('SendMessageAsTitle')}</div>
|
||||||
{usersById && chatsById && sendAsIds?.map((id, index) => {
|
{usersById && chatsById && sendAsIds?.map((id, index) => {
|
||||||
|
|||||||
@ -232,6 +232,7 @@ const SymbolMenu: FC<OwnProps & StateProps> = ({
|
|||||||
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
||||||
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
||||||
noCloseOnBackdrop={!IS_TOUCH_ENV}
|
noCloseOnBackdrop={!IS_TOUCH_ENV}
|
||||||
|
noCompact
|
||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|||||||
@ -9,11 +9,15 @@
|
|||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.compact .scrollable-content {
|
||||||
|
padding: 0.25rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
.bubble {
|
.bubble {
|
||||||
transition: opacity 0.15s cubic-bezier(0.2, 0, 0.2, 1), transform 0.15s cubic-bezier(0.2, 0, 0.2, 1) !important;
|
transition: opacity 0.15s cubic-bezier(0.2, 0, 0.2, 1), transform 0.15s cubic-bezier(0.2, 0, 0.2, 1) !important;
|
||||||
transform: scale(0.7);
|
transform: scale(0.7);
|
||||||
overflow: initial;
|
overflow: initial;
|
||||||
padding: 0;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.with-reactions .bubble {
|
&.with-reactions .bubble {
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
top: -3.5rem;
|
top: -3.5rem;
|
||||||
|
|
||||||
&__bubble-big {
|
&__bubble-big {
|
||||||
|
border: 0.5rem solid var(--color-background);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
content: "";
|
content: "";
|
||||||
@ -18,8 +19,10 @@
|
|||||||
bottom: -0.5rem;
|
bottom: -0.5rem;
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
border-radius: 50%;
|
border-top: 0;
|
||||||
background: var(--color-background);
|
border-left: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-radius: 0 0 50% 50%;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,4 +67,22 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
border-radius: 3rem;
|
border-radius: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--compact {
|
||||||
|
background: var(--color-background-compact-menu-reactions);
|
||||||
|
height: 2rem;
|
||||||
|
top: -2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--compact &__items {
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--compact &__bubble-big {
|
||||||
|
border-color: var(--color-background-compact-menu-reactions);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--compact &__bubble-small {
|
||||||
|
background: var(--color-background-compact-menu-reactions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
|
|||||||
import useFlag from '../../../hooks/useFlag';
|
import useFlag from '../../../hooks/useFlag';
|
||||||
import { getTouchY } from '../../../util/scrollLock';
|
import { getTouchY } from '../../../util/scrollLock';
|
||||||
import { createClassNameBuilder } from '../../../util/buildClassName';
|
import { createClassNameBuilder } from '../../../util/buildClassName';
|
||||||
|
import { IS_COMPACT_MENU } from '../../../util/environment';
|
||||||
|
|
||||||
import ReactionSelectorReaction from './ReactionSelectorReaction';
|
import ReactionSelectorReaction from './ReactionSelectorReaction';
|
||||||
|
|
||||||
import './ReactionSelector.scss';
|
import './ReactionSelector.scss';
|
||||||
@ -50,7 +52,7 @@ const ReactionSelector: FC<OwnProps> = ({
|
|||||||
if ((!isPrivate && !enabledReactions?.length) || !availableReactions) return undefined;
|
if ((!isPrivate && !enabledReactions?.length) || !availableReactions) return undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn('&')} onWheelCapture={handleWheel} onTouchMove={handleWheel}>
|
<div className={cn('&', IS_COMPACT_MENU && 'compact')} onWheelCapture={handleWheel} onTouchMove={handleWheel}>
|
||||||
<div className={cn('bubble-big')} />
|
<div className={cn('bubble-big')} />
|
||||||
<div className={cn('bubble-small')} />
|
<div className={cn('bubble-small')} />
|
||||||
<div className={cn('items-wrapper')}>
|
<div className={cn('items-wrapper')}>
|
||||||
|
|||||||
@ -23,4 +23,9 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--compact {
|
||||||
|
min-width: 1.5rem;
|
||||||
|
min-height: 1.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,13 @@ import useMedia from '../../../hooks/useMedia';
|
|||||||
import useFlag from '../../../hooks/useFlag';
|
import useFlag from '../../../hooks/useFlag';
|
||||||
import useShowTransition from '../../../hooks/useShowTransition';
|
import useShowTransition from '../../../hooks/useShowTransition';
|
||||||
import { createClassNameBuilder } from '../../../util/buildClassName';
|
import { createClassNameBuilder } from '../../../util/buildClassName';
|
||||||
|
import { IS_COMPACT_MENU } from '../../../util/environment';
|
||||||
|
|
||||||
import AnimatedSticker from '../../common/AnimatedSticker';
|
import AnimatedSticker from '../../common/AnimatedSticker';
|
||||||
|
|
||||||
import './ReactionSelectorReaction.scss';
|
import './ReactionSelectorReaction.scss';
|
||||||
|
|
||||||
const REACTION_SIZE = 32;
|
const REACTION_SIZE = IS_COMPACT_MENU ? 24 : 32;
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
reaction: ApiAvailableReaction;
|
reaction: ApiAvailableReaction;
|
||||||
@ -48,7 +49,7 @@ const ReactionSelectorReaction: FC<OwnProps> = ({ reaction, previewIndex, onSend
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn('&')}
|
className={cn('&', IS_COMPACT_MENU && 'compact')}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
onMouseEnter={isReady ? activate : undefined}
|
onMouseEnter={isReady ? activate : undefined}
|
||||||
@ -59,7 +60,7 @@ const ReactionSelectorReaction: FC<OwnProps> = ({ reaction, previewIndex, onSend
|
|||||||
'static',
|
'static',
|
||||||
isReady ? [staticClassNames] : undefined,
|
isReady ? [staticClassNames] : undefined,
|
||||||
)}
|
)}
|
||||||
style={`background-position-x: ${previewIndex * -32}px;`}
|
style={`background-position-x: ${previewIndex * -REACTION_SIZE}px;`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{shouldRenderAnimated && (
|
{shouldRenderAnimated && (
|
||||||
|
|||||||
@ -78,4 +78,16 @@
|
|||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.compact {
|
||||||
|
.bubble {
|
||||||
|
background: var(--color-background-compact-menu);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
padding: 0.25rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import buildClassName from '../../util/buildClassName';
|
|||||||
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
||||||
import useHistoryBack from '../../hooks/useHistoryBack';
|
import useHistoryBack from '../../hooks/useHistoryBack';
|
||||||
import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMessageInputBlur';
|
import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMessageInputBlur';
|
||||||
|
import { IS_COMPACT_MENU } from '../../util/environment';
|
||||||
|
|
||||||
import './Menu.scss';
|
import './Menu.scss';
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ type OwnProps = {
|
|||||||
shouldSkipTransition?: boolean;
|
shouldSkipTransition?: boolean;
|
||||||
footer?: string;
|
footer?: string;
|
||||||
noCloseOnBackdrop?: boolean;
|
noCloseOnBackdrop?: boolean;
|
||||||
|
noCompact?: boolean;
|
||||||
onKeyDown?: (e: React.KeyboardEvent<any>) => void;
|
onKeyDown?: (e: React.KeyboardEvent<any>) => void;
|
||||||
onCloseAnimationEnd?: () => void;
|
onCloseAnimationEnd?: () => void;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
@ -53,6 +55,7 @@ const Menu: FC<OwnProps> = ({
|
|||||||
autoClose = false,
|
autoClose = false,
|
||||||
footer,
|
footer,
|
||||||
noCloseOnBackdrop = false,
|
noCloseOnBackdrop = false,
|
||||||
|
noCompact,
|
||||||
onCloseAnimationEnd,
|
onCloseAnimationEnd,
|
||||||
onClose,
|
onClose,
|
||||||
onMouseEnter,
|
onMouseEnter,
|
||||||
@ -110,7 +113,7 @@ const Menu: FC<OwnProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={buildClassName('Menu no-selection', className)}
|
className={buildClassName('Menu no-selection', !noCompact && IS_COMPACT_MENU && 'compact', className)}
|
||||||
onKeyDown={isOpen ? handleKeyDown : undefined}
|
onKeyDown={isOpen ? handleKeyDown : undefined}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseLeave={isOpen ? onMouseLeave : undefined}
|
onMouseLeave={isOpen ? onMouseLeave : undefined}
|
||||||
|
|||||||
@ -64,7 +64,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.has-ripple):not(.disabled):active {
|
&:not(.has-ripple):not(.disabled):not(.compact):active {
|
||||||
background-color: var(--color-item-active);
|
background-color: var(--color-item-active);
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
}
|
}
|
||||||
@ -89,4 +89,35 @@
|
|||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.compact {
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
margin: 0.125rem 0.25rem;
|
||||||
|
padding: 0.25rem;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
width: auto;
|
||||||
|
font-weight: 500;
|
||||||
|
transform: scale(1);
|
||||||
|
transition: 0.15s ease-in-out transform;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
margin-right: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
&:hover,
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
background: var(--color-background-compact-menu-hover);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import React, { FC, useCallback } from '../../lib/teact/teact';
|
|||||||
|
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import useLang from '../../hooks/useLang';
|
import useLang from '../../hooks/useLang';
|
||||||
|
import { IS_COMPACT_MENU } from '../../util/environment';
|
||||||
|
|
||||||
import './MenuItem.scss';
|
import './MenuItem.scss';
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ const MenuItem: FC<OwnProps> = (props) => {
|
|||||||
className,
|
className,
|
||||||
disabled && 'disabled',
|
disabled && 'disabled',
|
||||||
destructive && 'destructive',
|
destructive && 'destructive',
|
||||||
|
IS_COMPACT_MENU && 'compact',
|
||||||
);
|
);
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
|
|||||||
@ -65,6 +65,9 @@ $color-message-reaction-own-hover: #b5e0a4;
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
--color-background: #{$color-white};
|
--color-background: #{$color-white};
|
||||||
|
--color-background-compact-menu: #FFFFFFBB;
|
||||||
|
--color-background-compact-menu-reactions: #FFFFFFEB;
|
||||||
|
--color-background-compact-menu-hover: #000000B2;
|
||||||
--color-background-selected: #f4f4f5;
|
--color-background-selected: #f4f4f5;
|
||||||
--color-background-secondary: #f4f4f5;
|
--color-background-secondary: #f4f4f5;
|
||||||
--color-background-secondary-accent: #e4e4e5;
|
--color-background-secondary-accent: #e4e4e5;
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
"--color-primary-opacity": ["#50A2E980", "#8378DB80"],
|
"--color-primary-opacity": ["#50A2E980", "#8378DB80"],
|
||||||
"--color-primary-shade": ["#4a95d6", "#7b71c6"],
|
"--color-primary-shade": ["#4a95d6", "#7b71c6"],
|
||||||
"--color-background": ["#FFFFFF", "#212121"],
|
"--color-background": ["#FFFFFF", "#212121"],
|
||||||
|
"--color-background-compact-menu": ["#FFFFFFBB", "#212121DD"],
|
||||||
|
"--color-background-compact-menu-reactions": ["#FFFFFFEB", "#212121DD"],
|
||||||
|
"--color-background-compact-menu-hover": ["#00000011", "#00000066"],
|
||||||
"--color-background-secondary": ["#f4f4f5", "#0F0F0F"],
|
"--color-background-secondary": ["#f4f4f5", "#0F0F0F"],
|
||||||
"--color-background-secondary-accent": ["#E4E4E5", "#100f10"],
|
"--color-background-secondary-accent": ["#E4E4E5", "#100f10"],
|
||||||
"--color-background-own": ["#EEFFDE", "#8774E1"],
|
"--color-background-own": ["#EEFFDE", "#8774E1"],
|
||||||
|
|||||||
@ -86,6 +86,7 @@ export const DPR = window.devicePixelRatio || 1;
|
|||||||
|
|
||||||
export const MASK_IMAGE_DISABLED = true;
|
export const MASK_IMAGE_DISABLED = true;
|
||||||
|
|
||||||
|
export const IS_COMPACT_MENU = !IS_TOUCH_ENV;
|
||||||
export const IS_SCROLL_PATCH_NEEDED = !IS_MAC_OS && !IS_IOS && !IS_ANDROID;
|
export const IS_SCROLL_PATCH_NEEDED = !IS_MAC_OS && !IS_IOS && !IS_ANDROID;
|
||||||
|
|
||||||
// Smaller area reduces scroll jumps caused by `patchChromiumScroll`
|
// Smaller area reduces scroll jumps caused by `patchChromiumScroll`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user