Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
56ff803
remove sx, Box from UnderlineNav
liuliu-dev Aug 25, 2025
7a931cf
changeset
liuliu-dev Aug 25, 2025
6b390bc
fix lint and format
liuliu-dev Aug 25, 2025
07f4df0
use 4px instead of 1 for inline style
liuliu-dev Aug 25, 2025
f9ef25d
Merge branch 'main' into liuliu/migrate-underlinenav
liuliu-dev Aug 26, 2025
9f5f349
Merge branch 'main' into liuliu/migrate-underlinenav
liuliu-dev Aug 26, 2025
484eff5
remove sx support from CounterLabel
llastflowers Aug 27, 2025
e08db63
remove sx from docs
llastflowers Aug 27, 2025
226ef2c
Update CounterLabel to remove sx support
llastflowers Aug 27, 2025
b8b577b
Merge remote-tracking branch 'origin/main' into liuliu/migrate-underl…
liuliu-dev Sep 11, 2025
1fd4809
Merge branch 'main' into llastflowers/5783/no-sx-CounterLabel
llastflowers Sep 12, 2025
9fbafc8
Merge remote-tracking branch 'origin/main' into liuliu/migrate-underl…
liuliu-dev Sep 16, 2025
ac6cd91
export underlinenav in styled-react
liuliu-dev Sep 16, 2025
88e9f0e
fix lint issues
liuliu-dev Sep 16, 2025
b089415
Merge branch 'main' into llastflowers/5783/no-sx-CounterLabel
llastflowers Sep 17, 2025
9b48904
use new pattern for UnderlineNavItem
liuliu-dev Sep 17, 2025
cdf8f05
would adding onSelect explicitly work?
liuliu-dev Sep 17, 2025
eb72548
lint fix
liuliu-dev Sep 17, 2025
879f8ca
update tests for counterlabel sx removal
llastflowers Sep 17, 2025
0845ea0
ElementType | 'a'?
liuliu-dev Sep 17, 2025
38dc682
HTMLButtonElement
liuliu-dev Sep 17, 2025
cd43b92
use as?
liuliu-dev Sep 17, 2025
18e65dd
more generic types
liuliu-dev Sep 17, 2025
8b703d6
as ForwardRefComponent
liuliu-dev Sep 17, 2025
048298e
revert
liuliu-dev Sep 17, 2025
26c0b29
React.ElementType | 'a'
liuliu-dev Sep 17, 2025
dc4ea6f
fix types
liuliu-dev Sep 18, 2025
1f214a7
clean up
liuliu-dev Sep 18, 2025
2ba0527
add id in UnderlineNavItemProps instead
liuliu-dev Sep 18, 2025
a3edc81
build polymorphic.d.ts into dist?
liuliu-dev Sep 18, 2025
6a8e752
fix lint
liuliu-dev Sep 18, 2025
3435a0d
remove comments
liuliu-dev Sep 18, 2025
dd5896d
polymorphic.ts
liuliu-dev Sep 18, 2025
2d88dfc
lint ignore
liuliu-dev Sep 18, 2025
d8dafd7
ignore polymorphic.ts in config, remove unused NavigationList
liuliu-dev Sep 18, 2025
23ffbd5
Merge branch 'main' into liuliu/migrate-underlinenav
primer[bot] Sep 22, 2025
ac7804d
conflicts
liuliu-dev Sep 22, 2025
1da2ad8
Merge branch 'liuliu/migrate-underlinenav' of https://github.com/prim…
liuliu-dev Sep 22, 2025
e8a8ea2
Merge branch 'main' into llastflowers/5783/no-sx-CounterLabel
llastflowers Sep 22, 2025
60ade2a
Merge remote-tracking branch 'origin/main' into liuliu/migrate-underl…
liuliu-dev Sep 22, 2025
984fbd5
Merge branch 'main' into llastflowers/5783/no-sx-CounterLabel
llastflowers Sep 22, 2025
c7f8fe8
conflicts
liuliu-dev Sep 22, 2025
f45fd91
conflicts
liuliu-dev Sep 22, 2025
d59c187
conflicts..
liuliu-dev Sep 22, 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/hot-mirrors-feel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': major
---

