Skip to content

Commit

Permalink
fix(SimleysPanel):fix SimleysPanel ux
Browse files Browse the repository at this point in the history
  • Loading branch information
HazemAbdo committed Mar 28, 2024
1 parent 56eecab commit 14362b0
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 12 deletions.
17 changes: 11 additions & 6 deletions react/features/base/ui/components/web/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface IProps extends IInputProps {
* info (label, error) so that screen reader users don't get lost.
*/
id: string;
inputIconRef?: React.RefObject<any>;
maxLength?: number;
maxRows?: number;
maxValue?: number;
Expand Down Expand Up @@ -163,6 +164,7 @@ const Input = React.forwardRef<any, IProps>(({
icon,
iconClick,
id,
inputIconRef,
label,
maxValue,
maxLength,
Expand Down Expand Up @@ -199,12 +201,15 @@ const Input = React.forwardRef<any, IProps>(({
{label}
</label>}
<div className = { styles.fieldContainer }>
{icon && <Icon
{ ...(iconClick ? { tabIndex: 0 } : {}) }
className = { cx(styles.icon, iconClick && styles.iconClickable) }
onClick = { iconClick }
size = { 20 }
src = { icon } />}
{icon && <div ref = { inputIconRef }>
<Icon
{ ...(iconClick ? { tabIndex: 0 } : {}) }
className = { cx(styles.icon, iconClick && styles.iconClickable) }
onClick = { iconClick }
size = { 20 }
src = { icon } />
</div>
}
{textarea ? (
<TextareaAutosize
aria-label = { accessibilityLabel }
Expand Down
22 changes: 17 additions & 5 deletions react/features/chat/components/web/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ interface IState {
*/
class ChatInput extends Component<IProps, IState> {
_textArea?: RefObject<HTMLTextAreaElement>;
_inputIconRef?: RefObject<any>;

state = {
message: '',
Expand All @@ -77,13 +78,15 @@ class ChatInput extends Component<IProps, IState> {
super(props);

this._textArea = React.createRef<HTMLTextAreaElement>();
this._inputIconRef = React.createRef();

// Bind event handlers so they are only bound once for every instance.
this._onDetectSubmit = this._onDetectSubmit.bind(this);
this._onMessageChange = this._onMessageChange.bind(this);
this._onSmileySelect = this._onSmileySelect.bind(this);
this._onSubmitMessage = this._onSubmitMessage.bind(this);
this._toggleSmileysPanel = this._toggleSmileysPanel.bind(this);
this._closeSmileysPanel = this._closeSmileysPanel.bind(this);
}

/**
Expand Down Expand Up @@ -127,6 +130,8 @@ class ChatInput extends Component<IProps, IState> {
<div
className = 'smileys-panel' >
<SmileysPanel
closeSmileysPanel = { this._closeSmileysPanel }
inputIconRef = { this._inputIconRef }
onSmileySelect = { this._onSmileySelect } />
</div>
</div>
Expand All @@ -136,6 +141,7 @@ class ChatInput extends Component<IProps, IState> {
icon = { this.props._areSmileysDisabled ? undefined : IconFaceSmile }
iconClick = { this._toggleSmileysPanel }
id = 'chat-input-messagebox'
inputIconRef = { this._inputIconRef }
maxRows = { 5 }
onChange = { this._onMessageChange }
onKeyPress = { this._onDetectSubmit }
Expand Down Expand Up @@ -237,11 +243,7 @@ class ChatInput extends Component<IProps, IState> {
if (smileyText) {
this.setState({
message: `${this.state.message} ${smileyText}`,
showSmileysPanel: false
});
} else {
this.setState({
showSmileysPanel: false
showSmileysPanel: true
});
}

Expand All @@ -260,6 +262,16 @@ class ChatInput extends Component<IProps, IState> {
}
this.setState({ showSmileysPanel: !this.state.showSmileysPanel });
}

/**
* Closes the smileys selector.
*
* @private
* @returns {void}
*/
_closeSmileysPanel() {
this.setState({ showSmileysPanel: false });
}
}

/**
Expand Down
61 changes: 60 additions & 1 deletion react/features/chat/components/web/SmileysPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { PureComponent } from 'react';
import React, { PureComponent, RefObject } from 'react';
import Emoji from 'react-emoji-render';

import { smileys } from '../../smileys';
Expand All @@ -8,6 +8,18 @@ import { smileys } from '../../smileys';
*/
interface IProps {

/**
* Callback to invoke to close the smiley panel.
*
* @returns {void}
*/
closeSmileysPanel: Function;

/**
* Ref to input icon.
*/
inputIconRef?: RefObject<any>;

/**
* Callback to invoke when a smiley is selected. The smiley will be passed
* back.
Expand All @@ -21,6 +33,8 @@ interface IProps {
* @augments Component
*/
class SmileysPanel extends PureComponent<IProps> {
private _wrapperRef: RefObject<HTMLDivElement>;

/**
* Initializes a new {@code SmileysPanel} instance.
*
Expand All @@ -30,12 +44,37 @@ class SmileysPanel extends PureComponent<IProps> {
constructor(props: IProps) {
super(props);

this._wrapperRef = React.createRef();

// Bind event handler so it is only bound once for every instance.
this._onClick = this._onClick.bind(this);
this._onKeyPress = this._onKeyPress.bind(this);
this._onEscKey = this._onEscKey.bind(this);
this._onClickOutside = this._onClickOutside.bind(this);
}

/**
* Component lifecycle method that is called after the component has been mounted.
* Adds an event listener for the "mousedown" event on the document, which triggers the
* _onClickOutside method when a click event occurs outside of the component.
*
* @returns {void} This function does not return anything.
*/
componentDidMount() {
document.addEventListener('mousedown', this._onClickOutside);
}

/**
* Component lifecycle method that is called after the component has been unmounted.
* Removes the event listener for the "mousedown" event on the document.
*
* @returns {void} This function does not return anything.
*/
componentWillUnmount() {
document.removeEventListener('mousedown', this._onClickOutside);
}


/**
* KeyPress handler for accessibility.
*
Expand Down Expand Up @@ -78,6 +117,25 @@ class SmileysPanel extends PureComponent<IProps> {
this.props.onSmileySelect(e.currentTarget.id && smileys[e.currentTarget.id as keyof typeof smileys]);
}

/**
* Handles the click event outside of the component.
*
* @param {MouseEvent} e - The click event.
*
* @returns {void}
*/
_onClickOutside(e: MouseEvent) {
const inputIconNotClicked = this.props.inputIconRef?.current
&& !this.props.inputIconRef?.current?.contains(e.target as Node);

if (inputIconNotClicked) {
if (this._wrapperRef.current && !this._wrapperRef.current.contains(e.target as Node)) {
this.props.closeSmileysPanel();
}
}
}


/**
* Implements React's {@link Component#render()}.
*
Expand Down Expand Up @@ -106,6 +164,7 @@ class SmileysPanel extends PureComponent<IProps> {
aria-orientation = 'horizontal'
id = 'smileysContainer'
onKeyDown = { this._onEscKey }
ref = { this._wrapperRef }
role = 'listbox'
tabIndex = { -1 }>
{ smileyItems }
Expand Down

0 comments on commit 14362b0

Please sign in to comment.