Skip to content
This repository was archived by the owner on Jun 20, 2022. It is now read-only.

Commit f6314a3

Browse files
committed
feat: add form validation
Also expose defaultTheme
1 parent 4b80ff6 commit f6314a3

File tree

7 files changed

+159
-18
lines changed

7 files changed

+159
-18
lines changed

src/ControlFeedBack.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react'
2+
import styled from 'styled-components'
3+
import PropTypes from 'prop-types'
4+
import classNames from 'classnames'
5+
import defaultTheme from './style/defaultTheme'
6+
7+
const ControlFeedbackComponent = ({ className, valid, ...props }) => (
8+
<div
9+
className={classNames(
10+
'sui-control-feedback',
11+
{
12+
'sui-is-valid': valid === true,
13+
'sui-is-invalid': valid === false,
14+
},
15+
className,
16+
)}
17+
{...props}
18+
/>
19+
)
20+
21+
const ControlFeedback = styled(ControlFeedbackComponent)`
22+
width: 100%;
23+
margin-top: 0.25rem;
24+
font-size: 80%;
25+
26+
&.sui-is-valid {
27+
color: ${props => props.theme.colors.success};
28+
}
29+
30+
&.sui-is-invalid {
31+
color: ${props => props.theme.colors.danger};
32+
}
33+
`
34+
35+
ControlFeedback.propTypes = {
36+
children: PropTypes.node,
37+
className: PropTypes.string,
38+
valid: PropTypes.bool.isRequired,
39+
}
40+
41+
ControlFeedback.defaultProps = {
42+
theme: defaultTheme,
43+
}
44+
45+
/** @component */
46+
export default ControlFeedback

