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
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
291d5a2ba7
Коммит
80b61ad79b
@@ -3,155 +3,150 @@
|
||||
exports[`components/emoji_picker/EmojiPicker should match snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="emoji-picker__inner"
|
||||
role="application"
|
||||
aria-live="assertive"
|
||||
class="sr-only"
|
||||
>
|
||||
grinning emoji
|
||||
</div>
|
||||
<div
|
||||
class="emoji-picker__search-container"
|
||||
>
|
||||
<div
|
||||
aria-live="assertive"
|
||||
class="sr-only"
|
||||
class="emoji-picker__text-container"
|
||||
>
|
||||
grinning emoji
|
||||
<span
|
||||
class="icon-magnify icon emoji-picker__search-icon"
|
||||
/>
|
||||
<input
|
||||
aria-label="Search for an emoji"
|
||||
autocomplete="off"
|
||||
class="emoji-picker__search"
|
||||
data-testid="emojiInputSearch"
|
||||
id="emojiPickerSearch"
|
||||
placeholder="Search emojis"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
</div>
|
||||
<div
|
||||
class="emoji-picker__categories"
|
||||
data-testid="emojiPickerCategories"
|
||||
id="emojiPickerCategories"
|
||||
>
|
||||
<button
|
||||
aria-label="Smileys & Emotion"
|
||||
aria-pressed="true"
|
||||
class="style--none emoji-picker__category emoji-picker__category--selected"
|
||||
>
|
||||
<i
|
||||
class="icon-emoticon-happy-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="People & Body"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-account-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Animals & Nature"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-leaf-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Food & Drink"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-food-apple"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Travel & Places"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-airplane-variant"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Activities"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-basketball"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Objects"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-lightbulb-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Symbols"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-heart-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Flags"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-flag-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Custom"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-emoticon-custom-outline"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="emoji-picker__items"
|
||||
style="height: 290px;"
|
||||
>
|
||||
<div
|
||||
class="emoji-picker__search-container"
|
||||
aria-labelledby="emojiPickerSearch"
|
||||
class="emoji-picker__container"
|
||||
role="grid"
|
||||
>
|
||||
<div
|
||||
class="emoji-picker__text-container"
|
||||
>
|
||||
<span
|
||||
class="icon-magnify icon emoji-picker__search-icon"
|
||||
/>
|
||||
<input
|
||||
aria-label="Search for an emoji"
|
||||
autocomplete="off"
|
||||
class="emoji-picker__search"
|
||||
data-testid="emojiInputSearch"
|
||||
id="emojiPickerSearch"
|
||||
placeholder="Search emojis"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
style="overflow: visible; height: 0px; width: 0px;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="emoji-picker__footer"
|
||||
>
|
||||
<div
|
||||
class="emoji-picker__categories"
|
||||
data-testid="emojiPickerCategories"
|
||||
id="emojiPickerCategories"
|
||||
class="emoji-picker__preview"
|
||||
>
|
||||
<button
|
||||
aria-label="Smileys & Emotion"
|
||||
aria-pressed="true"
|
||||
class="style--none emoji-picker__category emoji-picker__category--selected"
|
||||
>
|
||||
<i
|
||||
class="icon-emoticon-happy-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="People & Body"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-account-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Animals & Nature"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-leaf-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Food & Drink"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-food-apple"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Travel & Places"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-airplane-variant"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Activities"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-basketball"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Objects"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-lightbulb-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Symbols"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-heart-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Flags"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-flag-outline"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Custom"
|
||||
aria-pressed="false"
|
||||
class="style--none emoji-picker__category"
|
||||
>
|
||||
<i
|
||||
class="icon-emoticon-custom-outline"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="emoji-picker__items"
|
||||
style="height: 290px;"
|
||||
>
|
||||
<div
|
||||
aria-labelledby="emojiPickerSearch"
|
||||
class="emoji-picker__container"
|
||||
role="grid"
|
||||
>
|
||||
<div
|
||||
style="overflow: visible; height: 0px; width: 0px;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="emoji-picker__footer"
|
||||
>
|
||||
<div
|
||||
class="emoji-picker__preview"
|
||||
>
|
||||
Preview for grinning emoji
|
||||
</div>
|
||||
Preview for grinning emoji
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`components/emoji_picker/components/EmojiPickerHeader handleEmojiPickerClose, should have called props.handleEmojiPickerClose 1`] = `
|
||||
<div
|
||||
className="emoji-picker__header modal-header"
|
||||
className="emoji-picker__header"
|
||||
>
|
||||
<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`] = `
|
||||
<div
|
||||
className="emoji-picker__header modal-header"
|
||||
className="emoji-picker__header"
|
||||
>
|
||||
<button
|
||||
className="close emoji-picker__header-close-button"
|
||||
|
||||
@@ -15,7 +15,7 @@ interface Props {
|
||||
function EmojiPickerCategoryRow({categoryName, style}: Props) {
|
||||
return (
|
||||
<div
|
||||
className='emoji-picker-items__container'
|
||||
className='emoji-picker__row'
|
||||
style={style}
|
||||
role='row'
|
||||
>
|
||||
|
||||
@@ -11,7 +11,7 @@ type Props = {
|
||||
|
||||
const EmojiPickerHeader = ({handleEmojiPickerClose}: Props) => {
|
||||
return (
|
||||
<div className='emoji-picker__header modal-header'>
|
||||
<div className='emoji-picker__header'>
|
||||
<button
|
||||
type='button'
|
||||
className='close emoji-picker__header-close-button'
|
||||
|
||||
@@ -80,6 +80,7 @@ export type Props = {
|
||||
|
||||
type State = {
|
||||
pickerExtended: boolean;
|
||||
pickerMounted: boolean;
|
||||
}
|
||||
|
||||
export class EmojiPickerSkin extends React.PureComponent<Props, State> {
|
||||
@@ -88,6 +89,7 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
|
||||
|
||||
this.state = {
|
||||
pickerExtended: false,
|
||||
pickerMounted: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -109,7 +111,16 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
showSkinTonePicker = () => {
|
||||
this.setState({pickerExtended: true});
|
||||
this.setState({
|
||||
pickerExtended: true,
|
||||
pickerMounted: true,
|
||||
});
|
||||
};
|
||||
|
||||
handleSkinToneHidden = () => {
|
||||
this.setState({
|
||||
pickerMounted: false,
|
||||
});
|
||||
};
|
||||
|
||||
skinTonePickerButton() {
|
||||
@@ -194,16 +205,17 @@ export class EmojiPickerSkin extends React.PureComponent<Props, State> {
|
||||
return (
|
||||
<CSSTransition
|
||||
in={this.state.pickerExtended}
|
||||
onExited={this.handleSkinToneHidden}
|
||||
classNames='skin-tones-animation'
|
||||
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
|
||||
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'
|
||||
>
|
||||
{this.skinTonePickerButton()}
|
||||
{this.state.pickerExtended &&
|
||||
{this.state.pickerMounted &&
|
||||
<>
|
||||
<div className='skin-tones__close-text'>
|
||||
<FormattedMessage
|
||||
|
||||
@@ -147,14 +147,6 @@ const EmojiPicker = ({
|
||||
infiniteLoaderRef?.current?._listRef?.scrollToItem(0, 'start');
|
||||
}, [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(() => {
|
||||
searchInputRef.current?.focus();
|
||||
}, []);
|
||||
@@ -209,6 +201,9 @@ const EmojiPicker = ({
|
||||
emojiId: '',
|
||||
emoji: undefined,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
infiniteLoaderRef.current?._listRef?.scrollTo(0);
|
||||
}, []);
|
||||
|
||||
const onAddCustomEmojiClickInner = useCallback(() => {
|
||||
@@ -348,6 +343,9 @@ const EmojiPicker = ({
|
||||
emojiId: newCursor.emojiId,
|
||||
emoji: newCursorEmoji,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
infiniteLoaderRef?.current?._listRef?.scrollToItem(newCursor.rowIndex, 'auto');
|
||||
};
|
||||
|
||||
const handleEnterOnEmoji = useCallback(() => {
|
||||
@@ -378,10 +376,7 @@ const EmojiPicker = ({
|
||||
const areSearchResultsEmpty = filter.length !== 0 && categoryOrEmojisRows.length === 1 && categoryOrEmojisRows?.[0]?.items?.[0]?.categoryName === SEARCH_RESULTS;
|
||||
|
||||
return (
|
||||
<div
|
||||
className='emoji-picker__inner'
|
||||
role='application'
|
||||
>
|
||||
<>
|
||||
<div
|
||||
aria-live='assertive'
|
||||
className='sr-only'
|
||||
@@ -456,7 +451,7 @@ const EmojiPicker = ({
|
||||
onClick={onAddCustomEmojiClickInner}
|
||||
/>
|
||||
</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-modal='true'
|
||||
>
|
||||
<EmojiPickerHeader handleEmojiPickerClose={props.onEmojiClose}/>
|
||||
<Tabs
|
||||
id='emoji-picker-tabs'
|
||||
defaultActiveKey={1}
|
||||
@@ -51,7 +52,6 @@ export default function EmojiPickerTabs(props: Props) {
|
||||
activeKey={activeKey}
|
||||
onSelect={(activeKey) => setActiveKey(activeKey)}
|
||||
>
|
||||
<EmojiPickerHeader handleEmojiPickerClose={props.onEmojiClose}/>
|
||||
<Tab
|
||||
eventKey={1}
|
||||
title={
|
||||
|
||||
@@ -44,7 +44,7 @@ function GifPickerSearch(props: Props) {
|
||||
|
||||
return (
|
||||
<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'/>
|
||||
<input
|
||||
id='emojiPickerSearch'
|
||||
|
||||
@@ -34,7 +34,7 @@ const GifPicker = (props: Props) => {
|
||||
}, [props.getRootPickerNode]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<GifPickerSearch
|
||||
value={props.filter}
|
||||
onChange={props.handleFilterChange}
|
||||
@@ -44,7 +44,7 @@ const GifPicker = (props: Props) => {
|
||||
filter={props.filter}
|
||||
onClick={handleItemClick}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -70,3 +70,35 @@
|
||||
.custom-emoji-tab__icon {
|
||||
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;
|
||||
|
||||
.emoji-picker__header {
|
||||
background: var(--sidebar-header-bg);
|
||||
}
|
||||
|
||||
&.emoji-picker--single {
|
||||
.emoji-picker__header {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.browser--ie & {
|
||||
width: 325px;
|
||||
}
|
||||
@@ -135,11 +125,11 @@
|
||||
}
|
||||
|
||||
a {
|
||||
height: 40px;
|
||||
padding: 7px 12px;
|
||||
border: none !important;
|
||||
border-bottom: 2px solid transparent !important;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 0;
|
||||
margin-left: 5px;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
@@ -153,8 +143,6 @@
|
||||
|
||||
&.active {
|
||||
a {
|
||||
height: 34px;
|
||||
padding-top: 9px;
|
||||
border-radius: 0;
|
||||
margin-right: 5px;
|
||||
margin-left: 5px;
|
||||
@@ -226,15 +214,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-picker__header,
|
||||
.modal-body .emoji-picker .emoji-picker__header {
|
||||
position: absolute;
|
||||
.emoji-picker__header {
|
||||
top: 0;
|
||||
display: none; // only visible < 480px width screen
|
||||
width: 100%;
|
||||
padding: 13px 10px 13px 15px;
|
||||
border: 1px solid variables.$light-gray;
|
||||
background: variables.$primary-color;
|
||||
background: var(--sidebar-header-bg);
|
||||
color: var(--sidebar-header-text-color);
|
||||
|
||||
.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 {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-color: transparent !important;
|
||||
margin: 12px;
|
||||
|
||||
.skin-tones-animation {
|
||||
&-enter {
|
||||
transform: translateX(100%);
|
||||
transform: translateX(calc(100% - 32px));
|
||||
}
|
||||
|
||||
&-enter-active {
|
||||
@@ -279,30 +257,34 @@
|
||||
transition: transform 200ms ease-in-out;
|
||||
}
|
||||
|
||||
&-enter-done {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
|
||||
&-exit {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transform: translateX(0%);
|
||||
}
|
||||
|
||||
&-exit-active {
|
||||
transform: translateX(90%);
|
||||
transform: translateX(calc(100% - 32px));
|
||||
transition: transform 200ms ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.skin-tones {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
background: var(--center-channel-bg);
|
||||
margin-inline-start: 8px;
|
||||
|
||||
&--active {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
width: fit-content;
|
||||
justify-content: flex-start;
|
||||
|
||||
.skin-tones__close,
|
||||
.skin-tones__icons {
|
||||
@@ -351,13 +333,15 @@
|
||||
}
|
||||
|
||||
.emoji-picker__text-container {
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
flex: 1;
|
||||
border: 1px solid rgba(var(--center-channel-color-rgb), 0.24);
|
||||
border-radius: 4px;
|
||||
|
||||
&:not(.gif-picker__text-container) {
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
border: 2px solid functions.v(button-bg);
|
||||
|
||||
@@ -459,8 +443,8 @@
|
||||
}
|
||||
|
||||
.gif-attribution {
|
||||
padding: 5px 0 5px 5px;
|
||||
margin-inline-start: 8px;
|
||||
padding-inline-start: 5px;
|
||||
|
||||
& > img {
|
||||
width: 100%;
|
||||
@@ -476,14 +460,13 @@ $emoji-footer-height: $emoji-footer-border-width + $emoji-half-height + $emoji-
|
||||
|
||||
.emoji-picker__items {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 270px;
|
||||
padding: 4px 0 4px 12px;
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding-block: 4px;
|
||||
padding-inline: 0px;
|
||||
|
||||
&:has(.no-results__wrapper) {
|
||||
display: flex;
|
||||
@@ -507,11 +490,11 @@ $emoji-footer-height: $emoji-footer-border-width + $emoji-half-height + $emoji-
|
||||
|
||||
.emoji-picker__category-header {
|
||||
position: relative;
|
||||
padding-top: 3px;
|
||||
margin-top: 6px;
|
||||
align-content: center;
|
||||
color: rgba(var(--center-channel-color-rgb), 0.48);
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: normal;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@@ -531,6 +514,8 @@ $emoji-footer-height: $emoji-footer-border-width + $emoji-half-height + $emoji-
|
||||
.emoji-picker__row {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
padding-inline-end: 4px;
|
||||
padding-inline-start: 12px;
|
||||
}
|
||||
|
||||
.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);
|
||||
}
|
||||
|
||||
> div {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
transition: transform 0.2s ease-in-out;
|
||||
|
||||
@@ -378,41 +378,19 @@
|
||||
}
|
||||
|
||||
.emoji-picker {
|
||||
// !important is used to overide inline styles
|
||||
// used on larger screens
|
||||
top: 0 !important;
|
||||
right: auto !important;
|
||||
bottom: auto !important;
|
||||
left: 0 !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
flex-direction: column;
|
||||
border-radius: 0;
|
||||
|
||||
>ul {
|
||||
margin-top: 66px;
|
||||
}
|
||||
margin-right: 0;
|
||||
|
||||
.search-grid-container {
|
||||
height: calc(100vh - 170px);
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-picker__inner {
|
||||
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 {
|
||||
.emoji-picker__header {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -423,19 +401,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-picker__search-container {
|
||||
height: 40px;
|
||||
|
||||
.emoji-picker__text-container {
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-picker__items {
|
||||
flex-grow: 1;
|
||||
flex: 1;
|
||||
|
||||
.emoji-picker__category-header {
|
||||
padding-top: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
@@ -444,20 +413,7 @@
|
||||
width: calc(100% / 15);
|
||||
height: auto;
|
||||
padding: 0;
|
||||
padding-top: calc(100% / 15);
|
||||
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%);
|
||||
}
|
||||
margin-inline: calc(100% / 45);
|
||||
}
|
||||
|
||||
.emoji-picker__preview {
|
||||
@@ -1815,7 +1771,6 @@
|
||||
|
||||
.emoji-picker__item {
|
||||
width: calc(100% / #{variables.$emoji-per-row});
|
||||
padding-top: calc(100% / #{variables.$emoji-per-row});
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ $announcement-bar-height: 40px;
|
||||
$backstage-bar-height: 43px;
|
||||
|
||||
// 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-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 .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('.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 .btn.btn-transparent', 'color:' + changeOpacity(theme.centerChannelColor, 0.7));
|
||||
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', '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__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('.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));
|
||||
|
||||
Ссылка в новой задаче
Block a user