Browse Source

Added slide show and its tests

Snow 8 years ago
parent
commit
0538bf4bf0

+ 1 - 0
package.json

@@ -6,6 +6,7 @@
     "prop-types": "^15.5.10",
     "react": "^15.6.1",
     "react-dom": "^15.6.1",
+    "react-flip-move": "^2.9.14",
     "react-motion": "^0.5.0",
     "react-redux": "^5.0.5",
     "react-router-dom": "^4.1.1",

+ 3 - 3
src/__test__/Modal.test.js

@@ -5,15 +5,15 @@ import { mount, shallow } from 'enzyme';
 describe('<Modal />', () => {
   it('Clicking show button shows a new node with class named "modal"', () => {
     const modal = mount(<Modal />);
-    expect(modal.find('.modal').hasClass('active')).toBe(false);
+    expect(modal.find('.modal').exists()).toBe(false);
     modal.find('button.show').simulate('click');
-    expect(modal.find('.modal').hasClass('active')).toBe(true);
+    expect(modal.find('.modal').exists()).toBe(true);
   });
 
   it('Clicking the close button close the modal window and make the class inactive', () => {
     const modal = mount(<Modal />);
     modal.find('button.show').simulate('click');
     modal.find('button.hide').simulate('click');
-    expect(modal.find('.modal').hasClass('active')).toBe(false);
+    expect(modal.find('.modal').exists()).toBe(false);
   });
 });

+ 28 - 0
src/__test__/SlideShow.test.js

@@ -0,0 +1,28 @@
+import React from 'react';
+import SlideShow from '../components/SlideShow';
+import { mount } from 'enzyme';
+
+describe('<SlideShow />', () => {
+  it('The SlideShow has 5 slides', () => {
+    const SlideShowWindow = mount(<SlideShow />);
+    expect(SlideShowWindow.find('.slide').length).toBe(5);
+  });
+  it('Clicking on buttons does not change the center position', () => {
+    const SlideShowWindow = mount(<SlideShow />);
+    expect(SlideShowWindow.find('.slide').at(2).hasClass('center')).toBe(true);
+    SlideShowWindow.find('button.right').simulate('click');
+    expect(SlideShowWindow.find('.slide').at(2).hasClass('center')).toBe(true);
+    SlideShowWindow.find('button.left').simulate('click');
+    expect(SlideShowWindow.find('.slide').at(2).hasClass('center')).toBe(true);
+  });
+
+  it('Clicking on buttons add z-index style to the corresponding box', () => {
+    const SlideShowWindow = mount(<SlideShow />);
+    SlideShowWindow.find('button.left').simulate('click');
+    expect(SlideShowWindow.find('.slide4').props().style.zIndex).toBeTruthy();
+    expect(SlideShowWindow.find('.slide0').props().style.zIndex).toBeFalsy();
+    SlideShowWindow.find('button.right').simulate('click');
+    expect(SlideShowWindow.find('.slide0').props().style.zIndex).toBeTruthy();
+    expect(SlideShowWindow.find('.slide4').props().style.zIndex).toBeFalsy();
+  });
+});

+ 15 - 5
src/components/Modal/index.jsx

@@ -1,15 +1,25 @@
 import React from 'react'
+import PropTypes from 'prop-types'
 
 import './style.css'
 
-const ModalWindow = ({ isActive, onClickClose }) => <div className={'modal' + isActive}>
-<button className="hide" onClick={onClickClose}>X</button>
+const ModalWindow = ({ isActive, handleClickClose }) => {
+	if (isActive) {
+		return (<div className={'modal'}>
+<button className="hide" onClick={handleClickClose}>X</button>
 <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
-</div>
+</div>)}
+		return null
+}
+
+ModalWindow.PropTypes = {
+	isActive: PropTypes.bool.isRequired,
+	handleClickClose: PropTypes.func.isRequired,
+}
 
 export default class Modal extends React.Component {
 	state = {isActive: false}
-
+	
 	handleClick = () => {
 		this.setState({isActive: true}) 
 	}
@@ -23,7 +33,7 @@ export default class Modal extends React.Component {
 		<div>
 			<p>A modal will show after clicking the button</p>
 			<button className="show" onClick={this.handleClick}>Show Modal</button>
-			<ModalWindow isActive={(this.state.isActive) ? ' active' : ''} onClickClose={this.handleCloseModal}/>
+			<ModalWindow isActive={this.state.isActive} handleClickClose={this.handleCloseModal}/>
 		</div>)
 	}
 }

+ 0 - 4
src/components/Modal/style.css

@@ -1,8 +1,4 @@
 .modal {
-	display: none;
-}
-
-.modal.active {
 	display: block;
 	position: absolute;
 	top: 0;

+ 3 - 3
src/components/Nav/NavLink.js

@@ -2,10 +2,10 @@
 import React from 'react';
 import { NavLink } from 'react-router-dom';
 
-export default React.createClass({
+export default class MyNav extends React.Component {
   render() {
     return (
       <NavLink {...this.props} activeStyle={{ backgroundColor: '#111' }} />
     );
-  },
-});
+  }
+}

