MM-61611 Fix layout of emoji picker in mobile view (#30747)

* Stop emoji picker header from overlapping tabs

* Move emoji picker header above tabs

There was also some stuff I could remove because the header will always
be visible.

* Don't scroll the emoji picker on hover

* MM-61611 Fix emoji picker tabs being covered in mobile view

* Improve layout of emoji picker and gif picker

A lot of the emoji picker was explicitly sized before which made it
difficult to make everything responsive in mobile view. Making the emoji
picker layout into a flexbox fixed that, but due to the way that it's
nested, that was a bit tricky, and it required a couple tricks:

1. The AutoSizer doesn't work if it's placed inside a flexbox container,
   but you can fix that by putting a div with position: relative in
   between it and the flexbox parent. That was already the case, but I
   accidentally removed it while trying to sort out the seemingly
   excessive nesting.
2. Children of flexbox elements will cause the parent to expand if they
   don't have min-height/min-width set. That's because the default
   value for those is 0 outside of flexbox, but it's auto inside of one.

This breaks the layout and animation of the skin tone selector in the
emoji picker, but that has issues on master as well, so it'll be
addressed in the next commit.

* Improve and fix opening animation for skin tone selector

While this looked worse before in mobile view, it had some weirdness in
desktop as well. I ended up rewriting the way that that animation worked
so that I could position it correctly in both mobile (where it doesn't
cover the input) and desktop (where it does).

Notably, that change required:

1. Changing the skin tone selector to wait until its contents are hidden
   to unmount them so that the position and size could be calculated
   correctly.
2. Removed the flexbox from the search row and used a margin to make the
   skin tone button pretend to offset the input. That let us smoothy
   expand the selector over the input without having the input resize
   behind it.

* Update CSS for positioning emojis and headings in emoji picker
Этот коммит содержится в:
Harrison Healey
2025-04-25 12:28:31 -04:00
коммит произвёл GitHub
родитель 291d5a2ba7
Коммит 80b61ad79b
14 изменённых файлов: 234 добавлений и 265 удалений

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

@@ -2,10 +2,6 @@
exports[`components/emoji_picker/EmojiPicker should match snapshot 1`] = ` exports[`components/emoji_picker/EmojiPicker should match snapshot 1`] = `
<DocumentFragment> <DocumentFragment>
<div
class="emoji-picker__inner"
role="application"
>
<div <div
aria-live="assertive" aria-live="assertive"
class="sr-only" class="sr-only"
@@ -153,6 +149,5 @@ exports[`components/emoji_picker/EmojiPicker should match snapshot 1`] = `
Preview for grinning emoji Preview for grinning emoji
</div> </div>
</div> </div>
</div>
</DocumentFragment> </DocumentFragment>
`; `;

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

@@ -2,7 +2,7 @@
exports[`components/emoji_picker/components/EmojiPickerHeader handleEmojiPickerClose, should have called props.handleEmojiPickerClose 1`] = ` exports[`components/emoji_picker/components/EmojiPickerHeader handleEmojiPickerClose, should have called props.handleEmojiPickerClose 1`] = `
<div <div
className="emoji-picker__header modal-header" className="emoji-picker__header"
> >
<button <button
className="close emoji-picker__header-close-button" className="close emoji-picker__header-close-button"
@@ -36,7 +36,7 @@ exports[`components/emoji_picker/components/EmojiPickerHeader handleEmojiPickerC
exports[`components/emoji_picker/components/EmojiPickerHeader should match snapshot, 1`] = ` exports[`components/emoji_picker/components/EmojiPickerHeader should match snapshot, 1`] = `
<div <div
className="emoji-picker__header modal-header" className="emoji-picker__header"
> >
<button <button
className="close emoji-picker__header-close-button" className="close emoji-picker__header-close-button"

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

@@ -15,7 +15,7 @@ interface Props {
function EmojiPickerCategoryRow({categoryName, style}: Props) { function EmojiPickerCategoryRow({categoryName, style}: Props) {
return ( return (
<div <div
className='emoji-picker-items__container' className='emoji-picker__row'
style={style} style={style}
role='row' role='row'
> >

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

@@ -11,7 +11,7 @@ type Props = {
const EmojiPickerHeader = ({handleEmojiPickerClose}: Props) => { const EmojiPickerHeader = ({handleEmojiPickerClose}: Props) => {
return ( return (
<div className='emoji-picker__header modal-header'> <div className='emoji-picker__header'>
<button <button
type='button' type='button'
className='close emoji-picker__header-close-button' className='close emoji-picker__header-close-button'

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

@@ -80,6 +80,7 @@ export type Props = {
type State = { type State = {
pickerExtended: boolean; pickerExtended: boolean;
pickerMounted: boolean;
} }
export class EmojiPickerSkin extends React.PureComponent<Props, State> { export class EmojiPickerSkin extends React.PureComponent<Props, State> {
@@ -88,6 +89,7 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
this.state = { this.state = {
pickerExtended: false, pickerExtended: false,
pickerMounted: false,
}; };
} }
@@ -109,7 +111,16 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
}; };
showSkinTonePicker = () => { showSkinTonePicker = () => {
this.setState({pickerExtended: true}); this.setState({
pickerExtended: true,
pickerMounted: true,
});
};
handleSkinToneHidden = () => {
this.setState({
pickerMounted: false,
});
}; };
skinTonePickerButton() { skinTonePickerButton() {
@@ -194,16 +205,17 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
return ( return (
<CSSTransition <CSSTransition
in={this.state.pickerExtended} in={this.state.pickerExtended}
onExited={this.handleSkinToneHidden}
classNames='skin-tones-animation' classNames='skin-tones-animation'
timeout={200} timeout={200}
> >
<div className={classNames('skin-tones', {'skin-tones--active': this.state.pickerExtended})}> <div className={classNames('skin-tones', {'skin-tones--active': this.state.pickerMounted})}>
<div <div
className={classNames('skin-tones__content', {'skin-tones__content__single': !this.state.pickerExtended}, {'skin-tones__close': this.state.pickerExtended})} className={classNames('skin-tones__content', {'skin-tones__content__single': !this.state.pickerMounted}, {'skin-tones__close': this.state.pickerMounted})}
aria-orientation='horizontal' aria-orientation='horizontal'
> >
{this.skinTonePickerButton()} {this.skinTonePickerButton()}
{this.state.pickerExtended && {this.state.pickerMounted &&
<> <>
<div className='skin-tones__close-text'> <div className='skin-tones__close-text'>
<FormattedMessage <FormattedMessage

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

@@ -147,14 +147,6 @@ const EmojiPicker = ({
infiniteLoaderRef?.current?._listRef?.scrollToItem(0, 'start'); infiniteLoaderRef?.current?._listRef?.scrollToItem(0, 'start');
}, [filter]); }, [filter]);
// scroll as little as possible on cursor navigation
useEffect(() => {
if (cursor.emojiId) {
// eslint-disable-next-line no-underscore-dangle
infiniteLoaderRef?.current?._listRef?.scrollToItem(cursor.rowIndex, 'auto');
}
}, [cursor.rowIndex]);
const focusOnSearchInput = useCallback(() => { const focusOnSearchInput = useCallback(() => {
searchInputRef.current?.focus(); searchInputRef.current?.focus();
}, []); }, []);
@@ -209,6 +201,9 @@ const EmojiPicker = ({
emojiId: '', emojiId: '',
emoji: undefined, emoji: undefined,
}); });
// eslint-disable-next-line no-underscore-dangle
infiniteLoaderRef.current?._listRef?.scrollTo(0);
}, []); }, []);
const onAddCustomEmojiClickInner = useCallback(() => { const onAddCustomEmojiClickInner = useCallback(() => {
@@ -348,6 +343,9 @@ const EmojiPicker = ({
emojiId: newCursor.emojiId, emojiId: newCursor.emojiId,
emoji: newCursorEmoji, emoji: newCursorEmoji,
}); });
// eslint-disable-next-line no-underscore-dangle
infiniteLoaderRef?.current?._listRef?.scrollToItem(newCursor.rowIndex, 'auto');
}; };
const handleEnterOnEmoji = useCallback(() => { const handleEnterOnEmoji = useCallback(() => {
@@ -378,10 +376,7 @@ const EmojiPicker = ({
const areSearchResultsEmpty = filter.length !== 0 && categoryOrEmojisRows.length === 1 && categoryOrEmojisRows?.[0]?.items?.[0]?.categoryName === SEARCH_RESULTS; const areSearchResultsEmpty = filter.length !== 0 && categoryOrEmojisRows.length === 1 && categoryOrEmojisRows?.[0]?.items?.[0]?.categoryName === SEARCH_RESULTS;
return ( return (
<div <>
className='emoji-picker__inner'
role='application'
>
<div <div
aria-live='assertive' aria-live='assertive'
className='sr-only' className='sr-only'
@@ -456,7 +451,7 @@ const EmojiPicker = ({
onClick={onAddCustomEmojiClickInner} onClick={onAddCustomEmojiClickInner}
/> />
</div> </div>
</div> </>
); );
}; };

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

@@ -42,6 +42,7 @@ export default function EmojiPickerTabs(props: Props) {
aria-label={activeKey === 1 ? intl.formatMessage({id: 'emoji_gif_picker.dialog.emojis', defaultMessage: 'Emoji Picker'}) : intl.formatMessage({id: 'emoji_gif_picker.dialog.gifs', defaultMessage: 'GIF Picker'})} aria-label={activeKey === 1 ? intl.formatMessage({id: 'emoji_gif_picker.dialog.emojis', defaultMessage: 'Emoji Picker'}) : intl.formatMessage({id: 'emoji_gif_picker.dialog.gifs', defaultMessage: 'GIF Picker'})}
aria-modal='true' aria-modal='true'
> >
<EmojiPickerHeader handleEmojiPickerClose={props.onEmojiClose}/>
<Tabs <Tabs
id='emoji-picker-tabs' id='emoji-picker-tabs'
defaultActiveKey={1} defaultActiveKey={1}
@@ -51,7 +52,6 @@ export default function EmojiPickerTabs(props: Props) {
activeKey={activeKey} activeKey={activeKey}
onSelect={(activeKey) => setActiveKey(activeKey)} onSelect={(activeKey) => setActiveKey(activeKey)}
> >
<EmojiPickerHeader handleEmojiPickerClose={props.onEmojiClose}/>
<Tab <Tab
eventKey={1} eventKey={1}
title={ title={

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

@@ -44,7 +44,7 @@ function GifPickerSearch(props: Props) {
return ( return (
<div className='emoji-picker__search-container'> <div className='emoji-picker__search-container'>
<div className='emoji-picker__text-container'> <div className='emoji-picker__text-container gif-picker__text-container'>
<span className='icon-magnify icon emoji-picker__search-icon'/> <span className='icon-magnify icon emoji-picker__search-icon'/>
<input <input
id='emojiPickerSearch' id='emojiPickerSearch'

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

@@ -34,7 +34,7 @@ const GifPicker = (props: Props) => {
}, [props.getRootPickerNode]); }, [props.getRootPickerNode]);
return ( return (
<div> <>
<GifPickerSearch <GifPickerSearch
value={props.filter} value={props.filter}
onChange={props.handleFilterChange} onChange={props.handleFilterChange}
@@ -44,7 +44,7 @@ const GifPicker = (props: Props) => {
filter={props.filter} filter={props.filter}
onClick={handleItemClick} onClick={handleItemClick}
/> />
</div> </>
); );
}; };

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

@@ -70,3 +70,35 @@
.custom-emoji-tab__icon { .custom-emoji-tab__icon {
margin-right: 7px; margin-right: 7px;
} }
#emoji-picker-tabs {
display: flex;
// These prevent a flex element from overflowing its parent
min-width: 0;
min-height: 0;
flex: 1;
flex-direction: column;
.tab-content {
display: flex;
// These prevent a flex element from overflowing its parent
min-width: 0;
min-height: 0;
flex: 1;
.tab-pane {
display: flex;
// These prevent a flex element from overflowing its parent
min-width: 0;
min-height: 0;
flex: 1;
flex-direction: column;
}
}
}

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

@@ -100,16 +100,6 @@
@include mixins.clearfix; @include mixins.clearfix;
.emoji-picker__header {
background: var(--sidebar-header-bg);
}
&.emoji-picker--single {
.emoji-picker__header {
position: relative;
}
}
.browser--ie & { .browser--ie & {
width: 325px; width: 325px;
} }
@@ -135,11 +125,11 @@
} }
a { a {
height: 40px;
padding: 7px 12px; padding: 7px 12px;
border: none !important; border: none !important;
border-bottom: 2px solid transparent !important; border-bottom: 2px solid transparent !important;
margin-right: 5px; margin-right: 5px;
margin-bottom: 0;
margin-left: 5px; margin-left: 5px;
background: transparent; background: transparent;
outline: none; outline: none;
@@ -153,8 +143,6 @@
&.active { &.active {
a { a {
height: 34px;
padding-top: 9px;
border-radius: 0; border-radius: 0;
margin-right: 5px; margin-right: 5px;
margin-left: 5px; margin-left: 5px;
@@ -226,15 +214,12 @@
} }
} }
.emoji-picker__header, .emoji-picker__header {
.modal-body .emoji-picker .emoji-picker__header {
position: absolute;
top: 0; top: 0;
display: none; // only visible < 480px width screen display: none; // only visible < 480px width screen
width: 100%; width: 100%;
padding: 13px 10px 13px 15px; padding: 13px 10px 13px 15px;
border: 1px solid variables.$light-gray; background: var(--sidebar-header-bg);
background: variables.$primary-color;
color: var(--sidebar-header-text-color); color: var(--sidebar-header-text-color);
.emoji-picker__header-title { .emoji-picker__header-title {
@@ -255,23 +240,16 @@
} }
} }
.modal-body .emoji-picker .emoji-picker__header {
.emoji-picker__header-title {
margin-top: 0;
}
}
.emoji-picker__search-container { .emoji-picker__search-container {
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
border-color: transparent !important;
margin: 12px; margin: 12px;
.skin-tones-animation { .skin-tones-animation {
&-enter { &-enter {
transform: translateX(100%); transform: translateX(calc(100% - 32px));
} }
&-enter-active { &-enter-active {
@@ -279,30 +257,34 @@
transition: transform 200ms ease-in-out; transition: transform 200ms ease-in-out;
} }
&-enter-done {
transform: translateX(0%);
}
&-exit { &-exit {
position: absolute;
width: 100%;
transform: translateX(0%); transform: translateX(0%);
} }
&-exit-active { &-exit-active {
transform: translateX(90%); transform: translateX(calc(100% - 32px));
transition: transform 200ms ease-in-out; transition: transform 200ms ease-in-out;
} }
} }
.skin-tones { .skin-tones {
position: absolute;
z-index: 10; z-index: 10;
right: 0;
bottom: 0;
display: flex; display: flex;
height: 100%; height: 100%;
align-items: center; align-items: center;
background: var(--center-channel-bg); background: var(--center-channel-bg);
margin-inline-start: 8px;
&--active { &--active {
position: absolute; position: absolute;
width: 100%; width: fit-content;
justify-content: space-around; justify-content: flex-start;
.skin-tones__close, .skin-tones__close,
.skin-tones__icons { .skin-tones__icons {
@@ -351,13 +333,15 @@
} }
.emoji-picker__text-container { .emoji-picker__text-container {
position: relative;
z-index: 5;
width: 100%;
height: 32px; height: 32px;
flex: 1;
border: 1px solid rgba(var(--center-channel-color-rgb), 0.24); border: 1px solid rgba(var(--center-channel-color-rgb), 0.24);
border-radius: 4px; border-radius: 4px;
&:not(.gif-picker__text-container) {
margin-right: 40px;
}
&:focus-within { &:focus-within {
border: 2px solid functions.v(button-bg); border: 2px solid functions.v(button-bg);
@@ -459,8 +443,8 @@
} }
.gif-attribution { .gif-attribution {
padding: 5px 0 5px 5px;
margin-inline-start: 8px; margin-inline-start: 8px;
padding-inline-start: 5px;
& > img { & > img {
width: 100%; width: 100%;
@@ -476,14 +460,13 @@ $emoji-footer-height: $emoji-footer-border-width + $emoji-half-height + $emoji-
.emoji-picker__items { .emoji-picker__items {
position: relative; position: relative;
width: 100%;
height: 270px;
padding: 4px 0 4px 12px;
border-top-width: 1px; border-top-width: 1px;
border-top-style: solid; border-top-style: solid;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
padding-block: 4px;
padding-inline: 0px;
&:has(.no-results__wrapper) { &:has(.no-results__wrapper) {
display: flex; display: flex;
@@ -507,11 +490,11 @@ $emoji-footer-height: $emoji-footer-border-width + $emoji-half-height + $emoji-
.emoji-picker__category-header { .emoji-picker__category-header {
position: relative; position: relative;
padding-top: 3px; align-content: center;
margin-top: 6px;
color: rgba(var(--center-channel-color-rgb), 0.48); color: rgba(var(--center-channel-color-rgb), 0.48);
font-size: 12px; font-size: 12px;
font-weight: bold; font-weight: bold;
line-height: normal;
text-transform: uppercase; text-transform: uppercase;
} }
@@ -531,6 +514,8 @@ $emoji-footer-height: $emoji-footer-border-width + $emoji-half-height + $emoji-
.emoji-picker__row { .emoji-picker__row {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
padding-inline-end: 4px;
padding-inline-start: 12px;
} }
.emoji-picker__item { .emoji-picker__item {
@@ -578,10 +563,6 @@ $emoji-footer-height: $emoji-footer-border-width + $emoji-half-height + $emoji-
background-color: rgba(var(--center-channel-color-rgb), 0.32); background-color: rgba(var(--center-channel-color-rgb), 0.32);
} }
> div {
text-align: center;
}
img { img {
position: relative; position: relative;
transition: transform 0.2s ease-in-out; transition: transform 0.2s ease-in-out;

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

@@ -378,41 +378,19 @@
} }
.emoji-picker { .emoji-picker {
// !important is used to overide inline styles display: flex;
// used on larger screens width: 100vw;
top: 0 !important; height: 100vh;
right: auto !important; flex-direction: column;
bottom: auto !important;
left: 0 !important;
width: 100%;
height: 100%;
border-radius: 0; border-radius: 0;
margin-right: 0;
>ul {
margin-top: 66px;
}
.search-grid-container { .search-grid-container {
height: calc(100vh - 170px); height: calc(100vh - 170px);
} }
} }
.emoji-picker__inner { .emoji-picker__header {
display: flex;
height: calc(100vh - 100px);
flex-direction: column;
.emoji-picker--single & {
height: calc(100vh - 55px);
}
>* {
flex-grow: 0;
}
}
.emoji-picker__header,
.modal-body .emoji-picker .emoji-picker__header {
display: block; display: block;
} }
@@ -423,19 +401,10 @@
} }
} }
.emoji-picker__search-container {
height: 40px;
.emoji-picker__text-container {
width: 95%;
}
}
.emoji-picker__items { .emoji-picker__items {
flex-grow: 1; flex: 1;
.emoji-picker__category-header { .emoji-picker__category-header {
padding-top: 8px;
font-size: 14px; font-size: 14px;
} }
} }
@@ -444,20 +413,7 @@
width: calc(100% / 15); width: calc(100% / 15);
height: auto; height: auto;
padding: 0; padding: 0;
padding-top: calc(100% / 15); margin-inline: calc(100% / 45);
margin: calc(100% / 45);
> div {
position: absolute;
top: 50%;
left: 50%;
display: flex;
width: 30px;
height: 30px;
align-items: center;
justify-content: center;
transform: translate(-50%, -50%);
}
} }
.emoji-picker__preview { .emoji-picker__preview {
@@ -1815,7 +1771,6 @@
.emoji-picker__item { .emoji-picker__item {
width: calc(100% / #{variables.$emoji-per-row}); width: calc(100% / #{variables.$emoji-per-row});
padding-top: calc(100% / #{variables.$emoji-per-row});
margin: 0; margin: 0;
} }

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

@@ -24,7 +24,7 @@ $announcement-bar-height: 40px;
$backstage-bar-height: 43px; $backstage-bar-height: 43px;
// Random variables // Random variables
$emoji-per-row: 9; // needs to match variable `EMOJI_PER_ROW` in emoji_picker.jsx $emoji-per-row: 9; // needs to match variable `EMOJI_PER_ROW` in components/emoji_picker/constants/index.ts
// Transition timing defaults // Transition timing defaults
$transition-quick: 0.12s; $transition-quick: 0.12s;

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

@@ -323,7 +323,6 @@ export function applyTheme(theme: Theme) {
changeCss('.app__body .channel-header .pinned-posts-button svg', 'fill:' + changeOpacity(theme.centerChannelColor, 0.75)); changeCss('.app__body .channel-header .pinned-posts-button svg', 'fill:' + changeOpacity(theme.centerChannelColor, 0.75));
changeCss('.app__body .channel-header .channel-header_plugin-dropdown svg', 'fill:' + changeOpacity(theme.centerChannelColor, 0.75)); changeCss('.app__body .channel-header .channel-header_plugin-dropdown svg', 'fill:' + changeOpacity(theme.centerChannelColor, 0.75));
changeCss('.app__body .file-preview, .app__body .post-image__details, .app__body .markdown__table th, .app__body .markdown__table td, .app__body .webhooks__container, .app__body .dropdown-menu', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2)); changeCss('.app__body .file-preview, .app__body .post-image__details, .app__body .markdown__table th, .app__body .markdown__table td, .app__body .webhooks__container, .app__body .dropdown-menu', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
changeCss('.emoji-picker .emoji-picker__header', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
changeCss('.app__body .popover.bottom>.arrow', 'border-bottom-color:' + changeOpacity(theme.centerChannelColor, 0.25)); changeCss('.app__body .popover.bottom>.arrow', 'border-bottom-color:' + changeOpacity(theme.centerChannelColor, 0.25));
changeCss('.app__body .btn.btn-transparent', 'color:' + changeOpacity(theme.centerChannelColor, 0.7)); changeCss('.app__body .btn.btn-transparent', 'color:' + changeOpacity(theme.centerChannelColor, 0.7));
changeCss('.app__body .popover.right>.arrow', 'border-right-color:' + changeOpacity(theme.centerChannelColor, 0.25)); changeCss('.app__body .popover.right>.arrow', 'border-right-color:' + changeOpacity(theme.centerChannelColor, 0.25));
@@ -366,7 +365,7 @@ export function applyTheme(theme: Theme) {
changeCss('.app__body .emoji-picker', 'color:' + theme.centerChannelColor); changeCss('.app__body .emoji-picker', 'color:' + theme.centerChannelColor);
changeCss('.app__body .emoji-picker', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2)); changeCss('.app__body .emoji-picker', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
changeCss('.app__body .emoji-picker__search-icon', 'color:' + changeOpacity(theme.centerChannelColor, 0.4)); changeCss('.app__body .emoji-picker__search-icon', 'color:' + changeOpacity(theme.centerChannelColor, 0.4));
changeCss('.app__body .emoji-picker__preview, .app__body .emoji-picker__items, .app__body .emoji-picker__search-container', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2)); changeCss('.app__body .emoji-picker__preview, .app__body .emoji-picker__items', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
changeCss('.emoji-picker__category .fa:hover', 'color:' + changeOpacity(theme.centerChannelColor, 0.8)); changeCss('.emoji-picker__category .fa:hover', 'color:' + changeOpacity(theme.centerChannelColor, 0.8));
changeCss('.app__body .emoji-picker__item-wrapper:hover', 'background-color:' + changeOpacity(theme.centerChannelColor, 0.8)); changeCss('.app__body .emoji-picker__item-wrapper:hover', 'background-color:' + changeOpacity(theme.centerChannelColor, 0.8));
changeCss('.app__body .icon__postcontent_picker:hover', 'color:' + changeOpacity(theme.centerChannelColor, 0.8)); changeCss('.app__body .icon__postcontent_picker:hover', 'color:' + changeOpacity(theme.centerChannelColor, 0.8));