1
1
import type { To } from 'history'
2
- import styled , { css } from 'styled-components'
3
-
4
- import Box from './Box'
5
2
import type { ComponentProps } from './utils/types'
6
3
import Link , { type LinkProps } from './Link'
7
4
import React , { type PropsWithChildren } from 'react'
8
5
import { clsx } from 'clsx'
9
6
import type { SxProp } from './sx'
10
- import sx from './sx'
11
- import { toggleStyledComponent } from './internal/utils/toggleStyledComponent'
12
7
import classes from './SideNav.module.css'
13
- import { useFeatureFlag } from './FeatureFlags'
14
-
15
- const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_ga'
8
+ import { toggleSxComponent } from './internal/utils/toggleSxComponent'
9
+ import { defaultSxProp } from './utils/defaultSxProp'
16
10
17
11
type SideNavBaseProps = {
18
12
as ?: React . ElementType
@@ -23,63 +17,33 @@ type SideNavBaseProps = {
23
17
'aria-label' ?: string
24
18
} & SxProp
25
19
26
- const StyledNav = toggleStyledComponent (
27
- CSS_MODULES_FEATURE_FLAG ,
28
- 'nav' ,
29
- styled ( Box ) < SideNavBaseProps > `
30
- background-color: var(--bgColor-muted);
31
-
32
- ${ props =>
33
- props . bordered &&
34
- css `
35
- border-color : var (--borderColor-default );
36
- border-style : solid;
37
- border-width : var (--borderWidth-thin );
38
- border-radius : var (--borderRadius-medium );
39
-
40
- // Remove duplicate borders from nested SideNavs
41
- & > & {
42
- border-left : 0 ;
43
- border-right : 0 ;
44
- border-bottom : 0 ;
45
- }
46
- ` }
47
-
48
- ${ sx } ;
49
- ` ,
50
- )
51
-
52
20
function SideNav ( {
53
21
as = 'nav' ,
54
22
variant = 'normal' ,
55
23
className,
56
24
bordered,
57
25
children,
58
26
'aria-label' : ariaLabel ,
59
- sx : sxProp ,
27
+ sx : sxProp = defaultSxProp ,
60
28
} : SideNavBaseProps ) {
61
- const enabled = useFeatureFlag ( CSS_MODULES_FEATURE_FLAG )
62
29
const variantClassName = variant === 'lightweight' ? 'lightweight' : 'normal'
63
30
const newClassName = clsx (
31
+ classes . SideNav ,
32
+ classes [ `SideNavVariant--${ variantClassName } ` ] ,
33
+ 'sidenav' ,
34
+ `variant-${ variantClassName } ` ,
35
+ className ,
64
36
{
65
- [ classes . SideNav ] : enabled ,
66
- [ classes . SideNavBordered ] : enabled && bordered ,
67
- [ classes [ `SideNavVariant--${ variantClassName } ` ] ] : enabled ,
68
- sidenav : ! enabled ,
69
- [ `variant-${ variantClassName } ` ] : ! enabled ,
37
+ [ classes . SideNavBordered ] : bordered ,
70
38
} ,
71
- className ,
72
39
)
40
+
41
+ const BaseComponent = toggleSxComponent ( as ) as React . ComponentType < SideNavBaseProps >
42
+
73
43
return (
74
- < StyledNav
75
- as = { as }
76
- bordered = { enabled ? undefined : bordered }
77
- className = { newClassName }
78
- aria-label = { ariaLabel }
79
- sx = { sxProp }
80
- >
44
+ < BaseComponent className = { newClassName } aria-label = { ariaLabel } sx = { sxProp } >
81
45
{ children }
82
- </ StyledNav >
46
+ </ BaseComponent >
83
47
)
84
48
}
85
49
@@ -90,134 +54,21 @@ type StyledSideNavLinkProps = PropsWithChildren<{
90
54
} > &
91
55
LinkProps
92
56
93
- // used for variant normal hover, focus pseudo selectors
94
- const CommonAccessibilityVariantNormalStyles = css `
95
- background-color : var (--bgColor-neutral-muted );
96
- text-decoration : none;
97
- `
98
-
99
- // used for light weight hover, focus pseudo selectors
100
- const CommonAccessibilityVariantLightWeightStyles = css `
101
- color : var (--fgColor-default );
102
- text-decoration : none;
103
- `
104
-
105
- const StyledSideNavLink = toggleStyledComponent (
106
- CSS_MODULES_FEATURE_FLAG ,
107
- Link ,
108
- styled ( Link ) < StyledSideNavLinkProps & SxProp > `
109
- position: relative;
110
- display: block;
111
- width: 100%;
112
- font-size: 14px;
113
- text-align: left;
114
- text-decoration: none;
115
- ${ props =>
116
- props . variant === 'full' &&
117
- css `
118
- display : flex;
119
- align-items : center;
120
- justify-content : space-between;
121
- ` }
122
-
123
- & > .sidenav {
124
- border-bottom: none;
125
- }
126
-
127
- .sidenav.variant-normal > & {
128
- color: var(--fgColor-default);
129
- padding: var(--base-size-16);
130
- border: 0;
131
- border-top: var(--borderWidth-thin) solid var(--borderColor-muted);
132
-
133
- &:first-child {
134
- border-top: 0;
135
- border-top-right-radius: var(--borderRadius-medium);
136
- border-top-left-radius: var(--borderRadius-medium);
137
- }
138
-
139
- &:last-child {
140
- border-bottom-right-radius: var(--borderRadius-medium);
141
- border-bottom-left-radius: var(--borderRadius-medium);
142
- }
143
-
144
- // Bar on the left
145
- &::before {
146
- position: absolute;
147
- top: 0;
148
- bottom: 0;
149
- left: 0;
150
- z-index: 1;
151
- width: 3px;
152
- pointer-events: none;
153
- content: '';
154
- }
155
-
156
- &:hover {
157
- ${ CommonAccessibilityVariantNormalStyles }
158
- }
159
-
160
- &:focus {
161
- ${ CommonAccessibilityVariantNormalStyles }
162
- outline: solid 2px var(--fgColor-accent);
163
- z-index: 1;
164
- }
165
-
166
- &[aria-current='page'],
167
- &[aria-selected='true'] {
168
- background-color: var(--bgColor-default);
169
-
170
- // Bar on the left
171
- &::before {
172
- background-color: var(--underlineNav-borderColor-active, var(--color-primer-border-active, #fd8c73));
173
- }
174
- }
175
- }
176
-
177
- .sidenav.variant-lightweight > & {
178
- padding: var(--base-size-4) 0;
179
- color: var(--fgColor-accent);
180
-
181
- &:hover {
182
- ${ CommonAccessibilityVariantLightWeightStyles }
183
- }
184
-
185
- &:focus {
186
- ${ CommonAccessibilityVariantLightWeightStyles }
187
- outline: solid 1px var(--fgColor-accent);
188
- z-index: 1;
189
- }
190
-
191
- &[aria-current='page'],
192
- &[aria-selected='true'] {
193
- color: var(--fgColor-default);
194
- font-weight: var(--base-text-weight-medium);
195
- }
196
- }
197
-
198
- ${ sx } ;
199
- ` ,
200
- )
201
-
202
57
const SideNavLink = ( { selected, to, variant, className, children, ...rest } : StyledSideNavLinkProps ) => {
203
58
const isReactRouter = typeof to === 'string'
204
- const enabled = useFeatureFlag ( CSS_MODULES_FEATURE_FLAG )
205
- const newClassName = clsx (
206
- { [ classes . SideNavLink ] : true , [ classes . SideNavLinkFull ] : enabled && variant === 'full' } ,
207
- className ,
208
- )
209
-
59
+ const newClassName = clsx ( classes . SideNavLink , className , { [ classes . SideNavLinkFull ] : variant === 'full' } )
60
+ const BaseComponent = toggleSxComponent ( Link ) as React . ComponentType < StyledSideNavLinkProps >
210
61
// according to their docs, NavLink supports aria-current:
211
62
// https://reacttraining.com/react-router/web/api/NavLink/aria-current-string
212
63
return (
213
- < StyledSideNavLink
64
+ < BaseComponent
214
65
aria-current = { isReactRouter || selected ? 'page' : undefined }
215
66
className = { newClassName }
216
67
variant = { variant }
217
68
{ ...rest }
218
69
>
219
70
{ children }
220
- </ StyledSideNavLink >
71
+ </ BaseComponent >
221
72
)
222
73
}
223
74
0 commit comments