Reworked mobile UI for some components
This commit is contained in:
@@ -65,9 +65,9 @@ export default function ChatContainer(props: Props) {
|
||||
|
||||
const MessagesTable = useMemo(
|
||||
() => (
|
||||
<>
|
||||
<div style={{ height: '100%' }}>
|
||||
<Virtuoso
|
||||
style={{ height: isMobile ? 500 : '77vh', width: 'auto' }}
|
||||
style={{ height: '100%', width: 'auto' }}
|
||||
ref={chatContainerRef}
|
||||
initialTopMostItemIndex={messages.length - 1} // Force alignment to bottom
|
||||
data={messages}
|
||||
@@ -92,7 +92,7 @@ export default function ChatContainer(props: Props) {
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
),
|
||||
[messages, usernameToHighlight, chatUserId, isModerator, atBottom, isMobile],
|
||||
);
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
interface Props {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export default function ChatTextField(props: Props) {
|
||||
const [value, setValue] = useState('');
|
||||
const [showEmojis, setShowEmojis] = useState(false);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
value={value}
|
||||
onChange={e => setValue(e.target.value)}
|
||||
placeholder="Type a message here then hit ENTER"
|
||||
/>
|
||||
<button type="button" onClick={() => setShowEmojis(!showEmojis)}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="icon"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -7,48 +7,62 @@
|
||||
overflow-x: hidden;
|
||||
div[role=textbox] {
|
||||
font-size: 0.9rem;
|
||||
border-radius: .2rem;
|
||||
padding: .6rem;
|
||||
padding-right: calc(0.6rem + 44px);
|
||||
border-radius: .35rem;
|
||||
background-color: var(--color-owncast-gray-700);
|
||||
box-shadow: 0;
|
||||
transition: box-shadow 50ms ease-in-out;
|
||||
&:focus {
|
||||
box-shadow: inset 0px 0px 0x 1px var(--color-owncast-purple-700);
|
||||
outline: 1px solid var(--color-owncast-gray-500) !important;
|
||||
}
|
||||
& > p {
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.inputWrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin-right: .3rem;
|
||||
border-radius: .2rem;
|
||||
& > div {
|
||||
transition: box-shadow .2s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.emojiButton {
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
padding: 0 1rem;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
svg {
|
||||
fill: var(--color-owncast-gray-300);
|
||||
}
|
||||
}
|
||||
|
||||
.submitButtonWrapper {
|
||||
display: flex;
|
||||
padding: 6px 0;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.inputWrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
border-radius: var(--theme-rounded-corners);
|
||||
outline: 1px solid var(--color-owncast-gray-500);
|
||||
&:hover {
|
||||
box-shadow: 0 0 1px 1px var(--color-owncast-gray-300);
|
||||
}
|
||||
& > div {
|
||||
transition: box-shadow .2s ease-in-out;
|
||||
&:focus {
|
||||
// box-shadow: 0 0 1px 1px var(--color-owncast-gray-300);
|
||||
|
||||
|
||||
.mobile {
|
||||
&.root {
|
||||
display: flex;
|
||||
.inputWrapper {
|
||||
flex: 1;
|
||||
}
|
||||
.submitButtonWrapper {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.emojiButton {
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
padding: 0 1rem;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
svg {
|
||||
fill: var(--color-owncast-gray-300);
|
||||
}
|
||||
}
|
||||
|
||||
.submitButtonWrapper {
|
||||
display: flex;
|
||||
padding: 6px 0;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,10 @@ import React, { useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { Transforms, createEditor, BaseEditor, Text } from 'slate';
|
||||
import { Slate, Editable, withReact, ReactEditor } from 'slate-react';
|
||||
import cn from 'classnames';
|
||||
import EmojiPicker from './EmojiPicker';
|
||||
import WebsocketService from '../../../services/websocket-service';
|
||||
import { websocketServiceAtom } from '../../stores/ClientConfigStore';
|
||||
import { isMobileAtom, websocketServiceAtom } from '../../stores/ClientConfigStore';
|
||||
import { MessageType } from '../../../interfaces/socket-events';
|
||||
import s from './ChatTextField.module.scss';
|
||||
|
||||
@@ -101,6 +102,7 @@ export default function ChatTextField(props: Props) {
|
||||
// const { value: originalValue } = props;
|
||||
const [showEmojis, setShowEmojis] = useState(false);
|
||||
const websocketService = useRecoilValue<WebsocketService>(websocketServiceAtom);
|
||||
const isMobile = useRecoilValue<boolean>(isMobileAtom);
|
||||
const [editor] = useState(() => withImages(withReact(createEditor())));
|
||||
|
||||
const sendMessage = () => {
|
||||
@@ -120,7 +122,7 @@ export default function ChatTextField(props: Props) {
|
||||
|
||||
const handleChange = () => {};
|
||||
|
||||
const handleEmojiSelect = e => {
|
||||
const handleEmojiSelect = (e: any) => {
|
||||
ReactEditor.focus(editor);
|
||||
|
||||
if (e.url) {
|
||||
@@ -134,7 +136,7 @@ export default function ChatTextField(props: Props) {
|
||||
}
|
||||
};
|
||||
|
||||
const onKeyDown = e => {
|
||||
const onKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
sendMessage();
|
||||
@@ -142,7 +144,11 @@ export default function ChatTextField(props: Props) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={s.root}>
|
||||
<div
|
||||
className={cn(s.root, {
|
||||
[s.mobile]: isMobile,
|
||||
})}
|
||||
>
|
||||
<div className={s.inputWrapper}>
|
||||
<Slate
|
||||
editor={editor}
|
||||
@@ -167,9 +173,13 @@ export default function ChatTextField(props: Props) {
|
||||
</button>
|
||||
</div>
|
||||
<div className={s.submitButtonWrapper}>
|
||||
<Button size="middle" type="primary" icon={<SendOutlined />} onClick={sendMessage}>
|
||||
Send
|
||||
</Button>
|
||||
{isMobile ? (
|
||||
<Button size="large" type="ghost" icon={<SendOutlined />} onClick={sendMessage} />
|
||||
) : (
|
||||
<Button type="primary" icon={<SendOutlined />} onClick={sendMessage}>
|
||||
Send
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<Popover
|
||||
content={<EmojiPicker onEmojiSelect={handleEmojiSelect} />}
|
||||
|
||||
Reference in New Issue
Block a user