Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a258f93
Remove sx prop in UnderlinePanels
pksjce Sep 9, 2025
96e6bd7
Change '@primer/react' version and remove sx prop
pksjce Sep 9, 2025
976f44c
Fix up panels
pksjce Sep 10, 2025
5e5e44f
Merge branch 'main' into pk/underline-panels
pksjce Sep 10, 2025
cd524ef
Release tracking (rc) (#6707)
primer[bot] Sep 11, 2025
7318c1b
Remove `sx` from the `SegmentedControl` component (#6741)
liuliu-dev Sep 11, 2025
192cda2
chore: use Banner instead of custom implementation for SelectPanel no…
francinelucca Sep 11, 2025
8f01621
chore(deps-dev): bump @modelcontextprotocol/inspector from 0.14.1 to …
dependabot[bot] Sep 11, 2025
73af8f1
Breadcrumbs : Add overflow menu for responsive behavior (#6664)
pksjce Sep 11, 2025
e32d52a
Remove overflow property from popover (#6709)
pksjce Sep 11, 2025
4aa22c3
Remove styled-system usage - TextInputWrapper and related (#6666)
mperrotti Sep 12, 2025
b2ca11d
Remove unused classes from ProgressBar CSS Module (#6814)
mperrotti Sep 12, 2025
826c522
test: update vitest config to include browser tests (#6818)
joshblack Sep 12, 2025
ee6827b
feat: remove sx prop from Announce, AriaAlert, AriaStatus (#6806)
joshblack Sep 12, 2025
64cf4a8
Popover: Remove `sx` from component (#6754)
TylerJDev Sep 12, 2025
ac7dfe6
chore: add portal context (#6815)
francinelucca Sep 12, 2025
51e6b1a
styled-react: Fix browser tests not running (#6822)
siddharthkp Sep 15, 2025
2839045
Add a MCP tool that helps review alt text in context of surrounding t…
kendallgassner Sep 15, 2025
16106f6
Add `count` to SegmentedControlButton (#6721)
cheshire137 Sep 15, 2025
040dc2e
chore(deps-dev): bump vite from 7.1.3 to 7.1.5 (#6819)
dependabot[bot] Sep 15, 2025
00c4b76
chore(deps-dev): bump @vitest/eslint-plugin from 1.3.5 to 1.3.9 in th…
dependabot[bot] Sep 15, 2025
d5420cb
chore(deps): bump @primer/behaviors from 1.8.0 to 1.8.2 (#6853)
dependabot[bot] Sep 15, 2025
e3e6c7a
chore(deps-dev): bump the eslint group with 2 updates (#6850)
dependabot[bot] Sep 15, 2025
5cc3fea
Allow changing initially focused button in `ConfirmationDialog` (#6843)
camchenry Sep 15, 2025
956c118
chore(deps): bump actions/create-github-app-token from 2.1.1 to 2.1.4…
dependabot[bot] Sep 15, 2025
554e4d2
Revert `TextInputWithWrapper` changes to remove sx and styled-system …
mperrotti Sep 15, 2025
8923017
feat: only publish esm bundles from @primer/react (#6425)
joshblack Sep 15, 2025
d9f909f
not a good state
pksjce Sep 17, 2025
e08ccec
Fix the underlineitem types
pksjce Sep 18, 2025
90d4803
Merge branch 'main' into pk/underline-panels
pksjce Sep 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cool-tips-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": major
---

Remove sx prop in UnderlinePanels
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,13 @@ 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'
import {useResizeObserver, type ResizeObserverEntry} from '../../hooks/useResizeObserver'
import useIsomorphicLayoutEffect from '../../utils/useIsomorphicLayoutEffect'
import classes from './UnderlinePanels.module.css'
import {clsx} from 'clsx'
import {BoxWithFallback} from '../../internal/components/BoxWithFallback'

export type UnderlinePanelsProps = {
/**
Expand All @@ -52,7 +44,7 @@ export type UnderlinePanelsProps = {
* Class name for custom styling
*/
className?: string
} & SxProp
}

export type TabProps = PropsWithChildren<{
/**
Expand All @@ -71,10 +63,9 @@ export type TabProps = PropsWithChildren<{
* Icon rendered before the tab text label
*/
icon?: FC<IconProps>
}> &
SxProp
}>

export type PanelProps = Omit<BoxProps, 'as'>
export type PanelProps = React.HTMLAttributes<HTMLDivElement>

const TabContainerComponent = createComponent(TabContainerElement, 'tab-container')

Expand Down Expand Up @@ -104,12 +95,14 @@ const UnderlinePanels: FC<UnderlinePanelsProps> = ({
let panelIndex = 0

const childrenWithProps = Children.map(children, child => {
if (isValidElement<UnderlineItemProps>(child) && child.type === Tab) {
if (isValidElement(child) && child.type === Tab) {
return cloneElement(child, {id: `${parentId}-tab-${tabIndex++}`, loadingCounters, iconsVisible})
}

if (isValidElement<PanelProps>(child) && child.type === Panel) {
return cloneElement(child, {'aria-labelledby': `${parentId}-tab-${panelIndex++}`})
return cloneElement(child as React.ReactElement, {
'aria-labelledby': `${parentId}-tab-${panelIndex++}`,
})
}
return child
})
Expand Down Expand Up @@ -221,8 +214,12 @@ const Tab: FC<TabProps> = ({'aria-selected': ariaSelected, onSelect, ...props})

Tab.displayName = 'UnderlinePanels.Tab'

const Panel: FC<PanelProps> = props => {
return <BoxWithFallback as="div" role="tabpanel" {...props} />
const Panel: FC<PanelProps> = ({children, ...rest}) => {
return (
<div role="tabpanel" {...rest}>
{children}
</div>
)
}

Panel.displayName = 'UnderlinePanels.Panel'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
// Used for UnderlineNav and UnderlinePanels components

import type React from 'react'
import {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'
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
Expand All @@ -19,15 +17,15 @@ type UnderlineWrapperProps = {
slot?: string
as?: React.ElementType
className?: string
ref?: React.Ref<unknown>
} & SxProp
ref?: React.Ref<HTMLDivElement>
}

export const UnderlineWrapper = forwardRef(
({children, className, ...rest}: PropsWithChildren<UnderlineWrapperProps>, forwardedRef) => {
export const UnderlineWrapper = forwardRef<HTMLDivElement, PropsWithChildren<UnderlineWrapperProps>>(
({children, className, ...rest}, forwardedRef) => {
return (
<BoxWithFallback className={clsx(classes.UnderlineWrapper, className)} ref={forwardedRef} {...rest}>
<div className={clsx(classes.UnderlineWrapper, className)} ref={forwardedRef} {...rest}>
{children}
</BoxWithFallback>
</div>
)
},
)
Expand All @@ -44,51 +42,38 @@ export const LoadingCounter = () => {
return <span className={classes.LoadingCounter} />
}

export type UnderlineItemProps = {
as?: React.ElementType | 'a' | 'button'
export type UnderlineItemProps<As extends React.ElementType> = {
as?: As | 'a' | 'button'
className?: string
iconsVisible?: boolean
loadingCounters?: boolean
counter?: number | string
icon?: FC<IconProps> | React.ReactElement
id?: string
ref?: React.Ref<unknown>
} & SxProp
} & React.ComponentPropsWithoutRef<As extends 'a' ? 'a' : As extends 'button' ? 'button' : As>

export const UnderlineItem = forwardRef(
(
{
as = 'a',
children,
counter,
icon: Icon,
iconsVisible,
loadingCounters,
className,
...rest
}: PropsWithChildren<UnderlineItemProps>,
forwardedRef,
) => {
return (
<BoxWithFallback ref={forwardedRef} as={as} className={clsx(classes.UnderlineItem, className)} {...rest}>
{iconsVisible && Icon && <span data-component="icon">{isElement(Icon) ? Icon : <Icon />}</span>}
{children && (
<span data-component="text" data-content={children}>
{children}
export const UnderlineItem = React.forwardRef((props, ref) => {
const {as: Component = 'a', children, counter, icon: Icon, iconsVisible, loadingCounters, className, ...rest} = props
return (
<Component {...rest} ref={ref} className={clsx(classes.UnderlineItem, className)}>
{iconsVisible && Icon && <span data-component="icon">{isElement(Icon) ? Icon : <Icon />}</span>}
{children && (
<span data-component="text" data-content={children}>
{children}
</span>
)}
{counter !== undefined ? (
loadingCounters ? (
<span data-component="counter">
<LoadingCounter />
</span>
)}
{counter !== undefined ? (
loadingCounters ? (
<span data-component="counter">
<LoadingCounter />
</span>
) : (
<span data-component="counter">
<CounterLabel>{counter}</CounterLabel>
</span>
)
) : null}
</BoxWithFallback>
)
},
) as PolymorphicForwardRefComponent<'a', UnderlineItemProps>
) : (
<span data-component="counter">
<CounterLabel>{counter}</CounterLabel>
</span>
)
) : null}
</Component>
)
}) as PolymorphicForwardRefComponent<ElementType, UnderlineItemProps<ElementType>>
Loading