Skip to content

Commit

Permalink
Add Why and Demo sections to README
Browse files Browse the repository at this point in the history
  • Loading branch information
vovacodes committed Apr 1, 2021
1 parent a00be6b commit f3b2a05
Showing 1 changed file with 81 additions and 93 deletions.
174 changes: 81 additions & 93 deletions packages/react-sunbeam/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div align="center">
<div align="center"><img src="./logo.svg" width="170" height="170" alt="Sunbeam Logo"/></div>
<h1 align="center">react-sunbeam</h1>
<h1 align="center">React Sunbeam</h1>
<p>
Spatial navigation and key press management solution for React apps
</p>
Expand All @@ -11,119 +11,107 @@
</p>
</div>

## Installation

```bash
npm install react-sunbeam
```

or
## 🧐 Why

```bash
yarn add react-sunbeam
```
React Sunbeam provides a flexible and easy-to-use solution for spacial navigation and focus management.
There is wide variety of applications that can benefit from it.

## Usage
### 🎮 TV and Gaming Console Apps

```js
// app.js
import React, { useCallback, useEffect } from "react"
import { Root, Focusable, FocusManager, useFocusManager } from "react-sunbeam"
import { FocusableCard } from "./FocusableCard"

function App() {
const { setFocus, moveFocusLeft, moveFocusRight, moveFocusUp, moveFocusDown } = useFocusManager()

const onKeyDown = useCallback(
(event) => {
if (!(event instanceof KeyboardEvent)) return
switch (event.key) {
case "ArrowRight":
moveFocusRight()
return
case "ArrowLeft":
moveFocusLeft()
return
case "ArrowUp":
moveFocusUp()
return
case "ArrowDown":
moveFocusDown()
return
}
},
[focusManager]
)
Most of the applications that are running on leanback devices and controlled with a remote or gaming controller need an implementation of directional navigation.
A lot of companies end up rolling out their own custom solutions for that.
Usually those solutions are either very simple, like using column and row indices, or implementing spatial navigation which works much better for the end user but is tricky to implement correctly and hard to maintain.
React Sunbeam provides a well-tested, opensource implementation of spatial navigation that is easy to integrate into any existing React app.

useEffect(() => {
document.addEventListener("keydown", onKeyDown)
return () => document.removeEventListener("keydown", onKeyDown)
}, [onKeyDown])
### ⌨️ Web Apps with Keyboard Navigation

return (
<div>
<FocusableCard focusKey="card-1" />
<Focusable focusKey="item1">
{({ focused }) => <div>{focused ? "I am focused" : "I am not focused"}</div>}
</Focusable>
<Focusable focusKey="menuContainer">
<div>
<Focusable focusKey="menuItem1">
{({ focused }) => (
<div style={{ backgroundColor: focused ? "salmon" : "deepskyblue" }}>
You can nest Focusables
</div>
)}
</Focusable>
<Focusable focusKey="menuItem2">
{({ focused }) => (
<div style={{ backgroundColor: focused ? "salmon" : "deepskyblue" }}>
In this case Sunbeam will try to find the best candidate for the focus within the common
Focusable parent first
</div>
)}
</Focusable>
</div>
</Focusable>
<Focusable focusKey="item2">
{({ focused, path }) => (
<div style={{ textDecoration: focused ? "underline" : "none" }} onClick={() => setFocus(path)}>
You can also programmatically change focus by using `setFocus` API
</div>
)}
</Focusable>
</div>
)
}
React Sunbeam can also be very useful in the regular web apps that want to add support for directional keyboard navigation and thus make this app more accessible to the keyboard-only users.
Spreadsheets and tables, different kinds of dashboards etc, all can benefit from React Sunbeam.

const focusManager = new FocusManager({
initialFocusPath: ["menuContainer", "menuItem2"],
})
## 🪄 Demo

render(
<Root focusManager={focusManager}>
<App />
</Root>,
document.getElementById("app")
)
Try our [demos](https://sunbeam.vova.codes/#demo-selector) on the documentation website to see what kind of interactions you can build with React Sunbeam.

### [Home Screen](https://sunbeam.vova.codes/console-ui)

![demo_home_screen](https://user-images.githubusercontent.com/1524432/113286891-1577a880-92ed-11eb-9119-0d8d4a781180.gif)

### [Setting Menu](https://sunbeam.vova.codes/settings-menu)

// FocusableCard.js
import React, { useRef } from "react"
![demo_setting_menu](https://user-images.githubusercontent.com/1524432/113286880-114b8b00-92ed-11eb-983f-a2a9086a2042.gif)

## 🎬 Getting Started

**Create a focusable component**

```tsx
import { useFocusable } from "react-sunbeam"

export function FocusableCard({ focusKey }) {
export function Button() {
const elementRef = useRef(null)
const { focused } = useFocusable({ focusKey, elementRef })
const { focused } = useFocusable({ elementRef })

return (
<div ref={elementRef} style={{ border: focused ? "1px solid salmon" : "1px solid transparent" }}>
Card
</div>
<button
ref={ref}
style={{
border: focused ? "2px solid black" : "none",
}}
>
Click me
</button>
)
}
```

## API
**Start managing focus**

```tsx
import { FocusManager, Root } from "react-sunbeam"

// 1. Create a `FocusManager`.
const focusManager = new FocusManager()

// 2. Assign its method calls to an event listener of your choice.
// This can be a keyboard `keydown` event or your custom code using Gamepad API.
window.addEventListener("keydown", (event) => {
switch (event.key) {
case "ArrowRight":
event.preventDefault()
focusManager.moveRight()
return

case "ArrowLeft":
event.preventDefault()
focusManager.moveLeft()
return

case "ArrowUp":
event.preventDefault()
focusManager.moveUp()
return

case "ArrowDown":
event.preventDefault()
focusManager.moveDown()
return
}
})

// 3. Pass the `focusMananger` instance into the `Root` provider that wraps the rest of your app.
ReactDOM.render(
<Root focusManager={focusManager}>
<App />
</Root>,
rootElement
)
```

## 🍉 API

### `FocusManager`

Expand Down

0 comments on commit f3b2a05

Please sign in to comment.