Update UnderlineNav component to no longer support sx and remove Box usage from it.
12 changes: 1 addition & 11 deletions packages/react/src/UnderlineNav/UnderlineNav.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@
"type": "'inset' | 'flush'",
"defaultValue": "'inset'",
"description": "`inset` children are offset horizontally from container edges. `flush` children are flush horizontally with container edges"
},
{
"name": "sx",
"type": "SystemStyleObject",
"deprecated": true
}
],
"subcomponents": [
Expand Down Expand Up @@ -100,11 +95,6 @@
"name": "as",
"type": "React.ElementType",
"defaultValue": "\"a\""
},
{
"name": "sx",
"type": "SystemStyleObject",
"deprecated": true
}
],
"passthrough": {
Expand All @@ -113,4 +103,4 @@
}
}
]
}
}
5 changes: 5 additions & 0 deletions packages/react/src/UnderlineNav/UnderlineNav.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.MenuItemContent {
display: flex;
align-items: center;
justify-content: space-between;
}
35 changes: 9 additions & 26 deletions packages/react/src/UnderlineNav/UnderlineNav.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import type {MutableRefObject, RefObject} from 'react'
import React, {useRef, forwardRef, useCallback, useState, useEffect} from 'react'
import Box from '../Box'
import type {SxProp} from '../sx'
import sx from '../sx'
import {UnderlineNavContext} from './UnderlineNavContext'
import type {ResizeObserverEntry} from '../hooks/useResizeObserver'
import {useResizeObserver} from '../hooks/useResizeObserver'
Expand All @@ -18,16 +15,15 @@ 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'
import classes from './UnderlineNav.module.css'