src/ControlFeedBack.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
See [`FormGroup`](#formgroup).

src/FormGroup.md

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
1+
`FormGroup` creates easy form layout.
2+
13
```js
2-
<FormGroup>
3-
<Label htmlFor="form-group-input">This is it</Label>
4-
<Input control id="form-group-input" />
5-
</FormGroup>
4+
<div>
5+
<FormGroup>
6+
<Label htmlFor="form-group-input-name">Name</Label>
7+
<Input control id="form-group-input-name" />
8+
</FormGroup>
9+
<FormGroup>
10+
<Label htmlFor="form-group-input-firstname">Firstname</Label>
11+
<Input control id="form-group-input-firstname" />
12+
</FormGroup>
13+
</div>
14+
```
15+
16+
### Validation
17+
18+
You can set validation using `valid` props.
19+
20+
```js
21+
<div>
22+
<FormGroup>
23+
<Label htmlFor="form-group-input-valid">Name</Label>
24+
<Input control valid id="form-group-input-valid" />
25+
<ControlFeedback valid>Looks good!</ControlFeedback>
26+
</FormGroup>
27+
<FormGroup>
28+
<Label htmlFor="form-group-input-invalid">Firstname</Label>
29+
<Input control valid={false} id="form-group-input-invalid" />
30+
<ControlFeedback valid={false}>It is required.</ControlFeedback>
31+
</FormGroup>
32+
</div>
633
```

src/Input.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ import styled from 'styled-components'
55
import handleRef from './internal/handleRef'
66
import defaultTheme from './style/defaultTheme'
77

8-
const InputComponent = ({ className, size, control, ...props }) => (
8+
const InputComponent = ({ className, size, control, valid, ...props }) => (
99
<input
1010
{...props}
1111
className={classNames(
1212
'sui-input',
1313
{
1414
'sui-control': control,
15+
'sui-is-valid': valid === true,
16+
'sui-is-invalid': valid === false,
1517
[`sui-input-${size}`]: size,
1618
},
1719
className,
@@ -66,6 +68,7 @@ Input.propTypes = {
6668
theme: PropTypes.object,
6769
control: PropTypes.bool,
6870
size: PropTypes.oneOf(['sm', 'lg']),
71+
valid: PropTypes.bool,
6972
}
7073

7174
Input.defaultProps = {

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export { default as Box } from './Box'
22
export { default as Button } from './Button'
33
export { default as Checkbox } from './Checkbox'
44
export { default as Col } from './Col'
5+
export { default as ControlFeedBack } from './ControlFeedBack'
56
export { default as FormCheck } from './FormCheck'
67
export { default as FormCheckLabel } from './FormCheckLabel'
78
export { default as FormGroup } from './FormGroup'
@@ -13,3 +14,4 @@ export { default as Row } from './Row'
1314
export { default as Select } from './Select'
1415
export { default as Switch } from './Switch'
1516
export { default as Textarea } from './Textarea'
17+
export { default as defaultTheme } from './style/defaultTheme'

src/style/defaultTheme.js

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-unused-vars */
12
import { injectGlobal, css } from 'styled-components'
23
import { transparentize, lighten } from 'polished'
34

@@ -14,9 +15,39 @@ injectGlobal`
1415
`
1516
/* eslint-enable no-unused-expressions */
1617

18+
const white = '#fff'
19+
const gray100 = '#f8f9fa'
20+
const gray200 = '#e9ecef'
21+
const gray300 = '#dee2e6'
22+
const gray400 = '#ced4da'
23+
const gray500 = '#adb5bd'
24+
const gray600 = '#6c757d'
25+
const gray700 = '#495057'
26+
const gray800 = '#343a40'
27+
const gray900 = '#212529'
28+
const black = '#000'
29+
30+
const blue = '#007bff'
31+
const indigo = '#6610f2'
32+
const purple = '#6f42c1'
33+
const pink = '#e83e8c'
34+
const red = '#dc3545'
35+
const orange = '#fd7e14'
36+
const yellow = '#ffc107'
37+
const green = '#28a745'
38+
const teal = '#20c997'
39+
const cyan = '#17a2b8'
40+
41+
const primary = blue
42+
const secondary = gray600
43+
const success = green
44+
const info = cyan
45+
const warning = yellow
46+
const danger = red
47+
const light = gray100
48+
const dark = gray800
49+
1750
const primaryColor = '#bd4932'
18-
const secondaryColor = '#063855'
19-
const accentColor = '#46AFBD'
2051
const grayLightColor = '#f6f6f6'
2152
const grayDarkColor = '#aaa'
2253
const grayDarkerColor = '#333'
@@ -25,9 +56,19 @@ export default {
2556
colors: {
2657
primary: primaryColor,
2758
primaryLight: lighten(0.3, primaryColor),
28-
secondary: secondaryColor,
29-
secondaryLight: '#E6EBEE',
30-
accent: accentColor,
59+
danger,
60+
success,
61+
white,
62+
gray100,
63+
gray200,
64+
gray300,
65+
gray400,
66+
gray500,
67+
gray600,
68+
gray700,
69+
gray800,
70+
gray900,
71+
black,
3172
grayLight: '#f6f6f6',
3273
gray: '#cfcfcf',
3374
grayDark: grayDarkColor,
@@ -40,7 +81,6 @@ export default {
4081
disabledControlBg: grayLightColor,
4182
disabledControlText: grayDarkColor,
4283
placeholder: grayDarkColor,
43-
white: '#fff',
4484
},
4585
borderRadius: {
4686
sm: '.2rem',
@@ -72,19 +112,40 @@ export default {
72112
padding: 0.375rem 0.75rem;
73113
font-size: 1rem;
74114
line-height: 1.5;
75-
color: #495057;
76-
background-color: #fff;
115+
color: ${props => props.theme.colors.gray700};
116+
background-color: ${props => props.theme.colors.white};
77117
background-clip: padding-box;
78-
border: 1px solid #ced4da;
118+
border: 1px solid ${props => props.theme.colors.gray400};
79119
border-radius: 0.25rem;
80120
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
81121
82122
&:focus {
83-
color: #495057;
84-
background-color: #fff;
85-
border-color: #80bdff;
123+
color: ${props => props.theme.colors.gray700};
124+
background-color: ${props => props.theme.colors.white};
125+
border-color: ${props => lighten(0.25, props.theme.colors.primary)};
86126
outline: 0;
87-
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
127+
box-shadow: 0 0 0 0.2rem
128+
${props => transparentize(0.75, props.theme.colors.primary)};
129+
}
130+
131+
&.sui-is-valid {
132+
border-color: ${props => props.theme.colors.success};
133+
134+
&:focus {
135+
border-color: ${props => props.theme.colors.success};
136+
box-shadow: 0 0 0 0.2rem
137+
${props => transparentize(0.75, props.theme.colors.success)};
138+
}
139+
}
140+
141+
&.sui-is-invalid {
142+
border-color: ${props => props.theme.colors.danger};
143+
144+
&:focus {
145+
border-color: ${props => props.theme.colors.danger};
146+
box-shadow: 0 0 0 0.2rem
147+
${props => transparentize(0.75, props.theme.colors.danger)};
148+
}
88149
}
89150
}
90151
`,

styleguide.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ module.exports = {
4040
path.resolve(__dirname, 'src/Box.js'),
4141
path.resolve(__dirname, 'src/Button.js'),
4242
path.resolve(__dirname, 'src/Checkbox.js'),
43+
path.resolve(__dirname, 'src/ControlFeedBack.js'),
4344
path.resolve(__dirname, 'src/FormCheck.js'),
4445
path.resolve(__dirname, 'src/FormCheckLabel.js'),
4546
path.resolve(__dirname, 'src/FormGroup.js'),

0 commit comments

Comments
 (0)