diff --git a/.changeset/chilly-lemons-promise.md b/.changeset/chilly-lemons-promise.md new file mode 100644 index 00000000000..8eea7b9e0d2 --- /dev/null +++ b/.changeset/chilly-lemons-promise.md @@ -0,0 +1,5 @@ +--- +"@primer/react": major +--- + +Remove sx from UnderlinePanels diff --git a/packages/react/src/UnderlineNav/UnderlineNav.tsx b/packages/react/src/UnderlineNav/UnderlineNav.tsx index 989395eca2c..0c8a417773d 100644 --- a/packages/react/src/UnderlineNav/UnderlineNav.tsx +++ b/packages/react/src/UnderlineNav/UnderlineNav.tsx @@ -1,4 +1,4 @@ -import type {MutableRefObject, RefObject} from 'react' +import type {RefObject} from 'react' import React, {useRef, forwardRef, useCallback, useState, useEffect} from 'react' import {UnderlineNavContext} from './UnderlineNavContext' import type {ResizeObserverEntry} from '../hooks/useResizeObserver' @@ -144,7 +144,7 @@ export const UnderlineNav = forwardRef( forwardedRef, ) => { const backupRef = useRef(null) - const navRef = (forwardedRef ?? backupRef) as MutableRefObject + const navRef = (forwardedRef ?? backupRef) as RefObject const listRef = useRef(null) const moreMenuRef = useRef(null) const moreMenuBtnRef = useRef(null) @@ -205,7 +205,7 @@ export const UnderlineNav = forwardRef( const widthToFitIntoList = getItemsWidth(prospectiveListItem.props.children) // Check if there is any empty space on the right side of the list const availableSpace = - navRef.current.getBoundingClientRect().width - (listRef.current?.getBoundingClientRect().width ?? 0) + (navRef.current?.getBoundingClientRect().width ?? 0) - (listRef.current?.getBoundingClientRect().width ?? 0) // Calculate how many items need to be pulled in to the menu to make room for the selected menu item // I.e. if we need to pull 2 items in (index 0 and index 1), breakpoint (index) will return 1. diff --git a/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx b/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx index 0a9ca088c3b..1d7dc2f19c2 100644 --- a/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx +++ b/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx @@ -11,13 +11,7 @@ import React, { import {TabContainerElement} from '@github/tab-container-element' import type {IconProps} from '@primer/octicons-react' import {createComponent} from '../../utils/create-component' -import { - UnderlineItemList, - UnderlineWrapper, - UnderlineItem, - type UnderlineItemProps, -} from '../../internal/components/UnderlineTabbedInterface' -import {type BoxProps} from '../../Box' +import {UnderlineItemList, UnderlineWrapper, UnderlineItem} from '../../internal/components/UnderlineTabbedInterface' import {useId} from '../../hooks' import {invariant} from '../../utils/invariant' import {type SxProp} from '../../sx' @@ -25,7 +19,6 @@ import {useResizeObserver, type ResizeObserverEntry} from '../../hooks/useResize import useIsomorphicLayoutEffect from '../../utils/useIsomorphicLayoutEffect' import classes from './UnderlinePanels.module.css' import {clsx} from 'clsx' -import {BoxWithFallback} from '../../internal/components/BoxWithFallback' export type UnderlinePanelsProps = { /** @@ -74,7 +67,7 @@ export type TabProps = PropsWithChildren<{ }> & SxProp -export type PanelProps = Omit +export type PanelProps = React.HTMLAttributes const TabContainerComponent = createComponent(TabContainerElement, 'tab-container') @@ -104,23 +97,44 @@ const UnderlinePanels: FC = ({ let panelIndex = 0 const childrenWithProps = Children.map(children, child => { - if (isValidElement(child) && child.type === Tab) { + if ( + isValidElement(child) && + (typeof child.type === 'function' || typeof child.type === 'object') && + 'displayName' in child.type && + child.type.displayName === 'UnderlinePanels.Tab' + ) { return cloneElement(child, {id: `${parentId}-tab-${tabIndex++}`, loadingCounters, iconsVisible}) } - if (isValidElement(child) && child.type === Panel) { - return cloneElement(child, {'aria-labelledby': `${parentId}-tab-${panelIndex++}`}) + if ( + isValidElement(child) && + (typeof child.type === 'function' || typeof child.type === 'object') && + 'displayName' in child.type && + child.type.displayName === 'UnderlinePanels.Panel' + ) { + const childPanel = child as React.ReactElement + return cloneElement(childPanel, {'aria-labelledby': `${parentId}-tab-${panelIndex++}`}) } return child }) const newTabs = Children.toArray(childrenWithProps).filter(child => { - return isValidElement(child) && child.type === Tab + return ( + isValidElement(child) && + (typeof child.type === 'function' || typeof child.type === 'object') && + 'displayName' in child.type && + child.type.displayName === 'UnderlinePanels.Tab' + ) }) - const newTabPanels = Children.toArray(childrenWithProps).filter( - child => isValidElement(child) && child.type === Panel, - ) + const newTabPanels = Children.toArray(childrenWithProps).filter(child => { + return ( + isValidElement(child) && + (typeof child.type === 'function' || typeof child.type === 'object') && + 'displayName' in child.type && + child.type.displayName === 'UnderlinePanels.Panel' + ) + }) setTabs(newTabs) setTabPanels(newTabPanels) @@ -221,8 +235,12 @@ const Tab: FC = ({'aria-selected': ariaSelected, onSelect, ...props}) Tab.displayName = 'UnderlinePanels.Tab' -const Panel: FC = props => { - return +const Panel: FC = ({children, ...rest}) => { + return ( +
+ {children} +
+ ) } Panel.displayName = 'UnderlinePanels.Panel' diff --git a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx index a2887dd13ad..6bb6a388cae 100644 --- a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx +++ b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx @@ -1,36 +1,37 @@ // Used for UnderlineNav and UnderlinePanels components -import type React from 'react' -import {forwardRef, type FC, type PropsWithChildren} from 'react' +import React from 'react' +import {type ForwardedRef, forwardRef, type FC, type PropsWithChildren, type ElementType} from 'react' import {isElement} from 'react-is' import type {IconProps} from '@primer/octicons-react' import CounterLabel from '../../CounterLabel' -import {type SxProp} from '../../sx' import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../../utils/polymorphic' import classes from './UnderlineTabbedInterface.module.css' import {clsx} from 'clsx' -import {BoxWithFallback} from './BoxWithFallback' // The gap between the list items. It is a constant because the gap is used to calculate the possible number of items that can fit in the container. export const GAP = 8 -type UnderlineWrapperProps = { +type UnderlineWrapperProps = { slot?: string - as?: React.ElementType + as?: As className?: string - ref?: React.Ref -} & SxProp + ref?: React.Ref +} -export const UnderlineWrapper = forwardRef( - ({children, className, ...rest}: PropsWithChildren, forwardedRef) => { - return ( - - {children} - - ) - }, -) +export const UnderlineWrapper = forwardRef((props, ref) => { + const {children, className, as: Component = 'nav', ...rest} = props + return ( + } + {...rest} + > + {children} + + ) +}) as PolymorphicForwardRefComponent> export const UnderlineItemList = forwardRef(({children, ...rest}: PropsWithChildren, forwardedRef) => { return ( @@ -44,8 +45,8 @@ export const LoadingCounter = () => { return } -export type UnderlineItemProps = { - as?: React.ElementType | 'a' | 'button' +export type UnderlineItemProps = { + as?: As | 'a' | 'button' className?: string iconsVisible?: boolean loadingCounters?: boolean @@ -53,42 +54,29 @@ export type UnderlineItemProps = { icon?: FC | React.ReactElement id?: string ref?: React.Ref -} & SxProp +} & React.ComponentPropsWithoutRef -export const UnderlineItem = forwardRef( - ( - { - as = 'a', - children, - counter, - icon: Icon, - iconsVisible, - loadingCounters, - className, - ...rest - }: PropsWithChildren, - forwardedRef, - ) => { - return ( - - {iconsVisible && Icon && {isElement(Icon) ? Icon : }} - {children && ( - - {children} +export const UnderlineItem = React.forwardRef((props, ref) => { + const {as: Component = 'a', children, counter, icon: Icon, iconsVisible, loadingCounters, className, ...rest} = props + return ( + + {iconsVisible && Icon && {isElement(Icon) ? Icon : }} + {children && ( + + {children} + + )} + {counter !== undefined ? ( + loadingCounters ? ( + + - )} - {counter !== undefined ? ( - loadingCounters ? ( - - - - ) : ( - - {counter} - - ) - ) : null} - - ) - }, -) as PolymorphicForwardRefComponent<'a', UnderlineItemProps> + ) : ( + + {counter} + + ) + ) : null} + + ) +}) as PolymorphicForwardRefComponent> diff --git a/packages/styled-react/src/components/TabNav.tsx b/packages/styled-react/src/components/TabNav.tsx index 94e39f50eb3..0ac8c3d7634 100644 --- a/packages/styled-react/src/components/TabNav.tsx +++ b/packages/styled-react/src/components/TabNav.tsx @@ -13,8 +13,9 @@ const StyledTabNav = styled(PrimerTabNav).withConfig({ ${sx} ` -// @ts-ignore forwardedAs is valid here but I don't know how to fix the typescript error -const TabNavImpl = ({as, ...props}: TabNavProps) => +const TabNavImpl = ({as, ...props}: TabNavProps) => { + return +} const StyledTabNavLink: ForwardRefComponent<'a', TabNavLinkProps> = styled(PrimerTabNav.Link).withConfig({ shouldForwardProp: prop => (prop as keyof TabNavLinkProps) !== 'sx', @@ -22,8 +23,9 @@ const StyledTabNavLink: ForwardRefComponent<'a', TabNavLinkProps> = styled(Prime ${sx} ` -// @ts-ignore forwardedAs is valid here but I don't know how to fix the typescript error -const TabNavLink = ({as, ...props}: TabNavLinkProps) => +const TabNavLink = ({as, ...props}: TabNavLinkProps) => ( + +) const TabNav = Object.assign(TabNavImpl, { Link: TabNavLink, diff --git a/packages/styled-react/src/components/UnderlinePanels.tsx b/packages/styled-react/src/components/UnderlinePanels.tsx new file mode 100644 index 00000000000..1f5f68eacf1 --- /dev/null +++ b/packages/styled-react/src/components/UnderlinePanels.tsx @@ -0,0 +1,59 @@ +import { + UnderlinePanels as PrimerUnderlinePanels, + type UnderlinePanelsProps as PrimerUnderlinePanelsProps, + type UnderlinePanelsPanelProps as PrimerUnderlinePanelsPanelProps, + type UnderlinePanelsTabProps as PrimerUnderlinePanelsTabProps, +} from '@primer/react/experimental' +import styled from 'styled-components' +import {sx, type SxProp} from '../sx' + +type UnderlinePanelsProps = PrimerUnderlinePanelsProps & SxProp + +const StyledUnderlinePanels = styled(PrimerUnderlinePanels).withConfig({ + shouldForwardProp: prop => prop !== 'sx', +})` + ${sx} +` + +// @ts-ignore forwardedAs is valid here but I don't know how to fix the typescript error +const UnderlinePanelsImpl = ({as, ...props}: UnderlinePanelsProps) => ( + +) + +UnderlinePanelsImpl.displayName = 'UnderlinePanels' + +type UnderlinePanelsPanelProps = PrimerUnderlinePanelsPanelProps & SxProp + +const StyledUnderlinePanelsPanel = styled(PrimerUnderlinePanels.Panel).withConfig({ + shouldForwardProp: prop => prop !== 'sx', +})` + ${sx} +` + +// @ts-ignore forwardedAs is valid here but I don't know how to fix the typescript error +const UnderlinePanelsPanel = ({as, ...props}: UnderlinePanelsPanelProps) => { + return +} + +UnderlinePanelsPanel.displayName = 'UnderlinePanels.Panel' + +type UnderlinePanelsTabProps = PrimerUnderlinePanelsTabProps & SxProp + +const StyledUnderlinePanelsTab = styled(PrimerUnderlinePanels.Tab).withConfig({ + shouldForwardProp: prop => prop !== 'sx', +})` + ${sx} +` +// @ts-ignore forwardedAs is valid here but I don't know how to fix the typescript error +const UnderlinePanelsTab = ({as, ...props}: UnderlinePanelsTabProps) => ( + +) + +UnderlinePanelsTab.displayName = 'UnderlinePanels.Tab' + +const UnderlinePanels = Object.assign(UnderlinePanelsImpl, { + Tab: UnderlinePanelsTab, + Panel: UnderlinePanelsPanel, +}) + +export {UnderlinePanels, type UnderlinePanelsProps, type UnderlinePanelsTabProps, type UnderlinePanelsPanelProps} diff --git a/packages/styled-react/src/experimental.tsx b/packages/styled-react/src/experimental.tsx index 84f0becab80..19f620aff3c 100644 --- a/packages/styled-react/src/experimental.tsx +++ b/packages/styled-react/src/experimental.tsx @@ -1,8 +1,16 @@ export {Dialog, type DialogProps} from './components/Dialog' + export { PageHeader, type PageHeaderProps, type PageHeaderActionsProps, type PageHeaderTitleProps, } from './components/PageHeader' -export {Table, Tooltip, UnderlinePanels} from '@primer/react/experimental' + +export { + UnderlinePanels, + type UnderlinePanelsProps, + type UnderlinePanelsTabProps, + type UnderlinePanelsPanelProps, +} from './components/UnderlinePanels' +export {Table, Tooltip} from '@primer/react/experimental'