export type UnderlineNavProps = {
children: React.ReactNode
'aria-label'?: React.AriaAttributes['aria-label']
as?: React.ElementType
className?: string
sx?: SxProp['sx']
/**
* loading state for all counters. It displays loading animation for individual counters (UnderlineNav.Item) until all are resolved. It is needed to prevent multiple layout shift.
*/
Expand All @@ -45,11 +41,6 @@ export const MORE_BTN_WIDTH = 86
// The height is needed to make sure we don't have a layout shift when the more button is the only item in the nav.
const MORE_BTN_HEIGHT = 45

// Needed this because passing a ref using HTMLULListElement to `Box` causes a type error
export const NavigationList = styled.ul`
${sx};
`

export const MoreMenuListItem = styled.li`
display: flex;
align-items: center;
Expand Down Expand Up @@ -145,7 +136,6 @@ export const UnderlineNav = forwardRef(
{
as = 'nav',
'aria-label': ariaLabel,
sx: sxProp = defaultSxProp,
loadingCounters = false,
variant = 'inset',
className,
Expand Down Expand Up @@ -316,19 +306,12 @@ export const UnderlineNav = forwardRef(
}}
>
{ariaLabel && <VisuallyHidden as="h2">{`${ariaLabel} navigation`}</VisuallyHidden>}
<UnderlineWrapper
as={as}
aria-label={ariaLabel}
className={className}
ref={navRef}
sx={sxProp}
data-variant={variant}
>
<UnderlineWrapper as={as} aria-label={ariaLabel} className={className} ref={navRef} data-variant={variant}>
<UnderlineItemList ref={listRef} role="list">
{listItems}
{menuItems.length > 0 && (
<MoreMenuListItem ref={moreMenuRef}>
{!onlyMenuVisible && <Box sx={getDividerStyle(theme)}></Box>}
{!onlyMenuVisible && <div style={getDividerStyle(theme)}></div>}
<Button
ref={moreMenuBtnRef}
sx={moreBtnStyles}
Expand All @@ -337,7 +320,7 @@ export const UnderlineNav = forwardRef(
onClick={onAnchorClick}
trailingAction={TriangleDownIcon}
>
<Box as="span">
<span>
{onlyMenuVisible ? (
<>
<VisuallyHidden as="span">{`${ariaLabel}`}&nbsp;</VisuallyHidden>Menu
Expand All @@ -347,7 +330,7 @@ export const UnderlineNav = forwardRef(
More<VisuallyHidden as="span">&nbsp;{`${ariaLabel} items`}</VisuallyHidden>
</>
)}
</Box>
</span>
</Button>
<ActionList
selectionVariant="single"
Expand Down Expand Up @@ -398,18 +381,18 @@ export const UnderlineNav = forwardRef(
}}
{...menuItemProps}
>
<Box as="span" sx={{display: 'flex', alignItems: 'center', justifyContent: 'space-between'}}>
<span className={classes.MenuItemContent}>
{menuItemChildren}
{loadingCounters ? (
<LoadingCounter />
) : (
counter !== undefined && (
<Box as="span" data-component="counter">
<span data-component="counter">
<CounterLabel>{counter}</CounterLabel>
</Box>
</span>
)
)}
</Box>
</span>
</ActionList.LinkItem>
)
})}
Expand Down
5 changes: 5 additions & 0 deletions packages/react/src/UnderlineNav/UnderlineNavItem.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.UnderlineNavItem {
display: flex;
flex-direction: column;
align-items: center;
}
24 changes: 5 additions & 19 deletions packages/react/src/UnderlineNav/UnderlineNavItem.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import type {MutableRefObject, RefObject} from 'react'
import React, {forwardRef, useRef, useContext} from 'react'
import Box from '../Box'
import type {SxProp} from '../sx'
import type {IconProps} from '@primer/octicons-react'
import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic'
import {UnderlineNavContext} from './UnderlineNavContext'
import useLayoutEffect from '../utils/useIsomorphicLayoutEffect'
import {defaultSxProp} from '../utils/defaultSxProp'
import {UnderlineItem} from '../internal/components/UnderlineTabbedInterface'
import classes from './UnderlineNavItem.module.css'

// adopted from React.AnchorHTMLAttributes
export type LinkProps = {
Expand Down Expand Up @@ -47,22 +45,11 @@ export type UnderlineNavItemProps = {
* Counter
*/
counter?: number | string
} & SxProp &
LinkProps
} & LinkProps

export const UnderlineNavItem = forwardRef(
(
{
sx: sxProp = defaultSxProp,
as: Component = 'a',
href = '#',
children,
counter,
onSelect,
'aria-current': ariaCurrent,
icon: Icon,
...props
},
{as: Component = 'a', href = '#', children, counter, onSelect, 'aria-current': ariaCurrent, icon: Icon, ...props},
forwardedRef,
) => {
const backupRef = useRef<HTMLElement>(null)
Expand Down Expand Up @@ -111,7 +98,7 @@ export const UnderlineNavItem = forwardRef(
)

return (
<Box as="li" sx={{display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
<li className={classes.UnderlineNavItem}>
<UnderlineItem
ref={ref}
as={Component}
Expand All @@ -123,12 +110,11 @@ export const UnderlineNavItem = forwardRef(
icon={Icon}
loadingCounters={loadingCounters}
iconsVisible={iconsVisible}
sx={sxProp}
{...props}
>
{children}
</UnderlineItem>
</Box>
</li>
)
},
) as PolymorphicForwardRefComponent<'a', UnderlineNavItemProps>
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/UnderlineNav/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const getDividerStyle = (theme?: Theme) => ({
borderLeft: '1px solid',
width: '1px',
borderLeftColor: `${theme?.colors.border.muted}`,
marginRight: 1,
marginRight: '4px',
height: '24px', // The height of the divider - reference from Figma
})

Expand Down
41 changes: 38 additions & 3 deletions packages/styled-react/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ import {
SegmentedControl as PrimerSegmentedControl,
type SegmentedControlButtonProps as PrimerSegmentedControlButtonProps,
type SegmentedControlIconButtonProps as PrimerSegmentedControlIconButtonProps,
UnderlineNav as PrimerUnderlineNav,
type UnderlineNavProps as PrimerUnderlineNavProps,
type UnderlineNavItemProps as PrimerUnderlineNavItemProps,
sx,
} from '@primer/react'
import React, {forwardRef, type PropsWithChildren} from 'react'
import React, {type PropsWithChildren, forwardRef} from 'react'
import type {
BackgroundProps,
BorderProps,
Expand All @@ -32,6 +36,8 @@ import type {
SpaceProps,
TypographyProps,
} from 'styled-system'
import styled from 'styled-components'
import type {ForwardRefComponent} from './polymorphic'
import {LinkButton, type LinkButtonProps} from './components/LinkButton'

type StyledProps = SxProp &
Expand Down Expand Up @@ -107,7 +113,37 @@ const ToggleSwitch = forwardRef<HTMLButtonElement, ToggleSwitchProps>(function T
return <Box as={PrimerToggleSwitch} ref={ref} {...props} />
})

export {LinkButton, type LinkButtonProps, Checkbox, CounterLabel, SegmentedControl, StateLabel, SubNav, ToggleSwitch}
type UnderlineNavProps = PrimerUnderlineNavProps & SxProp

const UnderlineNavImpl = forwardRef<HTMLElement, UnderlineNavProps>(function UnderlineNav(props, ref) {
return <Box as={PrimerUnderlineNav} ref={ref} {...props} />
})

type UnderlineNavItemProps = PrimerUnderlineNavItemProps & SxProp

const UnderlineNavItem: ForwardRefComponent<'a', UnderlineNavItemProps> = styled(
PrimerUnderlineNav.Item,
).withConfig<UnderlineNavItemProps>({
shouldForwardProp: prop => prop !== 'sx',
})`
${sx}
`

const UnderlineNav = Object.assign(UnderlineNavImpl, {
Item: UnderlineNavItem,
})

export {
LinkButton,
type LinkButtonProps,
Checkbox,
CounterLabel,
SegmentedControl,
StateLabel,
SubNav,
ToggleSwitch,
UnderlineNav,
}

export {
ActionList,
Expand Down Expand Up @@ -145,7 +181,6 @@ export {
type TokenProps,
Tooltip,
Truncate,
UnderlineNav,

// styled-components components or types
Box,
Expand Down
Loading