React <hr /> with dynamically set colors - html

I want to have a <hr /> in my react application. I want to change the color of it in different places? Is there any way of doing it? If we use a functional component to achieve this, how should be do it?

There's nothing special to it really.
const Rule = ({ color }) => (
<hr
style={{
borderColor: color,
}}
/>
);
const App = () => (
<div>
Here's an orange rule. <Rule color="orange" />
Here's a blue rule. <Rule color="blue" />
</div>
);
ReactDOM.render(<App />, document.querySelector("main"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<main/>

The <hr> element, from my experience, if you're leaving it unstyled beyond a color, is best styled through the CSS rule border-color, as in the following example:
.foo { border-color: black; }
<hr class="foo" />
As for React, you could start with their basic CSS prop and expand it from there.
render() {
let className = 'hr-color';
if (this.props.isActive) {
className += ' foo';
}
return <hr className={className}/>
}

you need to set with below css for that :
hr {
background-color: red; //or whatever color you want.
height: 1px;
}

Related

CSS attribute selectors in JSX with TypeScript

I can do the following in pure HTML/CSS
<div color="red">
red
</div>
<div color="yellow">
yellow
</div>
div[color="red"] {
color: red;
}
div[color="yellow"] {
color: yellow;
}
However, using React and TypeScript, I want to do something like this:
const Colored = ({ color }: { color: "yellow" | "red" ) => (
<div color={color}>
{ color }
</div>
);
However, I can't add abritrary props to div!!
so we could do exactly the same as the above, but instead
<Colored color="red" />
<Colored color="yellow" />
How can I do something like this? Additionally, should I even be doing this? Is there a better way of doing this in React?
In this case using the type React.HTMLAttributes<HTMLDivElement> you can pass additional properties to the DIV mantaining your component Colored.
type IColoredProps = { color: "yellow" | "red" } & React.HTMLAttributes<HTMLDivElement>
const Colored: FC<IColoredProp> = (props) => (
<div {...props}>
{props.color}
</div>
);
Now the color is mandatory and can only be "red" or "yellow", and you can pass the rest of properties a normal div can have.
<Colored style={{ fontSize: "25px" }} color="red"/>
I created a codeSandBox example for you :
instead of <Colored text="red" /> you should use <Colored color="red" />

unable to remove css of span class due to $(...).css is not a function

I am trying to change the css of a html given a span class.
I have an html as follows:
<form id=thing>
<div id=a>
<span class=x>
</span>
</div>
<div id=b>
<span class=x>
</span>
</div>
</form>
When I inspect the webpage I see the following style being applied:
#thing .x {
display: none !important;
}
Now my goal is to get rid of this display css property completely.
I tried $("#thing .x").css("display", ""); but i keep getting "$(...).css is not a function - unable to remove css "
Any tips on how to solve this?
Using inline style with setAttribute()
I assume you are trying to remove the styling for display from none. '' => nothing would not be a valid style to use, use a valid property value recognized by the display property, like inline or block for example.
You can override the !important rule set in CSS with the same CSS hack used in inline style as inline style takes presidence over styles set in CSS sheet. The only way I was able to do it was by setting the style attribute using el.setAttribute('style', 'display: inline !important;'). See snippit and a few examples of failure and finally success below...
let dontUseImportant = document.querySelectorAll('#thing .x')
dontUseImportant.forEach(el => {
// style display inline !important is ignored
// this is likely a rule in JS that will disallow
// spaces in values passed into properties for style
// more research on this may be fruitful
// however note the outcome in console.log
el.style.display = "inline !important";
el.textContent = 'this will not parse to DOM'
console.log(el)
})
dontUseImportant.forEach(el => {
// style display is added but is over written by !important used in CSS
el.style.display = "inline";
el.textContent = 'this will not parse to DOM'
console.log(el)
})
// this also will not work
dontUseImportant.forEach(el => {
el.setAttribute('style', 'display: null !important;');
el.textContent = 'this will not parse to DOM'
console.log(el)
})
// by adding !important using setAttribute behind our
// property, this affects the elements style
// however, we are putting a bandaid on a bandaid
dontUseImportant.forEach(el => {
el.setAttribute('style', 'display: inline !important;');
el.textContent = 'content x is finally shown!'
console.log(el)
})
#thing .x {
display: none !important;
}
.y {
display: inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="thing">
<div id="a">content a
<span class="x">content x
</span>
</div>
<div id="b">content b
<span class="x">content x
</span>
</div>
</form>
Swapping classes on element
Because the CSS file is using !important this unfortunately will override any styles you place on the element using el.style.property = '' regardless of using JS or a JS library like JQuery.
You could add a new class using JS that has a defining display: inline and then remove the old class. Keep in mind that you must add a valid property value when using styles. display = '' is not valid.
Your particular issue is a great example as to why !important is a BAD IDEA for styling as a crutch!
let $dontUseImportant = $('#thing .x')
// iterate over elements and swap out the classes
// make sure to add the new class 'y' first
// then remove initial class 'x'
$.each($dontUseImportant, function(i){
$(this).addClass('y')
$(this).removeClass('x')
console.log($dontUseImportant[i])
})
#thing .x {
display: none !important;
}
.y {
display: inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="thing">
<div id="a">content a
<span class="x" >content x
</span>
</div>
<div id="b">content b
<span class="x">content x
</span>
</div>
</form>
Why not using the hidden attribute? It is supported in all modern browsers. So in your case, you don't even need CSS.
jQuery:
$('button').on('click', function() {
$('.x').each(function() {
$(this).show();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="thing">
<div id="a">
<span class="x" hidden>
1
</span>
</div>
<div id="b">
<span class="x" hidden>
2
</span>
</div>
</form>
<button>Show</button>
Vanilla JS
const x = document.querySelectorAll('.x');
document.querySelector('button').addEventListener('click', (e) => {
for (let item of x) {
item.removeAttribute('hidden');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="thing">
<div id="a">
<span class="x" hidden>
1
</span>
</div>
<div id="b">
<span class="x" hidden>
2
</span>
</div>
</form>
<button>Show</button>

Is there tag styling in react js inline style

For example, there is react js code,
<p> hello </p>
<p> world </p>
In here, i want change font size with inline style.
I know this can be resolved to
<p style={{fontSize: '24px',}}> hello</p>
<p style={{fontSize: '24px',}}> world</p>
But i want to know about how to change all tag to one const styling
const fontStyles = {
fontSize:"24px"
}
Add the styled object to your p tag.
<p style={fontStyles}> hello </p>
<p style={fontStyles}> world </p>
You can use Styled components. It's recommended in React and good best practices Check the Docs
https://styled-components.com/
Using Styled Components
const MyStyledParagraph = styled.p`
font-size : 24px
`
Best this if you export the MyStyledParagraph Component you can use anywhere in the project. Styled Component use CSS styled syntax. (fontSize is use as font-size, like in CSS)
<MyStyledParagraph>Hello</MyStyledParagraph>
<MyStyledParagraph>World</MyStyledParagraph>
To do this you can try something like this:
const mystyle = {
fontSize: '24px'
}
and use it like:
<p style={mystyle}>Hello</p>
<p style={mystyle}>World</p>
Reference
Working example
Example code:
class MyHeader extends React.Component {
render() {
const mystyle = {
color: "white",
backgroundColor: "DodgerBlue",
padding: "10px",
fontFamily: "Arial"
};
return (
<div>
<h1 style={mystyle}>Hello Style!</h1>
<p>Add a little style!</p>
</div>
);
}
}
const paragraphStyle = {
fontSize: '24px'
}
Then apply it
<p style={paragraphStyle}> hello</p>
<p style={paragraphStyle}> world</p>

Design of a custom accordion

I am trying to design a custom accordion with these fancy red lines connecting parent and children (see photo).
I am using Grommet components here but in summary, the layout it's just a bunch of divs (the Box tag) and a collapsible panel component for the children(the Collapsible tag). Children panels can be opened and show more content.
After a couple of tries, what I did to connect parent and children is to wrap the outer box with a left-border and then remove the extra border on the bottom using a white box on top of it (the Stack tag of the second example code). The horizontal line connecting the card and the left-border is just a styled div placed next to the Child tab ( inside the SubMenuElement component ).
I think this is quite an intricate solution ( also because I need to make the white box responsive ) but I couldn't think about a simpler one.
Do you have any suggestion on how can I improve or re-do the red connections?
Thanks in advance for the help!
Please note that I am aware all the panels are using the same variables on click
<MenuButton
open={openMenu}
label="PARENT TAB-XYZ"
onClick={() => {
const newOpenMenu = !openMenu;
setOpenMenu(newOpenMenu);
setOpenSubmenu1(!newOpenMenu ? false : openSubmenu1);
}}
/>
<Collapsible open={openMenu}>
<Box background="antiquewhite" margin={{ left: 'small' }} border={{ side: 'left', size: '2px', color: 'red' }}>
{Tabs.map(el => {
return (
<SubMenuElement
key={el.title}
open={openSubmenu1}
label={el.title}
onClick={() => setOpenSubmenu1(!openSubmenu1)}
/>
);
})}
</Box>
</Collapsible>
<MenuButton
open={openMenu}
label="PARENT TAB-POU"
onClick={() => {
const newOpenMenu = !openMenu;
setOpenMenu(newOpenMenu);
setOpenSubmenu1(!newOpenMenu ? false : openSubmenu1);
}}
/>
<Collapsible open={openMenu}>
<Stack anchor="bottom-left">
<Box
background="antiquewhite"
margin={{ left: 'small' }}
border={{ side: 'left', size: '2px', color: 'red' }}
>
{Tabs.map(el => {
return (
<SubMenuElement
key={el.title}
open={openSubmenu1}
label={el.title}
onClick={() => setOpenSubmenu1(!openSubmenu1)}
/>
);
})}
</Box>
<Box background="white" height="39px" width="35px"></Box>
</Stack>
</Collapsible>
</Box>
);
Based on one of my answer for someone who needed a divider, I can propose you something like that: repro on Stackblitz
You will find the original divider code on the first link. for your needs, i modified it a little so it just add the link on the left of the content. There is still a border-left on the content wrapper tho, it seems the easiest solution for me.
Your main file :
import React, { Component } from "react";
import { render } from "react-dom";
import Divider from "./divider";
import "./style.css";
const App = () => {
const toggleAccordion = e => {
e.target.classList.toggle("hidden");
};
return (
<>
<div className="accordion hidden" onClick={toggleAccordion}>
accordion header
<div className="accordion-content-wrapper">
<Divider>
<div>Content</div>
</Divider>
<Divider>
<div>Content</div>
</Divider>
<Divider>
<div>Content</div>
</Divider>
</div>
</div>
</>
);
};
render(<App />, document.getElementById("root"));
My accordion css (your component already have this feature i guess, i just made a minimal reproduction):
.accordion.hidden {
height: 18px;
overflow: hidden;
}
.accordion-content-wrapper{
margin-left: 10px;
border-left: 1px solid black;
}
And for the divider, there not a lot of change from my original answer, here is the code:
import React from 'react';
const Divider = ({ children }) => {
return (
<div className="divider-component">
<div className="container">
<div className="border" />
<span className="content">{children}</span>
</div>
</div>
);
};
export default Divider;
css:
.divider-component .container{
display: flex;
align-items: center;
}
.divider-component .border{
border-bottom: 1px solid black;
width: 15px;
}
.divider-component .content {
width: 100%;
}
Even if you'll have to edit it to fit your needs, the idea is to add a flex container so you can add the little link on the left of your content, correctly aligned with your content.
For whoever will encounter the same issue, I ended up using two 50% height flexboxes inside a div that replace the horizontal line. This allows managing the responsive resize automatically while giving flexibility on the last item border.
const SubMenuElement = ({ last, label, open, onClick }: { last?: boolean; label: string; open: any; onClick: any }) => {
return (
<Box direction="row">
<Line last={last} />
<Box width="100%" margin={{ vertical: 'small' }}>
<Card background="white" onClick={onClick}>
....
</Card>
</Box>
</Box>
);
};
Where the Line is
const Line = ({ last }: { last?: boolean }) => (
<Box direction="column" width="20px" flex="grow">
<Box height="50%" style={{ borderLeft: '1px solid red', borderBottom: '1px solid red' }} />
<Box height="50%" style={last ? {} : { borderLeft: '1px solid red' }} />
</Box>
);

how can i change color of separated div based on focus on nested input using CSS?

The structure is similar to this:
<div>
<div id="selected">
<div id="inBetweenDiv">
<input id="action"></input>
</div>
</div>
<div id="changeThis"></div>
</div>
I want to change background of #changeThis on the focus of the input element.
In pure CSS you could use the :focus-within pseudoclass
#selected:focus-within ~ #changeThis {
background: yellowgreen
}
<div>
<div id="selected">
<div id="inBetweenDiv">
<input id="action" />
</div>
</div>
<div id="changeThis">Change this</div>
</div>
Otherwise you could do the same via JS, if you need to support older browsers e.g.
var input = document.getElementById('action');
var ct = document.getElementById('changeThis');
input.addEventListener('focus', () => { ct.classList.add('focus'); });
input.addEventListener('blur', () => { ct.classList.remove('focus'); });
and in CSS – assuming that #changeThis has a default background already applied – you need to use a more specific selector like
#changeThis.focus {
background: yellowgreen;
}