Skip to content

Commit

Permalink
Creates highlight management utilities in descendants [LG-4389] (#2423
Browse files Browse the repository at this point in the history
)

* creates highlight package

* mv descendants files to subdir

* mv highlight to descendants

* cleanup descendants utils

* types for highlight fns

* creates useHighlightContext

* create basic story

* create Grid story

* create getRelativeDescendant util

* adds tests for getRelativeDescendant

* mv onChange to options.onChange

* adds `filter` option

* Cleanup ActionType

* implement Position action

* Creates ValuesOf

* improve setter types & logic

* add docs & changelog

* adds onInit

* Update README.md

* adds todo tests

* Update README.md

* Update Highlight.stories.tsx

* Update Highlight.stories.tsx

* Descendants DX (#2430)

* useInitDescendants accepts context

* Create swift-points-sip.md

* Update Highlight.stories.tsx

* Update Tabs to use latest Descendants API

* Update Menu to use latest Descendants API

* rename setters. rm setter from context

* Returns Provider from useHighlight

* Update README.md

* adds tests for useHighlight

* Update Highlight.spec.tsx

* Update Descendants.stories.tsx

* Update README.md

* Update README.md
  • Loading branch information
TheSonOfThomp authored Jul 15, 2024
1 parent 76d605e commit 4c04aa0
Show file tree
Hide file tree
Showing 55 changed files with 1,456 additions and 229 deletions.
5 changes: 5 additions & 0 deletions .changeset/lemon-pets-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@leafygreen-ui/lib': minor
---

Creates utility types `Only`, `ExclusiveUnion` and `ValuesOf`
5 changes: 5 additions & 0 deletions .changeset/mean-pandas-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@leafygreen-ui/menu': patch
---

Update Menu to use latest Descendants API
5 changes: 5 additions & 0 deletions .changeset/sour-kangaroos-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@leafygreen-ui/tabs': patch
---

Updates Tabs to use latest Descendants API
37 changes: 37 additions & 0 deletions .changeset/swift-points-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
'@leafygreen-ui/descendants': major
---

Updates `useInitDescendants` signature to require a Context value, and return a `Provider` component.

Eliminates the need to destructure `descendants` and `dispatch` from the hook's return value just to pass into the provider. Instead, the hook will construct a pre-populated provider unique to the Context value given.

Note: `descendants`, `dispatch` and `getDescendants` are still returned by the hook for use in the parent component if necessary.

Before:
```tsx
const MyDescendantContext = createDescendantsContext();
const { descendants, dispatch } = useInitDescendants();

return (
<DescendantsProvider
context={MyDescendantContext}
descendants={descendants}
dispatch={dispatch}
>
<MyDescendantItem />
</DescendantsProvider>
)
```

After:
```tsx
const MyDescendantContext = createDescendantsContext();
const { Provider } = useInitDescendants(MyDescendantContext);

return (
<Provider>
<MyDescendantItem />
</Provider>
)
```
9 changes: 9 additions & 0 deletions .changeset/tidy-dancers-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@leafygreen-ui/descendants': minor
---

Adds Highlight management utilities.
- `useHighlight`: A hook to initialize the highlight state management
- `HighlightProvider`: A context provider for consuming the highlight state from descendant components
- `createHighlightContext`: Constructs a unique Context object in order to support nested contexts

50 changes: 23 additions & 27 deletions packages/descendants/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,16 @@ There are 4 steps required to set up a pair of components as Parent/Descendent.
* shouldn't track fly-out menu items as its own descendants)
*
*/
const MyDescendantsContext = createDescendantsContext('MyDescendantsContext');
const MyDescendantsContext = createDescendantsContext<HTMLDivElement>(
'MyDescendantsContext',
);

export const MyParent = ({ children, ...rest }: ComponentProps<'div'>) => {
/**
* 2. Initialize an empty descendants list and setter
*
* We call this _outside_ the Provider
* so we can access the `descendants` object
* from the Parent level.
* 2. Initialize an empty descendants list and provider
*/
const { descendants, dispatch } = useInitDescendants<HTMLDivElement>();
const { getDescendants, Provider: MyDescendantsProvider } =
useInitDescendants(MyDescendantsContext);

/**
* 3. Pass the context, descendants list and setter into the provider
Expand All @@ -69,13 +68,9 @@ export const MyParent = ({ children, ...rest }: ComponentProps<'div'>) => {
* (see fly-out menu example in step 1.)
*/
return (
<DescendantsProvider
context={MyDescendantsContext}
descendants={descendants}
dispatch={dispatch}
>
<MyDescendantsProvider>
<div {...rest}>{children}</div>
</DescendantsProvider>
</MyDescendantsProvider>
);
};

Expand All @@ -84,15 +79,11 @@ export const TestDescendant = ({
...rest
}: ComponentProps<'div'>) => {
/**
* 4. Establish a child component as a descendant
*
* Pass the context value into the hook
* in order to establish this element
* 4. Establish a child component as a descendant of our context
*/
const { index, ref } = useDescendant(MyDescendantsContext);

// This component has access to its index within the Parent context

// This component has access to its relative index within the Parent context
return (
<div ref={ref} {...rest}>
{children}
Expand All @@ -105,28 +96,33 @@ export const TestDescendant = ({

Sometimes you'll need to access descendants from within an event handler or `useEffect` callback, where the descendants may have updated between renders, resulting in a `descendants` object with references to stale/non-existent DOM nodes. In this case, use the `getDescendants()` function to access the most up-to-date descendants object.

In general: **Prefer using `getDescendants()`, since it will guarantee references to the most up-to-date descendants objects.**

```typescript
const { descendants, dispatch, getDescendants } =
useInitDescendants<HTMLDivElement>();
const {
Provider: MyDescendantsProvider,
getDescendants,
descendants,
} = useInitDescendants(MyDescendantsContext);

const handleTransition = () => {
console.log(descendants); // this list will be empty, or contain references to old DOM nodes
console.log(getDescendants()); // this call will return a list of the updated descendants list
};

return (
<DescendantsProvider
context={MyDescendantsContext}
descendants={descendants}
dispatch={dispatch}
>
<MyDescendantsProvider>
<Transition onEntered={handleTransition}>
<div {...rest}>{children}</div>
</Transition>
</DescendantsProvider>
</MyDescendantsProvider>
);
```

## Highlight Management

See [Highlight/README.md](./src/Highlight/README.md)

## Prior Art

This package heavily references the work of [`pacocoursey/use-descendants`](https://github.com/pacocoursey/use-descendants/tree/v0) and [`@reach-ui/descendants`](https://github.com/reach/reach-ui/tree/dev/packages/descendants). Many thanks to the authors of those packages!
Expand Down
1 change: 1 addition & 0 deletions packages/descendants/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@leafygreen-ui/hooks": "^8.1.3",
"@leafygreen-ui/lib": "^13.6.1",
"lodash": "^4.17.21"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit 4c04aa0

Please sign in to comment.