I'm using react-moveable to have drag and drop support for some component. I'm trying to make the control box disappear until the user clicks on the target.
So first, I want to apply some CSS to the control box, but I can't seem to do it. The docs specify that a className could be set, but it doesn't work for me for some reason.
The component looks something like this:
import React from "react";
import Moveable from "react-moveable";
import { makeMoveable, DraggableProps, ResizableProps, RotatableProps, Rotatable, Draggable, Resizable } from "react-moveable";
import MoveableHelper from "moveable-helper";
import styles from './label.module.css';
const Label = () => {
const [helper] = React.useState(() => {
return new MoveableHelper();
})
const targetRef = React.useRef<HTMLDivElement>(null);
return (
<div className="container">
<div>
name
</div>
<Moveable
className={styles.moveable1}
target={targetRef}
draggable={true}
resizable={true}
rotatable={true}
origin={false}
onDragStart={helper.onDragStart}
onDrag={helper.onDrag}
onResizeStart={helper.onResizeStart}
onResize={helper.onResize}
onRotateStart={helper.onRotateStart}
onRotate={helper.onRotate}
/>
</div>
);
};
export default Label;
And the css module file label.module.css:
.moveable1 .moveable-line .moveable-direction {
background: red !important;
}
I tried to set the className as string, play around with the class names in the css files and more, but nothing changes the control box style.
Any ideas?
The control box is defined by the zoom and the renderDirection
We can make it disappear (zoom default is 1 )
zoom={0}
and modify / hide the border controls. (Default)
renderDirections={["nw", "n", "ne", "w", "e", "sw", "s", "se"]} )
And then you can apply some styles to the target div with a normal onClick function and useState hook.
import React from "react";
import Moveable from "react-moveable";
import { makeMoveable, DraggableProps, ResizableProps, RotatableProps, Rotatable, Draggable, Resizable } from "react-moveable";
import MoveableHelper from "moveable-helper";
import styles from './label.module.css';
const Label = () => {
const [helper] = React.useState(() => {
return new MoveableHelper();
})
const targetRef = React.useRef<HTMLDivElement>(null);
const [styles, setStyles] = useState( {border: "1px solid green";} )
const handleStyles = e => {
// Your styles...
// Your setState Hook
setStyles({border: "1px solid blue"})
}
return (
<div className="container">
<div onclick={handleStyles} style={styles}>
name
</div>
<Moveable
className={styles.moveable1}
target={targetRef}
draggable={true}
resizable={true}
rotatable={true}
origin={false}
onDragStart={helper.onDragStart}
onDrag={helper.onDrag}
onResizeStart={helper.onResizeStart}
onResize={helper.onResize}
onRotateStart={helper.onRotateStart}
onRotate={helper.onRotate}
{ /** Hide the control box * / }
zoom={0}
renderDirections{["nw", "n", "ne"]}
/>
</div>
);
};
export default Label;
Docs:
Zoom Types:
https://daybrush.com/moveable/release/latest/doc/Moveable.html#zoom
Render Directions: https://daybrush.com/moveable/release/latest/doc/Moveable.html#.RenderDirections
CSS style Box:
https://github.com/daybrush/moveable/blob/master/handbook/handbook.md#toc-directions
👀 style={{ background: 'yellow' }}
Hope you find this useful.
Regards,
M.
💀
Just to be sure, did you try .moveable-control css class name as in:
.moveable-control {
background: red !important;
}
Related
I am trying to write a react application where the App component renders an array of components to the screen. But the inline CSS are not showing up.
//App component
import data from "./data.js"
import Item from "./Item"
export default function App(){
const cardElements = data.map(item => <Item/>)
return (<div className='app'>
{cardElements}
</div>);
}
//Item component
export default function Item(){
const customStyle = {border: "2px solid black"};
return (<div style={customStyle} >Item component</div>);
}
The inline CSS in the Item component does not reflect on the webpage.
As you can see in the snippet below the inline style does indeed work. What is likely happening here is your style is bering overridden but we'd need more information to know for sure.
Sidenote: don't forget to add key prop when using .map in React.
const data = [1, 2, 3, 4];
function App() {
const cardElements = data.map(item => <Item key={item} />)
return (
<div className='app'>
{cardElements}
</div>
);
}
function Item() {
const customStyle = { border: "2px solid black" };
return <div style={customStyle}>Item component</div>;
}
ReactDOM.createRoot(
document.getElementById("root")
).render(
<App />
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
Let's say you have a navbar and when you're using this component on your homepage you want it to have a certain background color and display property, but when you use that same navbar component on another page in your application you want to change these CSS properties. Seeing as the component has one CSS file linked how would you change the style of a component depending on where it is being rendered?
My personal favourite method nowadays is styled components. Your component might look something like this:
// NavBar.js
import styled from 'styled-components'
const StyledDiv = styled.div`
width: 100%;
height: 2rem;
background-color: ${props => props.bgColor};
`
const NavBar = (bgColor) => {
return <StyledDiv bgColor={bgColor}>
}
Then to use it in your different contexts you simply pass the color prop:
// homepage.js
<NavBar bgColor="red" />
// otherpage.js
<NavBar bgColor="#123ABC" />
Styled components are becoming a very popular way of doing things, but be aware that there are a huge array of ways you can do this.
https://styled-components.com/
(Code not tested)
Well If you just want to use plain CSS then you can change the className based on route so the styles also changes.
Example:
import { useLocation } from "react-router-dom";
const Navigation = () => {
let location = useLocation();
...
return(
<nav className={location.pathname === "/home" ? "homepage-navbar" : "default-navbar"}>
...
</nav>
)
}
You can write longer condition for multiple pages as well.
Other better thing you can do is pass the location.pathname and value of className as prop.
import { useLocation } from "react-router-dom";
const Home = () => {
let location = useLocation();
...
return (
<>...
<Navigation location={location.pathname} styleClass={"homepage-navbar"}/>
</>
)
}
const Navigation = ({location, styleClass}) => {
...
return(
<nav className={location === "/home" ? styleClass : "default-navbar"}>
...
</nav>
)
}
So now you can pass different values for className from different components and get different styles for the navbar.
Say I have a React functional component with some simple state:
import React, { useState } from 'react'
import { makeStyles } from "#material-ui/core"
export default function Basket() {
const [itemCount, setItemCount] = useState<number>(0)
return (
<div>
<Count count={itemCount} />
<button onClick={() => setItemCount(itemCount + 1)}>
Add One
</button>
</div>
)
}
function Count({count}: {count: number}) {
const classes = useStyles()
return (
<div className={classes.count}>
{count}
</div>
)
}
const useStyles = makeStyles({
count: {
backgroundColor: "yellow",
transition: "backgroundColor 2s ease" // ???
}
}
I want the Count component to apply a property whenever the count changes and then remove it again; say, turn on backgroundColor: yellow for 2 seconds and then gradually fade it over 1 second. What's the simplest way to achieve this?
Note that presumably this could be either triggered by a state change on the parent or by a re-rendering of the child. Alternatively, I could add the key property to <Count/> to force a re-mount of the child:
<Count
key={itemCount}
count={itemCount}
/>
Any of those would be acceptable; I'm looking for the simplest, cleanest solution, hopefully one that doesn't require additional state and is compatible with Material-UI styling APIs.
Just an idea.
const Component = () => {
useEffect(() => {
// will trigger on component mount
return () => {
// will trigger on component umount
}
}, [])
}
...
document.getElementById('transition').classList.add('example')
You can use useEffect along with useRef containing a reference to the element or directly getting it with document.getElementById and then update the transition class that way in component mount/unmount. Not sure if it'll work, I haven't tested it myself.
I have the following class with a function, that opens a modal (open_modal(...)) in a separate file to a component as I have a large number of modals that use this functionality.
import open from "open";
import $ from "jquery";
class ReactHelpers {
static open_webpage(page_url) {
open(page_url);
}
static open_modal(overlay_id, modal_id) {
$(overlay_id).css("display", "block");
$(modal_id).css("display", "block");
}
static close_modal(overlay_id, modal_id) {
$(overlay_id).css("display", "none");
$(modal_id).css("display", "none");
}
}
export default ReactHelpers;
I am trying to assert that the open_modal function has added css to the divs in question as below:
it('should close the modal', function () {
const wrapper = shallow(
<div id="overlay_id">
<div id="modal_id">
<p>modal</p>
</div>
</div>
)
const overlay = wrapper.find('#overlay_id')
const modal = wrapper.find('#modal_id')
ReactHelpers.open_modal(overlay, modal);
console.log('OVERLAY ', overlay);
expect(overlay.prop('style')).toHaveProperty('display', 'block');
expect(modal_style).toHaveProperty('display', 'block');
});
Further, I'm sure to how the open_webpage function would be tested as this is a library function. In my other tests in my other components, I'm mocking this so it's never actually been tested.
Any help is greatly appreciated.
Thanks
To test style of dom elements:
You should mount the component (using mount), instead of just creating it (using shallow).
Since you're changing the style of dom element directly, You should test the style of the dom element (component.getDOMNode().style.display), instead of testing the react style property (component.prop.style).
example:
import $ from "jquery";
it("should create a div and changes its color to red", () => {
const wrap = mount(
<div id="red_el"></div>
);
const el = wrap.find("#red_el").getDOMNode()
$(el).css("color", "red");
expect(el.style.color).toEqual("red");
});
In your case:
it("should open modal", () => {
const wrapper = mount(
<div>
<div id="overlay" style={{ display: "none" }}>
<div id="modal" style={{ display: "none" }}>
overlay
</div>
</div>
</div>
);
const overlay = wrapper.find("#overlay").getDOMNode();
const modal = wrapper.find("#modal").getDOMNode();
ReactHelpers.open_modal(overlay, modal);
expect(overlay.style.display).toEqual("block");
expect(modal.style.display).toEqual("block");
});
See it live on codesandbox (switch to the tests tab to run the tests .)
I am trying to overwrite the CSS of react range slider.It uses the custom style sheet of which i need to add in the head section.My project is built on next.js
<link rel="stylesheet" href="https://unpkg.com/react-rangeslider/umd/rangeslider.min.css" />
Otherwise, the slider doesn't show anything if i don't add the link in head even though I installed the library. It's not even overwriting the CSS. I want to change the background color.This is my code:
import React, { Component } from 'react'
import 'react-rangeslider/lib/index.css';
import './slider.css';
import Slider from 'react-rangeslider'
class Horizontal extends Component {
constructor (props, context) {
super(props, context)
this.state = {
value: 850
}
}
handleChangeStart = () => {
console.log('Change event started')
};
handleChange = value => {
this.setState({
value: value
})
};
handleChangeComplete = () => {
console.log('Change event completed')
};
render () {
const { value } = this.state
return (
<div>
<div className='slider' style={{ marginTop:'165px',marginLeft:'319px',width:'700px',backgroundColor:'EF5350'}} >
<div style={{ textAlign:'center',color:'gray',fontSize:'35px',marginBottom:'82px'}}>
<p> What is the size of your property?</p>
</div>
<Slider
min={850}
max={5000}
value={value}
onChangeStart={this.handleChangeStart}
onChange={this.handleChange}
onChangeComplete={this.handleChangeComplete}
/>
<div className='value'>{value}</div>
</div>
</div>
)
}
}
export default Horizontal
I tried to change the background color in slider.css.
.rangeslider-horizontal .rangeslider__fill {
background-color: red;
}
The library needs to be installed first:
npm install react-rangeslider --save
It doesn't work as the slider stylesheet overwrite yours. Include the style like
// To include the default styles
import 'react-rangeslider/lib/index.css'
// import your css
import './style.css';
Demo
always make your own CSS stylesheet file the last file to import after any other CSS stylesheet files to make overwrite you need
otherwise, you can always use the console in the browser to auto-detect any error by pressing F12 in the browser then go to the tab called (console)
I think you can style element you want to live in the console to know the detail of how to nesting element
you also can open the CSS file in the editor and press Ctrl+F then find the line of code you want to style then copy its property and value to your own CSS file and then you can edit it so easy