Skip to content

Commit a1be16b

Browse files
committed
feat(CPlaceholder): add new component
1 parent fbae716 commit a1be16b

File tree

7 files changed

+385
-7
lines changed

7 files changed

+385
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import React, { ElementType, forwardRef, HTMLAttributes } from 'react'
2+
import PropTypes from 'prop-types'
3+
import classNames from 'classnames'
4+
5+
import { Colors, colorPropType } from '../Types'
6+
7+
export interface CPlaceholderProps extends HTMLAttributes<HTMLSpanElement> {
8+
animation?: 'glow' | 'wave'
9+
/**
10+
* A string of all className you want applied to the component.
11+
*/
12+
className?: string
13+
/**
14+
* Sets the color context of the component to one of CoreUI’s themed colors.
15+
*
16+
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string
17+
*/
18+
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
23+
/**
24+
* Size the component extra small, small, or large.
25+
*/
26+
size?: 'xs' | 'sm' | 'lg'
27+
/**
28+
* The number of columns on extra small devices (<576px).
29+
*/
30+
xs?: number
31+
/**
32+
* The number of columns on small devices (<768px).
33+
*/
34+
sm?: number
35+
/**
36+
* The number of columns on medium devices (<992px).
37+
*/
38+
md?: number
39+
/**
40+
* The number of columns on large devices (<1200px).
41+
*/
42+
lg?: number
43+
/**
44+
* The number of columns on X-Large devices (<1400px).
45+
*/
46+
xl?: number
47+
/**
48+
* The number of columns on XX-Large devices (≥1400px).
49+
*/
50+
xxl?: number
51+
}
52+
53+
const BREAKPOINTS = [
54+
'xxl' as const,
55+
'xl' as const,
56+
'lg' as const,
57+
'md' as const,
58+
'sm' as const,
59+
'xs' as const,
60+
]
61+
62+
export const CPlaceholder = forwardRef<HTMLSpanElement, CPlaceholderProps>(
63+
(
64+
{ children, animation, className, color, component: Component = 'span', size, ...rest },
65+
ref,
66+
) => {
67+
const repsonsiveClassNames: string[] = []
68+
69+
BREAKPOINTS.forEach((bp) => {
70+
const breakpoint = rest[bp]
71+
delete rest[bp]
72+
73+
const infix = bp === 'xs' ? '' : `-${bp}`
74+
75+
if (typeof breakpoint === 'number') {
76+
repsonsiveClassNames.push(`col${infix}-${breakpoint}`)
77+
}
78+
79+
if (typeof breakpoint === 'boolean') {
80+
repsonsiveClassNames.push(`col${infix}`)
81+
}
82+
})
83+
84+
const _className = classNames(
85+
animation ? `placeholder-${animation}` : 'placeholder',
86+
{
87+
[`bg-${color}`]: color,
88+
[`placeholder-${size}`]: size,
89+
},
90+
repsonsiveClassNames,
91+
className,
92+
)
93+
94+
return (
95+
<Component className={_className} {...rest} ref={ref}>
96+
{children}
97+
</Component>
98+
)
99+
},
100+
)
101+
102+
CPlaceholder.propTypes = {
103+
animation: PropTypes.oneOf(['glow', 'wave']),
104+
children: PropTypes.node,
105+
className: PropTypes.string,
106+
color: colorPropType.isRequired,
107+
component: PropTypes.string,
108+
size: PropTypes.oneOf(['xs', 'sm', 'lg']),
109+
}
110+
111+
CPlaceholder.displayName = 'CPlaceholder'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as React from 'react'
2+
import { render } from '@testing-library/react'
3+
import '@testing-library/jest-dom/extend-expect'
4+
import { CPlaceholder } from '../../../index'
5+
6+
test('loads and displays CPlaceholder component', async () => {
7+
const { container } = render(<CPlaceholder color="primary" />)
8+
expect(container).toMatchSnapshot()
9+
})
10+
11+
test('CPlaceholder customize', async () => {
12+
const { container } = render(
13+
<CPlaceholder animation="glow" className="bazinga" color="secondary" size="lg" sm={7} />,
14+
)
15+
expect(container).toMatchSnapshot()
16+
expect(container.firstChild).toHaveClass('bazinga')
17+
expect(container.firstChild).toHaveClass('bg-secondary')
18+
expect(container.firstChild).toHaveClass('col-sm-7')
19+
expect(container.firstChild).toHaveClass('placeholder-lg')
20+
expect(container.firstChild).toHaveClass('placeholder-glow')
21+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`CPlaceholder customize 1`] = `
4+
<div>
5+
<span
6+
class="placeholder-glow bg-secondary placeholder-lg col-sm-7 bazinga"
7+
/>
8+
</div>
9+
`;
10+
11+
exports[`loads and displays CPlaceholder component 1`] = `
12+
<div>
13+
<span
14+
class="placeholder bg-primary"
15+
/>
16+
</div>
17+
`;

packages/coreui-react/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ import { CNavbarText } from './components/navbar/CNavbarText'
8686
import { CNavbarToggler } from './components/navbar/CNavbarToggler'
8787
import { CPagination } from './components/pagination/CPagination'
8888
import { CPaginationItem } from './components/pagination/CPaginationItem'
89+
import { CPlaceholder } from './components/placeholder/CPlaceholder'
8990
import { CPopover } from './components/popover/CPopover'
9091
import { CProgress } from './components/progress/CProgress'
9192
import { CProgressBar } from './components/progress/CProgressBar'
@@ -206,6 +207,7 @@ export {
206207
CNavbarToggler,
207208
CPagination,
208209
CPaginationItem,
210+
CPlaceholder,
209211
CPopover,
210212
CProgress,
211213
CProgressBar,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
```jsx
3+
import { CPlaceholder } from '@coreui/react'
4+
// or
5+
import CPlaceholder from '@coreui/react/src/components/placeholder/CPlaceholder'
6+
```
7+
8+
| Property | Description | Type | Default |
9+
| --- | --- | --- | --- |
10+
| **animation** | - | `'glow'` \| `'wave'` | - |
11+
| **className** | A string of all className you want applied to the component. | `string` | - |
12+
| **color** | Sets the color context of the component to one of CoreUI’s themed colors. | `'primary'` \| `'secondary'` \| `'success'` \| `'danger'` \| `'warning'` \| `'info'` \| `'dark'` \| `'light'` \| `string` | - |
13+
| **component** | Component used for the root node. Either a string to use a HTML element or a component. | `string` \| `ComponentClass<any, any>` \| `FunctionComponent<any>` | - |
14+
| **lg** | The number of columns on large devices (<1200px). | `number` | - |
15+
| **md** | The number of columns on medium devices (<992px). | `number` | - |
16+
| **size** | Size the component extra small, small, or large. | `'xs'` \| `'sm'` \| `'lg'` | - |
17+
| **sm** | The number of columns on small devices (<768px). | `number` | - |
18+
| **xl** | The number of columns on X-Large devices (<1400px). | `number` | - |
19+
| **xs** | The number of columns on extra small devices (<576px). | `number` | - |
20+
| **xxl** | The number of columns on XX-Large devices (≥1400px). | `number` | - |

0 commit comments

Comments
 (0)