Actually, I have two questions
The First one is that Why is the following code using styled-components not working, I removed node modules, installed it again globally etc and it's not working. The output render is blank.
Am I using the Pseudo classes correctly in styled components If not please show me
I would really appreciate it if you could show me through the code I have.
I will List my Js file plus the desired CSS below,
I only want the CSS through styled-components
import React, { useRef} from "react";
import ReactDOM from 'react-dom/client';
import Home from "../Dashboard/Home";
import App from '../../App';
import Bye from "./Login"
import styled from "styled-components"
function Register(){
const name=useRef()
const email=useRef()
const password=useRef()
const root = ReactDOM.createRoot(document.getElementById('root'));
const handleClick=()=>{
if(name.current.value&&email.current.value&&password.current.value)
{
localStorage.setItem("name",name.current.value)
localStorage.setItem("email",email.current.value)
localStorage.setItem("password",password.current.value)
localStorage.setItem("signUp",email.current.value)
alert("Account created successfully!!")
root.render(
<React.StrictMode>
<Home/>
</React.StrictMode>
);
}
}
const goHome=()=>{
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
const handleSignIn=()=>{
root.render(
<React.StrictMode>
<Bye />
</React.StrictMode>
);
}
const Body = styled.div`
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: black;
`
const Box = styled.div`
position: relative;
width: 600px;
height: 540px;
background: #1c1c1c;
border-radius: 8px;
overflow: hidden;
&:before{
content: "";
position: absolute;
top: -50px;
left: -50px;
width: 600px;
height: 440px;
transform-origin: bottom right;
background: linear-gradient(0deg, transparent, transparent, #45f3ff, #45f3ff);
animation: animate 6s linear infinite
}
`
const Title = styled.h2`
align-items: center;
color: #45f3ff;
font-size: 25px;
font-weight: 500;
`
return(
<Body>
<Box>
<div className="form">
<Title>Hello Lets Get you Started</Title>
<div className="inputBox">
<input type="text"required="required" ref={name}/>
<span>Your Full Name: </span>
<i></i>
</div>
<div className="inputBox">
<input type="text"required="required" ref={email}/>
<span>Your Email: </span>
<i></i>
</div>
<div className="inputBox">
<input type="password" required="required" ref={password}/>
<span> Your Password: </span>
<i></i>
</div>
<div class="Links">
<button className="btn-2 btn" onClick={handleSignIn}> Sign In</button>
<button className="btn-3 btn" onClick={goHome}>Return Home</button>
</div>
<button type="submit" className="btn-1" onClick={handleClick}>Sign Up </button>
</div>
</Box>
</Body>
)
}
export default Register;
thats my JS file (not jsx)
below is the desired Css
#import url('https://fonts.googleapis.com/css2?family=Poppins:wght#300;400;500;600;700,800,900,&display=swap');
.body{
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: black;
}
.box{
position: relative;
width: 600px;
height: 540px;
background: #1c1c1c;
border-radius: 8px;
overflow: hidden;
}
.title{
align-items: center;
color: #45f3ff;
font-size: 25px;
font-weight: 500;
}
.box::before{
content: "";
position: absolute;
top: -50px;
left: -50px;
width: 600px;
height: 440px;
transform-origin: bottom right;
background: linear-gradient(0deg, transparent, transparent, #45f3ff, #45f3ff);
animation: animate 6s linear infinite
}
.box::after{
content: "";
position: absolute;
top: -50px;
left: -50px;
width: 600px;
height: 440px;
background: linear-gradient(0deg, transparent, #45f3ff, #45f3ff);
transform-origin: bottom right;
animation: animate 6s linear infinite;
animation-delay: -3s;
}
#keyframes animate{
0%{
transform: rotate(0deg)
}
100%{
transform: rotate(360deg)
}
}
.form{
position: absolute;
inset: 2px;
border-radius: 8px;
background: #28292d;
z-index: 10;
padding: 50px 40px;
display: flex;
flex-direction: column;
}
.inputBox span{
display: flex;
justify-content: space-between;
margin-right: 55px;
margin-top: -60px;
font-size: 18px;
font-weight: 500;
left: 0;
padding: 20px 10px 10px;
pointer-events: none;
letter-spacing: 0.05em;
transition: 0.5s
}
.inputBox{
position: relative;
width: 300px;
margin-top: 35px;
}
.inputBox input{
position: relative;
width: 165%;
padding: 20px 10px 10px;
background: transparent;
border: none;
text-align: left;
font-weight: 500;
outline: none;
color: black;
font-size: 1em;
letter-spacing: 0.05em;
font-size: 20px;
z-index: 10;
}
.btn-1{
margin-top: 30px;
pointer-events: auto;
cursor: pointer;
}
.Links{
margin-top: 25px;
}
.btn-2{
display: flex;
align-items: left;
margin-top: -10px;
font-size: 1.25em;
border: none;
outline: none;
background: none;
padding: 0;
color: #8f8f8f;
cursor: pointer;
}
.Links button:hover
{
color: #45f3ff;
}
.btn-3{
display: flex;
flex-direction: column;
margin-left: 25rem;
margin-top: -20px;
font-size: 1.25em;
cursor: pointer;
border: none;
outline: none;
background: none;
padding: 0;
color: #8f8f8f;
}
.inputBox input:valid ~ span,
.inputBox input:focus ~ span
{
color: #45f3ff;
transform: translateY(-44px);
font-size: 1.25em;
}
.inputBox i{
position: absolute;
left: 0;
bottom: -7px;
width: 170%;
height: 2px;
background: #45f3ff;
border-radius: 4px;
transition: 0.5s;
pointer-events: none;
z-index: 9;
}
.inputBox input:valid ~ i,
.inputBox input:focus ~ i
{
height: 55px;
width: 170%;
top: 2px;
}
.btn-1{
border: none;
outline: none;
background: #45f3ff;
padding: 11px 25px;
width: 100px;
margin-top: 10px;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
}
.btn-1:active{
opacity: 0.8
}
Edit: There seems to be that the code works now randomly but i didnt even put all my css and its giving me the exact output i want weird?
It is important to define your styled components outside of the main react component, otherwise it will be recreated on every single render pass. Defining a styled component within the react component will prevent caching and drastically slow down rendering speed, and should be avoided.
import React, { useRef } from 'react';
import ReactDOM from 'react-dom/client';
import styled from 'styled-components';
const Body = styled.div`
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
display: flex;
justify-content: center;
align-items: center;
`;
const Box = styled.div`
position: relative;
width: 600px;
height: 540px;
border-radius: 8px;
overflow: hidden;
&:before{
content: "";
position: absolute;
top: -50px;
left: -50px;
width: 600px;
height: 440px;
transform-origin: bottom right;
animation: animate 6s linear infinite
}
`;
const Title = styled.h2`
align-items: center;
font-size: 55px;
font-weight: 600;
color: red;
`;
function App() {
const name = useRef();
const email = useRef();
const password = useRef();
const handleClick = () => {
if (name.current.value && email.current.value && password.current.value) {
localStorage.setItem('name', name.current.value);
localStorage.setItem('email', email.current.value);
localStorage.setItem('password', password.current.value);
localStorage.setItem('signUp', email.current.value);
alert('Account created successfully!!');
}
};
const goHome = () => {};
const handleSignIn = () => {
root.render();
};
return (
<Body>
<Box>
<div className='form'>
<Title>Hello Lets Get you Started</Title>
<div className='inputBox'>
<input type='text' required='required' ref={name} />
<span>Your Full Nameeee: </span>
</div>
<div className='input-box'>
<input type='text' required='required' ref={email} />
<span>Your Email: </span>
<i></i>
</div>
<div className='input-box'>
<input type='password' required='required' ref={password} />
<span> Your Password: </span>
</div>
<div className='Links'>
<button className='btn-2 btn' onClick={handleSignIn}>
{' '}
Sign In
</button>
<button className='btn-3 btn' onClick={goHome}>
Return Home
</button>
</div>
<button type='submit' className='btn-1' onClick={handleClick}>
Sign Up{' '}
</button>
</div>
</Box>
</Body>
);
}
export { App };
Here is my solution. Keep styled component outside of Register component.
import React, { useRef } from 'react';
import ReactDOM from 'react-dom/client';
import Home from '../Dashboard/Home';
import App from '../../App';
import Bye from './Login';
import styled from 'styled-components';
const Body = styled.div`
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: black;
`;
const Box = styled.div`
position: relative;
width: 600px;
height: 540px;
background: #1c1c1c;
border-radius: 8px;
overflow: hidden;
&:before {
content: '';
position: absolute;
top: -50px;
left: -50px;
width: 600px;
height: 440px;
transform-origin: bottom right;
background: linear-gradient(
0deg,
transparent,
transparent,
#45f3ff,
#45f3ff
);
animation: animate 6s linear infinite;
}
`;
const Title = styled.h2`
align-items: center;
color: #45f3ff;
font-size: 25px;
font-weight: 500;
`;
function Register() {
const name = useRef();
const email = useRef();
const password = useRef();
const root = ReactDOM.createRoot(document.getElementById('root'));
const handleClick = () => {
if (name.current.value && email.current.value && password.current.value) {
localStorage.setItem('name', name.current.value);
localStorage.setItem('email', email.current.value);
localStorage.setItem('password', password.current.value);
localStorage.setItem('signUp', email.current.value);
alert('Account created successfully!!');
root.render(
<React.StrictMode>
<Home />
</React.StrictMode>
);
}
};
const goHome = () => {
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
};
const handleSignIn = () => {
root.render(
<React.StrictMode>
<Bye />
</React.StrictMode>
);
};
return (
<Body>
<Box>
<div className="form">
<Title>Hello Lets Get you Started</Title>
<div className="inputBox">
<input type="text" required="required" ref={name} />
<span>Your Full Name: </span>
<i></i>
</div>
<div className="inputBox">
<input type="text" required="required" ref={email} />
<span>Your Email: </span>
<i></i>
</div>
<div className="inputBox">
<input type="password" required="required" ref={password} />
<span> Your Password: </span>
<i></i>
</div>
<div class="Links">
<button className="btn-2 btn" onClick={handleSignIn}>
{' '}
Sign In
</button>
<button className="btn-3 btn" onClick={goHome}>
Return Home
</button>
</div>
<button type="submit" className="btn-1" onClick={handleClick}>
Sign Up{' '}
</button>
</div>
</Box>
</Body>
);
}
export default Register;
Hope this help you.
Related
I got this very beautiful and sleek sign-in/sign-up form with React Styled Component from Youtube. However, it is not responsive. I have tried using my inspector tool to manipulate every single css detail but it just doesn't work.
Should I give up on using the sleek form/ It's the best I've seen so far.
This is the Styled Component.js
import styled from 'styled-components';
export const Container = styled.div`
background-color: #fff;
border-radius: 10px;
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
position: fixed;
overflow: hidden;
width: 678px;
max-width: 100%;
height: 500px;
`;
export const SignUpContainer = styled.div`
position: absolute;
top: 0;
height: 100%;
transition: all 0.6s ease-in-out;
left: 0;
width: 50%;
opacity: 0;
z-index: 1;
${props => props.signinIn !== true ? `
transform: translateX(100%);
opacity: 1;
z-index: 5;
`
: null}
`;
export const SignInContainer = styled.div`
position: absolute;
top: 0;
height: 100%;
transition: all 0.6s ease-in-out;
left: 0;
width: 50%;
z-index: 2;
${props => (props.signinIn !== true ? `transform: translateX(100%);` : null)}
`;
export const Form = styled.form`
background-color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 50px;
height: 100%;
text-align: center;
`;
export const Title = styled.h1`
font-weight: bold;
margin: 0;
`;
export const Input = styled.input`
background-color: #eee;
border: none;
padding: 12px 15px;
margin: 8px 0;
width: 100%;
`;
export const Button = styled.button`
border-radius: 20px;
border: 1px solid #ff4b2b;
background-color: #ff4b2b;
color: #ffffff;
font-size: 12px;
font-weight: bold;
padding: 12px 45px;
letter-spacing: 1px;
text-transform: uppercase;
transition: transform 80ms ease-in;
&:active{
transform: scale(0.95);
}
&:focus {
outline: none;
}
`;
export const GhostButton = styled(Button)`
background-color: transparent;
border-color: #ffffff;
`;
export const Anchor = styled.a`
color: #333;
font-size: 14px;
text-decoration: none;
margin: 15px 0;
`;
export const OverlayContainer = styled.div`
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 100%;
overflow: hidden;
transition: transform 0.6s ease-in-out;
z-index: 100;
${props =>
props.signinIn !== true ? `transform: translateX(-100%);` : null}
`;
export const Overlay = styled.div`
background: #ff416c;
background: -webkit-linear-gradient(to right, #ff4b2b, #ff416c);
background: linear-gradient(to right, #ff4b2b, #ff416c);
background-repeat: no-repeat;
background-size: cover;
background-position: 0 0;
color: #ffffff;
position: relative;
left: -100%;
height: 100%;
width: 200%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
${props => (props.signinIn !== true ? `transform: translateX(50%);` : null)}
`;
export const OverlayPanel = styled.div`
position: absolute;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 40px;
text-align: center;
top: 0;
height: 100%;
width: 50%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
`;
export const LeftOverlayPanel = styled(OverlayPanel)`
transform: translateX(-20%);
${props => props.signinIn !== true ? `transform: translateX(0);` : null}
`;
export const RightOverlayPanel = styled(OverlayPanel)`
right: 0;
transform: translateX(0);
${props => props.signinIn !== true ? `transform: translateX(20%);` : null}
`;
export const Paragraph = styled.p`
font-size: 14px;
font-weight: 100;
line-height: 20px;
letter-spacing: 0.5px;
margin: 20px 0 30px
`;
This is how I implement it on my Auth2.js (the reason for Auth2 is because I had created an Auth.js but I just want to use this new sign-in/up form which is very sick).
import React from "react";
import Modal from "../Modal/AuthModal";
import * as Components from "./Components";
function Auth2() {
const [signIn, toggle] = React.useState(true);
return (
<Modal>
<Components.Container>
<Components.SignUpContainer signinIn={signIn}>
<Components.Form>
<Components.Title>Create Account</Components.Title>
<Components.Input type="text" placeholder="Name" required />
<Components.Input type="email" placeholder="Email" required />
<Components.Input type="password" placeholder="Password" required />
<Components.Input
type="number"
placeholder="Phone number"
required
/>
<Components.Input type="text" placeholder="Address" required />
<Components.Button>Sign Up</Components.Button>
</Components.Form>
</Components.SignUpContainer>
<Components.SignInContainer signinIn={signIn}>
<Components.Form>
<Components.Title>Sign in</Components.Title>
<Components.Input type="email" placeholder="Email" />
<Components.Input type="password" placeholder="Password" />
<Components.Anchor href="#">
Forgot your password?
</Components.Anchor>
<Components.Button>Sigin In</Components.Button>
</Components.Form>
</Components.SignInContainer>
<Components.OverlayContainer signinIn={signIn}>
<Components.Overlay signinIn={signIn}>
<Components.LeftOverlayPanel signinIn={signIn}>
<Components.Title>Welcome Back!</Components.Title>
<Components.Paragraph>
To keep connected with us please login with your personal info
</Components.Paragraph>
<Components.GhostButton onClick={() => toggle(true)}>
Sign In
</Components.GhostButton>
</Components.LeftOverlayPanel>
<Components.RightOverlayPanel signinIn={signIn}>
<Components.Title>Hello, Friend!</Components.Title>
<Components.Paragraph>
Enter Your personal details and start journey with us
</Components.Paragraph>
<Components.GhostButton onClick={() => toggle(false)}>
Sigin Up
</Components.GhostButton>
</Components.RightOverlayPanel>
</Components.Overlay>
</Components.OverlayContainer>
</Components.Container>
</Modal>
);
}
export default Auth2;
I passed it into a custom Modal.js reusable Component I made;
import { Fragment } from "react";
import classes from "./AuthModal.module.css";
const Backdrop = (props) => {
return <div className={classes.backdrop} onClick={props.onClose} />;
};
const ModalOverlay = (props) => {
return (
<div className={classes.modal}>
<div className={classes.content}>{props.children}</div>
</div>
);
};
const Modal = (props) => {
return (
<Fragment>
<Backdrop onClose={props.onClose} />
<ModalOverlay>{props.children}</ModalOverlay>
</Fragment>
);
};
export default Modal;
The AuthModal.module.css file
.backdrop {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 20;
background-color: rgba(0, 0, 0, 0.8);
}
.modal {
position: relative;
top: 250px;
left: 5%;
width: 90%;
padding: 1rem;
border-radius: 14px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
z-index: 30;
animation: slide-down 300ms ease-out forwards;
}
#media (min-width: 768px) {
.modal {
width: 40rem;
left: calc(50% - 20rem);
}
}
#keyframes slide-down {
from {
opacity: 0;
transform: translateY(-3rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}
In the styled component, I tried using the display: flex but nothing happened. I also use inspector tool to see if I could manipulate all and sundry --- you guessed it - Nothing happened!
Please how do I make my sign in/out responsive? Please!
I am trying to make the google recaptcha function properly on nodejs.
Currently the recaptcha doesn't work with the login function.
I want it to be required for the user to solve the recaptcha before logging in.
If you have any information on how to do this please let me know, I truly appreciate it
What I have in login.jsx is:
import { useContext,useRef } from "react";
import "./login.css";
import {loginCall} from "../../apiCalls";
import {AuthContext} from "../../context/AuthContext";
import {CircularProgress} from "#material-ui/core";
import {Link} from "react-router-dom";
import ReCAPTCHA from "react-google-recaptcha";
import ReactDOM from 'react-dom'
// This is for recaptcha:
function onChange(value) {
console.log("Captcha value:", value);
}
ReactDOM.render(
<ReCAPTCHA class = "reCAPTCHA"
sitekey="6LfOgRwfAAAAAE5mPhZiirYWIRhY-Tt5Sb5SQOt_"
onChange={onChange}
required
/>,
document.body.appendChild(document.createElement("root"))
);
////
export default function Login() {
const username = useRef();
const password = useRef();
const { user, isFetching, dispatch } = useContext(AuthContext);
const handleClick = (e) => {
e.preventDefault();
console.log("clicked");
loginCall(
{ username: username.current.value, password: password.current.value },
dispatch
);
};
console.log(user);
return (
<div className="login">
<div className="loginWrapper">
<div className="loginLeft">
<h3 className="loginLogo">Cybercsun</h3>
<span className="loginDesc">
Connect with friends and the world around you on Cybercsun.
</span>
</div>
<div className="loginRight">
<form className="loginBox" onSubmit={handleClick}>
<input
placeholder="Username"
type="username"
required
className="loginInput"
ref={username}
/>
<input
placeholder="Password"
type="password"
required
minLength="3"
className="loginInput"
ref={password}
/>
<button className="loginButton" type="submit" disabled={isFetching}>
{isFetching
? <CircularProgress color="white" size="20px"/>
: "Log In"}
</button>
<span className="loginForgot">Forgot Password?</span>
<Link to="/register" className="loginRegisterButton">
<button className="loginRegisterButton">
{isFetching ? (
<CircularProgress color="white" size="20px" />
) : (
"Create a New Account"
)}
</button>
</Link>
</form>
</div>
</div>
</div>
);
}
And this is what I have in login.css:
.login {
width: 100vw;
height: 100vh;
background-color: #f0f2f5;
display: flex;
align-items: center;
justify-content: center;
}
.loginWrapper {
width: 70%;
height: 70%;
display: flex;
}
.loginLeft,
.loginRight {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.loginLogo {
font-size: 50px;
font-weight: 800;
color: #ff0000;
margin-bottom: 10px;
}
.loginDesc {
font-size: 24px;
}
.loginBox{
height: 300px;
padding: 20px;
background-color: white;
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.loginInput{
height: 50px;
border-radius: 10px;
border: 1px solid gray;
font-size: 18px;
padding-left: 20px;
}
.loginInput:focus{
outline: none;
}
.loginButton{
height: 50px;
border-radius: 10px;
border: none;
background-color: #ff0000;
color: white;
font-size: 20px;
font-weight: 500;
cursor: pointer;
}
.loginButton:focus{
outline: none;
}
.loginButton:disabled{
cursor: not-allowed;
}
.reCAPTCHA{
position: absolute;
z-index: 999;
bottom: 160px;
right: 495px;
}
.loginForgot{
text-align: center;
color: #ff0000;
}
.loginRegisterButton{
width: 60%;
align-self: center;
height: 50px;
border-radius: 10px;
border: none;
background-color: #ff0000;
color: white;
font-size: 20px;
font-weight: 500;
cursor: pointer;
}
This is what it looks like:
IMG
I'm writing a code for a UI for a certain group, and i have the following code:
App.js:
import React, { Component } from 'react'
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import Helmet from 'react-helmet';
import TextField from "#mui/material/TextField";
import HRLOGO from './images/highradius-logo-3.png';
import ABCLOGO from './images/Group 20399.png';
export default class App extends Component
{
state = {};
render()
{
return (
<div className="Bod">
<div>
<img src={HRLOGO} alt="" className="container-div"/>
</div>
<div>
<img src={ABCLOGO} alt="" className="container-div2"/>
</div>
<Helmet>
<style>{'body { background-color: #2d4250; }'}</style>
</Helmet>
<div>
<h1 className="InvoiceStyle">Invoice List</h1>
</div>
<div className="Rectangle">
</div>
<div className="search">
<TextField
id="outlined-basic"
variant="outlined"
fullWidth
label="Search Customer ID"
/>
</div>
<footer className="Privacy">
<p>
Pivacy Policy
</p>
</footer >
</div>
);
}
}
App.css:
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
#media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.Rectangle {
width: 2000px;
height: 500px;
background: #293d48;
position: fixed;
top: 165px;
}
.container-div {
display: flex;
height: 8vh;
width: 20vw;
position: fixed;
top: 8px;
right: 600px;
text-align: center;
}
.InvoiceStyle {
display: flex;
color: #fff;
font-family: "Open Sans";
position: fixed;
top: 100px;
left: 25px;
}
.container-div2 {
display: flex;
height: 8vh;
width: 20vw;
position: fixed;
top: 7px;
left: 15px;
}
.Privacy {
display: flex;
position: fixed;
top: 700px;
left: 600px;
}
.search {
position: fixed;
top: 175px;
left: 600px;
width: 20%;
/* height: 40px; */
background-color: #fff;
border: none;
border-top-left-radius: 10px !important;
border-bottom-left-radius: 10px !important;
border-top-right-radius: 10px !important;
border-bottom-right-radius: 10px !important;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: rgb(11, 68, 253);
}
.App-link {
color: #ff0000;
}
#keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
How do i make it such that the images and text change according to the aspect area of the platform it is being viewed it? For example, normally on a 16:9 ratio it looks like this:
When browser size changes:
How do I prevent this? Any help would be useful. Thanks!
I am currently making a chat application and having trouble making the div scroll to the bottom when a new chat message is added, I used the css overflow-y:auto to make it be able to scroll but can't figure out how to make it always scroll to the bottom when a new chat is loaded.
Here is my app.js file:
import "./App.css";
import React, { useEffect, useState ,useRef} from "react";
import io from 'socket.io-client';
let socket;
const CONNECTION_PORT = "localhost:3002/";
function App() {
//before login
const [logged, setLogged] = useState(false);
const [name,setName] = useState("");
const [room,setRoom] = useState("");
//after login
const [message,setMessage] = useState("");
const [messageList,setMessageList] = useState([]);
const ref = useRef();
useEffect(()=>{
socket = io(CONNECTION_PORT,{transports: ['websocket', 'polling', 'flashsocket']});
},[])
useEffect(()=>{
socket.on('recieve_message', (data)=>{
setMessageList([...messageList,data])
})
});
// useEffect(()=>{
// const objDiv = document.getElementById('scroll');
// objDiv.scrollTop = objDiv.scrollHeight;
// },[message])
function connectRoom(){
socket.emit('join', room)
setLogged(true);
}
function sendMessage(e){
let messageContent = {
room:room,
content:{
author:name,
message:message
}
}
socket.emit('send_message',messageContent)
setMessageList([...messageList,messageContent.content])
setMessage("");
}
return (
<div className="App">
{!logged?(
<div className="background">
<div className="box">
<span className="text-center">login</span>
<div className="input-container">
<input type="text" required="" onChange={e=> setName(e.target.value)}/>
<label>Full Name</label>
</div>
<div className="input-container">
<input type="text" required="" onChange={ e=> setRoom(e.target.value)}/>
<label>Room</label>
</div>
<button type="button" className="btn" onClick={connectRoom}>submit</button>
</div>
</div>
):(
<>
<div className="chatContainer">
<div className="messages" id="scroll">
{messageList.map((val,key)=>{
return (
<div className="messageContainer" id={val.author == name ? "You" : "Other"}>
<div className="messageIndividual">
{val.message}
</div>
<h1> {val.author}</h1>
</div>
);
})}
</div>
<div className="messageInputs">
<input type="text" placeholder="Type Here" onChange={ e=> setMessage(e.target.value)}/>
<button type="submit" onClick={sendMessage}> Send</button>
</div>
</div>
</>
)}
</div>
);
}
export default App;
here is my css file:
body{
margin: 0px;
padding: 0px;
}
.App{
margin: 0px;
padding: 0px;
display: grid;
place-items: center;
height: 100vh;
background-color: #2a2730;
}
.background{
margin: 0px;
padding: 0px;
width: 100%;
height: 100vh;
background-color: #e74c3c;
}
.text-center{
color:#fff;
text-transform:uppercase;
font-size: 23px;
margin: -50px 0 80px 0;
display: block;
text-align: center;
}
.box{
position:absolute;
left:50%;
top:50%;
transform: translate(-50%,-50%);
background-color: rgba(0, 0, 0, 0.89);
border-radius:3px;
padding:70px 100px;
}
.input-container{
position:relative;
margin-bottom:25px;
}
.input-container label{
position:absolute;
top:0px;
left:0px;
font-size:16px;
color:#fff;
pointer-event:none;
transition: all 0.5s ease-in-out;
}
.input-container input{
border:0;
border-bottom:1px solid #555;
background:transparent;
width:100%;
padding:8px 0 5px 0;
font-size:16px;
color:#fff;
}
.input-container input:focus{
border:none;
outline:none;
border-bottom:1px solid #e74c3c;
}
.btn{
color:#fff;
background-color:#e74c3c;
outline: none;
border: 0;
color: #fff;
padding:10px 20px;
text-transform:uppercase;
margin-top:50px;
border-radius:2px;
cursor:pointer;
position:relative;
}
/*.btn:after{
content:"";
position:absolute;
background:rgba(0,0,0,0.50);
top:0;
right:0;
width:100%;
height:100%;
}*/
.input-container input:focus ~ label,
.input-container input:valid ~ label{
top:-12px;
font-size:12px;
}
.chatContainer {
width: 600px;
height: 350px;
border: 5px solid #0091ff;
border-radius: 10px;
display: flex;
flex-direction: column;
}
.chatContainer .messages {
flex: 80%;
width: 100%;
padding-left: 20px;
overflow-y: scroll;
/* flex-direction: column-reverse; */
}
.chatContainer .messageInputs {
flex: 20%;
width: 100%;
display: flex;
flex-direction: row;
}
.chatContainer .messageInputs input{
flex: 80%;
height: calc(100% -5px);
border: none;
border-top: 5px solid #0091ff;
padding-left: 20px;
font-size: 20px;
}
.chatContainer .messageInputs button{
flex: 20%;
height: 100%;
background-color: #0091ff;
border: none;
color: white;
font-size: 18px;
}
.messageContainer {
display: flex;
flex-direction: column;
width: calc(100% - 30px);
height: auto;
}
.messageContainer h1{
color: white;
font-family: Arial, Helvetica, sans-serif;
font-weight: 300;
font-size: 17px;
}
#You{
align-items: flex-end;
}
#Other {
align-items: flex-start;
}
#You .messageIndividual {
background-color: #5ff064;
color: black;
}
.messageIndividual {
width: 200px;
height: auto;
border-radius: 10px;
display: grid;
place-items: center;
background-color: #0091ff;
opacity: 0.9;
color: white;
font-family: Arial, Helvetica, sans-serif;
margin-right: 10px;
margin-top: 20px;
word-break: break-all;
white-space: pre-wrap;
padding: 4px;
}
here is what the chat application looks like:
You can add a span with ref bellow messages list that will be scroll into it when new messages are received.
Try this example :
useEffect :
useEffect(() => {
scrollSpan.current.scrollIntoView({ behavior: "smooth" });
}, [messageList]);
useRef :
const scrollSpan= useRef();
JSX :
<div className="messages" id="scroll">
{messageList.map((val,key)=>{
return (
<div className="messageContainer" id={val.author == name ?
"You" : "Other"}>
<div className="messageIndividual">
{val.message}
</div>
<h1> {val.author}</h1>
</div>
);
})}
<span ref={scrollSpan}></span>
</div>
On your 'messageContainer' div, create a reference using the 'useRef' React hook.
...
const container = useRef();
...
..
return (
...
<div class="messageContainer" ref={ container }>...</div>
);
and use one more useEffect as follows:
useEffect(() => {
container.current.scrollTop = chatBoxRef.current.scrollHeight;
}, [messageList]);
Some improvements(!important) to your code, which could prevent memory leaks in your app:
-so you're doing this:
useEffect(()=>{
socket.on('recieve_message', (data)=>{
setMessageList([...messageList,data])
})
});
This causes a new 'receive message' event to get registered to the socket every time your component re-renders. You don't want that. You want this event to get registered just once. So do as follows:
useEffect(()=>{
socket.on('recieve_message', (data)=>{
setMessageList(prevMessageList => [...prevMessageList, data]);
})
}, []);
Note the change in setMessageList.(Look up why I did that, it is related to closures since this useEffect now runs only on the first render).
I have this part of component:
<div id="container">
<span id="magnify">🔍</span>
<input id="search" />
<span id="user">👤</span>
<span
#click="dialog = true"
id="buttonMenuHamburger">Ⓜ️</span>
</div>
<transition name="fade">
<div
id="menuOverlay"
v-if="dialog"
>
<div
class="fondOverlay"
#click="dialog = false">
</div>
<ul class="contenuMenuOverlay">
<li>
<router-link to="/home">
➕ Home
</router-link>
</li>
</ul>
</div>
</transition>
<script>
import {
ref,
} from 'vue';
import { useRouter } from 'vue-router';
export default {
name: 'SearchBar',
setup() {
const router = useRouter();
const dialog = ref(false);
router.beforeEach((to, from, next) => {
dialog.value = false;
next();
});
return {
dialog,
};
},
};
</script>
<style scoped>
a {
color: black;
}
#menuOverlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
#menuOverlay .fondOverlay {
background-color: rgba(10, 10, 10, 0.5);
height: 100%;
width: 100%;
position: absolute;
z-index: 99;
}
#menuOverlay .contenuMenuOverlay {
padding: 20px;
margin: 20px;
border: 2px solid white;
text-align: left;
font-size: 2em;
font-variant: small-caps;
border: 2px solid white;
border-radius: 30px;
background-color: rgba(255, 255, 255, 0.5);
z-index: 100;
}
ul {
list-style-type: none;
font-family: "Champagne & Limousines";
font-variant: small-caps;
}
#container {
margin-bottom: 10px;
}
#container span {
padding-top: 7px;
cursor: pointer;
position: absolute;
}
#magnify {
padding-left: 5px;
min-width: 30px;
}
#user {
margin-left: -60px;
}
#buttonMenuHamburger {
margin-left: -30px;
}
#search {
background: transparent;
text-align: center;
color: white;
font-weight: bold;
font-size: 24px;
padding: 0 80px;
height: 30px;
width: 25%;
border: 2px solid white;
border-radius: 30px;
font-family: 'Caviar Dream';
transition: width 0.2s;
outline: none;
}
#search:focus {
width: 50%;
}
#search:before { content: 'Some'; }
</style>
When I click on the Ⓜ️, the dialog value changes correctly. But if I have the focus on the input, when I click on Ⓜ️ it just loses the focus on the input. I have to click again on the Ⓜ️ to get the dialog value set to true.
Is there something I'm missing?
Thanks in advance.
EDIT: it seems to come from the width change...
I might be misunderstanding your problem but I can't replicate the issue.
const { watchEffect, ref, onMounted, nextTick } = Vue;
Vue.createApp({
setup() {
const dialog = ref(false);
const input = ref(null);
// log when `dialog` is changed
watchEffect(() => console.log(dialog.value));
// focus on `input` from the beginning
onMounted(() => nextTick(() => input.value.focus()));
return { dialog, input };
},
}).mount('#app');
<script src="https://unpkg.com/vue#3.0.7/dist/vue.global.js"></script>
<div id="app">
<span id="magnify">🔍</span>
<input id="search" ref="input" />
<span id="user">👤</span>
<transition name="fade">
<span
#click="dialog = true"
id="buttonMenuHamburger">Ⓜ️</span>
</transition>
</div>