From b4e4356cb7d0173c14caa0d0b33b77139cda3f01 Mon Sep 17 00:00:00 2001 From: Sharon Kennedy Date: Wed, 25 Mar 2020 19:01:29 -0400 Subject: [PATCH] add emoji selector --- package.json | 2 + src/components/_chat.scss | 151 +++++++++++++++++++++++------- src/components/chatbox.jsx | 63 +++++++++---- src/components/emoji-selector.jsx | 47 ++++++++++ src/components/emoji_icon.svg | 9 ++ yarn.lock | 10 ++ 6 files changed, 233 insertions(+), 49 deletions(-) create mode 100644 src/components/emoji-selector.jsx create mode 100644 src/components/emoji_icon.svg diff --git a/package.json b/package.json index b3ece2a..4443e08 100644 --- a/package.json +++ b/package.json @@ -117,6 +117,7 @@ }, "dependencies": { "browser-encrypt-attachment": "^0.3.0", + "emoji-picker-react": "^3.1.3", "isomorphic-fetch": "^2.2.1", "linkifyjs": "^2.1.9", "matrix-js-sdk": "^4.0.0", @@ -125,6 +126,7 @@ "prop-types": "^15.6.2", "react": "^16.8.6", "react-dom": "^16.8.6", + "react-onclickoutside": "^6.9.0", "react-test-renderer": "^16.13.0", "react-transition-group": "^4.0.0", "uuidv4": "^6.0.2" diff --git a/src/components/_chat.scss b/src/components/_chat.scss index 8dbff05..c3bac66 100644 --- a/src/components/_chat.scss +++ b/src/components/_chat.scss @@ -195,7 +195,7 @@ } &:focus { - background: $theme-light-color; + background-color: $theme-light-color; outline: none; } } @@ -366,36 +366,6 @@ margin-bottom: 0; } - input[placeholder] { - text-overflow: ellipsis; - overflow: hidden; - } - - input[type="text"] { - font-size: 1rem; - padding: 0.5rem; - border: none; - display: flex; - flex: 1 1 auto; - border: 1px solid $dark-color; - background: $white; - color: $dark-color; - font-family: $theme-font; - margin-right: 0.2rem; - transition: all 0.2s ease-in-out; - border-radius: 10px; - - &:hover { - box-shadow: inset 0px 0px 0px 1px $dark-color; - } - - &:focus { - outline: none; - box-shadow: inset 0px 0px 0px 1px $dark-color; - background: $theme-light-color; - } - } - input[type="submit"] { background-color: $theme-color; height: 100%; @@ -423,12 +393,122 @@ background-color: $theme-highlight-color; } } + + .message-input-container { + display: flex; + flex: 1 1 auto; + position: relative; + + input[type="text"] { + font-size: 1rem; + padding: 0.5rem; + padding-right: 32px; + border: none; + display: flex; + flex: 1 1 auto; + background: $white; + color: $dark-color; + font-family: $theme-font; + margin-right: 0.2rem; + transition: all 0.2s ease-in-out; + border-radius: 10px; + border: 1px solid $dark-color; + + &:hover { + box-shadow: inset 0px 0px 0px 1px $dark-color; + } + + &:focus { + outline: none; + box-shadow: inset 0px 0px 0px 1px $dark-color; + background: $theme-light-color; + } + } + + .emoji-button-container { + position: absolute; + right: 6px; + top: 0; + bottom: 0; + height: 100%; + display: flex; + align-items: center; + justify-content: flex-start; + + + button { + transition: all 0.2s ease-in-out; + + &:hover { + box-shadow: none; + } + + &:focus { + outline: none; + } + + &#emoji-button { + background: transparent; + border: none; + padding: 0; + margin-right: 3px; + transition: all 0.2s ease-in-out; + + &:hover { + svg path#icon { + fill: $theme-color; + } + } + + &:focus { + svg path#icon { + fill: $theme-highlight-color; + } + } + } + } + } + + .emoji-picker { + animation-duration: 0.2s; + animation-fill-mode: forwards; + position: absolute; + bottom: 32px; + right: -4px; + + &-entering { + animation-name: slideInUp; + opacity: 0.5; + } + &-entered { + display: inherit; + visibility: visible; + opacity: 1; + } + &-exiting { + animation-name: slideOutDown; + opacity: 0.5; + } + &-exited { + display: none; + visibility: hidden; + opacity: 0; + } + } + } } .highlight-text { color: $theme-color; } + .pos-relative { + position: relative; + } +} + +.hidden { + display: none; } @media screen and (max-width: 420px){ @@ -448,6 +528,11 @@ } } -.hidden { - display: none; +@media screen and (max-width: 360px){ + #ocrcc-chatbox .input-window .message-input-container .emoji-picker { + position: fixed; + left: 5px; + right: 5px; + bottom: 42px; + } } diff --git a/src/components/chatbox.jsx b/src/components/chatbox.jsx index b2047ab..d1ebbbd 100644 --- a/src/components/chatbox.jsx +++ b/src/components/chatbox.jsx @@ -15,6 +15,7 @@ import {uuid} from "uuidv4" import Message from "./message"; import Dock from "./dock"; import Header from "./header"; +import EmojiSelector from './emoji-selector'; import './styles.scss'; @@ -54,6 +55,7 @@ class ChatBox extends React.Component { roomId: null, typingStatus: null, awaitingAgreement: true, + emojiSelectorOpen: false, } this.state = this.initialState this.chatboxInput = React.createRef(); @@ -74,6 +76,14 @@ class ChatBox extends React.Component { }); } + toggleEmojiSelector = () => { + this.setState({ emojiSelectorOpen: !this.state.emojiSelectorOpen }) + } + + closeEmojiSelector = () => { + this.setState({ emojiSelectorOpen: false }, () => this.chatboxInput.current.focus()) + } + handleWidgetExit = () => { this.setState({ showDock: true, @@ -357,9 +367,13 @@ class ChatBox extends React.Component { } - handleEscape = (e) => { - if (e.keyCode === 27 && this.state.opened) { - this.handleToggleOpen() + handleKeyDown = (e) => { + if (e.keyCode === 27) { + if (this.state.emojiSelectorOpen) { + this.closeEmojiSelector() + } else if (this.state.opened) { + this.handleToggleOpen() + } } } @@ -413,12 +427,12 @@ class ChatBox extends React.Component { } componentDidMount() { - document.addEventListener("keydown", this.handleEscape, false); + document.addEventListener("keydown", this.handleKeyDown, false); window.addEventListener('beforeunload', this.exitChat) } componentWillUnmount() { - document.removeEventListener("keydown", this.handleEscape, false); + document.removeEventListener("keydown", this.handleKeyDown, false); window.removeEventListener('beforeunload', this.exitChat) this.exitChat(); } @@ -449,8 +463,16 @@ class ChatBox extends React.Component { } } + onEmojiClick = (event, emojiObject) => { + const { emoji } = emojiObject; + this.setState({ + inputValue: this.state.inputValue.concat(emoji), + emojiSelectorOpen: false, + }, () => this.chatboxInput.current.focus()) + } + render() { - const { ready, messages, inputValue, userId, roomId, typingStatus, opened, showDock } = this.state; + const { ready, messages, inputValue, userId, roomId, typingStatus, opened, showDock, emojiSelectorOpen } = this.state; const inputLabel = 'Send a message...' return ( @@ -501,16 +523,25 @@ class ChatBox extends React.Component {
- +
+ this.setState({ inputValue: this.state.inputValue })} + ref={this.chatboxInput} + /> + +
diff --git a/src/components/emoji-selector.jsx b/src/components/emoji-selector.jsx new file mode 100644 index 0000000..7424d82 --- /dev/null +++ b/src/components/emoji-selector.jsx @@ -0,0 +1,47 @@ +import React from "react" +import PropTypes from "prop-types" +import { Transition } from 'react-transition-group'; +import EmojiPicker from 'emoji-picker-react'; +import onClickOutside from "react-onclickoutside"; + + +const SVG = () => + +class EmojiSelector extends React.Component { + constructor(props){ + super(props) + } + + handleClickOutside = e => { + this.props.closeEmojiSelector() + }; + + + render() { + const { onEmojiClick, emojiSelectorOpen, toggleEmojiSelector } = this.props; + + return( +
+
+ + { + status => { + return( +
+ +
+ ) + } + } +
+ +
+
+ ) + } +} + +export default onClickOutside(EmojiSelector) + diff --git a/src/components/emoji_icon.svg b/src/components/emoji_icon.svg new file mode 100644 index 0000000..43da057 --- /dev/null +++ b/src/components/emoji_icon.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/yarn.lock b/yarn.lock index e997e3c..41cf607 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4765,6 +4765,11 @@ email-addresses@^3.0.1: resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-3.1.0.tgz#cabf7e085cbdb63008a70319a74e6136188812fb" integrity sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg== +emoji-picker-react@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/emoji-picker-react/-/emoji-picker-react-3.1.3.tgz#eaa48d6980701c00d24bdbfa53f44d39aa9b2380" + integrity sha512-3VfxTeR6mUsdtXM3mEp9olUSbZsIatRsJhzULujhIz4yO9YanXELwrzWN3ApK7TAniNPMcUM0Z4CzUEbh2IlvQ== + emoji-regex@^7.0.1, emoji-regex@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -10082,6 +10087,11 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-onclickoutside@^6.9.0: + version "6.9.0" + resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz#a54bc317ae8cf6131a5d78acea55a11067f37a1f" + integrity sha512-8ltIY3bC7oGhj2nPAvWOGi+xGFybPNhJM0V1H8hY/whNcXgmDeaeoCMPPd8VatrpTsUWjb/vGzrmu6SrXVty3A== + react-popper-tooltip@^2.8.3: version "2.10.1" resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.10.1.tgz#e10875f31916297c694d64a677d6f8fa0a48b4d1"