diff --git a/src/ExitSensor/__story__/StoryExitSensorExample.tsx b/src/ExitSensor/__story__/StoryExitSensorExample.tsx
new file mode 100644
index 00000000..be767ec2
--- /dev/null
+++ b/src/ExitSensor/__story__/StoryExitSensorExample.tsx
@@ -0,0 +1,49 @@
+import {Component} from 'react';
+import {h} from '../../util';
+import {ExitSensor} from '..';
+
+const Rectangle = ({exiting}: any) => {
+ return (
+
+ );
+};
+
+const Circle = ({exiting}: any) => {
+ return (
+
+ );
+};
+
+export class StoryExitSensorExample extends Component {
+ state = {
+ shape: 'rectangle'
+ };
+
+ render () {
+ const shape = this.state.shape === 'rectangle' ?
+ : ;
+
+ return (
+
+
+ {shape}
+
+
+
+
+ );
+ }
+}
diff --git a/src/ExitSensor/__story__/story.tsx b/src/ExitSensor/__story__/story.tsx
new file mode 100644
index 00000000..223a6f2e
--- /dev/null
+++ b/src/ExitSensor/__story__/story.tsx
@@ -0,0 +1,10 @@
+import {Component, createElement as h} from 'react';
+import {storiesOf} from '@storybook/react';
+import {action} from '@storybook/addon-actions';
+import {linkTo} from '@storybook/addon-links';
+import {ExitSensor} from '..';
+import ShowDocs from '../../../.storybook/ShowDocs'
+import {StoryExitSensorExample} from './StoryExitSensorExample';
+
+storiesOf('Sensors/ExitSensor', module)
+ .add('Example', () => );
diff --git a/src/ExitSensor/index.ts b/src/ExitSensor/index.ts
new file mode 100644
index 00000000..6d424545
--- /dev/null
+++ b/src/ExitSensor/index.ts
@@ -0,0 +1,78 @@
+import {Component, cloneElement} from 'react';
+import {h} from '../util';
+import renderProp from '../util/renderProp';
+
+export interface IExitSensorProps {
+ children?: React.ReactElement;
+ time?: number;
+}
+
+export interface IExitSensorState {
+
+}
+
+export class ExitSensor extends Component {
+ static defaultProps = {
+ time: 200
+ };
+
+ element: React.ReactElement;
+ nextElement: React.ReactElement;
+ exitInFlight: boolean = false;
+ exitFinish: boolean = false;
+ timeout;
+
+ state: IExitSensorState = {
+
+ };
+
+ componentWillUnmount () {
+ clearTimeout(this.timeout);
+ }
+
+ transition = () => {
+ this.exitFinish = true;
+ this.forceUpdate();
+ };
+
+ render () {
+ if (this.exitFinish) {
+ this.exitFinish = false;
+ this.exitInFlight = false;
+ this.element = this.nextElement;
+
+ return this.element;
+ }
+
+ const element = this.props.children;
+
+ if (this.exitInFlight) {
+ this.nextElement = element;
+
+ return this.element;
+ }
+
+ if (!this.element) {
+ this.element = element;
+
+ return element;
+ }
+
+ if (!element || (this.element.key !== element.key)) {
+ this.exitInFlight = true;
+ this.nextElement = element;
+
+ this.timeout = setTimeout(this.transition, this.props.time);
+
+ return cloneElement(this.element, {
+ exiting: true
+ });
+ }
+
+ if (this.exitInFlight) {
+ return this.element;
+ }
+
+ return element;
+ }
+}