Im new to React JS, working on my first soon-to-be live site. I have styled input in a form in a seperate component, then imported the styles to that component. After implementing routing, it seems that this
style is applied to forms across the site, whether or not i import them. Note, i was initially putting all
styles in index.css until I expanded the scope of the site, and this was no longer practical. It now seems
that the index.css styles remain, even after i removed the styles im trying to get rid of from index.css. Either that, or there is something wrong with my routing, importing, exporting, that im not seeing, which is causing this bug:
This style is being applied from a different component with its own imported stylesheet.
I want the sign up form to appear like a normal form input, but its hidden because of the styles
applied to BrowsePhotos.js. I am completely unsure why this happens.
here is my project directory tree
and here is some source code related to possible problem sources
src/components/auth/SignUp.js
import React, { useState } from 'react'
import './auth.css';
const SignUp = () => {
return(
<form onSubmit={handleSubmit} className="App-sign-up">
<label className="auth-field"> Email:
<input onChange={handleEmailChange} type="text"/>
{ !emailError && <div className="error">{emailError}</div>}
</label>
<label className="auth-field"> Password:
<input onChange={handlePasswordChange} type="password"/>
{ !passwordError && <div className="error">{passwordError}</div>}
{/* should also define errors for the other offenders- length, expected characters */}
</label>
{ password &&
<label className="auth-field"> Password:
<input onChange={handleConfirmPasswordChange} type="password"/>
{ !confirmPasswordError && <div className="error">{confirmPasswordError}</div>}
{ password !== confirmPassword && <div className="error">Password and Confirm Password must match</div> }
</label>
}
<button type="submit">Create Account</button>
<div>Already have an account? Sign In!</div>
</form>
)
}
export default SignUp;
src/components/photos/UploadForm.js
import React, { useState } from 'react';
import ProgressBar from './ProgressBar';
import './UploadForm.css'
// TODO: add a new controlled component for providing text to use
// as photo description/ alt text.
const UploadForm = () => {
//equivalent to setting state to '' in class based component
const [file, setFile] = useState(null);
// const [description, setDescription] = useState(null);
const [error, setError] = useState(null);
const handleChange = event => {
// reference to the selected file,
// and a list of allowable image types
const selected = event.target.files[0]
const types = ['image/png','image/jpeg']
if (selected && types.includes(selected.type)) {
setFile(selected);
setError('');
// if (event.target.type === 'textarea') {
// console.log("we got a description")
// }
} else {
setFile(null);
setError('Enter a valid photo type : jpg or png')
}
}
return (
<form>
<label>
<span>+</span>
<input onChange={handleChange} type="file"/>
{/* <div className="description">
<label className="inner-label">Description of the uploaded file</label>
<textarea cols="30" rows="10"
onChange={handleChange}
></textarea>
</div> */}
</label>
<div className="output">
{ error && <div className="error" >{ error }</div>}
{ file && <ProgressBar file={file} setFile={setFile}/>}
</div>
</form>
);
}
export default UploadForm;
src/components/photos/UploadForm.css
form{
margin: 30px auto 10px;
text-align: center;
}
label input{
height: 0;
width: 0;
opacity: 0;
}
label{
display: block;
width: 30px;
height: 30px;
border: 1px solid var(--primary);
border-radius: 50%;
margin: 10px auto;
line-height: 30px;
color: var(--primary);
font-weight: bold;
font-size: 24px;
}
label:hover{
background: var(--primary);
color: white;
}
.output{
height: 60px;
font-size: 0.8rem;
}
.error{
color: var(--error);
}
src/index.css
#import url('https://fonts.googleapis.com/css2?family=Noto+Serif:wght#400;700&display=swap');
:root{
--primary: #efb6b2;
--secondary: #4e4e4e;
--error: #ff4a4a;
}
/* base styles & title */
body{
font-family: "Noto Serif";
color: var(--secondary);
}
.App{
max-width: 960px;
margin: 0 auto;
}
.title h1{
color: var(--primary);
font-size: 1.2rem;
letter-spacing: 2px;
font-weight: normal;
}
src/components/general/title // note: home of routing, ive tried commenting out BrowsePhotos from routing. this is then imported to app.js
import React from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import './general.css'
import About from '../general/About';
import SignIn from '../auth/SignIn';
import SignUp from '../auth/SignUp';
import BrowsePhotos from '../photo/BrowsePhotos';
import BrowseProfiles from '../auth/BrowseProfiles';
const Title = () => {
return (
<div className="title">
<Router>
<nav style={{padding: "5px"}}>
<h1 className="title">Oral-History</h1>
<h1>
<Link to="/about">About</Link>
</h1>
<h1>
<Link to="/sign-in">Sign In</Link>
{/* becomes sign-out when user is signed in */}
</h1>
<h1>
<Link to="/sign-up">Sign Up</Link>
{/* sign-up becomes 'my profile' after sign in */}
</h1>
<h1>
<Link to="/profiles">Profiles</Link>
</h1>
<h1>
<Link to="/photos">All Photos</Link>
</h1>
</nav>
<Route exact path="/about" component={About}/>
<Route exact path="/sign-in" component={SignIn}/>
<Route exact path="/sign-up" component={SignUp}/>
<Route exact path="/profiles" component={BrowseProfiles}/>
<Route exact path="/photos" component={BrowsePhotos}/>
</Router>
</div>
)
}
export default Title;
I've also tried redefining the rule set for label and label input within SignUp.css, to set all the properties to default, or inherits: false, with no luck there.
It sounds like the CSS is not being imported scoped but globally. You could use a CSS-in-JS library like CSS-Modules or react-scoped-css to fix this.
Another way would be to give the html-elements classes and not style them directly. That is usually more scalable.
Related
I am creating a website that utilizes the Spotify API and I have created a login page where the user can login through Spotify and if they successfully login they are redirected to my home page. I have CSS for the login that puts the login button in the center of the page and when they get redirected to the homepage I am trying to put the navigation bar on top of the page but for some reason, it takes the CSS of the Login component and ignores all the CSS I try to put in for the navigation bar component and I want to know why that is.
my App.js file:
import React, { useState, useEffect} from 'react';
import { Route, Routes } from 'react-router-dom';
import { Container } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import Login from './components/Login';
import Home from './components/Home';
import NavBar from './components/NavBar';
import Guesser from './components/Guesser';
import Feed from './components/Feed';
import Generator from './components/Generator';
const code = new URLSearchParams(window.location.search).get('code')
const App = () => {
return (
<div className='main-content'>
<Container>
{code ?
<div>
<Routes>
<Route path='/' element={<NavBar />}>
<Route index element={<Home />} />
<Route path='/guesser' element={<Guesser />} />
<Route path='/feed' element={<Feed />} />
<Route path='/generator' element={<Generator />} />
</Route>
</Routes>
</div> :
<Login />}
</Container>
</div>
)
}
export default App
my App.css file:
.main-content{
display: flex;
height: 100vh;
width: 100%;
background-color: black;
color:white;
padding: 0;
}
My Login.js File:
import React from 'react'
import {Button} from 'react-bootstrap';
import "./index.css"
import SpotifyLogo from '../../spotify-logo2.png';
const Login = () => {
const authEndPoint = "https://accounts.spotify.com/authorize";
const clientId = "{My client id}";
const redirectUri = "http://localhost:3000";
const scopes = [
"streaming",
"user-read-email",
"user-read-private",
"user-library-read",
"user-library-modify",
"user-read-playback-state",
"user-modify-playback-state"
];
const AUTH_URL = `${authEndPoint}?client_id=${clientId}&response_type=code&redirect_uri=${redirectUri}&scope=${scopes.join("%20")}`;
return(
<div className="main-content">
<div className='spot-img'>
<img src={SpotifyLogo} alt='Spotify Logo'/>
</div>
<Button
href={AUTH_URL}
className='button'
>
login
</Button>
</div>
)
}
export default Login
My Login.css File:
.main-content{
align-items: center;
justify-content: center;
display:flex;
flex-direction: column;
position: relative;
}
.spot-img{
position: absolute;
top: 100px;
}
.button{
background-color: green;
width: 100px;
}
My Navbar.js File:
import "./index.css";
import { NavLink, Outlet } from 'react-router-dom';
const NavBar = () => {
return(
<div className='main-content'>
<nav >
<NavLink
exact='true'
activeclassname='active'
to='/'
>
Home
</NavLink> |
<NavLink
exact='true'
activeclassname='active'
to='/guesser'
>
Guesser
</NavLink> |
<NavLink
exact='true'
activeclassname='active'
to='/feed'
>
Feed
</NavLink> |
<NavLink
exact='true'
activeclassname='active'
to='/Generator'
>
Generator
</NavLink> |
</nav>
<Outlet />
</div>
)
}
export default NavBar;
My NavBar.css File:
.nagivation{
position: absolute;
top: 10px;
background-color: gray;
}
All the other component file are simple and only output the name of the webpage and have no CSS filed in yet.
Login image
Home page after successfully logging in
The problem is that you are reusing the same CSS for the logo and the navbar. The parent div of both the logo and the navbar uses the .main-content which centers everything
.main-content{
align-items: center;
justify-content: center;
display:flex;
flex-direction: column;
position: relative;
}
I suggest you use different styling for the parent div of your navbar.
I have modal and want to put/open in container, with modal's native property "container", but as soon as I specify class name of the container element, it shows error TypeError: Cannot use 'in' operator to search for 'current' in config
I created example SandBox
Thank you
I'm not entirely sure if this is what you're aiming for, but here's a bootstrap modal that is contained within a div.
Demo
Code
App.js
import { useEffect, useState, useRef } from "react";
import Config from "./Config";
export default function App() {
// create a container ref
const containerRef = useRef(null);
const [show, setShow] = useState(false);
const [isLoading, setLoading] = useState(true);
const hideModal = () => {
setShow(false);
};
useEffect(() => {
// make sure the DOM node is assigned to the containerRef.current property
if (isLoading && containerRef && containerRef.current) setLoading(false);
}, [isLoading]);
return (
<div className="app">
<div className="container">
<div className="row">
<div className="row-items col-3">
<button onClick={() => setShow(true)}>Show</button>
<button onClick={() => setShow(false)}>Close</button>
<hr />
<button>Info</button>
<button>Tests</button>
</div>
<div ref={containerRef} className="modal-container row-items col-9">
Modal should appear here...
<Config
ref={!isLoading ? containerRef.current : null}
hideModal={hideModal}
show={show}
/>
</div>
</div>
</div>
</div>
);
}
Config.js
import { forwardRef } from "react";
import { Modal } from "react-bootstrap";
/*
Forwards the "containerRef" to the "Modal"
The "Modal" component will then be inserted
within the "modal-container" div
*/
const Config = forwardRef(({ hideModal, show }, ref) => (
<Modal
container={ref}
show={show}
backdrop="static"
keyboard={false}
size="md"
centered
>
<div className="analysis-config-header d-block-header">
<i className="fas fa-info-circle align-middle text-info" />
Before we move on...
</div>
<div className="analysis-config-body d-block-body">Options</div>
<div className="analysis-config-action-buttons d-block-action-buttons">
<hr />
<button className="btn btn-danger btn-sm">Save</button>
<button onClick={hideModal} className="btn btn-secondary btn-sm">
Cancel
</button>
</div>
</Modal>
));
export default Config;
index.js
import ReactDOM from "react-dom";
import App from "./App";
import "bootstrap/dist/css/bootstrap.min.css";
import "./styles.css";
ReactDOM.render(<App />, document.getElementById("root"));
styles.css
html,
body,
#root {
min-height: 100vh;
width: 100%;
margin: 0;
padding: 0;
}
.app {
padding: 20px;
}
/* prevents the modal content from bleeding into the container borders */
.modal-content {
margin: auto 20px;
}
/* allows child elements to be positioned relative to the parent div */
.modal-container {
position: relative;
}
/* positions the grey background relative to the parent div */
.modal-backdrop {
position: relative;
width: 100%;
height: calc(100% - 40px);
}
/* positions the modal within the parent div, but in front of the grey
background */
.modal {
position: absolute;
}
.row-items {
border: 1px solid red;
height: 300px;
padding-top: 5px;
}
I want to implement a color option in my button components to use it in all my global components so I can change the text and color Dynamically
is it correct?
import React from 'react';
import './Button.css';
const Button = ({text, BtnVersion1}) => {
return (
{text}
)
}
export default Button;
<Button style={{color: "red"}} text="SHOP NOW" />
Your component code seems to be fully correct. But when using your component you have to pass props this way:
<Button text={"SHOP NOW"} BtnVersion1={"red"} />
This is where styled components can be very useful. Where you're declaring 'style' on the component, that is an inline style and would only exist on that instance of the button. You can pass a prop, say 'btnColor' to the button which is used by the styled component to change the color. See below.
import React from 'react';
import styled from 'styled-component';
import './Button.css';
const StyledButton = styled.a`
background-color: ${props => props.btnColor ? props.btnColor : 'red'};
`
const Button = ({
text,
btnColor
}) => {
return (
<StyledButton href="#" btnColor={btnColor} className="buy">{text}</StyledButton>
)
}
export default Button;
<Button btnColor='red' text="SHOP NOW" />
You can see above in the StyledButton that if we provide the btnColor prop than use that color, else default to 'red.'
For more information on styled components - https://styled-components.com/
You can have a more "dynamic" way of doing it (so your instance of <Button> doesn't change):
import React from 'react';
import './Button.css';
const Button = ({ text, style }) => {
return (
{text}
)
}
export default Button;
<Button style={{ color: "red" }} text="SHOP NOW" />
If you want to just control the color (or other properties) you can do something like:
import React from 'react';
import './Button.css';
const Button = ({ text, color }) => {
return (
{text}
)
}
export default Button;
<Button color="red" text="SHOP NOW" />
You might want to use your component this way:
The advantage here is that you can pass all your custom styles for every single one of your buttons.
const Button = ({text, style}) => {
return (
{text}
);
};
ReactDOM.render(<Button style={{color: "red"}} text="SHOP NOW" />, document.querySelector("#root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root">
<!-- Your root container -->
</div>
Donot use anchor tag as a button in react , If you want to know the reason read this doc
https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md
I think best way to style a button is using styled component , I have given an example code in this sandbox , you can pass props for things only you want to change like for background, if no value is given it will take default color
try it
code :
import "./styles.css";
import styled from "styled-components";
const Button = styled.button`
font-family: "Work Sans", sans-serif;
font-size: 14px;
font-weight: 600;
color: #ffffff;
line-height: 16px;
background: ${(props) => (props.background ? props.background : "#00D2AD")};
transition: all 0.4s ease-out;
transition: all 0.4s ease-out;
padding: 14px 24px;
outline: none;
text-align: center;
display: inline-block;
border: none;
cursor: pointer;
border-radius: 4px;
`;
export default function App() {
return (
<div className="App">
<Button>Default Button </Button>
<br />
<br />
<Button background={"gray"}>Custom Button</Button>
</div>
);
}
I'm new to styling in React. I tried CSS modules and styled components but I'm not able to change layout and styles.
The goal is to have a group of buttons to display as flex on the main page and as an inline with different style attributes in another page by re-using the HomeButtons.js component.
HomeButtons.js is the home page and it has a map() function looping through a button called ButtonCategory.js.
HomeButtons.js renders the map() inside a styled using CSS modules file. ButtonCategory is styled with a CSS modules file as well.
HomeButtons.js is then returned inside a in another class Component called CardsCategory.js. It is in this component that I'm trying to change the display and styl... With a styled Component on the I can show a border but the display attribute doesn't works.With CardsCategory.module.css I can't change the display either...
Not sure what to do... How to change the layout of the re-used component and the style of its nested button component ?
Any feedback is welcome!
HomeButtons.js
import React, { Component } from 'react'
import classes from './HomeButtons.module.css';
import ButtonCategory from '../../components/ButtonCategory/ButtonCategory'
class HomeButtons extends Component {
handleClick = (buttonValue) => {
buttonValue = buttonValue.slice(0, 3).toLowerCase();
this.props.history.push("/" + buttonValue);
};
render() {
const allCategoriesButtons = ["Physics", "Chemistry", "Medicine", "Literature", "Peace", "Economics"];
const allCatMap = allCategoriesButtons.map(button =>
< ButtonCategory
key={button.toString()}
value={button}
name={button}
onClick={e => this.handleClick(e.target.value)}
/>
)
return (
<div>
<div className={classes.container__section}>
{allCatMap}
</div >
</div>
)
}
}
export default HomeButtons;
HomeButtons.module.css
.container__section {
display: flex;
flex-flow: row wrap;
margin: auto;
align-items: center;
justify-content: space-around;
}
ButtonCategory
import React from 'react'
import classes from './ButtonCategory.module.css';
function buttonCategory(props) {
return (
<button
className={classes.b}
name={props.name}
onClick={props.onClick}
value={props.value}
>
{props.name}
</button>
)
}
export default buttonCategory;
ButtonCategory.module.css
opacity: 0.5;
color: red;
font-size: 2em;
margin: 10px 20px 10px 20px;
flex: 1 400px;
height: 3em;
}
CardsCategory
import React, { Component } from 'react';
import axios from 'axios';
import classes from './CardsCategory.module.css';
import HomeButtons from "../HomeButtons/HomeButtons"
import styled from 'styled-components';
const StyledDiv = styled.div`
border: 10px solid orange;
//display: inline; //NOT working
`
class Cards extends Component {
render() {
return (
<div>
<StyledDiv>
<HomeButtons className={classes.test}/>
</StyledDiv>
</div>
)
}
}
export default Cards;
CardsCategory.module.css
.test {
display: inline;
}
You can send styles thru the props and in the component set them as your styles ex.
<MyComponent textAlign='center' ...>
in MyComponent component
<div style={{textAlign: this.props.textAlign}}>
...
</div>
or send whole styles as objects ex.
render(){
const stl = {textAlign: 'center',width:'500px'};
return(
<MyComponent wholeStyle={stl}/>
)
}
and in MyComponent
<div style={this.props.wholeStyle}>
...
</div>
They are 3 ways you can style through props
You can pass an entire style object
Eg:
<MappedComponent style={'display':'flex','alignItems':'center'} />
In the mapped component
Function MappedComponent ({style}){
return (
What's popaining !
);
}
You can style by passing in the specific style you want
Eg:
<MappedComponent textAlign={'center'} />
In the mapped component
Function MappedComponent ({textAlign}){
return (
What's popaining !
);
}
The third way you can style is by defining styles in a CSS file and just passing in the class name
Eg:
<MappedComponent className={''flex-button-style'} />
In the mapped component
Function MappedComponent ({className}){
return (
What's popaining !
);
}
Pick what works best for you and stay consistent with it :) .
I have a collapse/accordion component from Antd that I customized and exported from an elements folder from within my application so that I could reuse it across the app.
When I import it and include it inside another component I can't render any of the body elements inside. Does anyone have any idea why this is happening and if there's a way around it?
Also as a smaller side issue when the body of the accordion opens to display, the whitespace doesn't fill the entire container and it looks like there's a grey column running down the right side.
I've included a code sandbox here to better show what I mean
Custom Collapse Component
import React, { useState } from "react";
import styled from "styled-components";
import { Collapse as AntCollapse } from "antd";
const StyledCollapse = styled(AntCollapse)`
&&& {
border: none;
border-radius: 0px;
background-color: #f7f7f7;
box-shadow: none;
}
`;
const CustomCollapse = props => {
const [disabled, setDisabled] = useState(true);
return (
<StyledCollapse onChange={() => setDisabled(prev => !prev)}>
<AntCollapse.Panel
header={props.header}
key="1"
showArrow={false}
bordered={false}
extra={<p style={{ color: "#0076de" }}>{disabled ? "SHOW" : "HIDE"}</p>}
/>
</StyledCollapse>
);
};
export default CustomCollapse;
Main Component
import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
import "antd/dist/antd.css";
import AntCollapse from "./CustomCollapse";
const Flexbox = styled.div`
font-family: sans-serif;
flex-direction: column;
display: flex;
justify-content: center;
border: solid 1px palevioletred;
padding: 10%;
margin: 10%;
`;
const ConfigurationOptions = () => (
<Flexbox>
<AntCollapse header="configuration test">
<h1>Test</h1>
<p>Test Paragraph</p>
<p>Test Paragraph</p>
</AntCollapse>
</Flexbox>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<ConfigurationOptions />, rootElement);
You forgot to pass down the children in your custom collapse component.
To get it to work, do this:
const CustomCollapse = props => {
const [disabled, setDisabled] = useState(true);
return (
<StyledCollapse onChange={() => setDisabled(prev => !prev)}>
<AntCollapse.Panel
header={props.header}
key="1"
showArrow={false}
bordered={false}
extra={<p style={{ color: "#0076de" }}>{disabled ? "SHOW" : "HIDE"}</p>}
>
{props.children}
</AntCollapse.Panel>
</StyledCollapse>
);
};
(also to get the weird grey side column off the side you should do it like this:
const CustomCollapse = props => {
const [disabled, setDisabled] = useState(true);
return (
<StyledCollapse onChange={() => setDisabled(prev => !prev)}>
<AntCollapse.Panel
header={
<span>
{props.header}
<span style={{ color: "#0076de", float: "right" }}>
{disabled ? "SHOW" : "HIDE"}
</span>
</span>
}
key="1"
showArrow={false}
bordered={false}
>
{props.children}
</AntCollapse.Panel>
</StyledCollapse>
);
};
)