Skip to content

Commit 2652a91

Browse files
committed
refactor: improve polymorphic components typings
1 parent d8e71a6 commit 2652a91

File tree

128 files changed

+1166
-874
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+1166
-874
lines changed

packages/coreui-react/src/components/alert/CAlertHeading.tsx

+17-14
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,34 @@ import React, { ElementType, forwardRef, HTMLAttributes } from 'react'
22
import PropTypes from 'prop-types'
33
import classNames from 'classnames'
44

5+
import { PolymorphicRefForwardingComponent } from '../../helpers'
6+
57
export interface CAlertHeadingProps extends HTMLAttributes<HTMLHeadingElement> {
68
/**
7-
* A string of all className you want applied to the base component.
9+
* Component used for the root node. Either a string to use a HTML element or a component.
810
*/
9-
className?: string
11+
as?: ElementType
1012
/**
11-
* Component used for the root node. Either a string to use a HTML element or a component.
13+
* A string of all className you want applied to the base component.
1214
*/
13-
component?: string | ElementType
15+
className?: string
1416
}
1517

16-
export const CAlertHeading = forwardRef<HTMLHeadingElement, CAlertHeadingProps>(
17-
({ children, className, component: Component = 'h4', ...rest }, ref) => {
18-
return (
19-
<Component className={classNames('alert-heading', className)} {...rest} ref={ref}>
20-
{children}
21-
</Component>
22-
)
23-
},
24-
)
18+
export const CAlertHeading: PolymorphicRefForwardingComponent<'h4', CAlertHeadingProps> =
19+
forwardRef<HTMLHeadingElement, CAlertHeadingProps>(
20+
({ children, as: Component = 'h4', className, ...rest }, ref) => {
21+
return (
22+
<Component className={classNames('alert-heading', className)} {...rest} ref={ref}>
23+
{children}
24+
</Component>
25+
)
26+
},
27+
)
2528

2629
CAlertHeading.propTypes = {
30+
as: PropTypes.elementType,
2731
children: PropTypes.node,
2832
className: PropTypes.string,
29-
component: PropTypes.elementType,
3033
}
3134

3235
CAlertHeading.displayName = 'CAlertHeading'

