Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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/quick-ants-lead.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": minor
---

Add data-component attributes and associated tests for ActionMenu, AnchoredOverlay, Autocomplete, and NavList
13 changes: 13 additions & 0 deletions packages/react/src/ActionMenu/ActionMenu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,19 @@ function ExampleWithSubmenus(): JSX.Element {
describe('ActionMenu', () => {
implementsClassName(ActionMenu.Button)

it('renders data-component attributes for ActionMenu parts', async () => {
const component = HTMLRender(<Example />)
const user = userEvent.setup()

const trigger = component.getByRole('button', {name: 'Toggle Menu'})
expect(trigger).toHaveAttribute('data-component', 'ActionMenu.Button')

await user.click(trigger)

expect(component.baseElement.querySelector('[data-component="AnchoredOverlay"]')).not.toBeNull()
expect(component.baseElement.querySelector('[data-component="ActionMenu.Overlay"]')).not.toBeNull()
})

it('should open Menu on MenuButton click', async () => {
const component = HTMLRender(<Example />)
const button = component.getByRole('button')
Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/ActionMenu/ActionMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export type ActionMenuButtonProps = ButtonProps
const MenuButton = React.forwardRef(({...props}, anchorRef) => {
return (
<Anchor ref={anchorRef}>
<Button type="button" trailingAction={TriangleDownIcon} {...props} />
<Button data-component="ActionMenu.Button" type="button" trailingAction={TriangleDownIcon} {...props} />
</Anchor>
)
}) as PolymorphicForwardRefComponent<'button', ActionMenuButtonProps>
Expand Down Expand Up @@ -364,6 +364,7 @@ const Overlay: FCWithSlotMarker<React.PropsWithChildren<MenuOverlayProps>> = ({
<div
ref={containerRef}
className={styles.ActionMenuContainer}
data-component="ActionMenu.Overlay"
data-variant={responsiveVariant}
{...(overlayProps.overflow ? {[`data-overflow-${overlayProps.overflow}`]: ''} : {})}
{...(overlayProps.maxHeight ? {[`data-max-height-${overlayProps.maxHeight}`]: ''} : {})}
Expand Down
20 changes: 20 additions & 0 deletions packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,26 @@ describe.each([true, false])(
})
})

it('renders data-component attribute on the responsive close button container when shown', () => {
const {baseElement} = render(
<FeatureFlags flags={{primer_react_css_anchor_positioning: true}}>
<BaseStyles>
<AnchoredOverlay
open={true}
onOpen={() => {}}
onClose={() => {}}
renderAnchor={props => <Button {...props}>Anchor Button</Button>}
variant={{regular: 'anchored', narrow: 'fullscreen'}}
>
<div>content</div>
</AnchoredOverlay>
</BaseStyles>
</FeatureFlags>,
)

expect(baseElement.querySelector('[data-component="AnchoredOverlay.CloseButtonContainer"]')).toBeInTheDocument()
})

it('should support a `ref` through `overlayProps` on the overlay element', () => {
const ref = createRef<HTMLDivElement>()

Expand Down
5 changes: 4 additions & 1 deletion packages/react/src/AnchoredOverlay/AnchoredOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,10 @@ export const AnchoredOverlay: React.FC<React.PropsWithChildren<AnchoredOverlayPr
data-side={cssAnchorPositioning ? side : position?.anchorSide}
>
{showXIcon ? (
<div className={classes.ResponsiveCloseButtonContainer}>
<div
className={classes.ResponsiveCloseButtonContainer}
data-component="AnchoredOverlay.CloseButtonContainer"
>
<IconButton
{...(closeButtonProps as IconButtonProps)}
type="button"
Expand Down
14 changes: 14 additions & 0 deletions packages/react/src/Autocomplete/Autocomplete.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ describe('Autocomplete', () => {
<Autocomplete.Input {...props} />
</Autocomplete>
))

it('tags overlay with data-component when menu is shown', async () => {
const user = userEvent.setup()
const {container} = render(
<LabelledAutocomplete
menuProps={{items: mockItems, selectedItemIds: [], ['aria-labelledby']: 'autocompleteLabel'}}
/>,
)
const inputNode = container.querySelector('#autocompleteInput')!
await user.type(inputNode, 'z')

expect(container.querySelector('[data-component="Autocomplete.Overlay"]')).toBeInTheDocument()
})

it('calls onChange', async () => {
const user = userEvent.setup()
const onChangeMock = vi.fn()
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/Autocomplete/AutocompleteInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const AutocompleteInput = React.forwardRef(
autoComplete="off"
id={id}
{...props}
data-component="Autocomplete.Input"
/>
)
},
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/Autocomplete/AutocompleteOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function AutocompleteOverlay({
left={position?.left}
className={clsx(classes.Overlay, className)}
{...overlayProps}
data-component="Autocomplete.Overlay"
>
{children}
</Overlay>
Expand Down
21 changes: 21 additions & 0 deletions packages/react/src/NavList/NavList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,27 @@ const NextJSLikeLink = React.forwardRef<HTMLAnchorElement, NextJSLinkProps>(
describe('NavList', () => {
implementsClassName(NavList)

it('renders data-component attributes for NavList and NavList.SubNav', () => {
const {container} = render(
<NavList>
<NavList.Item href="#">Item 1</NavList.Item>
<NavList.Item>
Item 2
<NavList.SubNav>
<NavList.Item href="#">Sub Item 1</NavList.Item>
</NavList.SubNav>
</NavList.Item>
</NavList>,
)

const nav = container.querySelector('nav')
expect(nav).toBeInTheDocument()
expect(nav).toHaveAttribute('data-component', 'NavList')

const subNav = container.querySelector('[data-component="NavList.SubNav"]')
expect(subNav).toBeInTheDocument()
Comment thread
llastflowers marked this conversation as resolved.
})

it('supports TrailingAction', async () => {
const {getByRole} = render(
<NavList>
Expand Down
10 changes: 8 additions & 2 deletions packages/react/src/NavList/NavList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export type NavListProps = {

const Root = React.forwardRef<HTMLElement, NavListProps>(({children, ...props}, ref) => {
return (
<nav {...props} ref={ref}>
<nav {...props} ref={ref} data-component="NavList">
<ActionListContainerContext.Provider
value={{
container: 'NavList',
Expand Down Expand Up @@ -232,7 +232,13 @@ const SubNav = React.forwardRef<HTMLUListElement, NavListSubNavProps>(({children

return (
<SubNavContext.Provider value={{depth: depth + 1}}>
<ul className={classes.SubGroup} id={subNavId} aria-labelledby={buttonId} ref={forwardedRef}>
<ul
className={classes.SubGroup}
id={subNavId}
aria-labelledby={buttonId}
ref={forwardedRef}
data-component="NavList.SubNav"
>
{children}
</ul>
</SubNavContext.Provider>
Expand Down
Loading