From a38c00e6722373599e6be83b857c7f22c2014459 Mon Sep 17 00:00:00 2001 From: Cole Bemis Date: Fri, 31 Mar 2023 13:22:45 -0600 Subject: [PATCH] Use SSR-compatible slot implementation in TreeView (#3097) * Use SSR-compatible slot implementation in TreeView * Update generated/components.json * Create .changeset/sharp-eggs-crash.md * Disable no-explicit-any lint rule * Update .changeset/sharp-eggs-crash.md --------- Co-authored-by: colebemis --- .changeset/sharp-eggs-crash.md | 7 +++++++ src/TreeView/TreeView.tsx | 35 ++++++++++++++-------------------- src/hooks/useSlots.ts | 3 ++- 3 files changed, 23 insertions(+), 22 deletions(-) create mode 100644 .changeset/sharp-eggs-crash.md diff --git a/.changeset/sharp-eggs-crash.md b/.changeset/sharp-eggs-crash.md new file mode 100644 index 00000000000..3e64d1a28c1 --- /dev/null +++ b/.changeset/sharp-eggs-crash.md @@ -0,0 +1,7 @@ +--- +"@primer/react": patch +--- + +`TreeView` is now SSR-compatible. + +Warning: In this new implementation, `TreeView.LeadingVisual` and `TreeView.TrailingView` must be direct children of `TreeView.Item`. diff --git a/src/TreeView/TreeView.tsx b/src/TreeView/TreeView.tsx index b2644deff60..15c36120e31 100644 --- a/src/TreeView/TreeView.tsx +++ b/src/TreeView/TreeView.tsx @@ -7,16 +7,16 @@ import { import classnames from 'classnames' import React from 'react' import styled, {keyframes} from 'styled-components' -import {get} from '../constants' import {ConfirmationDialog} from '../Dialog/ConfirmationDialog' +import Spinner from '../Spinner' +import Text from '../Text' +import VisuallyHidden from '../_VisuallyHidden' +import {get} from '../constants' import {useControllableState} from '../hooks/useControllableState' import {useId} from '../hooks/useId' import useSafeTimeout from '../hooks/useSafeTimeout' -import Spinner from '../Spinner' +import {useSlots} from '../hooks/useSlots' import sx, {SxProp} from '../sx' -import Text from '../Text' -import createSlots from '../utils/create-slots' -import VisuallyHidden from '../_VisuallyHidden' import {getAccessibleName} from './shared' import {getFirstChildElement, useRovingTabIndex} from './useRovingTabIndex' import {useTypeahead} from './useTypeahead' @@ -318,8 +318,6 @@ export type TreeViewItemProps = { onSelect?: (event: React.MouseEvent | React.KeyboardEvent) => void } -const {Slots, Slot} = createSlots(['LeadingVisual', 'TrailingVisual']) - const Item = React.forwardRef( ( { @@ -334,6 +332,7 @@ const Item = React.forwardRef( }, ref, ) => { + const [slots, rest] = useSlots(children, {leadingVisual: LeadingVisual, trailingVisual: TrailingVisual}) const {expandedStateCache} = React.useContext(RootContext) const labelId = useId() const leadingVisualId = useId() @@ -349,7 +348,7 @@ const Item = React.forwardRef( onChange: onExpandedChange, }) const {level} = React.useContext(ItemContext) - const {hasSubTree, subTree, childrenWithoutSubTree} = useSubTree(children) + const {hasSubTree, subTree, childrenWithoutSubTree} = useSubTree(rest) const [isSubTreeEmpty, setIsSubTreeEmpty] = React.useState(!hasSubTree) const [isFocused, setIsFocused] = React.useState(false) @@ -478,15 +477,9 @@ const Item = React.forwardRef( ) : null}
- - {slots => ( - <> - {slots.LeadingVisual} - {childrenWithoutSubTree} - {slots.TrailingVisual} - - )} - + {slots.leadingVisual} + {childrenWithoutSubTree} + {slots.trailingVisual}
{subTree} @@ -773,14 +766,14 @@ const LeadingVisual: React.FC = props => { const {isExpanded, leadingVisualId} = React.useContext(ItemContext) const children = typeof props.children === 'function' ? props.children({isExpanded}) : props.children return ( - + <>
{props.label}
{children}
-
+ ) } @@ -790,14 +783,14 @@ const TrailingVisual: React.FC = props => { const {isExpanded, trailingVisualId} = React.useContext(ItemContext) const children = typeof props.children === 'function' ? props.children({isExpanded}) : props.children return ( - + <>
{props.label}
{children}
-
+ ) } diff --git a/src/hooks/useSlots.ts b/src/hooks/useSlots.ts index 6c1de73a3dd..e9df43bc449 100644 --- a/src/hooks/useSlots.ts +++ b/src/hooks/useSlots.ts @@ -1,7 +1,8 @@ import React from 'react' import {warning} from '../utils/warning' -export type SlotConfig = Record +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type SlotConfig = Record> type SlotElements = { [Property in keyof Type]: React.ReactElement