Skip to content

Commit d6b3842

Browse files
authored
feat: UiKit error states (#133)
1 parent c750d5a commit d6b3842

File tree

3 files changed

+64
-43
lines changed

3 files changed

+64
-43
lines changed

packages/fuselage-ui-kit/src/Input.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import {
99

1010
import { Block } from './Block';
1111

12-
export const Input = ({ label, element, parser, index }) => (
12+
export const Input = ({ label, element, parser, index, error, hint }) => (
1313
<Block>
1414
<FieldGroup>
1515
<Field>
1616
{label && <Field.Label>{label}</Field.Label>}
17-
{
18-
parser.renderInputs(element, BLOCK_CONTEXT.FORM, parser, index)
19-
}
17+
{parser.renderInputs(element, BLOCK_CONTEXT.FORM, parser, index)}
18+
{error && <Field.Error>{error}</Field.Error>}
19+
{hint && <Field.Hint>{hint}</Field.Hint>}
2020
</Field>
2121
</FieldGroup>
2222
</Block>

packages/fuselage-ui-kit/src/UIKitModal.stories.mdx

+42-32
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Meta, Preview, Props, Story } from '@storybook/addon-docs/blocks';
33
import {
44
Modal,
55
} from '@rocket.chat/fuselage';
6-
import { UiKitModal, kitContext, defaultContext } from './';
6+
import { UiKitModal, kitContext, defaultContext, UiKitComponent } from './';
77
import { Demo } from './Demo';
88
import { withKnobs, text, boolean, number } from "@storybook/addon-knobs";
99

@@ -15,36 +15,42 @@ import { withKnobs, text, boolean, number } from "@storybook/addon-knobs";
1515
<Preview>
1616
<Story name='Input'>
1717
<Demo visible={boolean('visible', true) ? 1 : 0}>
18-
{UiKitModal([{
19-
"type": "input",
20-
"element": {
21-
"type": "plain_text_input"
22-
},
23-
"label": {
24-
"type": "plain_text",
25-
"text": "Label",
26-
"emoji": true
27-
}
28-
}])}
18+
<kitContext.Provider value={{...defaultContext, errors: {'input-test': text('error', 'asdas') } }}>
19+
<UiKitComponent render={UiKitModal} blocks={[{
20+
"type": "input",
21+
"element": {
22+
"type": "plain_text_input",
23+
"actionId": "input-test",
24+
},
25+
"label": {
26+
"type": "plain_text",
27+
"text": "Label",
28+
"emoji": true
29+
}
30+
}]}/>
31+
</kitContext.Provider>
2932
</Demo>
3033
</Story>
3134
</Preview>
3235

3336
<Preview>
3437
<Story name='Input Multiline'>
3538
<Demo visible={boolean('visible', true) ? 1 : 0}>
36-
{UiKitModal([{
39+
<kitContext.Provider value={{...defaultContext, errors: {'input-test': text('error', 'asdas') } }}>
40+
<UiKitComponent render={UiKitModal} blocks= {[{
3741
"type": "input",
3842
"element": {
3943
"type": "plain_text_input",
40-
"multiline": true
44+
"multiline": true,
45+
"actionId": "input-test"
4146
},
4247
"label": {
4348
"type": "plain_text",
4449
"text": "Label",
4550
"emoji": true
4651
}
47-
}])}
52+
}]}/>
53+
</kitContext.Provider>
4854
</Demo>
4955
</Story>
5056
</Preview>
@@ -54,23 +60,27 @@ import { withKnobs, text, boolean, number } from "@storybook/addon-knobs";
5460
<Preview>
5561
<Story name='Input Datepicker'>
5662
<Demo visible={boolean('visible', true) ? 1 : 0}>
57-
{UiKitModal([{
58-
"type": "input",
59-
"element": {
60-
"type": "datepicker",
61-
"initial_date": "1990-04-28",
62-
"placeholder": {
63-
"type": "plain_text",
64-
"text": "Select a date",
65-
"emoji": true
66-
}
67-
},
68-
"label": {
69-
"type": "plain_text",
70-
"text": "Label",
71-
"emoji": true
72-
}
73-
}])}
63+
<kitContext.Provider value={{...defaultContext, errors: {'input-test': text('error', 'asdas') } }}>
64+
<UiKitComponent render={UiKitModal} blocks= {[{
65+
"type": "input",
66+
"element": {
67+
"type": "datepicker",
68+
"initial_date": "1990-04-28",
69+
"actionId": "input-test",
70+
"placeholder": {
71+
"type": "plain_text",
72+
"text": "Select a date",
73+
"emoji": true
74+
}
75+
},
76+
"label": {
77+
"type": "plain_text",
78+
"text": "Label",
79+
"emoji": true
80+
}
81+
}
82+
]}/>
83+
</kitContext.Provider>
7484
</Demo>
7585
</Story>
7686
</Preview>

packages/fuselage-ui-kit/src/index.js

+18-7
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,26 @@ export const defaultContext = {
3535
action: (...args) => console.log(JSON.stringify(args)),
3636
state: console.log,
3737
appId: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
38+
errors: {}
3839
};
3940

4041
export const kitContext = React.createContext(defaultContext);
4142

42-
const useBlockContext = ({ blockId, actionId, appId, initialValue }, context) => {
43+
export const useBlockContext = ({ blockId, actionId, appId, initialValue }, context) => {
4344
const [value, setValue] = useState(initialValue);
4445
const [loading, setLoading] = useState(false);
45-
const { action, appId: appIdFromContext, state } = useContext(kitContext);
46+
const { action, appId: appIdFromContext, state, errors } = useContext(kitContext);
47+
const error = errors && actionId && errors[actionId];
48+
4649
if ([BLOCK_CONTEXT.SECTION, BLOCK_CONTEXT.ACTION].includes(context)) {
47-
return [{ loading, setLoading }, async ({ target: { value } }) => {
50+
return [{ loading, setLoading, error }, async ({ target: { value } }) => {
4851
setLoading(true);
4952
await action({ blockId, appId: appId || appIdFromContext, actionId, value });
5053
setLoading(false);
5154
}];
5255
}
5356

54-
return [{ loading, setLoading, value }, async ({ target: { value } }) => {
57+
return [{ loading, setLoading, value, error }, async ({ target: { value } }) => {
5558
setValue(value);
5659
setLoading(true);
5760
await state({ blockId, appId, actionId, value });
@@ -156,11 +159,12 @@ class MessageParser extends UiKitParserMessage {
156159
}
157160

158161
datePicker(element, context, key) {
159-
const [{ loading, value }, action] = useBlockContext(element, context);
162+
const [{ loading, value, error }, action] = useBlockContext(element, context);
160163
const { actionId, placeholder } = element;
161164
return (
162165
<InputBox
163166
key={key}
167+
error={error}
164168
value={value}
165169
mod-mod-loading={loading}
166170
id={actionId}
@@ -244,12 +248,16 @@ class ModalParser extends UiKitParserModal {
244248
});
245249
}
246250

247-
input({ element, label, blockId, appId }, context, index) {
251+
input({ element, label, blockId, appId, ...args }, context, index) {
252+
const [{ loading, value, error }, action] = useBlockContext({ ...element, appId, blockId }, context);
253+
248254
return (
249255
<InputLayoutBlock
256+
error={error}
250257
key={index}
251258
index={index}
252259
parser={this}
260+
context={context}
253261
element={{ ...element, appId, blockId }}
254262
label={this.plainText(label)}
255263
/>
@@ -261,7 +269,7 @@ class ModalParser extends UiKitParserModal {
261269
}
262270

263271
plainInput(element, context, index) {
264-
const [{ loading, value }, action] = useBlockContext(element, context);
272+
const [{ loading, value, error }, action] = useBlockContext(element, context);
265273
const { multiline, actionId, placeholder } = element;
266274
const Component = multiline ? TextAreaInput : TextInput;
267275
return (
@@ -271,6 +279,7 @@ class ModalParser extends UiKitParserModal {
271279
id={actionId}
272280
name={actionId}
273281
rows={6}
282+
error={error}
274283
value={value}
275284
onInput={action}
276285
placeholder={this.plainText(placeholder)}
@@ -288,3 +297,5 @@ export const UiKitButtons = uiKitButtons();
288297
export const UiKitText = uiKitText(textParser);
289298
export const UiKitMessage = uiKitMessage(messageParser);
290299
export const UiKitModal = uiKitModal(modalParser);
300+
301+
export const UiKitComponent = ({render, blocks}) => render(blocks);

0 commit comments

Comments
 (0)