packages/coreui-react/src/components/alert/__tests__/CAlertHeading.spec.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ test('loads and displays CAlertHeading component', async () => {
1010

1111
test('CAlertHeading customize', async () => {
1212
const { container } = render(
13-
<CAlertHeading component="h3" className="bazinga">
13+
<CAlertHeading as="h3" className="bazinga">
1414
Test
1515
</CAlertHeading>,
1616
)

packages/coreui-react/src/components/badge/CBadge.tsx

+11-7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@ import React, { ElementType, forwardRef, HTMLAttributes } from 'react'
22
import PropTypes from 'prop-types'
33
import classNames from 'classnames'
44

5+
import { PolymorphicRefForwardingComponent } from '../../helpers'
56
import { colorPropType, shapePropType, textColorsPropType } from '../../props'
67
import type { Colors, Shapes, TextColors } from '../../types'
78

89
export interface CBadgeProps extends HTMLAttributes<HTMLDivElement | HTMLSpanElement> {
10+
/**
11+
* Component used for the root node. Either a string to use a HTML element or a component.
12+
*/
13+
as?: ElementType
914
/**
1015
* A string of all className you want applied to the component.
1116
*/
@@ -16,10 +21,6 @@ export interface CBadgeProps extends HTMLAttributes<HTMLDivElement | HTMLSpanEle
1621
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string
1722
*/
1823
color?: Colors
19-
/**
20-
* Component used for the root node. Either a string to use a HTML element or a component.
21-
*/
22-
component?: string | ElementType
2324
/**
2425
* Position badge in one of the corners of a link or button.
2526
*/
@@ -41,13 +42,16 @@ export interface CBadgeProps extends HTMLAttributes<HTMLDivElement | HTMLSpanEle
4142
*/
4243
textColor?: TextColors
4344
}
44-
export const CBadge = forwardRef<HTMLDivElement | HTMLSpanElement, CBadgeProps>(
45+
export const CBadge: PolymorphicRefForwardingComponent<'span', CBadgeProps> = forwardRef<
46+
HTMLDivElement | HTMLSpanElement,
47+
CBadgeProps
48+
>(
4549
(
4650
{
4751
children,
52+
as: Component = 'span',
4853
className,
4954
color,
50-
component: Component = 'span',
5155
position,
5256
shape,
5357
size,
@@ -83,10 +87,10 @@ export const CBadge = forwardRef<HTMLDivElement | HTMLSpanElement, CBadgeProps>(
8387
)
8488

8589
CBadge.propTypes = {
90+
as: PropTypes.string,
8691
children: PropTypes.node,
8792
className: PropTypes.string,
8893
color: colorPropType,
89-
component: PropTypes.string,
9094
position: PropTypes.oneOf(['top-start', 'top-end', 'bottom-end', 'bottom-start']),
9195
shape: shapePropType,
9296
size: PropTypes.oneOf(['sm']),

packages/coreui-react/src/components/badge/__tests__/CBadge.spec.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ test('loads and displays CBadge component', async () => {
1010

1111
test('CBadge customize', async () => {
1212
const { container } = render(
13-
<CBadge className="bazinga" color="warning" component="div" shape="rounded" textColor="white">
13+
<CBadge className="bazinga" color="warning" as="div" shape="rounded" textColor="white">
1414
Test
1515
</CBadge>,
1616
)

packages/coreui-react/src/components/button/CButton.tsx

+12-18
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import classNames from 'classnames'
44

55
import { CLink, CLinkProps } from '../link/CLink'
66

7+
import { PolymorphicRefForwardingComponent } from '../../helpers'
78
import { colorPropType } from '../../props'
89
import type { Colors, Shapes } from '../../types'
910

@@ -12,6 +13,10 @@ export interface CButtonProps extends Omit<CLinkProps, 'size'> {
1213
* Toggle the active state for the component.
1314
*/
1415
active?: boolean
16+
/**
17+
* Component used for the root node. Either a string to use a HTML element or a component.
18+
*/
19+
as?: ElementType
1520
/**
1621
* A string of all className you want applied to the base component.
1722
*/
@@ -22,10 +27,6 @@ export interface CButtonProps extends Omit<CLinkProps, 'size'> {
2227
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string
2328
*/
2429
color?: Colors
25-
/**
26-
* Component used for the root node. Either a string to use a HTML element or a component.
27-
*/
28-
component?: string | ElementType
2930
/**
3031
* Toggle the disabled state for the component.
3132
*/
@@ -59,24 +60,17 @@ export interface CButtonProps extends Omit<CLinkProps, 'size'> {
5960
variant?: 'outline' | 'ghost'
6061
}
6162

62-
export const CButton = forwardRef<HTMLButtonElement | HTMLAnchorElement, CButtonProps>(
63+
export const CButton: PolymorphicRefForwardingComponent<'button', CButtonProps> = forwardRef<
64+
HTMLButtonElement | HTMLAnchorElement,
65+
CButtonProps
66+
>(
6367
(
64-
{
65-
children,
66-
className,
67-
color,
68-
component = 'button',
69-
shape,
70-
size,
71-
type = 'button',
72-
variant,
73-
...rest
74-
},
68+
{ children, as = 'button', className, color, shape, size, type = 'button', variant, ...rest },
7569
ref,
7670
) => {
7771
return (
7872
<CLink
79-
component={rest.href ? 'a' : component}
73+
as={rest.href ? 'a' : as}
8074
{...(!rest.href && { type: type })}
8175
className={classNames(
8276
'btn',
@@ -95,10 +89,10 @@ export const CButton = forwardRef<HTMLButtonElement | HTMLAnchorElement, CButton
9589
)
9690

9791
CButton.propTypes = {
92+
as: PropTypes.elementType,
9893
children: PropTypes.node,
9994
className: PropTypes.string,
10095
color: colorPropType,
101-
component: PropTypes.elementType,
10296
shape: PropTypes.string,
10397
size: PropTypes.oneOf(['sm', 'lg']),
10498
type: PropTypes.oneOf(['button', 'submit', 'reset']),

packages/coreui-react/src/components/button/__tests__/CButton.spec.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ test('loads and displays CButton component', async () => {
1010

1111
test('CButton customize witch href', async () => {
1212
const { container } = render(
13-
<CButton color="primary" component="span" href="/bazinga">
13+
<CButton color="primary" as="span" href="/bazinga">
1414
Test
1515
</CButton>,
1616
)
@@ -23,7 +23,7 @@ test('CButton customize', async () => {
2323
active={true}
2424
className="bazinga"
2525
color="warning"
26-
component="span"
26+
as="span"
2727
disabled={true}
2828
role="bazinga"
2929
shape="rounded"

packages/coreui-react/src/components/card/CCardHeader.tsx

+17-14
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,34 @@ import React, { ElementType, forwardRef, HTMLAttributes } from 'react'
22
import PropTypes from 'prop-types'
33
import classNames from 'classnames'
44

5+
import { PolymorphicRefForwardingComponent } from '../../helpers'
6+
57
export interface CCardHeaderProps extends HTMLAttributes<HTMLDivElement> {
68
/**
7-
* A string of all className you want applied to the base component.
9+
* Component used for the root node. Either a string to use a HTML element or a component.
810
*/
9-
className?: string
11+
as?: ElementType
1012
/**
11-
* Component used for the root node. Either a string to use a HTML element or a component.
13+
* A string of all className you want applied to the base component.
1214
*/
13-
component?: string | ElementType
15+
className?: string
1416
}
1517

16-
export const CCardHeader = forwardRef<HTMLDivElement, CCardHeaderProps>(
17-
({ children, component: Component = 'div', className, ...rest }, ref) => {
18-
return (
19-
<Component className={classNames('card-header', className)} {...rest} ref={ref}>
20-
{children}
21-
</Component>
22-
)
23-
},
24-
)
18+
export const CCardHeader: PolymorphicRefForwardingComponent<'div', CCardHeaderProps> = forwardRef<
19+
HTMLDivElement,
20+
CCardHeaderProps
21+
>(({ children, as: Component = 'div', className, ...rest }, ref) => {
22+
return (
23+
<Component className={classNames('card-header', className)} {...rest} ref={ref}>
24+
{children}
25+
</Component>
26+
)
27+
})
2528

2629
CCardHeader.propTypes = {
30+
as: PropTypes.elementType,
2731
children: PropTypes.node,
2832
className: PropTypes.string,
29-
component: PropTypes.elementType,
3033
}
3134

3235
CCardHeader.displayName = 'CCardHeader'

packages/coreui-react/src/components/card/CCardImage.tsx

+9-7
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,28 @@ import React, { ElementType, forwardRef, ImgHTMLAttributes } from 'react'
22
import PropTypes from 'prop-types'
33
import classNames from 'classnames'
44

5+
import { PolymorphicRefForwardingComponent } from '../../helpers'
6+
57
export interface CCardImageProps
68
extends ImgHTMLAttributes<HTMLImageElement | HTMLOrSVGElement | HTMLOrSVGImageElement> {
79
/**
8-
* A string of all className you want applied to the base component.
10+
* Component used for the root node. Either a string to use a HTML element or a component.
911
*/
10-
className?: string
12+
as?: ElementType
1113
/**
12-
* Component used for the root node. Either a string to use a HTML element or a component.
14+
* A string of all className you want applied to the base component.
1315
*/
14-
component?: string | ElementType
16+
className?: string
1517
/**
1618
* Optionally orientate the image to the top, bottom, or make it overlaid across the card.
1719
*/
1820
orientation?: 'top' | 'bottom'
1921
}
2022

21-
export const CCardImage = forwardRef<
23+
export const CCardImage: PolymorphicRefForwardingComponent<'img', CCardImageProps> = forwardRef<
2224
HTMLImageElement | HTMLOrSVGElement | HTMLOrSVGImageElement,
2325
CCardImageProps
24-
>(({ children, className, component: Component = 'img', orientation, ...rest }, ref) => {
26+
>(({ children, as: Component = 'img', className, orientation, ...rest }, ref) => {
2527
return (
2628
<Component
2729
className={classNames(orientation ? `card-img-${orientation}` : 'card-img', className)}
@@ -34,9 +36,9 @@ export const CCardImage = forwardRef<
3436
})
3537

3638
CCardImage.propTypes = {
39+
as: PropTypes.elementType,
3740
children: PropTypes.node,
3841
className: PropTypes.string,
39-
component: PropTypes.elementType,
4042
orientation: PropTypes.oneOf(['top', 'bottom']),
4143
}
4244

packages/coreui-react/src/components/card/CCardSubtitle.tsx

+18-14
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,34 @@ import React, { ElementType, forwardRef, HTMLAttributes } from 'react'
22
import PropTypes from 'prop-types'
33
import classNames from 'classnames'
44

5+
import { PolymorphicRefForwardingComponent } from '../../helpers'
6+
57
export interface CCardSubtitleProps extends HTMLAttributes<HTMLHeadingElement> {
68
/**
7-
* A string of all className you want applied to the component.
9+
* Component used for the root node. Either a string to use a HTML element or a component.
810
*/
9-
className?: string
11+
as?: ElementType
1012
/**
11-
* Component used for the root node. Either a string to use a HTML element or a component.
13+
* A string of all className you want applied to the component.
1214
*/
13-
component?: string | ElementType
15+
className?: string
1416
}
15-
export const CCardSubtitle = forwardRef<HTMLHeadingElement, CCardSubtitleProps>(
16-
({ children, component: Component = 'h6', className, ...rest }, ref) => {
17-
return (
18-
<Component className={classNames('card-subtitle', className)} {...rest} ref={ref}>
19-
{children}
20-
</Component>
21-
)
22-
},
23-
)
17+
18+
export const CCardSubtitle: PolymorphicRefForwardingComponent<'h6', CCardSubtitleProps> =
19+
forwardRef<HTMLHeadingElement, CCardSubtitleProps>(
20+
({ children, as: Component = 'h6', className, ...rest }, ref) => {
21+
return (
22+
<Component className={classNames('card-subtitle', className)} {...rest} ref={ref}>
23+
{children}
24+
</Component>
25+
)
26+
},
27+
)
2428

2529
CCardSubtitle.propTypes = {
30+
as: PropTypes.elementType,
2631
children: PropTypes.node,
2732
className: PropTypes.string,
28-
component: PropTypes.elementType,
2933
}
3034

3135
CCardSubtitle.displayName = 'CCardSubtitle'

0 commit comments

Comments
 (0)