Skip to content

Commit c130cc4

Browse files
authored
refactor: add BoxWithFallback component to use with sx (#5919)
1 parent bb77751 commit c130cc4

File tree

7 files changed

+42
-45
lines changed

7 files changed

+42
-45
lines changed

packages/react/src/BranchName/BranchName.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,21 @@ import React, {type ForwardedRef} from 'react'
22
import {clsx} from 'clsx'
33
import type {SxProp} from '../sx'
44
import classes from './BranchName.module.css'
5-
import {toggleSxComponent} from '../internal/utils/toggleSxComponent'
5+
import {BoxWithFallback} from '../internal/components/BoxWithFallback'
66

77
type BranchNameProps<As extends React.ElementType> = {
88
as?: As
99
} & DistributiveOmit<React.ComponentPropsWithRef<React.ElementType extends As ? 'a' : As>, 'as'> &
1010
Omit<SxProp, 'sx'> &
1111
SxProp
1212

13-
const BaseComponent = toggleSxComponent('div') as React.ComponentType<
14-
React.PropsWithChildren<BranchNameProps<React.ElementType> & React.RefAttributes<HTMLElement>>
15-
>
16-
1713
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1814
function BranchName<As extends React.ElementType>(props: BranchNameProps<As>, ref: ForwardedRef<any>) {
1915
const {as: Component = 'a', className, children, ...rest} = props
2016
return (
21-
<BaseComponent as={Component} {...rest} ref={ref} className={clsx(className, classes.BranchName)}>
17+
<BoxWithFallback as={Component} {...rest} ref={ref} className={clsx(className, classes.BranchName)}>
2218
{children}
23-
</BaseComponent>
19+
</BoxWithFallback>
2420
)
2521
}
2622

packages/react/src/DataTable/Table.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {ScrollableRegion} from '../ScrollableRegion'
1313
import {Button} from '../internal/components/ButtonReset'
1414
import classes from './Table.module.css'
1515
import {defaultSxProp} from '../utils/defaultSxProp'
16-
import {toggleSxComponent} from '../internal/utils/toggleSxComponent'
16+
import {BoxWithFallback} from '../internal/components/BoxWithFallback'
1717

1818
// ----------------------------------------------------------------------------
1919
// Table
@@ -233,12 +233,11 @@ function TableCellPlaceholder({children}: TableCellPlaceholderProps) {
233233
// ----------------------------------------------------------------------------
234234
export type TableContainerProps = React.PropsWithChildren<SxProp & React.HTMLAttributes<HTMLDivElement>>
235235

236-
const TableContainerBaseComponent = toggleSxComponent('div') as React.ComponentType<TableContainerProps>
237236
function TableContainer({children, sx: sxProp = defaultSxProp}: TableContainerProps) {
238237
return (
239-
<TableContainerBaseComponent className={clsx(classes.TableContainer)} sx={sxProp}>
238+
<BoxWithFallback className={clsx(classes.TableContainer)} sx={sxProp}>
240239
{children}
241-
</TableContainerBaseComponent>
240+
</BoxWithFallback>
242241
)
243242
}
244243

packages/react/src/FormControl/FormControlCaption.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Text from '../Text'
44
import type {SxProp} from '../sx'
55
import classes from './FormControlCaption.module.css'
66
import {useFormControlContext} from './_FormControlContext'
7-
import {toggleSxComponent} from '../internal/utils/toggleSxComponent'
7+
import {BoxWithFallback} from '../internal/components/BoxWithFallback'
88

99
type FormControlCaptionProps = React.PropsWithChildren<
1010
{
@@ -13,20 +13,19 @@ type FormControlCaptionProps = React.PropsWithChildren<
1313
} & SxProp
1414
>
1515

16-
const Caption = toggleSxComponent(Text) as React.ComponentType<FormControlCaptionProps>
17-
1816
function FormControlCaption({id, children, sx, className}: FormControlCaptionProps) {
1917
const {captionId, disabled} = useFormControlContext()
2018

2119
return (
22-
<Caption
20+
<BoxWithFallback
21+
as={Text}
2322
id={id ?? captionId}
2423
className={clsx(className, classes.Caption)}
2524
data-control-disabled={disabled ? '' : undefined}
2625
sx={sx}
2726
>
2827
{children}
29-
</Caption>
28+
</BoxWithFallback>
3029
)
3130
}
3231

packages/react/src/SideNav.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import React, {type PropsWithChildren} from 'react'
55
import {clsx} from 'clsx'
66
import type {SxProp} from './sx'
77
import classes from './SideNav.module.css'
8-
import {toggleSxComponent} from './internal/utils/toggleSxComponent'
98
import {defaultSxProp} from './utils/defaultSxProp'
9+
import {BoxWithFallback} from './internal/components/BoxWithFallback'
1010

1111
type SideNavBaseProps = {
1212
as?: React.ElementType
@@ -38,12 +38,10 @@ function SideNav({
3838
},
3939
)
4040

41-
const BaseComponent = toggleSxComponent(as) as React.ComponentType<SideNavBaseProps>
42-
4341
return (
44-
<BaseComponent className={newClassName} aria-label={ariaLabel} sx={sxProp}>
42+
<BoxWithFallback as={as} className={newClassName} aria-label={ariaLabel} sx={sxProp}>
4543
{children}
46-
</BaseComponent>
44+
</BoxWithFallback>
4745
)
4846
}
4947

@@ -57,18 +55,18 @@ type StyledSideNavLinkProps = PropsWithChildren<{
5755
const SideNavLink = ({selected, to, variant, className, children, ...rest}: StyledSideNavLinkProps) => {
5856
const isReactRouter = typeof to === 'string'
5957
const newClassName = clsx(classes.SideNavLink, className, {[classes.SideNavLinkFull]: variant === 'full'})
60-
const BaseComponent = toggleSxComponent(Link) as React.ComponentType<StyledSideNavLinkProps>
6158
// according to their docs, NavLink supports aria-current:
6259
// https://reacttraining.com/react-router/web/api/NavLink/aria-current-string
6360
return (
64-
<BaseComponent
61+
<BoxWithFallback
62+
as={Link}
6563
aria-current={isReactRouter || selected ? 'page' : undefined}
6664
className={newClassName}
6765
variant={variant}
6866
{...rest}
6967
>
7068
{children}
71-
</BaseComponent>
69+
</BoxWithFallback>
7270
)
7371
}
7472

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from 'react'
2+
import Box from '../../Box'
3+
import {defaultSxProp} from '../../utils/defaultSxProp'
4+
import type {StyledComponent} from 'styled-components'
5+
import {includesSystemProps} from '../../utils/includeSystemProps'
6+
7+
const BoxWithFallback = React.forwardRef(function BoxWithFallback(
8+
{as: BaseComponent = 'div', sx = defaultSxProp, ...rest},
9+
ref,
10+
) {
11+
if (sx !== defaultSxProp || includesSystemProps(rest)) {
12+
return <Box {...rest} ref={ref} as={BaseComponent} sx={sx} />
13+
}
14+
return <BaseComponent {...rest} ref={ref} />
15+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
16+
}) as StyledComponent<'div', any, React.ComponentPropsWithoutRef<typeof Box>, never>
17+
18+
export {BoxWithFallback}

packages/react/src/internal/components/InputLabel.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {clsx} from 'clsx'
22
import React from 'react'
33
import {type SxProp} from '../../sx'
44
import classes from './InputLabel.module.css'
5-
import {toggleSxComponent} from '../utils/toggleSxComponent'
5+
import {BoxWithFallback} from './BoxWithFallback'
66

77
type BaseProps = SxProp & {
88
disabled?: boolean
@@ -26,8 +26,6 @@ export type LegendOrSpanProps = BaseProps & {
2626

2727
type Props = React.PropsWithChildren<LabelProps | LegendOrSpanProps>
2828

29-
const Label = toggleSxComponent('label') as React.ComponentType<Props>
30-
3129
function InputLabel({
3230
children,
3331
disabled,
@@ -44,7 +42,7 @@ function InputLabel({
4442
}: Props) {
4543
return (
4644
// @ts-ignore weird typing issue with union for `as` prop
47-
<Label
45+
<BoxWithFallback
4846
as={as}
4947
sx={sx}
5048
data-control-disabled={disabled ? '' : undefined}
@@ -62,7 +60,7 @@ function InputLabel({
6260
) : (
6361
children
6462
)}
65-
</Label>
63+
</BoxWithFallback>
6664
)
6765
}
6866

packages/react/src/internal/components/UnderlineTabbedInterface.tsx

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import {type SxProp} from '../../sx'
88
import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../../utils/polymorphic'
99
import {defaultSxProp} from '../../utils/defaultSxProp'
1010

11-
import {toggleSxComponent} from '../utils/toggleSxComponent'
1211
import classes from './UnderlineTabbedInterface.module.css'
1312
import {clsx} from 'clsx'
13+
import {BoxWithFallback} from './BoxWithFallback'
1414

1515
// The gap between the list items. It is a constant because the gap is used to calculate the possible number of items that can fit in the container.
1616
export const GAP = 8
@@ -22,24 +22,15 @@ type UnderlineWrapperProps = {
2222
ref?: React.Ref<unknown>
2323
} & SxProp
2424

25-
const UnderlineWrapperComponent = toggleSxComponent('div') as React.ComponentType<
26-
PropsWithChildren<UnderlineWrapperProps>
27-
>
28-
2925
export const UnderlineWrapper = forwardRef(
3026
(
3127
{children, className, sx: sxProp = defaultSxProp, ...rest}: PropsWithChildren<UnderlineWrapperProps>,
3228
forwardedRef,
3329
) => {
3430
return (
35-
<UnderlineWrapperComponent
36-
className={clsx(classes.UnderlineWrapper, className)}
37-
ref={forwardedRef}
38-
sx={sxProp}
39-
{...rest}
40-
>
31+
<BoxWithFallback className={clsx(classes.UnderlineWrapper, className)} ref={forwardedRef} sx={sxProp} {...rest}>
4132
{children}
42-
</UnderlineWrapperComponent>
33+
</BoxWithFallback>
4334
)
4435
},
4536
)
@@ -99,8 +90,6 @@ export type UnderlineItemProps = {
9990
ref?: React.Ref<unknown>
10091
} & SxProp
10192

102-
const UnderlineComponent = toggleSxComponent('a') as React.ComponentType<PropsWithChildren<UnderlineItemProps>>
103-
10493
export const UnderlineItem = forwardRef(
10594
(
10695
{
@@ -116,7 +105,7 @@ export const UnderlineItem = forwardRef(
116105
forwardedRef,
117106
) => {
118107
return (
119-
<UnderlineComponent ref={forwardedRef} as={as} sx={sxProp} className={classes.UnderlineItem} {...rest}>
108+
<BoxWithFallback ref={forwardedRef} as={as} sx={sxProp} className={classes.UnderlineItem} {...rest}>
120109
{iconsVisible && Icon && <span data-component="icon">{isElement(Icon) ? Icon : <Icon />}</span>}
121110
{children && (
122111
<span data-component="text" data-content={children}>
@@ -134,7 +123,7 @@ export const UnderlineItem = forwardRef(
134123
</span>
135124
)
136125
) : null}
137-
</UnderlineComponent>
126+
</BoxWithFallback>
138127
)
139128
},
140129
) as PolymorphicForwardRefComponent<'a', UnderlineItemProps>

0 commit comments

Comments
 (0)