Skip to content

Commit 78dc813

Browse files
Enforce correct semantics for TabNav (#2125)
* Swaps nav and div and adds semantically correct roles * Fix tests, add body div and move sx * Adds changeset * Fixing TabNavProps export Co-authored-by: Siddharth Kshetrapal <[email protected]>
1 parent 53713b2 commit 78dc813

File tree

3 files changed

+30
-13
lines changed

3 files changed

+30
-13
lines changed

.changeset/poor-wombats-lick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@primer/react': patch
3+
---
4+
5+
Adds roles of tablist and tab to the TabNav component, required rearranging the HTML elements to be semantically correct

src/TabNav.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,28 @@ const ITEM_CLASS = 'TabNav-item'
1111
const SELECTED_CLASS = 'selected'
1212

1313
const TabNavBase = styled.div<SxProp>`
14-
margin-top: 0;
15-
border-bottom: 1px solid ${get('colors.border.default')};
1614
${sx}
1715
`
1816

19-
const TabNavBody = styled.nav`
17+
const TabNavTabList = styled.div`
2018
display: flex;
2119
margin-bottom: -1px;
2220
overflow: auto;
2321
`
2422

23+
const TabNavNav = styled.nav`
24+
margin-top: 0;
25+
border-bottom: 1px solid ${get('colors.border.default')};
26+
`
27+
2528
export type TabNavProps = ComponentProps<typeof TabNavBase>
2629

2730
function TabNav({children, 'aria-label': ariaLabel, ...rest}: TabNavProps) {
2831
return (
2932
<TabNavBase {...rest}>
30-
<TabNavBody aria-label={ariaLabel}>{children}</TabNavBody>
33+
<TabNavNav aria-label={ariaLabel}>
34+
<TabNavTabList role="tablist">{children}</TabNavTabList>
35+
</TabNavNav>
3136
</TabNavBase>
3237
)
3338
}
@@ -39,7 +44,8 @@ type StyledTabNavLinkProps = {
3944

4045
const TabNavLink = styled.a.attrs<StyledTabNavLinkProps>(props => ({
4146
activeClassName: typeof props.to === 'string' ? 'selected' : '',
42-
className: classnames(ITEM_CLASS, props.selected && SELECTED_CLASS, props.className)
47+
className: classnames(ITEM_CLASS, props.selected && SELECTED_CLASS, props.className),
48+
role: 'tab'
4349
}))<StyledTabNavLinkProps>`
4450
padding: 8px 12px;
4551
font-size: ${get('fontSizes.1')};

src/__tests__/__snapshots__/TabNav.test.tsx.snap

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,11 @@ exports[`TabNav TabNav.Link renders consistently 1`] = `
4646
4747
<a
4848
className="c0 TabNav-item"
49+
role="tab"
4950
/>
5051
`;
5152

5253
exports[`TabNav renders consistently 1`] = `
53-
.c0 {
54-
margin-top: 0;
55-
border-bottom: 1px solid #d0d7de;
56-
}
57-
5854
.c1 {
5955
display: -webkit-box;
6056
display: -webkit-flex;
@@ -64,11 +60,21 @@ exports[`TabNav renders consistently 1`] = `
6460
overflow: auto;
6561
}
6662
63+
.c0 {
64+
margin-top: 0;
65+
border-bottom: 1px solid #d0d7de;
66+
}
67+
6768
<div
68-
className="c0"
69+
className=""
6970
>
7071
<nav
71-
className="c1"
72-
/>
72+
className="c0"
73+
>
74+
<div
75+
className="c1"
76+
role="tablist"
77+
/>
78+
</nav>
7379
</div>
7480
`;

0 commit comments

Comments
 (0)