Skip to content

Commit

Permalink
Fix chatFormatter Toolbar UI
Browse files Browse the repository at this point in the history
  • Loading branch information
abirc8010 committed Dec 17, 2024
1 parent 1058405 commit 00baef5
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 52 deletions.
20 changes: 12 additions & 8 deletions packages/react/src/views/ChatInput/ChatInput.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,14 @@ export const getChatInputStyles = (theme) => {
justify-content: center;
flex-direction: row;
padding: 0.5rem;
@media (max-width: 383px) {
min-height: 100px;
}
`,

iconCursor: css`
cursor: pointer;
`,

textInput: css`
min-width: 0;
flex: 1;
word-wrap: break-word;
white-space: pre-wrap;
Expand All @@ -54,7 +52,7 @@ export const getChatInputStyles = (theme) => {
&::placeholder {
padding-left: 5px;
}
@media (max-width: 383px) {
@media (min-width: 383px) {
font-size: 18px;
}
`,
Expand All @@ -80,10 +78,16 @@ export const getChatInputFormattingToolbarStyles = ({ theme, mode }) => {
position: relative;
gap: 0.1rem;
border-radius: 0 0 ${theme.radius} ${theme.radius};
@media (max-width: 383px) {
display: grid;
grid-template-columns: repeat(5, 0.2fr);
}
`,
popOverStyles: css`
position: absolute;
bottom: 4rem;
left: 0;
border: 1px solid ${theme.colors.border};
z-index: 1000;
background-color: ${theme.colors.background};
border-radius: 4px;
padding: 1rem;
`,
};
return styles;
Expand Down
180 changes: 136 additions & 44 deletions packages/react/src/views/ChatInput/ChatInputFormattingToolbar.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useRef, useEffect } from 'react';
import { css } from '@emotion/react';
import {
Box,
Expand Down Expand Up @@ -40,6 +40,20 @@ const ChatInputFormattingToolbar = ({
);

const [isEmojiOpen, setEmojiOpen] = useState(false);
const [isPopoverOpen, setPopoverOpen] = useState(false);
const popoverRef = useRef(null);
useEffect(() => {
const handleClickOutside = (event) => {
if (popoverRef.current && !popoverRef.current.contains(event.target)) {
setPopoverOpen(false);
}
};

document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);

const handleClickToOpenFiles = () => {
inputRef.current.click();
Expand All @@ -54,72 +68,150 @@ const ChatInputFormattingToolbar = ({
triggerButton?.(null, message);
};

const handleFormatterClick = (item) => {
formatSelection(messageRef, item.pattern);
setPopoverOpen(false);
};

const chatToolMap = {
emoji: (
<Tooltip text="Emoji" position="top" key="emoji-btn">
<ActionButton
square
ghost
disabled={isRecordingMessage}
onClick={() => {
setEmojiOpen(true);
}}
>
<Icon name="emoji" size="1.25rem" />
</ActionButton>
</Tooltip>
),
audio: (
<Tooltip text="Audio Message" position="top" key="audio">
<AudioMessageRecorder />
</Tooltip>
),
video: (
<Tooltip text="Video Message" position="top" key="video">
<ActionButton
square
ghost
disabled={isRecordingMessage}
onClick={() => {}}
>
<VideoMessageRecorder />
</Tooltip>
</ActionButton>
),
file: (
<Tooltip text="Upload File" position="top" key="file">
<ActionButton
square
ghost
disabled={isRecordingMessage}
onClick={handleClickToOpenFiles}
>
<Icon name="attachment" size="1.25rem" />
</ActionButton>
),
};

return (
<Box
css={styles.chatFormat}
className={`ec-chat-input-formatting-toolbar ${classNames}`}
style={styleOverrides}
>
<Tooltip text="Emoji" position="top" key="emoji-btn">
<ActionButton
square
ghost
disabled={isRecordingMessage}
onClick={handleClickToOpenFiles}
onClick={() => {
setEmojiOpen(true);
}}
>
<Icon name="attachment" size="1.25rem" />
<Icon name="emoji" size="1.25rem" />
</ActionButton>
</Tooltip>
),
formatter: formatters
.map((name) => formatter.find((item) => item.name === name))
.map((item) => (
<Tooltip text={item.name} position="top" key={`formatter-${item.name}`}>

<Box
css={css`
display: flex;
@media (max-width: 400px) {
display: none;
}
`}
>
{formatters
.map((name) => formatter.find((item) => item.name === name))
.map((item) => (
<Tooltip
text={item.name}
position="top"
key={`formatter-${item.name}`}
>
<ActionButton
square
disabled={isRecordingMessage}
ghost
onClick={() => {
formatSelection(messageRef, item.pattern);
}}
>
<Icon
disabled={isRecordingMessage}
name={item.name}
size="1.25rem"
/>
</ActionButton>
</Tooltip>
))}

{['audio', 'file', 'video'].map((key) => chatToolMap[key])}
</Box>

<Box
css={css`
@media (min-width: 400px) {
display: none;
}
`}
>
<Tooltip text="More" position="top" key="more-btn">
<ActionButton
square
disabled={isRecordingMessage}
ghost
onClick={() => {
formatSelection(messageRef, item.pattern);
}}
disabled={isRecordingMessage}
onClick={() => setPopoverOpen(true)}
>
<Icon
disabled={isRecordingMessage}
name={item.name}
size="1.25rem"
/>
<Icon name="kebab" size="1.25rem" />
</ActionButton>
</Tooltip>
)),
};
</Box>

return (
<Box
css={styles.chatFormat}
className={`ec-chat-input-formatting-toolbar ${classNames}`}
style={styleOverrides}
>
{surfaceItems.map((key) => chatToolMap[key])}
{isPopoverOpen && (
<Box ref={popoverRef} css={styles.popOverStyles}>
{formatters
.map((name) => formatter.find((item) => item.name === name))
.map((item) => (
<ActionButton
key={item.name}
square
disabled={isRecordingMessage}
ghost
onClick={() => handleFormatterClick(item)}
css={css`
padding: 8px;
cursor: pointer;
`}
>
<Icon
disabled={isRecordingMessage}
name={item.name}
size="1.25rem"
/>
</ActionButton>
))}
{['video', 'file'].map((key) => (
<Box
key={key}
css={css`
padding: 8px;
`}
>
{chatToolMap[key]}
</Box>
))}
</Box>
)}

{surfaceItems.includes('audio') && chatToolMap.audio}

{isEmojiOpen && (
<EmojiPicker
Expand All @@ -132,7 +224,7 @@ const ChatInputFormattingToolbar = ({
positionStyles={css`
position: absolute;
bottom: 7rem;
left: 1.85rem;
left: 0.7rem;
`}
/>
)}
Expand Down

0 comments on commit 00baef5

Please sign in to comment.