React - cursor pointer in component and child without directly CSS - reactjs

I'd like some help to implement a simple cursor pointer ( hand ) in a card (and affect all child components ) . I can't use directly css, only styled component and/or inline style.
my code: All code
I'd like to do some like in my parent component:
<div id="box" style={cursorPointerThatAffecAllChild}>
or similar
Parent component
...
render() {
return (
<div id="box">
<p style={{fontWeight:'800'}}>
My card
</p>
<Child1 > </Child1>
<p>
some text in parent
</p>
</div>
);
...
child
...
return (
<div>
<button > My button on child 1 </button>
<br/><br/><br/>
<span style={{color:'blue'}}> a span inside Child 1 </span>
</div>
);
...

If you have to avoid css, you can use styled components and write the css there.
const MyCursorPointer = styled.div`
cursor: pointer;
* { /* this would be for elements that override the cursor pointer but are children of this component */
cursor: pointer;
/* cursor: pointer !important; */
/* ^ Use this style if you still see a cursor other than type pointer on the children */
}
`
If you want to do inline you could do this
<div style={{cursor: 'pointer'}}>
but note elements that have a predefined cursor style may override this. the styled-components solution should enforce the pointer if thats what you want.

Related

ReactJS making a decorator with React.cloneElement: can't set new child's class (className)

I have an app like this, which uses various "thingies" of different kinds. It knows what stuff should be in the thingies:
function Thingy(props) {
const {top_stuff, bottom_stuff} = props;
return (
<div className="a-thingy">
<div>Today's thingy...</div>
<div className="top">
{top_stuff}
</div>
<div className="bottom">
{bottom_stuff}
</div>
</div>
)
}
It also needs to do some more sophisticated things with the Thingies, like putting a button along side them, or changing the way they layout.
So I want to provide these extras with a Decorator. The Decorator doesn't need to know anything about any sort of stuff
export default function App() {
return (
<div className="app">
<div className="title">
Decorator issue
</div>
<Decorator>
<Thingy top_stuff='top' bottom_stuff='bottom'/>
</Decorator>
</div>
);
}
This looks nice and clean: the App tells the Thingy what is in it, and it Decorates the Thingy the way it wants.
Anything that the Decorator does with css should clearly be in the Decorator css definition. This means that the Decorator needs a way of pointing at the Thingy in css.
I tried to annotate the Thingy's class name:
function Decorator({children}) {
return (
<div className="decorator">
<div className="decorator-heading">decorator</div>
{React.cloneElement(React.Children.only(children),
{className: "decorated"})}
<button>Do Stuff With Content</button>
</div>
)
}
... but that doesn't work.
Why is this? ( sandbox )
For clarification: I want the parent (Decorator) to be able to modify the className that the child has, so that the Decorator css can target that child by class name.
Your code looks fine, the reason it didn't work is because you're passing className from <Decorator /> but NOT using it inside <Thingy />.
So to make that work
function Thingy(props) {
const { top_stuff, bottom_stuff } = props;
return (
// here, concat props.className (passed from <Decorator />)
// make sure you have a space between classes
<div className={`a-thingy ${props.className}`}>
<div>The thingy...</div>
<div className="top">{top_stuff}</div>
<div className="bottom">{bottom_stuff}</div>
</div>
);
}
Now, you can control Thingy styles from Decorator like this
/* Thingy styles */
.decorated {
color: red;
}
/* top style */
.decorated .top {
color: blue;
}
CodeSanbox

I want to use RTL, but not through all of my components

I want to use RTL for some of my components in Nextjs. I also use material-ui. Unfortunately when I change direction in _documents.js with <HTML dir="rtl">, the direction of all of my components will change. material-ui's direction in createMuiTheme() doesn't affect direction at all.
Some of the components (like arrows) must not change based on direction. What should I do in order to keep them safe from changing direction.
Material Ui createMuiTheme get direction as an option itself
I also remember that it respect the direction of body tag
So for changing the direction of some part of your component, you have 3 ways as I know.
Change direction option in material createMuiTheme
It could be handle via your theme provider component for example
Use other instance of material Theme provider around your rtl components
Theme nesting
Put dir="rtl" on native DOM tags these will affect all lower subtree styles if you want e.g. flex-box direction and ...
for example
const ARABIC_PATTERN = /[\u0600-\u06FF]/
const getDirection = text => (ARABIC_PATTERN.test(text) ? 'rtl' : 'ltr')
<div dir={getDirection('what you want to test')}>
<Components />
</div>
Hacky suggestion. It's probably not the best answer, but it might be handy/decent if you need to just "reset" the position of 1-2 elements.
First invert everything like your are doing, then put a CSS class on the elements that shall not be "inverted":
.not-rtl-inteverted {
transform: scaleX(-1);
}
This way, you are basically inverting everything, and then inverting once again the elements with the class above.
section {
display: flex;
justify-content: space-around;
}
div {
background: green;
padding: 20px;
margin: 0 10px;
flex-basis: 33%;
}
.rtl {
transform: scaleX(-1);
}
<section>
<div>
<p>No RTL</p>
</div>
<div>
<p>Yes RTL</p>
</div>
<div>
<p>Yes RTL - but reset it on the 2nd line (by applying the same CSS class again)</p>
</div>
</section>
<section>
<div>
<p>text 1</p>
<p>text 2</p>
</div>
<div class="rtl">
<p>text 1</p>
<p>text 2</p>
</div>
<div class="rtl">
<p>text 1</p>
<p class="rtl">text 2</p>
</div>
</section>
In the example, by using twice the same class (once in the parent and once again the children that doesn't need to be rtl'd, we have this reset effect).
Again, might be handy for very simple use cases. I won't suggest this as a general solution to your problem.

make flex-item honour width only if there is content

I want create a flex-item which takes a width of 33% of the container only if there is some content present as follows:
<FlexItem width='33%'> <Somedom /> </FlexItem>
Here, the FlexItem is a component that can take all flex properties as props and renders a div. Now, Somedom can render null in the dom in which case I want the FlexItem to take no width at all and allow the sibling div to fill the entire container.
I was wondering if there is any flex based arrangement which can help me achieve that. Further I have no good way of knowing if its going to render content or not. I don't want to move FlexItem component in Somedom as well.
Using #04FS suggestion of :empty
You could do something as simple as this.
.FlxRw {
display: flex;
}
.Flx {
flex:0 0 33%;
background:#cdf;
}
.Flx:empty {
flex:0 0 0%;
}
<div class="FlxRw">
<div class="Flx"></div>
</div>
<div class="FlxRw">
<div class="Flx">Content</div>
</div>
<div class="FlxRw">
<div class="Flx"></div>
</div>

Style a property in ReactJS

I got React noob question.. The thing is that I have a method with a mount of JSX attributies with their respective properties.
The question is, how can I get to the imageUrl attribute a style? such as give border-radius: 10px or centering in the page.
xxxx (item:aaaa, index:bbb) {
return (
<div className="Post ms-u sm3 ms-u-lg3 ms-u-xl">
<div className="content">
<PersonaControl
id={"BlogItem" + index}
identifier={item.blogOwnerEMail}
displayName={item.blogOwnerName}
size={PersonaSize.extraLarge}
hidePersonaDetails={true}
imageUrl={item.blogLeaderPicture && item.blogLeaderPicture}
labels={this.props.labels}
/>
Here is the render method. I try to double the information of the property xxxx how calls me the content of the parameter aaaa:
render() {
return (
<div className="clearBoth"></div>
<div className="bandContent" style={{ backgroundColor: this.props.backgroundColor }}>
{this.state.leadershipBlogDataItems.map(i => {return this.leadershipBlogDataItems(i, this.state.leadershipBlogDataItems.indexOf(i))})}
<div className="blogPost"></div>
You simply have to add a style property. You can do this by adding:
<div style={{ border: "1px" }} > </div>
If you want to add the "classic" css, with a file, simply add a className to the div, and import the css file as shown below.
import "./style.css";
<div className="yourstylename"> </div>
Inside style.css you simply add your css. By the way, the import shown above only works if the css file is in the same folder as your component/js file.

Preserve class name when wrapping element with styled-components

I'm leveraging the Bootstrap grid so I'm creating components that render elements that include a class:
const Row = props => (
<div className="row" {...props}>
{props.children}
</div>
);
Now, at times I want my row to be padded, so I attempted to wrap my Row component:
const PaddedRow = styled(Row)`
padding: 20px;
`;
This applies the padding, but when the div is rendered, it is without the class.
Chrome's React plugin shows the following:
<Styled(Row)>
<Row className=".sc-cHds hQgwd">
<div className=".sc-cHds hQgwd"> // No "row" class
Is it not possible to preserve the class name for the wrapped component?
What you're doing with {...props} is spreading the passed-in props. styled-components passes the generated className via these props, and because you apply the spread after your className property it overrides the existing class.
If you were to write out manually what your code does in the end this is what it'd look like:
<div className="row" className="sc-cHds">
This makes it apparent what the issue is: the second className declaration is overriding the first one! The solution if I were to stick strictly to your code would be to concatenate the passed in class manually:
<div {...props} className={`row ${props.className}`}>
This works, however it's not idiomatic usage of styled-components. Rather than wrapping the component with styled(Row) we recommend creating a styled component for that <div />:
const RowWrapper = styled.div`
padding: 20px;
`
const Row = props => (
<RowWrapper className="row">
{props.children}
</RowWrapper>
);
This is the way styled-components is intended to be used, it will also automatically concatenate your Bootstrap class with the automatically generated one.

Resources