+ 1 - 0
src/components/Nav/index.js

@@ -10,6 +10,7 @@ const Nav = () =>
     <li><NavLink to="/tabs">Tab View</NavLink></li>
     <li><NavLink to="/counter">Counter</NavLink></li>
     <li><NavLink to="/modal">Modal</NavLink></li>
+    <li><NavLink to="/slideshow">Slide</NavLink></li>
     <li><NavLink to="/tabss">Test 404</NavLink></li>
   </ul>;
 

+ 72 - 0
src/components/SlideShow/index.jsx

@@ -0,0 +1,72 @@
+import React from 'react'
+import PropTypes from 'prop-types';
+import FlipMove from 'react-flip-move';
+
+import './style.css'
+
+class Slide extends React.Component {
+static propTypes = {
+	index: PropTypes.number.isRequired,
+	center: PropTypes.string.isRequired,
+	zIndex: PropTypes.number,
+	}
+render() {
+	const className = 'slide slide'+ this.props.index + this.props.center
+		return (
+			<div className={className} style={{zIndex: this.props.zIndex}}><h2>{this.props.slide}</h2></div>
+			)
+}
+}
+
+
+export default class SlideShow extends React.Component {
+	state = {
+		indices: [0,1,2,3,4],
+		direction: null,
+	}
+	
+
+	renderSlides = () => {
+		let nSlide = this.state.indices.length
+		return (
+			<div className='slide-group'>
+			<FlipMove duration={600} easing="ease-in-out">
+			{this.state.indices.map((slide, index) => {
+				const center = (index===(nSlide-1)/2) ? ' center' : ''
+				let zIndex = null
+				if (this.state.direction === 'left' && index === this.state.indices.length-1) {zIndex = -10}
+				if (this.state.direction === 'right' && index === 0) {zIndex = -10}
+				return (<Slide index={index} center={center} slide={slide} key={slide} zIndex={zIndex}/>)
+			})}
+			</FlipMove>
+			</div>
+			
+		)
+	}
+	handleLeftClick = () => {
+		let shiftedState = this.state.indices.slice(1)
+		let newState = [...shiftedState,this.state.indices[0]]
+		this.setState({indices: newState})
+		this.setState({direction: 'left'})
+	}
+	
+	handleRightClick = () => {
+		let shiftedState = this.state.indices.slice(0,-1)
+		let newState = [this.state.indices[this.state.indices.length-1],...shiftedState]
+		this.setState({indices: newState})
+		this.setState({direction: 'right'})
+	}
+
+	render() {
+		return (
+		
+		<div  className='slideshow'>
+			<p>Clicking the button will slide the blocks and the center block is always colored. The animation is borrowed from React-flip-move library with some hack. Overall doing transition animation in React is a bit hard. </p>
+			<button className="left" onClick={this.handleLeftClick}>&lt;</button>
+			{this.renderSlides()}
+			<button className="right" onClick={this.handleRightClick}>&gt;</button>
+		</div>
+		
+		)
+	}
+}

+ 26 - 0
src/components/SlideShow/style.css

@@ -0,0 +1,26 @@
+.slide0, .slide4, .slide1, .slide2, .slide3 {
+	width: 10vw;
+	height: 100px;
+	border: 2px solid black;
+	text-align: center;
+	float: left;
+	background-color: #fff;
+}
+
+.slide4 {
+	position: relative;
+	z-index: -1;
+}
+
+.slide0 {
+	position: relative;
+	z-index: -1;
+}
+.slide.center {
+	background-color: #666; 
+    transition: background-color 1000ms linear;
+}
+button.left, button.right {
+	height: 104px;
+	float: left;
+}

+ 10 - 3
src/index.css

@@ -28,6 +28,13 @@ main {
 	padding: 20px;
 }
 
-main>div {
-	width: 70vw;
-}
+.components {
+    width: 100vw;
+}
+
+@media screen and (min-width: 800px) {
+  .components {
+    width: 70vw;
+  }
+}
+

+ 2 - 0
src/routes.js

@@ -8,6 +8,7 @@ import Toggle from './components/Toggle';
 import Home from './components/Home';
 import TabView from './components/Tabs';
 import Modal from './components/Modal';
+import SlideShow from './components/SlideShow';
 import Counter from './components/Counter';
 import NotFound from './components/NotFound';
 
@@ -23,6 +24,7 @@ const Routes = props =>
           <Route path="/tabs" component={TabView} />
           <Route path="/counter" component={Counter} />
           <Route path="/modal" component={Modal} />
+          <Route path="/slideshow" component={SlideShow} />
           <Route component={NotFound} />
         </Switch>
       </main>