From 9548fcc7f788ca743a49544fd88bc4b3aca326b7 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Wed, 10 Sep 2025 16:18:01 +1000 Subject: [PATCH 01/15] Fix up panels --- .../UnderlinePanels/UnderlinePanels.tsx | 9 +++-- .../components/UnderlineTabbedInterface.tsx | 36 ++++++------------- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx b/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx index 0a9ca088c3b..8d40b089254 100644 --- a/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx +++ b/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx @@ -25,7 +25,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 = { /** @@ -221,8 +220,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..e3ce59a15bd 100644 --- a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx +++ b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx @@ -5,12 +5,10 @@ import {forwardRef, type FC, type PropsWithChildren} 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 @@ -19,15 +17,15 @@ type UnderlineWrapperProps = { slot?: string as?: React.ElementType className?: string - ref?: React.Ref -} & SxProp + ref?: React.Ref +} -export const UnderlineWrapper = forwardRef( - ({children, className, ...rest}: PropsWithChildren, forwardedRef) => { +export const UnderlineWrapper = forwardRef>( + ({children, className, ...rest}, forwardedRef) => { return ( - +
{children} - +
) }, ) @@ -53,24 +51,12 @@ export type UnderlineItemProps = { icon?: FC | React.ReactElement id?: string ref?: React.Ref -} & SxProp +} -export const UnderlineItem = forwardRef( - ( - { - as = 'a', - children, - counter, - icon: Icon, - iconsVisible, - loadingCounters, - className, - ...rest - }: PropsWithChildren, - forwardedRef, - ) => { +export const UnderlineItem = forwardRef>( + ({as = 'a', children, counter, icon: Icon, iconsVisible, loadingCounters, className, ...rest}, forwardedRef) => { return ( - +
{iconsVisible && Icon && {isElement(Icon) ? Icon : }} {children && ( @@ -88,7 +74,7 @@ export const UnderlineItem = forwardRef( ) ) : null} - +
) }, ) as PolymorphicForwardRefComponent<'a', UnderlineItemProps> From 7e4132efcb79e85b4dd19b70fb87e06b9a6a0191 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Thu, 18 Sep 2025 09:23:36 +1000 Subject: [PATCH 02/15] not a good state --- .../components/UnderlineTabbedInterface.tsx | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx index e3ce59a15bd..f0db244a12b 100644 --- a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx +++ b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx @@ -1,7 +1,7 @@ // Used for UnderlineNav and UnderlinePanels components import type React from 'react' -import {forwardRef, type FC, type PropsWithChildren} from 'react' +import {type ForwardedRef, forwardRef, type FC, type PropsWithChildren} from 'react' import {isElement} from 'react-is' import type {IconProps} from '@primer/octicons-react' import CounterLabel from '../../CounterLabel' @@ -42,8 +42,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 @@ -51,30 +51,30 @@ export type UnderlineItemProps = { icon?: FC | React.ReactElement id?: string ref?: React.Ref -} +} & React.ComponentPropsWithoutRef -export const UnderlineItem = forwardRef>( - ({as = 'a', children, counter, icon: Icon, iconsVisible, loadingCounters, className, ...rest}, forwardedRef) => { - return ( -
- {iconsVisible && Icon && {isElement(Icon) ? Icon : }} - {children && ( - - {children} +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function UnderlineItem(props: UnderlineItemProps, ref: ForwardedRef) { + 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} + + ) +} From 54c09fb8ce29899d05d89858fbf37def574f73db Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Thu, 18 Sep 2025 10:47:03 +1000 Subject: [PATCH 03/15] Fix the underlineitem types Co-authored-by: Marie Lucca --- .../experimental/UnderlinePanels/UnderlinePanels.tsx | 12 +++--------- .../internal/components/UnderlineTabbedInterface.tsx | 11 +++++------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx b/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx index 8d40b089254..4b957d42479 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' @@ -73,7 +67,7 @@ export type TabProps = PropsWithChildren<{ }> & SxProp -export type PanelProps = Omit +export type PanelProps = React.HTMLAttributes const TabContainerComponent = createComponent(TabContainerElement, 'tab-container') @@ -103,7 +97,7 @@ const UnderlinePanels: FC = ({ let panelIndex = 0 const childrenWithProps = Children.map(children, child => { - if (isValidElement(child) && child.type === Tab) { + if (isValidElement(child) && child.type === Tab) { return cloneElement(child, {id: `${parentId}-tab-${tabIndex++}`, loadingCounters, iconsVisible}) } diff --git a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx index f0db244a12b..5ac5df8ef12 100644 --- a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx +++ b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx @@ -1,7 +1,7 @@ // Used for UnderlineNav and UnderlinePanels components -import type React from 'react' -import {type ForwardedRef, forwardRef, type FC, type PropsWithChildren} from 'react' +import React from 'react' +import {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' @@ -53,11 +53,10 @@ export type UnderlineItemProps = { ref?: React.Ref } & React.ComponentPropsWithoutRef -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function UnderlineItem(props: UnderlineItemProps, ref: ForwardedRef) { +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 && ( @@ -77,4 +76,4 @@ export function UnderlineItem(props: UnderlineItem ) : null} ) -} +}) as PolymorphicForwardRefComponent> From 64d1fc9f8b5b84c87df4f98aa2f064eb78ca2e1a Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Thu, 18 Sep 2025 11:10:54 +1000 Subject: [PATCH 04/15] Create chilly-lemons-promise.md --- .changeset/chilly-lemons-promise.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/chilly-lemons-promise.md 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 From 82a68db9c9c2ef154597b3b64b438ddc881b8982 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Thu, 18 Sep 2025 14:19:45 +1000 Subject: [PATCH 05/15] Fix types --- .../react/src/UnderlineNav/UnderlineNav.tsx | 17 ++++------------- .../components/UnderlineTabbedInterface.tsx | 12 ++++++++---- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/packages/react/src/UnderlineNav/UnderlineNav.tsx b/packages/react/src/UnderlineNav/UnderlineNav.tsx index c0f44fe244c..739b0087486 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 Box from '../Box' import type {SxProp} from '../sx' @@ -18,7 +18,6 @@ import {useOnEscapePress} from '../hooks/useOnEscapePress' import {useOnOutsideClick} from '../hooks/useOnOutsideClick' import {useId} from '../hooks/useId' import {ActionList} from '../ActionList' -import {defaultSxProp} from '../utils/defaultSxProp' import CounterLabel from '../CounterLabel' import {invariant} from '../utils/invariant' @@ -145,7 +144,6 @@ export const UnderlineNav = forwardRef( { as = 'nav', 'aria-label': ariaLabel, - sx: sxProp = defaultSxProp, loadingCounters = false, variant = 'inset', className, @@ -154,7 +152,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) @@ -215,7 +213,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. @@ -316,14 +314,7 @@ export const UnderlineNav = forwardRef( }} > {ariaLabel && {`${ariaLabel} navigation`}} - + {listItems} {menuItems.length > 0 && ( diff --git a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx index 5ac5df8ef12..44dd76ffab5 100644 --- a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx +++ b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx @@ -1,7 +1,7 @@ // Used for UnderlineNav and UnderlinePanels components import React from 'react' -import {forwardRef, type FC, type PropsWithChildren, type ElementType} 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' @@ -17,13 +17,17 @@ type UnderlineWrapperProps = { slot?: string as?: React.ElementType className?: string - ref?: React.Ref + ref?: React.Ref } -export const UnderlineWrapper = forwardRef>( +export const UnderlineWrapper = forwardRef>( ({children, className, ...rest}, forwardedRef) => { return ( -
+
} + {...rest} + > {children}
) From da12e6e710acad5081d36ce46a487400d8f9f5e7 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Thu, 18 Sep 2025 14:44:29 +1000 Subject: [PATCH 06/15] Remove the browser test --- ...primer-react-experimental.browser.test.tsx | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/packages/styled-react/src/__tests__/primer-react-experimental.browser.test.tsx b/packages/styled-react/src/__tests__/primer-react-experimental.browser.test.tsx index 4e2a8fa64fe..87f3ec1c8e8 100644 --- a/packages/styled-react/src/__tests__/primer-react-experimental.browser.test.tsx +++ b/packages/styled-react/src/__tests__/primer-react-experimental.browser.test.tsx @@ -1,6 +1,6 @@ import {render, screen} from '@testing-library/react' import {describe, expect, test} from 'vitest' -import {Dialog, PageHeader, Table, Tooltip, UnderlinePanels} from '../experimental' +import {Dialog, PageHeader, Table, Tooltip} from '../experimental' describe('@primer/react/experimental', () => { test('Dialog supports `sx` prop', () => { @@ -26,26 +26,4 @@ describe('@primer/react/experimental', () => { ) expect(window.getComputedStyle(screen.getByRole('tooltip', {hidden: true})).backgroundColor).toBe('rgb(255, 0, 0)') }) - - test('UnderlinePanels supports `sx` prop', () => { - render( - - tab - panel - , - ) - expect(window.getComputedStyle(screen.getByTestId('component')).backgroundColor).toBe('rgb(255, 0, 0)') - }) - - test('UnderlinePanels.Panel supports `sx` prop', () => { - render( - - tab - - panel - - , - ) - expect(window.getComputedStyle(screen.getByTestId('component')).backgroundColor).toBe('rgb(255, 0, 0)') - }) }) From a868c4d21eafb85d4b65faea5a00fb589510596b Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Thu, 18 Sep 2025 22:43:07 +1000 Subject: [PATCH 07/15] Good catch by the tests --- .../components/UnderlineTabbedInterface.tsx | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx index 44dd76ffab5..6bb6a388cae 100644 --- a/packages/react/src/internal/components/UnderlineTabbedInterface.tsx +++ b/packages/react/src/internal/components/UnderlineTabbedInterface.tsx @@ -13,26 +13,25 @@ import {clsx} from 'clsx' // 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 } -export const UnderlineWrapper = forwardRef>( - ({children, className, ...rest}, forwardedRef) => { - return ( -
} - {...rest} - > - {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 ( From 842347df6fdfee4667efbad245e72e1ca665368d Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Thu, 18 Sep 2025 22:52:35 +1000 Subject: [PATCH 08/15] UnderlineNav.Item is sx free --- .../src/__tests__/primer-react.browser.test.tsx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/styled-react/src/__tests__/primer-react.browser.test.tsx b/packages/styled-react/src/__tests__/primer-react.browser.test.tsx index 2b061a08546..8193cb5514b 100644 --- a/packages/styled-react/src/__tests__/primer-react.browser.test.tsx +++ b/packages/styled-react/src/__tests__/primer-react.browser.test.tsx @@ -431,13 +431,4 @@ describe('@primer/react', () => { ) expect(window.getComputedStyle(screen.getByLabelText('navigation')).backgroundColor).toBe('rgb(255, 0, 0)') }) - - test('UnderlineNav.Item supports `sx` prop', () => { - render( - - test - , - ) - expect(window.getComputedStyle(screen.getByTestId('component')).backgroundColor).toBe('rgb(255, 0, 0)') - }) }) From aec771a41395762ab1325d41e68acf3c7cc8988b Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Fri, 19 Sep 2025 17:40:56 +1000 Subject: [PATCH 09/15] Remove UnderlineNav from test --- .../src/__tests__/primer-react.browser.test.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/styled-react/src/__tests__/primer-react.browser.test.tsx b/packages/styled-react/src/__tests__/primer-react.browser.test.tsx index 8193cb5514b..ac95ddfa4f8 100644 --- a/packages/styled-react/src/__tests__/primer-react.browser.test.tsx +++ b/packages/styled-react/src/__tests__/primer-react.browser.test.tsx @@ -43,7 +43,6 @@ import { Token, Tooltip, Truncate, - UnderlineNav, } from '../' describe('@primer/react', () => { @@ -422,13 +421,4 @@ describe('@primer/react', () => { render() expect(window.getComputedStyle(screen.getByTestId('component')).backgroundColor).toBe('rgb(255, 0, 0)') }) - - test('UnderlineNav supports `sx` prop', () => { - render( - - test - , - ) - expect(window.getComputedStyle(screen.getByLabelText('navigation')).backgroundColor).toBe('rgb(255, 0, 0)') - }) }) From 891bcf8fb035eda15fd3c3496c9b99316bc1bf8f Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Thu, 25 Sep 2025 18:24:41 -0400 Subject: [PATCH 10/15] re-add tests --- ...primer-react-experimental.browser.test.tsx | 24 ++++++++++++++++++- .../__tests__/primer-react.browser.test.tsx | 19 +++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/packages/styled-react/src/__tests__/primer-react-experimental.browser.test.tsx b/packages/styled-react/src/__tests__/primer-react-experimental.browser.test.tsx index 87f3ec1c8e8..4e2a8fa64fe 100644 --- a/packages/styled-react/src/__tests__/primer-react-experimental.browser.test.tsx +++ b/packages/styled-react/src/__tests__/primer-react-experimental.browser.test.tsx @@ -1,6 +1,6 @@ import {render, screen} from '@testing-library/react' import {describe, expect, test} from 'vitest' -import {Dialog, PageHeader, Table, Tooltip} from '../experimental' +import {Dialog, PageHeader, Table, Tooltip, UnderlinePanels} from '../experimental' describe('@primer/react/experimental', () => { test('Dialog supports `sx` prop', () => { @@ -26,4 +26,26 @@ describe('@primer/react/experimental', () => { ) expect(window.getComputedStyle(screen.getByRole('tooltip', {hidden: true})).backgroundColor).toBe('rgb(255, 0, 0)') }) + + test('UnderlinePanels supports `sx` prop', () => { + render( + + tab + panel + , + ) + expect(window.getComputedStyle(screen.getByTestId('component')).backgroundColor).toBe('rgb(255, 0, 0)') + }) + + test('UnderlinePanels.Panel supports `sx` prop', () => { + render( + + tab + + panel + + , + ) + expect(window.getComputedStyle(screen.getByTestId('component')).backgroundColor).toBe('rgb(255, 0, 0)') + }) }) diff --git a/packages/styled-react/src/__tests__/primer-react.browser.test.tsx b/packages/styled-react/src/__tests__/primer-react.browser.test.tsx index cec9c893321..89eeeb65764 100644 --- a/packages/styled-react/src/__tests__/primer-react.browser.test.tsx +++ b/packages/styled-react/src/__tests__/primer-react.browser.test.tsx @@ -42,6 +42,7 @@ import { Token, Tooltip, Truncate, + UnderlineNav, } from '../' describe('@primer/react', () => { @@ -420,4 +421,22 @@ describe('@primer/react', () => { render() expect(window.getComputedStyle(screen.getByTestId('component')).backgroundColor).toBe('rgb(255, 0, 0)') }) + + test('UnderlineNav supports `sx` prop', () => { + render( + + test + , + ) + expect(window.getComputedStyle(screen.getByLabelText('navigation')).backgroundColor).toBe('rgb(255, 0, 0)') + }) + + test('UnderlineNav.Item supports `sx` prop', () => { + render( + + test + , + ) + expect(window.getComputedStyle(screen.getByTestId('component')).backgroundColor).toBe('rgb(255, 0, 0)') + }) }) From 6587d22a31b581d560b29e193b13c923cba7b271 Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Thu, 25 Sep 2025 18:59:22 -0400 Subject: [PATCH 11/15] add underlinePanels --- .../src/components/UnderlinePanels.tsx | 54 +++++++++++++++++++ packages/styled-react/src/experimental.tsx | 8 ++- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 packages/styled-react/src/components/UnderlinePanels.tsx diff --git a/packages/styled-react/src/components/UnderlinePanels.tsx b/packages/styled-react/src/components/UnderlinePanels.tsx new file mode 100644 index 00000000000..df1bc4a21d1 --- /dev/null +++ b/packages/styled-react/src/components/UnderlinePanels.tsx @@ -0,0 +1,54 @@ +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) => ( + +) + +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) => { + console.log(props) + return +} + +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) => ( + +) + +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 7b1764bbcb9..d5d068942ea 100644 --- a/packages/styled-react/src/experimental.tsx +++ b/packages/styled-react/src/experimental.tsx @@ -4,4 +4,10 @@ export { type PageHeaderActionsProps, type PageHeaderTitleProps, } from './components/PageHeader' -export {Dialog, Table, Tooltip, UnderlinePanels} from '@primer/react/experimental' +export { + UnderlinePanels, + type UnderlinePanelsProps, + type UnderlinePanelsTabProps, + type UnderlinePanelsPanelProps, +} from './components/UnderlinePanels' +export {Dialog, Table, Tooltip} from '@primer/react/experimental' From 24c9bdfd3e7b7e21cc0f2caa0d07eb7a062ec68e Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Thu, 25 Sep 2025 19:02:36 -0400 Subject: [PATCH 12/15] remove console.log --- packages/styled-react/src/components/UnderlinePanels.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/styled-react/src/components/UnderlinePanels.tsx b/packages/styled-react/src/components/UnderlinePanels.tsx index df1bc4a21d1..a1e0f96c10f 100644 --- a/packages/styled-react/src/components/UnderlinePanels.tsx +++ b/packages/styled-react/src/components/UnderlinePanels.tsx @@ -30,7 +30,6 @@ const StyledUnderlinePanelsPanel = styled(PrimerUnderlinePanels.Panel).withConfi // @ts-ignore forwardedAs is valid here but I don't know how to fix the typescript error const UnderlinePanelsPanel = ({as, ...props}: UnderlinePanelsPanelProps) => { - console.log(props) return } From 163e7bd2bcd967c7f35cf8ef65fc6ca7a6d1ba0a Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Thu, 25 Sep 2025 21:50:23 -0400 Subject: [PATCH 13/15] fix types --- .../UnderlinePanels/UnderlinePanels.tsx | 35 +++++++++++++++---- .../src/components/UnderlinePanels.tsx | 6 ++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx b/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx index 4b957d42479..322a3524c7a 100644 --- a/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx +++ b/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx @@ -97,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 as any).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 as any).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 as any).displayName === 'UnderlinePanels.Panel' + ) + }) setTabs(newTabs) setTabPanels(newTabPanels) diff --git a/packages/styled-react/src/components/UnderlinePanels.tsx b/packages/styled-react/src/components/UnderlinePanels.tsx index a1e0f96c10f..1f5f68eacf1 100644 --- a/packages/styled-react/src/components/UnderlinePanels.tsx +++ b/packages/styled-react/src/components/UnderlinePanels.tsx @@ -20,6 +20,8 @@ const UnderlinePanelsImpl = ({as, ...props}: UnderlinePanelsProps) => ( ) +UnderlinePanelsImpl.displayName = 'UnderlinePanels' + type UnderlinePanelsPanelProps = PrimerUnderlinePanelsPanelProps & SxProp const StyledUnderlinePanelsPanel = styled(PrimerUnderlinePanels.Panel).withConfig({ @@ -33,6 +35,8 @@ const UnderlinePanelsPanel = ({as, ...props}: UnderlinePanelsPanelProps) => { return } +UnderlinePanelsPanel.displayName = 'UnderlinePanels.Panel' + type UnderlinePanelsTabProps = PrimerUnderlinePanelsTabProps & SxProp const StyledUnderlinePanelsTab = styled(PrimerUnderlinePanels.Tab).withConfig({ @@ -45,6 +49,8 @@ const UnderlinePanelsTab = ({as, ...props}: UnderlinePanelsTabProps) => ( ) +UnderlinePanelsTab.displayName = 'UnderlinePanels.Tab' + const UnderlinePanels = Object.assign(UnderlinePanelsImpl, { Tab: UnderlinePanelsTab, Panel: UnderlinePanelsPanel, From 4962e4f67b252ae740bf3e7fe0d9c977cebdaadd Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Thu, 25 Sep 2025 22:04:08 -0400 Subject: [PATCH 14/15] remove unnecessary any --- .../src/experimental/UnderlinePanels/UnderlinePanels.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx b/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx index 322a3524c7a..1d7dc2f19c2 100644 --- a/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx +++ b/packages/react/src/experimental/UnderlinePanels/UnderlinePanels.tsx @@ -101,7 +101,7 @@ const UnderlinePanels: FC = ({ isValidElement(child) && (typeof child.type === 'function' || typeof child.type === 'object') && 'displayName' in child.type && - (child.type as any).displayName === 'UnderlinePanels.Tab' + child.type.displayName === 'UnderlinePanels.Tab' ) { return cloneElement(child, {id: `${parentId}-tab-${tabIndex++}`, loadingCounters, iconsVisible}) } @@ -110,7 +110,7 @@ const UnderlinePanels: FC = ({ isValidElement(child) && (typeof child.type === 'function' || typeof child.type === 'object') && 'displayName' in child.type && - (child.type as any).displayName === 'UnderlinePanels.Panel' + child.type.displayName === 'UnderlinePanels.Panel' ) { const childPanel = child as React.ReactElement return cloneElement(childPanel, {'aria-labelledby': `${parentId}-tab-${panelIndex++}`}) @@ -132,7 +132,7 @@ const UnderlinePanels: FC = ({ isValidElement(child) && (typeof child.type === 'function' || typeof child.type === 'object') && 'displayName' in child.type && - (child.type as any).displayName === 'UnderlinePanels.Panel' + child.type.displayName === 'UnderlinePanels.Panel' ) }) From 0578bcbe3006ae5b072345a6ee9edc84e832d08f Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Mon, 29 Sep 2025 20:39:25 -0400 Subject: [PATCH 15/15] remove ts-ignore --- packages/styled-react/src/components/TabNav.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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,