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 :) .
Related
I got HTML come from backend and I need to renderer it inside div or whatever works
I sanitize the HTML before show it up
import DOMPurify from "dompurify";
......
var cleanHtml = DOMPurify.sanitize( HtmlPassedFromBackEnd , {
FORBID_TAGS: ["style"],
});
then passing sanitized HTML to component <HtmlComponent template={cleanHtml} />
import React from "react";
export default class HtmlComponent extends React.Component {
render() {
return <div dangerouslySetInnerHTML={{__html: this.props.template }}/>
}
}
it's working fine in most cases but its failed in another example is there anything like webview I can safely render my HTML
I have created a nice component that match iframe thanks to #diedu
import React from "react";
import DOMPurify from "dompurify";
import StyledFrame from "react-styled-frame";
import styled from "styled-components";
const InnerBox = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
`;
export default class HtmlComponent extends React.Component {
render() {
var {template} = this.props
template = DOMPurify.sanitize(template, {
FORBID_TAGS: ["style"],
});
return <StyledFrame
style={{
width: "100%",
margin: "0 auto"
}}
>
<InnerBox>
<div style={{
overflow: "auto",
width:"100%"
}}
dangerouslySetInnerHTML={{ __html: template }} />
</InnerBox>
</StyledFrame>
}
}
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 am dealing with 2 components:
header.js and footer.js.
I also have 2 css files:
header.module.css and footer.module.css.
Both of them use different styling for the a tag.
I import the respective CSS files within each js file, but the a styling in footer.module.css seems to overtake the styling in header.js even though it wasn't imported.
Here is the code:
header.js
import React from "react"
import { Link } from "gatsby"
import "../styles/header.module.css";
const ListLink = props => (
<li style={{display: `inline-block`, marginRight: `1rem`, fontSize: '1.15rem', fontWeight: 'bold'}}>
<Link className="link" to={props.to}>{props.children}</Link>
</li>
)
footer.js
import React from "react"
import "../styles/footer.module.css";
const FooterLink = props => (
<li style={{ display: `inline-block`, marginRight: `1rem`, marginBottom:'0rem', fontSize: '1.05rem', fontWeight: 'bold'}}>
{props.children}
</li>
)
header.module.css
a {
color: var(--textLink);
text-shadow: var(--textShadow);
transition:.2s;
background-image: var(--bgimage);
}
a:hover {
color: #da1e11;
background-image: none;
}
footer.module.css
a{
color: var(--textLink);
text-shadow: var(--textShadow);
transition:.2s;
background-image: none;
}
a:hover {
color: #da1e11;
background-image: none;
}
The background-image property from footer overtakes the one specified in header.
If you are using Gatsby's default <Layout>, it shares <Header> and <Footer> components so, both are loading each CSS in each page as you can see here:
return (
<>
<Header siteTitle={data.site.siteMetadata.title} />
<div>
<main>{children}</main>
<Footer>
© {new Date().getFullYear()}, Built with
{` `}
Gatsby
</Footer>
</div>
</>
)
}
The easiest solution is to wrap the each component in a class to make the CSS only available inside that class, something like this:
import React from "react"
import { Link } from "gatsby"
import "../styles/header.module.css";
const ListLink = props => (
<li className="list__item">
<Link className="link" to={props.to}>{props.children}</Link>
</li>
)
Note: you can even wrap the <Link> inside a <div> for example.
I would suggest removing inline styles if you are using CSS modules to avoid mixing styles and improve readability.
The same applies for the <Footer> component.
According to the documentation it's import something from './something.module.css' and then <Component className={something.error}
I trying to work with styled-components. However now, I 'm using "flex" for responsive design, But I can't figure it out.
CSS of styled-components doesn't work. I don't see those styles on my website
Below is outline of my styling
import TagsInput from 'react-tagsinput';
import PostTypeSelector from './PostTypeSelector';
import styled from 'styled-components';
import PostMarkdown from './PostMarkdown';
import PostSubmit from './PostSubmit';
// const StyledPostSubmit = styled(PostSubmit)`
// `;
// const StyledTagsInput = styled(TagsInput)`
// `;
const StyledPostTypeSelector = styled(PostTypeSelector)`
background-color: gray;
flex: 1 0;
`;
const StyledPostForm = styled(PostForm)`
flex: 9 0;
`;
const StyledPostMarkdown = styled(PostMarkdown)`
flex: 10 0;
border-left: 1px solid #222222;
`;
and I adjust like this
render() {
return (
<div className="posting">
<div className="plain-post-form-0">
<div className="plain-post-form-1">
<div style={{
display: 'flex',
flexDirection:'row',
width: '800px'
}}
className="plain-post-form-2"
>
<StyledPostForm
onSave={this.handleSave}
post={this.initValue()}
/>
<StyledPostTypeSelector
/>
<StyledPostMarkdown
post={this.state}
/>
</div>
<TagsInput
value={this.state.tags}
onChange={this.handleTagsChange}
/>
<PostSubmit
data={this.handleCommit}
target={post}
method="post"
value="Commit"
/>
</div>
</div>
</div>
);
}
As stated in the docs:
If you use the styled(MyComponent) notation and MyComponent does not render the passed-in className prop, then no styles will be applied.
// For this to work
const StyledPostForm = styled(PostForm)`
flex: 9 0;
`;
// You need to apply the className prop to component's top node (Container/Parent)
const PostForm = ({ className }) => (
<Container className={className}>...</Container>
)
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>
);
};
)