Skip to content

Commit

Permalink
update components using descendants and add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
chaance committed Feb 5, 2020
1 parent 257114e commit d33518b
Show file tree
Hide file tree
Showing 11 changed files with 513 additions and 685 deletions.
1 change: 1 addition & 0 deletions packages/accordion/package.json
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@reach/auto-id": "^0.8.0",
"@reach/descendants": "^0.1.0",
"@reach/utils": "^0.8.0",
"tslib": "1.10.0",
"warning": "^4.0.3"
Expand Down
10 changes: 6 additions & 4 deletions packages/accordion/src/index.tsx
Expand Up @@ -20,19 +20,21 @@ import React, {
import {
boolOrBoolString,
checkStyles,
createDescendantContext,
createNamedContext,
DescendantProvider,
forwardRefWithAs,
isBoolean,
isNumber,
makeId,
noop,
useDescendant,
useDescendants,
useForkedRef,
wrapEvent,
} from "@reach/utils";
import {
createDescendantContext,
DescendantProvider,
useDescendant,
useDescendants,
} from "@reach/descendants";
import { useId } from "@reach/auto-id";
import PropTypes from "prop-types";
import warning from "warning";
Expand Down
1 change: 1 addition & 0 deletions packages/combobox/package.json
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@reach/auto-id": "^0.8.0",
"@reach/descendants": "^0.1.0",
"@reach/popover": "^0.8.0",
"@reach/portal": "^0.8.0",
"@reach/utils": "^0.8.0",
Expand Down
10 changes: 6 additions & 4 deletions packages/combobox/src/index.tsx
Expand Up @@ -31,19 +31,21 @@ import PropTypes from "prop-types";
import {
checkStyles,
ComponentWithForwardedRef,
createDescendantContext,
createNamedContext,
DescendantProvider,
forwardRefWithAs,
getOwnerDocument,
makeId,
useDescendant,
useDescendants,
useIsomorphicLayoutEffect as useLayoutEffect,
useForkedRef,
wrapEvent,
noop,
} from "@reach/utils";
import {
createDescendantContext,
DescendantProvider,
useDescendant,
useDescendants,
} from "@reach/descendants";
import { findAll } from "highlight-words-core";
import escapeRegexp from "escape-regexp";
import { useId } from "@reach/auto-id";
Expand Down
64 changes: 63 additions & 1 deletion packages/descendants/README.md
Expand Up @@ -236,7 +236,7 @@ So now we need a way to define arbitrary components as a `MenuItem`. One workaro

## Our solution (for now): Descendants context registration

The `descendants` package provides three key tools:
The `descendants` package provides these key tools:

- `createDescendantContext`: Creates a special context object to deal with registering descendants in a tree (accepts a name string for better debugging)
- `useDescendants`: A hook to create a state object containing a descendants array and setter function.
Expand Down Expand Up @@ -319,3 +319,65 @@ function MenuItem(props) {
);
}
```

The key tradeoff here is that descendants won't be available on the first render, and as such any components that need this data for server-side rendering will need to manage their own state and pass descendant data from from the top of the tree. For example

```jsx
function Comp() {
<Listbox>
{/*
The button needs to know which value is selected to render its label!
The label will be empty on the server if we depend on descendant hooks
*/}
<ListboxButton />
<ListboxList>
<ListboxOption value="Apple" />
<ListboxOption value="Orange" />
<ListboxOption value="Banana" />
</ListboxList>
</Listbox>;
}

function CompSSR() {
// This limits composition, but now you have your data in one place at the top
let options = ["Apple", "Orange", "Banana"];
let [activeOption, setActiveOption] = useState(options[0]);
<Listbox onChange={setActiveOption} selected={activeOption}>
{/* The button needs to know which value is selected to render its label! */}
<ListboxButton>{activeOption}</ListboxButton>
<ListboxList>
{options.map(option => (
<ListboxOption value={option} key={option} />
))}
</ListboxList>
</Listbox>;
}

function ComposableSSR() {
// You can manage state at the top and still get back some composition, you'll
// just have to deal with a bit of repitition
let [activeOption, setActiveOption] = useState("Apple");
<Listbox onChange={setActiveOption} selected={activeOption}>
{/* The button needs to know which value is selected to render its label! */}
<ListboxButton>{activeOption}</ListboxButton>
<ListboxList>
<ListboxOption value="Apple">
Apple <span aria-hidden>🍎</span>
</ListboxOption>
<ListboxOption
value="Orange"
aria-labelledby="orange-label"
aria-describedby="orange-description"
>
<span id="orange-label">
Orange <span aria-hidden>🍊</span>
</span>
<span id="orange-description">Fun fact: Oranges are delicious!</span>
</ListboxOption>
<ListboxOption value="Banana">
Banana <span aria-hidden>🍌</span>
</ListboxOption>
</ListboxList>
</Listbox>;
}
```
1 change: 1 addition & 0 deletions packages/menu-button/package.json
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@reach/auto-id": "^0.8.0",
"@reach/descendants": "^0.1.0",
"@reach/popover": "^0.8.0",
"@reach/utils": "^0.8.0",
"prop-types": "^15.7.2",
Expand Down
10 changes: 6 additions & 4 deletions packages/menu-button/src/index.tsx
Expand Up @@ -24,19 +24,21 @@ import PropTypes from "prop-types";
import { useId } from "@reach/auto-id";
import Popover, { Position } from "@reach/popover";
import {
checkStyles,
createDescendantContext,
createNamedContext,
Descendant,
DescendantProvider,
useDescendant,
useDescendants,
} from "@reach/descendants";
import {
checkStyles,
createNamedContext,
forwardRefWithAs,
getOwnerDocument,
isFunction,
isString,
makeId,
noop,
useDescendant,
useDescendants,
useForkedRef,
usePrevious,
wrapEvent,
Expand Down
1 change: 1 addition & 0 deletions packages/tabs/package.json
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@reach/auto-id": "^0.8.0",
"@reach/descendants": "^0.1.0",
"@reach/utils": "^0.8.0",
"prop-types": "^15.7.2",
"tslib": "1.10.0",
Expand Down
10 changes: 6 additions & 4 deletions packages/tabs/src/index.tsx
Expand Up @@ -36,20 +36,22 @@ import React, {
} from "react";
import PropTypes from "prop-types";
import warning from "warning";
import {
createDescendantContext,
DescendantProvider,
useDescendant,
useDescendants,
} from "@reach/descendants";
import {
boolOrBoolString,
checkStyles,
cloneValidElement,
createDescendantContext,
createNamedContext,
DescendantProvider,
forwardRefWithAs,
isFunction,
isNumber,
makeId,
noop,
useDescendant,
useDescendants,
useForkedRef,
useIsomorphicLayoutEffect as useLayoutEffect,
useUpdateEffect,
Expand Down

0 comments on commit d33518b

Please sign in to comment.