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

Commit 6df34f3

Browse files
committed
feat(FormGroup): add FormGroup component
1 parent ac97297 commit 6df34f3

File tree

6 files changed

+334
-1
lines changed

6 files changed

+334
-1
lines changed

__tests__/FormGroup.test.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React from 'react';
2+
import { renderToStaticMarkup } from 'react-dom/server';
3+
import { FormGroup, Label } from '../src/index';
4+
5+
describe('<FormGroup />', () => {
6+
it('renders basic <FormGroup />', () => {
7+
expect(renderToStaticMarkup(<FormGroup />)).toEqual(
8+
'<div class="pt-form-group"></div>'
9+
);
10+
});
11+
12+
it('renders basic <FormGroup /> with props', () => {
13+
expect(renderToStaticMarkup(<FormGroup helper="Helper text" />)).toEqual(
14+
'<div class="pt-form-group"><div class="pt-form-content"><div class="pt-form-helper-text">Helper text</div></div></div>'
15+
);
16+
17+
expect(renderToStaticMarkup(<FormGroup disabled />)).toEqual(
18+
'<div class="pt-form-group pt-disabled"></div>'
19+
);
20+
21+
expect(renderToStaticMarkup(<FormGroup large />)).toEqual(
22+
'<div class="pt-form-group pt-large"></div>'
23+
);
24+
25+
expect(renderToStaticMarkup(<FormGroup inline />)).toEqual(
26+
'<div class="pt-form-group pt-inline"></div>'
27+
);
28+
29+
expect(renderToStaticMarkup(<FormGroup intent={1} />)).toEqual(
30+
'<div class="pt-form-group pt-intent-success"></div>'
31+
);
32+
});
33+
34+
it('renders basic <FormGroup /> with <Label />', () => {
35+
expect(
36+
renderToStaticMarkup(
37+
<FormGroup label={<Label text="Form Group Label" />} />
38+
)
39+
).toEqual(
40+
'<div class="pt-form-group"><label class="pt-label">Form Group Label</label></div>'
41+
);
42+
});
43+
44+
it('renders basic <FormGroup /> with children', () => {
45+
expect(
46+
renderToStaticMarkup(
47+
<FormGroup>
48+
<input type="text" placeholder="Enter a value" className="pt-input" />
49+
</FormGroup>
50+
)
51+
).toEqual(
52+
'<div class="pt-form-group"><div class="pt-form-content"><input type="text" placeholder="Enter a value" class="pt-input"/></div></div>'
53+
);
54+
});
55+
});
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import classnames from 'classnames';
4+
5+
const FormGroup = ({
6+
children,
7+
className,
8+
disabled,
9+
intent,
10+
inline,
11+
large,
12+
label,
13+
helper,
14+
...rest
15+
}) => {
16+
const intentStyles = {
17+
'pt-intent-primary': intent === 0,
18+
'pt-intent-success': intent === 1,
19+
'pt-intent-warning': intent === 2,
20+
'pt-intent-danger': intent === 3,
21+
};
22+
return (
23+
<div
24+
className={classnames(
25+
'pt-form-group',
26+
{ 'pt-inline': inline },
27+
{ 'pt-disabled': disabled },
28+
{ 'pt-large': large },
29+
intentStyles,
30+
className
31+
)}
32+
{...rest}
33+
>
34+
{label}
35+
{(children || helper) && (
36+
<div className="pt-form-content">
37+
{children}
38+
{helper && <div className="pt-form-helper-text">{helper}</div>}
39+
</div>
40+
)}
41+
</div>
42+
);
43+
};
44+
45+
/**
46+
* FormGroup property types.
47+
*/
48+
FormGroup.propTypes = {
49+
/**
50+
* Primary content.
51+
*/
52+
children: PropTypes.node,
53+
54+
/**
55+
* Additional CSS classes.
56+
*/
57+
className: PropTypes.string,
58+
59+
/**
60+
* Adds appereance of `disabled` style.
61+
*/
62+
disabled: PropTypes.bool,
63+
64+
/**
65+
* Visual intent color.
66+
*/
67+
intent: PropTypes.number,
68+
69+
/**
70+
* Align label and children elements on same line.
71+
*/
72+
inline: PropTypes.bool,
73+
74+
/**
75+
* Use large elements.
76+
*/
77+
large: PropTypes.bool,
78+
79+
/**
80+
* Use `Label` component.
81+
*/
82+
label: PropTypes.node,
83+
84+
/**
85+
* Helper text.
86+
*/
87+
helper: PropTypes.string,
88+
};
89+
90+
/**
91+
* FormGroup default properties.
92+
*/
93+
FormGroup.defaultProps = {
94+
children: null,
95+
className: '',
96+
disabled: false,
97+
intent: -1,
98+
inline: false,
99+
large: false,
100+
label: null,
101+
helper: '',
102+
};
103+
104+
export default FormGroup;
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
Form groups support more complex form controls than simple [labels](#label), such as [control groups](#controlgroup).
2+
3+
```js static
4+
import { FormGroup, Label } from 'blueprint-components';
5+
```
6+
7+
Additionally:
8+
9+
```js static
10+
import { Classes, InputGroup, Intent, Switch } from '@blueprintjs/core';
11+
```
12+
13+
```jsx
14+
<FormGroup
15+
label={<Label text="Label A" />}
16+
helper="Helper text with details / user feedback"
17+
>
18+
<InputGroup
19+
leftIconName="calendar"
20+
/>
21+
</FormGroup>
22+
```
23+
24+
### Form Group Intent
25+
26+
```html static
27+
<FormGroup intent={Intent.SUCCESS}>
28+
...
29+
</FormGroup>
30+
```
31+
32+
```jsx
33+
<div>
34+
<FormGroup
35+
intent={Intent.SUCCESS}
36+
label={<Label text="Label A" />}
37+
helper="Intent only FormGroup component"
38+
>
39+
<InputGroup
40+
leftIconName="calendar"
41+
/>
42+
</FormGroup>
43+
<FormGroup
44+
intent={Intent.DANGER}
45+
label={<Label text="Label A" />}
46+
helper="Disabled with FormGroup and InputGroup components"
47+
>
48+
<InputGroup
49+
intent={Intent.DANGER}
50+
leftIconName="calendar"
51+
/>
52+
</FormGroup>
53+
</div>
54+
```
55+
56+
### Form Group Large
57+
58+
To use larger form elements in `FormGroup`, add optional `large` prop:
59+
60+
> Note: This prop will not increase in size it's children elements. You have to add `className={Classes.LARGE}` prop or `.pt-large` CSS class to these elements. Take a look at the source code of example below.
61+
62+
```html static
63+
<FormGroup large>
64+
...
65+
</FormGroup>
66+
```
67+
68+
```jsx
69+
<div>
70+
<FormGroup
71+
large
72+
label={<Label text="Label A" />}
73+
helper="Helper text with details / user feedback"
74+
>
75+
<InputGroup
76+
className={Classes.LARGE}
77+
leftIconName="calendar"
78+
/>
79+
</FormGroup>
80+
<FormGroup
81+
className={Classes.LARGE}
82+
label={<Label text="Label A" />}
83+
helper="Note: Switch component does NOT work in this example."
84+
>
85+
<Switch className={Classes.LARGE} checked={false} label="Public" onChange={() => {}} />
86+
</FormGroup>
87+
</div>
88+
```
89+
90+
### Form Group Inline
91+
92+
To place form group elements on same line, add optional `inline` prop:
93+
94+
```html static
95+
<FormGroup inline>
96+
...
97+
</FormGroup>
98+
```
99+
100+
```jsx
101+
<div>
102+
<FormGroup
103+
inline
104+
label={<Label text="Label A" />}
105+
helper="Helper text with details / user feedback"
106+
>
107+
<InputGroup
108+
leftIconName="calendar"
109+
/>
110+
</FormGroup>
111+
<FormGroup
112+
inline
113+
label={<Label text="Label A" />}
114+
helper="Note: Switch component does NOT work in this example."
115+
>
116+
<Switch checked={false} label="Public" onChange={() => {}} />
117+
</FormGroup>
118+
</div>
119+
```
120+
121+
### Form Group Disabled
122+
123+
To make form group appear as disabled, add optional `disabled` prop:
124+
125+
> Note: This prop will not add `disabled` as attribute to it's children elements. You have to add it manualy on form elments (`input`, `select`) and `.pt-disabled` CSS class to input groups.
126+
127+
```html static
128+
<FormGroup disabled>
129+
...
130+
</FormGroup>
131+
```
132+
133+
```jsx
134+
<div>
135+
<FormGroup
136+
disabled
137+
label={<Label text="Label A" />}
138+
helper="Disabled only FormGroup component"
139+
>
140+
<InputGroup
141+
leftIconName="calendar"
142+
/>
143+
</FormGroup>
144+
<FormGroup
145+
disabled
146+
label={<Label disabled text="Label A" />}
147+
helper="Disabled with Label and InputGroup components"
148+
>
149+
<InputGroup
150+
disabled
151+
leftIconName="calendar"
152+
/>
153+
</FormGroup>
154+
<FormGroup
155+
disabled
156+
label={<Label text="Label A" />}
157+
helper="Disabled with FormGroup and Switch components"
158+
>
159+
<Switch disabled checked={false} label="Public" onChange={() => {}} />
160+
</FormGroup>
161+
</div>
162+
```

src/components/FormGroup/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as FormGroup } from './FormGroup';

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export { ButtonGroup } from './components/ButtonGroup';
22
export { Callout } from './components/Callout';
33
export { Card } from './components/Card';
44
export { ControlGroup } from './components/ControlGroup';
5+
export { FormGroup } from './components/FormGroup';
56
export { Label } from './components/Label';
67
export { Navbar } from './components/Navbar';
78
export { NavbarDivider } from './components/NavbarDivider';

styleguide/styleguide.setup.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1-
import { Button, Classes, Icon, InputGroup, Intent } from '@blueprintjs/core';
1+
import {
2+
Button,
3+
Classes,
4+
Icon,
5+
InputGroup,
6+
Intent,
7+
Switch,
8+
} from '@blueprintjs/core';
29
global.Button = Button;
310
global.Classes = Classes;
411
global.Icon = Icon;
512
global.InputGroup = InputGroup;
613
global.Intent = Intent;
14+
global.Switch = Switch;
715

816
import {
917
ButtonGroup,
1018
Callout,
1119
Card,
1220
ControlGroup,
21+
FormGroup,
1322
Label,
1423
Navbar,
1524
NavbarGroup,
@@ -20,6 +29,7 @@ global.ButtonGroup = ButtonGroup;
2029
global.Callout = Callout;
2130
global.Card = Card;
2231
global.ControlGroup = ControlGroup;
32+
global.FormGroup = FormGroup;
2333
global.Label = Label;
2434
global.Navbar = Navbar;
2535
global.NavbarGroup = NavbarGroup;

0 commit comments

Comments
 (0)