11import type { To } from 'history'
2- import styled , { css } from 'styled-components'
3-
4- import Box from './Box'
52import type { ComponentProps } from './utils/types'
63import Link , { type LinkProps } from './Link'
74import React , { type PropsWithChildren } from 'react'
85import { clsx } from 'clsx'
96import type { SxProp } from './sx'
10- import sx from './sx'
11- import { toggleStyledComponent } from './internal/utils/toggleStyledComponent'
127import 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'
1610
1711type SideNavBaseProps = {
1812 as ?: React . ElementType
@@ -23,63 +17,33 @@ type SideNavBaseProps = {
2317 'aria-label' ?: string
2418} & SxProp
2519
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-
5220function SideNav ( {
5321 as = 'nav' ,
5422 variant = 'normal' ,
5523 className,
5624 bordered,
5725 children,
5826 'aria-label' : ariaLabel ,
59- sx : sxProp ,
27+ sx : sxProp = defaultSxProp ,
6028} : SideNavBaseProps ) {
61- const enabled = useFeatureFlag ( CSS_MODULES_FEATURE_FLAG )
6229 const variantClassName = variant === 'lightweight' ? 'lightweight' : 'normal'
6330 const newClassName = clsx (
31+ classes . SideNav ,
32+ classes [ `SideNavVariant--${ variantClassName } ` ] ,
33+ 'sidenav' ,
34+ `variant-${ variantClassName } ` ,
35+ className ,
6436 {
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 ,
7038 } ,
71- className ,
7239 )
40+
41+ const BaseComponent = toggleSxComponent ( as ) as React . ComponentType < SideNavBaseProps >
42+
7343 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 } >
8145 { children }
82- </ StyledNav >
46+ </ BaseComponent >
8347 )
8448}
8549
@@ -90,134 +54,21 @@ type StyledSideNavLinkProps = PropsWithChildren<{
9054} > &
9155 LinkProps
9256
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-
20257const SideNavLink = ( { selected, to, variant, className, children, ...rest } : StyledSideNavLinkProps ) => {
20358 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 >
21061 // according to their docs, NavLink supports aria-current:
21162 // https://reacttraining.com/react-router/web/api/NavLink/aria-current-string
21263 return (
213- < StyledSideNavLink
64+ < BaseComponent
21465 aria-current = { isReactRouter || selected ? 'page' : undefined }
21566 className = { newClassName }
21667 variant = { variant }
21768 { ...rest }
21869 >
21970 { children }
220- </ StyledSideNavLink >
71+ </ BaseComponent >
22172 )
22273}
22374
0 commit comments