Я пишу приложение для чата на React. Текущий дизайн компонента Messenger имеет левую боковую панель, центральный блок и правую боковую панель. В идеале нижняя часть центрального блока представляет собой текстовое поле фиксированного размера, а остальная часть пространства от верхнего края до блока до верха текстового поля - это область для сообщений, которая позволяет прокручивать при переполнении.
Однако я не уверен, как добавить в свое приложение эту «прокрутку» и функциональность текстового поля фиксированного размера. В настоящее время начало текстового поля следует за последним сообщением, и когда последнее сообщение превышает размер экрана по вертикали, текстовое поле не отображается.
Может кто-нибудь подсказать, как это сделать? Вот мой код реакции, содержащий только основные элементы, а файл App.css
. При необходимости вы можете запросить дополнительный код.
Приложение. js
import React, { Component } from "react";
import "./App.css";
import classNames from "classnames";
import "./App.css";
// Components
import _ from "lodash";
const MESSENGER_HEIGHT = "height";
const MESSENGER_NEW_MESSAGE = "newMessage";
const MESSENGER_SEARCH_USER = "searchUser";
const MESSENGER_SHOW_SEARCH_USER = "showSearchUser";
const MESSENGER_ACTIVE_CHANNEL_ID = "channel_id";
const MESSENGER_MEMBERS = "members";
const MESSENGER_MESSAGES = "messages";
const MESSENGER_CHANNELS = "channels";
const MESSENGER_PROFILE_ID = "profile_id";
//remove the authentication routes
class App extends Component {
constructor(props) {
super(props);
this.state = {};
const locals = this.state;
locals[MESSENGER_HEIGHT] = window.innerHeight;
locals[MESSENGER_NEW_MESSAGE] = "";
locals[MESSENGER_SEARCH_USER] = "";
locals[MESSENGER_SHOW_SEARCH_USER] = false;
locals[MESSENGER_ACTIVE_CHANNEL_ID] = "Mk3d9WJRiyifxgtJ1Ep1"; //TODO: trial run set default one
locals[MESSENGER_MEMBERS] = ["person1", "person2"];
locals[MESSENGER_MESSAGES] = [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13"
];
locals[MESSENGER_CHANNELS] = [];
locals[MESSENGER_PROFILE_ID] = "Testing profile_id";
}
render() {
let component_variable = null;
let members_list;
//About the presence system
if (this.state.members.length > 0) {
members_list = (
<div>
<h2 className="title">Members</h2>
<div className="members">
{this.state.members.map(member => {
return (
<div className="member">
<div className="member-info">
<h2> {member}</h2>
</div>
</div>
);
})}
</div>
</div>
);
} else {
members_list = null;
}
let search_bar = null;
let messages_list;
if (this.state.messages !== undefined) {
messages_list = (
<div>
<div ref={ref => (this.messagesRef = ref)} className="messages">
{this.state.messages.map(message => {
return (
<div className={classNames("message", { me: true })}>
<div className="message-body">
<div className="message-author">{"You "} says:</div>
<div className="message-text">
{`Testing message ${message}`}
</div>
<div className="message-timestamp">Some Date</div>
</div>
</div>
);
})}
</div>
</div>
);
} else {
messages_list = null;
}
let text_box;
if (this.state.members.length > 0) {
text_box = (
<div className="messenger-input">
<div className="text-input">
<textarea
onKeyUp={this.handle_textbox_keyup}
onChange={this.handle_textbox_set_state}
value={this.state["newMessage"]}
placeholder="Write your message..."
/>
</div>
<div className="actions">
<button onClick={() => this.handleSend()} className="send">
Send
</button>
</div>
</div>
);
} else {
text_box = null;
}
return (
<div className="app-messenger">
<div className="header">
<div className="left">
<button className="left-action">
<i className="icon-settings-streamline-1" />
</button>
<button
onClick={this.handle_create_channel}
className="right-action"
>
<i className="icon-edit-modify-streamline" />
</button>
<h2>Messenger</h2>
</div>
<div className="content" />
<div className="right">Hello world</div>
</div>
<div className="main">
<div className="sidebar-left">
<div className="chanels">
{this.state.channels.map((channel, key) => {
return (
<div
onClick={key => {
this.props.select_or_create_message_room({
id: channel._id
});
}}
key={channel._id}
className={classNames("chanel", {
notify: _.get(channel, "notify") === true
})}
>
<div className="channel-id">
{channel[MESSENGER_ACTIVE_CHANNEL_ID]}
</div>
</div>
);
})}
</div>
</div>
<div className="content">
{messages_list},{text_box}
</div>
{/*TODO: Member list*/}
<div className="sidebar-right">{members_list}</div>
</div>
</div>
);
}
}
export default App;
Приложение. css
html,
/*body {*/
/* font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',*/
/* 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',*/
/* sans-serif;*/
/* background-color: rgb(245, 245, 245);*/
/*}*/
.container {
margin: 80px auto 0 auto;
max-width: 1200px;
/*Cannot hidden bc the home screen is ugly*/
}
.nav-container {
margin: auto;
}
.nav-container svg {
color: #fff;
}
a {
text-decoration: none;
}
body, html {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
body {
color: #2c3e50;
font-size: 13px;
font-family: 'Open Sans', sans-serif;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0; }
.app-messenger {
display: flex;
flex-direction: column;
}
.app-messenger .header {
height: 50px;
display: flex;
flex-direction: row;
border-bottom: 1px solid rgba(0, 0, 0, 0.05); }
.app-messenger .header .left {
width: 200px;
position: relative; }
.app-messenger .header .left .left-action {
position: absolute;
left: 8px;
top: 0; }
.app-messenger .header .left .right-action {
position: absolute;
right: 8px;
top: 0; }
.app-messenger .header .left h2 {
line-height: 50px;
font-size: 14px;
font-weight: 600;
display: block;
text-align: center; }
.app-messenger .header .left button {
background: none;
line-height: 50px;
border: 0 none;
font-size: 20px;
cursor: pointer; }
.app-messenger .header .content {
flex-grow: 1;
}
.app-messenger .header .content h2 {
line-height: 50px;
text-align: center; }
.app-messenger .header .right {
width: 300px; }
.app-messenger .header .right .user-bar {
line-height: 50px;
display: flex;
justify-content: flex-end;
padding: 0 10px; }
.app-messenger .header .right .user-bar .profile-name {
padding-right: 10px; }
.app-messenger .header .right .user-bar .profile-image {
line-height: 50px; }
.app-messenger .header .right .user-bar .profile-image img {
width: 30px;
height: 30px;
border-radius: 50%;
margin: 10px 0 0 0; }
.app-messenger .main {
height: 100%;
display: flex;
overflow: hidden; }
.app-messenger .main .sidebar-left {
width: 200px;
border-right: 1px solid rgba(0, 0, 0, 0.05); }
.app-messenger .main .sidebar-right {
border-left: 1px solid rgba(0, 0, 0, 0.05);
width: 300px; }
.app-messenger .main .sidebar-right .title {
padding: 10px; }
.app-messenger .main .content {
flex-grow: 1;
overflow: scroll;
display: flex;
flex-direction: column; }
.app-messenger .main .content .messages {
flex-grow: 1; }
.app-messenger .main .content .messenger-input {
border-top: 1px solid rgba(0, 0, 0, 0.05);
height: 50px;
display: flex;
flex-direction: row;
}
.app-messenger .main .content .messenger-input .text-input {
flex-grow: 1; }
.app-messenger .main .content .messenger-input .text-input textarea {
border: 0 none;
width: 100%;
height: 100%;
padding: 8px 15px; }
.app-messenger .main .content .messenger-input .actions button.send {
background: #2ecc71;
color: #FFF;
border: 0 none;
padding: 7px 15px;
line-height: 50px; }
.messages {
display: flex;
flex-direction: column;
overflow-y: auto;
height: 100%; }
.messages .message {
display: flex;
flex-direction: row;
justify-content: flex-start;
margin: 15px; }
.messages .message .message-user-image img {
width: 20px;
height: 20px;
border-radius: 50%; }
.messages .message .message-body {
padding-left: 10px; }
/*Try adding it manually, by right should make a message card, but will lose colour */
.messages .message .message-body .message-text {
background: rgba(0, 0, 0, 0.05);
padding: 10px;
border-radius: 10px; }
.messages .message.me {
justify-content: flex-end; }
.messages .message.me .message-body .message-text {
background: #2ecc71;
color: #FFF; }
.chanels {
overflow-y: auto;
height: 100%; }
.chanels .chanel {
cursor: pointer;
display: flex;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
padding: 8px; }
.chanels .chanel .user-image {
width: 30px; }
.chanels .chanel .user-image img {
max-width: 100%; }
.chanels .chanel .user-image .channel-avatars {
overflow: hidden;
width: 30px;
height: 30px;
border-radius: 50%;
background-color: #ccc;
position: relative; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-1 img {
width: 100%;
height: 100%;
border-radius: 50%; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-2 img {
width: 50%;
height: 100%;
position: absolute;
right: 0;
top: 0; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-2 img:first-child {
left: 0;
top: 0; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-3 img {
position: absolute;
width: 50%;
height: 50%;
right: 0;
top: 0; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-3 img:first-child {
left: 0;
top: 0;
width: 50%;
height: 100%; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-3 img:last-child {
bottom: 0;
right: 0;
top: 15px;
width: 50%;
height: 50%; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-4 img {
position: absolute;
width: 50%;
height: 50%;
right: 0;
top: 0; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-4 img:first-child {
left: 0;
top: 0;
width: 50%;
height: 100%; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-4 img:nth-child(3n) {
bottom: 0;
right: 0;
top: 15px;
width: 50%;
height: 50%; }
.chanels .chanel .user-image .channel-avatars.channel-avatars-4 img:last-child {
left: 0;
bottom: 0;
top: 15px; }
.chanels .chanel .chanel-info {
flex-grow: 1;
padding-left: 8px;
padding-right: 8px;
overflow: hidden; }
.chanels .chanel .chanel-info h2 {
font-size: 13px;
font-weight: 400;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden; }
.chanels .chanel .chanel-info p {
font-size: 12px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden; }
.chanels .chanel.active {
background: rgba(0, 0, 0, 0.05); }
.chanels .chanel.notify .chanel-info p {
color: #2ecc71; }
.members .member {
display: flex;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
padding: 8px; }
.members .member .member-info {
padding-left: 8px;
flex-grow: 1; }
.members .member .member-info h2 {
font-size: 14px; }
.members .member .member-info p {
font-size: 12px; }
h2.title {
font-size: 16px;
font-weight: 600;
color: rgba(0, 0, 0, 0.8); }
.app-message {
line-height: 1.5em;
padding: 10px;
font-size: 12px;
text-align: center;
border: 1px solid #2ecc71;
border-radius: 5px;
margin: 0 0 10px 0; }
.app-message.error {
background: #e74c3c;
color: #FFF;
border-color: #e74c3c; }
/*# sourceMappingURL=app.css.map */
Работающая версия также доступна на CodeSandBox