0

tl;dr: I'm finding that consecutive elements on my page with position: relative are overlapping, and really don't understand why.

Details: I'm trying to write a re-usable React component SlidePair that allows you to toggle between two other components with a slide animation, passing data between them. I'm using react-reveal for the animation, and positioning the elements at the same place in the page, so the exit of one accompanies the entry of the other. To make the divs overlap I followed the approach of this SO question.

My code, in the context of an App.js file from create-react-app, is below. You see that in the main App component I want to stack two SlidePair elements, which turn out to overlap instead. Everything else are just some example components for me to plug in; I've only included them for the sake of anyone who just wants to copy and paste the whole thing to get it running.

import React, {Component} from 'react';
import Slide from 'react-reveal/Slide';

class RedBox extends Component {
    constructor(props){
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.state = {
            text: props.text
        }
    }

    handleChange(event) {
        this.setState({text: event.target.value});
    }

    render(){
        const { toggleState, text, style} = this.props;
        return(

                <div style={style}
                     onClick={()=>{console.log('red clicked'); toggleState({text: this.state.text})}}>
                    <input onChange={this.handleChange}
                           type="text" value={this.state.text}
                           onClick={(event)=>{event.stopPropagation()}}
                            style={{zIndex: '999'}}
                    />
                    { text }
                </div>

        );
    }
}

const BlueBox = ({toggleState, passedProps, style })=> {
    return (
        <div onClick={toggleState} style={style}>
            { passedProps.text }
        </div>
    );
};

class MouseTracker extends React.Component {
    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick(event) {
        const coords = {
            x: event.clientX,
            y: event.clientY
        };
        this.props.toggleState(coords);
    }

    render() {
        return (
            <div style={{ height: '100px' }} onClick={this.handleClick}>
                <h1>Click me!</h1>
            </div>
        );
    }
}

const MouseInformer = ({toggleState, passedProps}) => (
    <div>
        You clicked {passedProps.x}, {passedProps.y}!
        <button onClick={toggleState}>Go Back</button>
    </div>
);

class SlidePair extends Component {
    constructor(props){
        super(props);
        this.state = { left: true, passedProps: {}};
        this.toggleState = this.toggleState.bind(this);
    }

    toggleState(passedProps){
        const left = !this.state.left;
        console.log(`Toggling left to ${left}`);
        this.setState({ left, passedProps });
    }

    render(){
        const {left, passedProps } = this.state;
        return(
            <div style={{position: 'relative'}}>
                 <Slide left when={left} >
                     <div style={ {position: 'absolute', top: '0px', right: '0px', width: '100%', zIndex: left ? '998' : -1 }}>
                        {this.props.renderLeft(this.toggleState, passedProps)}
                    </div>
                 </Slide>
                    <Slide right when={!left}>
                        <div style={{position: 'absolute', top: '0px', right: '0px', width: '100%', zIndex: left ?  -1 : 1}}>
                        { this.props.renderRight(this.toggleState, passedProps) }
                        </div>
                    </Slide>

            </div>
        )
    }
}

class App extends Component {

    render(){
        const redBox = (toggleState, passedProps)=>(
            <RedBox toggleState={toggleState}
                    style={{width: '100%', border: '5px solid red', height: '100px'}}/>
        );

        const blueBox = (toggleState, passedProps) => (
            <BlueBox
                toggleState={toggleState}
                passedProps={passedProps}
                style={{width: '100%', border: '5px solid blue', height: '100px'}}
            />
        );

        const mouseTracker = (toggleState, passedProps) => (
            <MouseTracker toggleState={toggleState} passedProps={passedProps} style={{top: '300px'}}/>
        );

        const mouseInformer = (toggleState, passedProps) => (
            <MouseInformer toggleState={toggleState} passedProps={passedProps} style={{top: '300px'}}/>
        );

        return (
            <div className="App">
                <SlidePair renderLeft={redBox} renderRight={blueBox}/>
                <br/>
                <SlidePair renderLeft={mouseTracker} renderRight={mouseInformer} />
            </div>
        );
    }

}

export default App;

Thanks in advance for any help.

rwold
  • 2,216
  • 1
  • 14
  • 22
  • What's your problem exactly? Your component seems to be working fine. https://codesandbox.io/s/jovial-sound-ydyzi – Dupocas May 23 '19 at 19:21
  • Thanks for the sandbox! The JS seems fine, yes. But the css is broken: I want two separate sliders, separated vertically by a
    , as in the App component layout. One should toggle between a red box and a blue one, with text from the red one passed to the blue; below that should be one where you click on it and it slides to something that reports the x, y coords of where you clicked. These components overlap. @ydyzi
    – rwold May 23 '19 at 19:50
  • Sorry, meant to tag @Dupocas – rwold May 24 '19 at 09:09

0 Answers0