8000 feat(CFormCheck): add form validation. · asmhasansarker/coreui-react@a63ab40 · GitHub
[go: up one dir, main page]

Skip to content

Commit a63ab40

Browse files
committed
feat(CFormCheck): add form validation.
1 parent dedf2a1 commit a63ab40

File tree

3 files changed

+144
-73
lines changed

3 files changed

+144
-73
lines changed

packages/coreui-react/src/components/form/CFormCheck.tsx

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import classNames from 'classnames'
55
import { useForkedRef } from '../../utils/hooks'
66
import { Colors, Shapes } from '../Types'
77

8-
import { CFormLabel } from './CFormLabel'
8+
import { CFormControlValidation, CFormControlValidationProps } from './CFormControlValidation'
9+
import { CFormLabel } from './'
910

1011
export type ButtonObject = {
1112
/**
@@ -30,7 +31,9 @@ export type ButtonObject = {
3031
variant?: 'outline' | 'ghost'
3132
}
3233

33-
export interface CFormCheckProps extends InputHTMLAttributes<HTMLInputElement> {
34+
export interface CFormCheckProps
35+
extends CFormControlValidationProps,
36+
InputHTMLAttributes<HTMLInputElement> {
3437
/**
3538
* Create button-like checkboxes and radio buttons.
3639
*/
@@ -78,6 +81,11 @@ export const CFormCheck = forwardRef<HTMLInputElement, CFormCheckProps>(
7881
{
7982
className,
8083
button,
84+
feedback,
85+
feedbackInvalid,
86+
feedbackValid,
87+
floatingLabel,
88+
tooltipFeedback,
8189
hitArea,
8290
id,
8391
indeterminate,
@@ -131,6 +139,19 @@ export const CFormCheck = forwardRef<HTMLInputElement, CFormCheckProps>(
131139
return <input type={type} className={inputClassName} id={id} {...rest} ref={forkedRef} />
132140
}
133141

142+
const formValidation = () => (
143+
<CFormControlValidation
144+
describedby={rest['aria-describedby']}
145+
feedback={feedback}
146+
feedbackInvalid={feedbackInvalid}
147+
feedbackValid={feedbackValid}
148+
floatingLabel={floatingLabel}
149+
invalid={invalid}
150+
tooltipFeedback={tooltipFeedback}
151+
valid={valid}
152+
/>
153+
)
154+
134155
const formLabel = () => {
135156
return (
136157
<CFormLabel customClassName={labelClassName} {...(id && { htmlFor: id })}>
@@ -143,17 +164,22 @@ export const CFormCheck = forwardRef<HTMLInputElement, CFormCheckProps>(
143164
<>
144165
{formControl()}
145166
{label && formLabel()}
167+
{formValidation()}
146168
</>
147169
) : label ? (
148170
hitArea ? (
149-
<CFormLabel customClassName={className} {...(id && { htmlFor: id })}>
150-
{formControl()}
151-
{label}
152-
</CFormLabel>
171+
<>
172+
<CFormLabel customClassName={className} {...(id && { htmlFor: id })}>
173+
{formControl()}
174+
{label}
175+
</CFormLabel>
176+
{formValidation()}
177+
</>
153178
) : (
154179
<div className={_className}>
155180
{formControl()}
156181
{formLabel()}
182+
{formValidation()}
157183
</div>
158184
)
159185
) : (
@@ -169,10 +195,9 @@ CFormCheck.propTypes = {
169195
id: PropTypes.string,
170196
indeterminate: PropTypes.bool,
171197
inline: PropTypes.bool,
172-
invalid: PropTypes.bool,
173198
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
174199
type: PropTypes.oneOf(['checkbox', 'radio']),
175-
valid: PropTypes.bool,
200+
...CFormControlValidation.propTypes,
176201
}
177202

178203
CFormCheck.displayName = 'CFormCheck'
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import React, { FC, ReactNode } from 'react'
2+
3+
import PropTypes from 'prop-types'
4+
5+
import { CFormFeedback } from './'
6+
7+
export interface CFormControlValidationProps {
8+
/**
9+
* @ignore
10+
*/
11+
describedby?: string
12+
/**
13+
* Provide valuable, actionable feedback.
14+
*
15+
* @since 4.2.0
16+
*/
17+
feedback?: ReactNode | string
18+
/**
19+
* Provide valuable, actionable feedback.
20+
*
21+
* @since 4.2.0
22+
*/
23+
feedbackInvalid?: ReactNode | string
24+
/**
25+
* Provide valuable, actionable invalid feedback when using standard HTML form validation which applied two CSS pseudo-classes, `:invalid` and `:valid`.
26+
*
27+
* @since 4.2.0
28+
*/
29+
feedbackValid?: ReactNode | string
30+
/**
31+
* Provide valuable, actionable valid feedback when using standard HTML form validation which applied two CSS pseudo-classes, `:invalid` and `:valid`.
32+
*
33+
* @since 4.2.0
34+
*/
35+
floatingLabel?: ReactNode | string
36+
/**
37+
* Set component validation state to invalid.
38+
*/
39+
invalid?: boolean
40+
/**
41+
* Display validation feedback in a styled tooltip.
42+
*
43+
* @since 4.2.0
44+
*/
45+
tooltipFeedback?: boolean
46+
/**
47+
* Set component validation state to valid.
48+
*/
49+
valid?: boolean
50+
}
51+
52+
export const CFormControlValidation: FC<CFormControlValidationProps> = ({
53+
describedby,
54+
feedback,
55+
feedbackInvalid,
56+
feedbackValid,
57+
invalid,
58+
tooltipFeedback,
59+
valid,
60+
}) => {
61+
return (
62+
<>
63+
{feedback && (valid || invalid) && (
64+
<CFormFeedback
65+
{...(invalid && { id: describedby })}
66+
invalid={invalid}
67+
tooltip={tooltipFeedback}
68+
valid={valid}
69+
>
70+
{feedback}
71+
</CFormFeedback>
72+
)}
73+
{feedbackInvalid && (
74+
<CFormFeedback id={describedby} invalid tooltip={tooltipFeedback}>
75+
{feedbackInvalid}
76+
</CFormFeedback>
77+
)}
78+
{feedbackValid && (
79+
<CFormFeedback valid tooltip={tooltipFeedback}>
80+
{feedbackValid}
81+
</CFormFeedback>
82+
)}
83+
</>
84+
)
85+
}
86+
87+
CFormControlValidation.propTypes = {
88+
describedby: PropTypes.string,
89+
feedback: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
90+
feedbackValid: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
91+
feedbackInvalid: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
92+
invalid: PropTypes.bool,
93+
tooltipFeedback: PropTypes.bool,
94+
valid: PropTypes.bool,
95+
}
96+
97+
CFormControlValidation.displayName = 'CFormControlValidation'

packages/coreui-react/src/components/form/CFormControlWrapper.tsx

Lines changed: 14 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,14 @@ import React, { FC, ReactNode } from 'react'
22

33
import PropTypes from 'prop-types'
44

5-
import { CFormFeedback, CFormFloating, CFormLabel, CFormText } from './'
5+
import { CFormControlValidation, CFormControlValidationProps } from './CFormControlValidation'
6+
import { CFormFloating, CFormLabel, CFormText } from './'
67

7-
export interface CFormControlWrapperProps {
8+
export interface CFormControlWrapperProps extends CFormControlValidationProps {
89
/**
910
* @ignore
1011
*/
1112
children?: ReactNode
12-
/**
13-
* @ignore
14-
*/
15-
describedby?: string
16-
/**
17-
* Provide valuable, actionable feedback.
18-
*
19-
* @since 4.2.0
20-
*/
21-
feedback?: ReactNode | string
22-
/**
23-
* Provide valuable, actionable feedback.
24-
*
25-
* @since 4.2.0
26-
*/
27-
feedbackInvalid?: ReactNode | string
28-
/**
29-
* Provide valuable, actionable invalid feedback when using standard HTML form validation which applied two CSS pseudo-classes, `:invalid` and `:valid`.
30-
*
31-
* @since 4.2.0
32-
*/
33-
feedbackValid?: ReactNode | string
3413
/**
3514
* Provide valuable, actionable valid feedback when using standard HTML form validation which applied two CSS pseudo-classes, `:invalid` and `:valid`.
3615
*
@@ -41,10 +20,6 @@ export interface CFormControlWrapperProps {
4120
* @ignore
4221
*/
4322
id?: string
44-
/**
45-
* Set component validation state to invalid.
46-
*/
47-
invalid?: boolean
4823
/**
4924
* Add a caption for a component.
5025
*
@@ -57,16 +32,6 @@ export interface CFormControlWrapperProps {
5732
* @since 4.2.0
5833
*/
5934
text?: ReactNode | string
60-
/**
61-
* Display validation feedback in a styled tooltip.
62-
*
63-
* @since 4.2.0
64-
*/
65-
tooltipFeedback?: boolean
66-
/**
67-
* Set component validation state to valid.
68-
*/
69-
valid?: boolean
7035
}
7136

7237
export const CFormControlWrapper: FC<CFormControlWrapperProps> = ({
@@ -93,42 +58,26 @@ export const CFormControlWrapper: FC<CFormControlWrapperProps> = ({
9358
{label && <CFormLabel htmlFor={id}>{label}</CFormLabel>}
9459
{children}
9560
{text && <CFormText id={describedby}>{text}</CFormText>}
96-
{feedback && (valid || invalid) && (
97-
<CFormFeedback
98-
{...(invalid && { id: describedby })}
99-
invalid={invalid}
100-
tooltip={tooltipFeedback}
101-
valid={valid}
102-
>
103-
{feedback}
104-
</CFormFeedback>
105-
)}
106-
{feedbackInvalid && (
107-
<CFormFeedback id={describedby} invalid tooltip={tooltipFeedback}>
108-
{feedbackInvalid}
109-
</CFormFeedback>
110-
)}
111-
{feedbackValid && (
112-
<CFormFeedback valid tooltip={tooltipFeedback}>
113-
{feedbackValid}
114-
</CFormFeedback>
115-
)}
61+
<CFormControlValidation
62+
describedby={describedby}
63+
feedback={feedback}
64+
feedbackInvalid={feedbackInvalid}
65+
feedbackValid={feedbackValid}
66+
floatingLabel={floatingLabel}
67+
invalid={invalid}
68+
tooltipFeedback={tooltipFeedback}
69+
valid={valid}
70+
/>
11671
</>
11772
)
11873
}
11974

12075
CFormControlWrapper.propTypes = {
12176
children: PropTypes.node,
122-
describedby: PropTypes.string,
123-
feedback: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
124-
feedbackValid: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
125-
feedbackInvalid: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
12677
floatingLabel: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
127-
invalid: PropTypes.bool,
12878
label: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
12979
text: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
130-
tooltipFeedback: PropTypes.bool,
131-
valid: PropTypes.bool,
80+
...CFormControlValidation.propTypes,
13281
}
13382

13483
CFormControlWrapper.displayName = 'CFormControlWrapper'

0 commit comments

Comments
 (0)
0