diff --git a/packages/react-events/README.md b/packages/react-events/README.md
index 00e728e8b3..f846ea5f39 100644
--- a/packages/react-events/README.md
+++ b/packages/react-events/README.md
@@ -7,251 +7,165 @@ Event components do not render a host node. They listen to native browser events
dispatched on the host node of their child and transform those events into
high-level events for applications.
+The core API is documented below. Documentation for individual Event Components
+can be found [here](./docs).
-## Focus
+## EventComponent
-The `Focus` module responds to focus and blur events on the element it wraps.
-Focus events are dispatched for `mouse`, `pen`, `touch`, and `keyboard`
-pointer types.
+An Event Component is defined by a module that exports an object of the
+following type:
```js
-// Example
-const TextField = (props) => (
-
-
-
-);
+type EventComponent = {|
+ $$typeof: REACT_EVENT_COMPONENT_TYPE,
+ displayName?: string,
+ props: null | Object,
+ responder: EventResponder,
+|};
```
+## EventResponder
+
+An Event Responder is defined using an object. Each responder can define DOM
+events to listen to, handle the synthetic responder events, dispatch custom
+events, and implement a state machine.
+
```js
-// Types
-type FocusEvent = {
+// types
+type ResponderEventType =
+ | string
+ | {name: string, passive?: boolean, capture?: boolean};
+
+type ResponderEvent = {|
+ nativeEvent: any,
+ target: Element | Document,
+ type: string,
+ passive: boolean,
+ passiveSupported: boolean,
+|};
+
+type CustomEvent = {
+ type: string,
target: Element,
- type: 'blur' | 'focus' | 'focuschange'
+ ...
}
```
-### disabled: boolean
+### createInitialState?: (props: null | Object) => Object
-Disables all `Focus` events.
+The initial state of that the Event Component is created with.
-### onBlur: (e: FocusEvent) => void
+### onEvent?: (event: ResponderEvent, context: ResponderContext, props, state)
-Called when the element loses focus.
+Called during the bubble phase of the `targetEventTypes` dispatched on DOM
+elements within the Event Component.
-### onFocus: (e: FocusEvent) => void
+### onEventCapture?: (event: ResponderEvent, context: ResponderContext, props, state)
-Called when the element gains focus.
+Called during the capture phase of the `targetEventTypes` dispatched on DOM
+elements within the Event Component.
-### onFocusChange: boolean => void
+### onMount?: (context: ResponderContext, props, state)
-Called when the element changes hover state (i.e., after `onBlur` and
-`onFocus`).
+Called after an Event Component in mounted.
+
+### onOwnershipChange?: (context: ResponderContext, props, state)
+
+Called when responder ownership is granted or terminated for an Event Component instance.
+
+### onRootEvent?: (event: ResponderEvent, context: ResponderContext, props, state)
+
+Called when any of the `rootEventTypes` are dispatched on the root of the app.
+
+### onUnmount?: (context: ResponderContext, props, state)
+
+Called before an Event Component in unmounted.
+
+### rootEventTypes?: Array
+
+Defines the DOM events to listen to on the root of the app.
+
+### stopLocalPropagation: boolean
+
+Defines whether or not synthetic events propagate to other Event Components *of
+the same type*. This has no effect on propagation of the source DOM events or
+the synthetic events dispatched to Event Components of different types.
+
+### targetEventTypes?: Array
+
+Defines the DOM events to listen to within the Event Component subtree.
-## Hover
+## ResponderContext
-The `Hover` module responds to hover events on the element it wraps. Hover
-events are only dispatched for `mouse` pointer types. Hover begins when the
-pointer enters the element's bounds and ends when the pointer leaves.
+The Event Responder Context is exposed via the `context` argument for certain methods
+on the `EventResponder` object.
+
+### addRootEventTypes(eventTypes: Array)
+
+This can be used to dynamically listen to events on the root of the app only
+when it is necessary to do so.
+
+### clearTimeout(id: Symbol): void
+
+Clear a timeout defined using `context.setTimeout`.
+
+### dispatchEvent(event: CustomEvent, listener, { discrete: boolean })
+
+Dispatches a custom synthetic event. The `type` and `target` are required
+fields, but any other fields can be defined on the `event` that will be passed
+to the `listener`. For example:
```js
-// Example
-const Link = (props) => (
- const [ hovered, setHovered ] = useState(false);
- return (
-
-
-
- );
-);
+const event = { type: 'press', target, pointerType, x, y };
+context.dispatchEvent(event, props.onPress, { discrete: true });
```
-```js
-// Types
-type HoverEvent = {
- pointerType: 'mouse',
- target: Element,
- type: 'hoverstart' | 'hoverend' | 'hovermove' | 'hoverchange'
-}
-```
+### getFocusableElementsInScope(): Array
-### delayHoverEnd: number
+Returns every DOM element that can be focused within the scope of the Event
+Component instance.
-The duration of the delay between when hover ends and when `onHoverEnd` is
-called.
+### hasOwnership(): boolean
-### delayHoverStart: number
+Returns `true` if the instance has taken ownership of the responder.
-The duration of the delay between when hover starts and when `onHoverStart` is
-called.
+### isPositionWithinTouchHitTarget(x: number, y: number): boolean
-### disabled: boolean
+Returns `true` if the global coordinates lie within the TouchHitTarget.
-Disables all `Hover` events.
+### isTargetDirectlyWithinEventComponent(target: Element): boolean
-### onHoverChange: boolean => void
+Returns `true` is the target element is within the direct subtree of the Event Component instance, i.e., the target is not nested within an Event Component instance that is a descendant of the current instance.
-Called when the element changes hover state (i.e., after `onHoverStart` and
-`onHoverEnd`).
+### isTargetWithinElement(target: Element, element: Element): boolean
-### onHoverEnd: (e: HoverEvent) => void
+Returns `true` if `target` is a child of `element`.
-Called once the element is no longer hovered. It will be cancelled if the
-pointer leaves the element before the `delayHoverStart` threshold is exceeded.
+### isTargetWithinEventComponent(target: Element): boolean
-### onHoverMove: (e: HoverEvent) => void
+Returns `true` is the target element is within the subtree of the Event Component instance.
-Called when the pointer moves within the hit bounds of the element. `onHoverMove` is
-called immediately and doesn't wait for delayed `onHoverStart`.
+### isTargetWithinEventResponderScope(target: Element): boolean
-### onHoverStart: (e: HoverEvent) => void
+Returns `true` is the target element is within the current responder.
-Called once the element is hovered. It will not be called if the pointer leaves
-the element before the `delayHoverStart` threshold is exceeded. And it will not
-be called more than once before `onHoverEnd` is called.
+### releaseOwnership(): boolean
-### preventDefault: boolean = true
+Returns `true` if the instance released ownership of the responder.
-Whether to `preventDefault()` native events.
+### removeRootEventTypes(eventTypes: Array)
+Remove the root event types added with `addRootEventTypes`.
-## Press
+### requestGlobalOwnership(): boolean
-The `Press` module responds to press events on the element it wraps. Press
-events are dispatched for `mouse`, `pen`, `touch`, and `keyboard` pointer types.
-Press events are only dispatched for keyboards when pressing the Enter or
-Spacebar keys. If neither `onPress` nor `onLongPress` are called, this signifies
-that the press ended outside of the element hit bounds (i.e., the user aborted
-the press).
+Request ownership of the global responder.
-```js
-// Example
-const Button = (props) => (
- const [ pressed, setPressed ] = useState(false);
- return (
-
-
-
- );
-);
-```
+### requestResponderOwnership(): boolean
-```js
-// Types
-type PressEvent = {
- pointerType: 'mouse' | 'touch' | 'pen' | 'keyboard',
- target: Element,
- type: 'press' | 'pressstart' | 'pressend' | 'presschange' | 'pressmove' | 'longpress' | 'longpresschange'
-}
+Request ownership of the responder.
-type PressOffset = {
- top: number,
- right: number,
- bottom: number,
- right: number
-};
-```
+### setTimeout(func: () => void, delay: number): Symbol
-### delayLongPress: number = 500ms
-
-The duration of a press before `onLongPress` and `onLongPressChange` are called.
-
-### delayPressEnd: number
-
-The duration of the delay between when the press ends and when `onPressEnd` is
-called.
-
-### delayPressStart: number
-
-The duration of a delay between when the press starts and when `onPressStart` is
-called. This delay is cut short (and `onPressStart` is called) if the press is
-released before the threshold is exceeded.
-
-### disabled: boolean
-
-Disables all `Press` events.
-
-### onLongPress: (e: PressEvent) => void
-
-Called once the element has been pressed for the length of `delayLongPress`. If
-the press point moves more than 10px `onLongPress` is cancelled.
-
-### onLongPressChange: boolean => void
-
-Called when the element changes long-press state.
-
-### onLongPressShouldCancelPress: () => boolean
-
-Determines whether calling `onPress` should be cancelled if `onLongPress` or
-`onLongPressChange` have already been called. Default is `false`.
-
-### onPress: (e: PressEvent) => void
-
-Called immediately after a press is released, unless either 1) the press is
-released outside the hit bounds of the element (accounting for
-`pressRetentionOffset` and `TouchHitTarget`), or 2) the press was a long press,
-and `onLongPress` or `onLongPressChange` props are provided, and
-`onLongPressCancelsPress()` is `true`.
-
-### onPressChange: boolean => void
-
-Called when the element changes press state (i.e., after `onPressStart` and
-`onPressEnd`).
-
-### onPressEnd: (e: PressEvent) => void
-
-Called once the element is no longer pressed (because it was released, or moved
-beyond the hit bounds). If the press starts again before the `delayPressEnd`
-threshold is exceeded then the delay is reset to prevent `onPressEnd` being
-called during a press.
-
-### onPressMove: (e: PressEvent) => void
-
-Called when a press moves within the hit bounds of the element. `onPressMove` is
-called immediately and doesn't wait for delayed `onPressStart`. Never called for
-keyboard-initiated press events.
-
-### onPressStart: (e: PressEvent) => void
-
-Called once the element is pressed down. If the press is released before the
-`delayPressStart` threshold is exceeded then the delay is cut short and
-`onPressStart` is called immediately.
-
-### pressRetentionOffset: PressOffset
-
-Defines how far the pointer (while held down) may move outside the bounds of the
-element before it is deactivated. Once deactivated, the pointer (still held
-down) can be moved back within the bounds of the element to reactivate it.
-Ensure you pass in a constant to reduce memory allocations.
-
-### preventDefault: boolean = true
-
-Whether to `preventDefault()` native events. Native behavior is prevented by
-default. If an anchor is the child of `Press`, internal and external navigation
-should be performed in `onPress`/`onLongPress`. To rely on native behavior
-instead, set `preventDefault` to `false`, but be aware that native behavior will
-take place immediately after interaction without respect for delays or long
-press.
+This can be used to dispatch async events, e.g., those that fire after a delay.
diff --git a/packages/react-events/docs/Focus.md b/packages/react-events/docs/Focus.md
new file mode 100644
index 0000000000..8f2ca5bda7
--- /dev/null
+++ b/packages/react-events/docs/Focus.md
@@ -0,0 +1,44 @@
+## Focus
+
+The `Focus` module responds to focus and blur events on its child. Focus events
+are dispatched for `mouse`, `pen`, `touch`, and `keyboard`
+pointer types.
+
+Focus events do not propagate between `Focus` event responders.
+
+```js
+// Example
+const TextField = (props) => (
+
+
+
+);
+```
+
+```js
+// Types
+type FocusEvent = {
+ target: Element,
+ type: 'blur' | 'focus' | 'focuschange'
+}
+```
+
+### disabled: boolean
+
+Disables all `Focus` events.
+
+### onBlur: (e: FocusEvent) => void
+
+Called when the element loses focus.
+
+### onFocus: (e: FocusEvent) => void
+
+Called when the element gains focus.
+
+### onFocusChange: boolean => void
+
+Called when the element changes hover state (i.e., after `onBlur` and
+`onFocus`).
diff --git a/packages/react-events/docs/FocusScope.md b/packages/react-events/docs/FocusScope.md
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/react-events/docs/Hover.md b/packages/react-events/docs/Hover.md
new file mode 100644
index 0000000000..7101419344
--- /dev/null
+++ b/packages/react-events/docs/Hover.md
@@ -0,0 +1,74 @@
+## Hover
+
+The `Hover` module responds to hover events on the element it wraps. Hover
+events are only dispatched for `mouse` pointer types. Hover begins when the
+pointer enters the element's bounds and ends when the pointer leaves.
+
+Hover events do not propagate between `Hover` event responders.
+
+```js
+// Example
+const Link = (props) => (
+ const [ hovered, setHovered ] = useState(false);
+ return (
+
+
+
+ );
+);
+```
+
+```js
+// Types
+type HoverEvent = {
+ pointerType: 'mouse' | 'pen',
+ target: Element,
+ type: 'hoverstart' | 'hoverend' | 'hovermove' | 'hoverchange'
+}
+```
+
+### delayHoverEnd: number
+
+The duration of the delay between when hover ends and when `onHoverEnd` is
+called.
+
+### delayHoverStart: number
+
+The duration of the delay between when hover starts and when `onHoverStart` is
+called.
+
+### disabled: boolean
+
+Disables all `Hover` events.
+
+### onHoverChange: boolean => void
+
+Called when the element changes hover state (i.e., after `onHoverStart` and
+`onHoverEnd`).
+
+### onHoverEnd: (e: HoverEvent) => void
+
+Called once the element is no longer hovered. It will be cancelled if the
+pointer leaves the element before the `delayHoverStart` threshold is exceeded.
+
+### onHoverMove: (e: HoverEvent) => void
+
+Called when the pointer moves within the hit bounds of the element. `onHoverMove` is
+called immediately and doesn't wait for delayed `onHoverStart`.
+
+### onHoverStart: (e: HoverEvent) => void
+
+Called once the element is hovered. It will not be called if the pointer leaves
+the element before the `delayHoverStart` threshold is exceeded. And it will not
+be called more than once before `onHoverEnd` is called.
+
+### preventDefault: boolean = true
+
+Whether to `preventDefault()` native events.
diff --git a/packages/react-events/docs/Press.md b/packages/react-events/docs/Press.md
new file mode 100644
index 0000000000..20330bf7b6
--- /dev/null
+++ b/packages/react-events/docs/Press.md
@@ -0,0 +1,130 @@
+## Press
+
+The `Press` module responds to press events on the element it wraps. Press
+events are dispatched for `mouse`, `pen`, `touch`, and `keyboard` pointer types.
+Press events are only dispatched for keyboards when pressing the Enter or
+Spacebar keys. If neither `onPress` nor `onLongPress` are called, this signifies
+that the press ended outside of the element hit bounds (i.e., the user aborted
+the press).
+
+Press events do not propagate between `Press` event responders.
+
+```js
+// Example
+const Button = (props) => (
+ const [ pressed, setPressed ] = useState(false);
+ return (
+
+
+
+ );
+);
+```
+
+```js
+// Types
+type PressEvent = {
+ pointerType: 'mouse' | 'touch' | 'pen' | 'keyboard',
+ target: Element,
+ type: 'press' | 'pressstart' | 'pressend' | 'presschange' | 'pressmove' | 'longpress' | 'longpresschange'
+}
+
+type PressOffset = {
+ top: number,
+ right: number,
+ bottom: number,
+ right: number
+};
+```
+
+### delayLongPress: number = 500ms
+
+The duration of a press before `onLongPress` and `onLongPressChange` are called.
+
+### delayPressEnd: number
+
+The duration of the delay between when the press ends and when `onPressEnd` is
+called.
+
+### delayPressStart: number
+
+The duration of a delay between when the press starts and when `onPressStart` is
+called. This delay is cut short (and `onPressStart` is called) if the press is
+released before the threshold is exceeded.
+
+### disabled: boolean
+
+Disables all `Press` events.
+
+### onLongPress: (e: PressEvent) => void
+
+Called once the element has been pressed for the length of `delayLongPress`. If
+the press point moves more than 10px `onLongPress` is cancelled.
+
+### onLongPressChange: boolean => void
+
+Called when the element changes long-press state.
+
+### onLongPressShouldCancelPress: () => boolean
+
+Determines whether calling `onPress` should be cancelled if `onLongPress` or
+`onLongPressChange` have already been called. Default is `false`.
+
+### onPress: (e: PressEvent) => void
+
+Called immediately after a press is released, unless either 1) the press is
+released outside the hit bounds of the element (accounting for
+`pressRetentionOffset` and `TouchHitTarget`), or 2) the press was a long press,
+and `onLongPress` or `onLongPressChange` props are provided, and
+`onLongPressCancelsPress()` is `true`.
+
+### onPressChange: boolean => void
+
+Called when the element changes press state (i.e., after `onPressStart` and
+`onPressEnd`).
+
+### onPressEnd: (e: PressEvent) => void
+
+Called once the element is no longer pressed (because it was released, or moved
+beyond the hit bounds). If the press starts again before the `delayPressEnd`
+threshold is exceeded then the delay is reset to prevent `onPressEnd` being
+called during a press.
+
+### onPressMove: (e: PressEvent) => void
+
+Called when a press moves within the hit bounds of the element. `onPressMove` is
+called immediately and doesn't wait for delayed `onPressStart`. Never called for
+keyboard-initiated press events.
+
+### onPressStart: (e: PressEvent) => void
+
+Called once the element is pressed down. If the press is released before the
+`delayPressStart` threshold is exceeded then the delay is cut short and
+`onPressStart` is called immediately.
+
+### pressRetentionOffset: PressOffset
+
+Defines how far the pointer (while held down) may move outside the bounds of the
+element before it is deactivated. Ensure you pass in a constant to reduce memory
+allocations.
+
+### preventDefault: boolean = true
+
+Whether to `preventDefault()` native events. Native behavior is prevented by
+default. If an anchor is the child of `Press`, internal and external navigation
+should be performed in `onPress`/`onLongPress`. To rely on native behavior
+instead, set `preventDefault` to `false`, but be aware that native behavior will
+take place immediately after interaction without respect for delays or long
+press.