Skip to content

Commit 36e3732

Browse files
authored
Show description or tooltip on react material boolean controls (#2072)
* Show description or tooltip for checkboxes * Add description to boolean example * Document hardcoded parameters in boolean control * Give toggle booleans the same description treatment as checkboxes
1 parent 3b32c9b commit 36e3732

File tree

3 files changed

+134
-47
lines changed

3 files changed

+134
-47
lines changed

packages/examples/src/examples/control-options.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ export const schema = {
3131
type: 'string'
3232
},
3333
boolean: {
34-
type: 'boolean'
34+
type: 'boolean',
35+
description: 'Boolean description as a tooltip'
3536
},
3637
number: {
3738
type: 'number'

packages/material-renderers/src/controls/MaterialBooleanControl.tsx

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,17 @@
2323
THE SOFTWARE.
2424
*/
2525
import isEmpty from 'lodash/isEmpty';
26+
import merge from 'lodash/merge';
2627
import React from 'react';
2728
import {
2829
isBooleanControl,
2930
RankedTester,
3031
rankWith,
31-
ControlProps
32+
ControlProps,
33+
isDescriptionHidden
3234
} from '@jsonforms/core';
3335
import { withJsonFormsControlProps } from '@jsonforms/react';
34-
import { FormControlLabel, Hidden } from '@mui/material';
36+
import { FormControlLabel, FormHelperText, Tooltip, Hidden } from '@mui/material';
3537
import { MuiCheckbox } from '../mui-controls/MuiCheckbox';
3638

3739
export const MaterialBooleanControl = ({
@@ -46,30 +48,71 @@ export const MaterialBooleanControl = ({
4648
handleChange,
4749
errors,
4850
path,
49-
config
51+
config,
52+
description
5053
}: ControlProps) => {
54+
55+
const isValid = errors.length === 0;
56+
const appliedUiSchemaOptions = merge({}, config, uischema.options);
57+
58+
const showDescription = !isDescriptionHidden(
59+
visible,
60+
description,
61+
// Checkboxes do not receive focus until they are used, so
62+
// we cannot rely on focus as criteria for showing descriptions.
63+
// So we pass "false" to treat it as unfocused.
64+
false,
65+
appliedUiSchemaOptions.showUnfocusedDescription
66+
);
67+
68+
const showTooltip = !showDescription && !isDescriptionHidden(
69+
visible,
70+
description,
71+
// Tooltips have their own focus handlers, so we do not need to rely
72+
// on focus state here. So we pass 'true' to treat it as focused.
73+
true,
74+
// We also pass true here for showUnfocusedDescription since it should
75+
// render regardless of that setting.
76+
true
77+
);
78+
79+
const firstFormHelperText = showDescription
80+
? description
81+
: !isValid
82+
? errors
83+
: null;
84+
const secondFormHelperText = showDescription && !isValid ? errors : null;
85+
5186
return (
5287
<Hidden xsUp={!visible}>
53-
<FormControlLabel
54-
label={label}
55-
id={id}
56-
control={
57-
<MuiCheckbox
58-
id={`${id}-input`}
59-
isValid={isEmpty(errors)}
60-
data={data}
61-
enabled={enabled}
62-
visible={visible}
63-
path={path}
64-
uischema={uischema}
65-
schema={schema}
66-
rootSchema={rootSchema}
67-
handleChange={handleChange}
68-
errors={errors}
69-
config={config}
70-
/>
71-
}
72-
/>
88+
<Tooltip title={(showTooltip) ? description : ''}>
89+
<FormControlLabel
90+
label={label}
91+
id={id}
92+
control={
93+
<MuiCheckbox
94+
id={`${id}-input`}
95+
isValid={isEmpty(errors)}
96+
data={data}
97+
enabled={enabled}
98+
visible={visible}
99+
path={path}
100+
uischema={uischema}
101+
schema={schema}
102+
rootSchema={rootSchema}
103+
handleChange={handleChange}
104+
errors={errors}
105+
config={config}
106+
/>
107+
}
108+
/>
109+
</Tooltip>
110+
<FormHelperText error={!isValid && !showDescription}>
111+
{firstFormHelperText}
112+
</FormHelperText>
113+
<FormHelperText error={!isValid}>
114+
{secondFormHelperText}
115+
</FormHelperText>
73116
</Hidden>
74117
);
75118
};

packages/material-renderers/src/controls/MaterialBooleanToggleControl.tsx

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,19 @@
2323
THE SOFTWARE.
2424
*/
2525
import isEmpty from 'lodash/isEmpty';
26+
import merge from 'lodash/merge';
2627
import React from 'react';
2728
import {
2829
isBooleanControl,
2930
RankedTester,
3031
rankWith,
3132
ControlProps,
3233
optionIs,
33-
and
34+
and,
35+
isDescriptionHidden
3436
} from '@jsonforms/core';
3537
import { withJsonFormsControlProps } from '@jsonforms/react';
36-
import { FormControlLabel, Hidden } from '@mui/material';
38+
import { FormControlLabel, FormHelperText, Tooltip, Hidden } from '@mui/material';
3739
import { MuiToggle } from '../mui-controls/MuiToggle';
3840

3941
export const MaterialBooleanToggleControl = ({
@@ -48,30 +50,71 @@ export const MaterialBooleanToggleControl = ({
4850
handleChange,
4951
errors,
5052
path,
51-
config
53+
config,
54+
description
5255
}: ControlProps) => {
56+
57+
const isValid = errors.length === 0;
58+
const appliedUiSchemaOptions = merge({}, config, uischema.options);
59+
60+
const showDescription = !isDescriptionHidden(
61+
visible,
62+
description,
63+
// Checkboxes do not receive focus until they are used, so
64+
// we cannot rely on focus as criteria for showing descriptions.
65+
// So we pass "false" to treat it as unfocused.
66+
false,
67+
appliedUiSchemaOptions.showUnfocusedDescription
68+
);
69+
70+
const showTooltip = !showDescription && !isDescriptionHidden(
71+
visible,
72+
description,
73+
// Tooltips have their own focus handlers, so we do not need to rely
74+
// on focus state here. So we pass 'true' to treat it as focused.
75+
true,
76+
// We also pass true here for showUnfocusedDescription since it should
77+
// render regardless of that setting.
78+
true
79+
);
80+
81+
const firstFormHelperText = showDescription
82+
? description
83+
: !isValid
84+
? errors
85+
: null;
86+
const secondFormHelperText = showDescription && !isValid ? errors : null;
87+
5388
return (
5489
<Hidden xsUp={!visible}>
55-
<FormControlLabel
56-
label={label}
57-
id={id}
58-
control={
59-
<MuiToggle
60-
id={`${id}-input`}
61-
isValid={isEmpty(errors)}
62-
data={data}
63-
enabled={enabled}
64-
visible={visible}
65-
path={path}
66-
uischema={uischema}
67-
schema={schema}
68-
rootSchema={rootSchema}
69-
handleChange={handleChange}
70-
errors={errors}
71-
config={config}
72-
/>
73-
}
74-
/>
90+
<Tooltip title={(showTooltip) ? description : ''}>
91+
<FormControlLabel
92+
label={label}
93+
id={id}
94+
control={
95+
<MuiToggle
96+
id={`${id}-input`}
97+
isValid={isEmpty(errors)}
98+
data={data}
99+
enabled={enabled}
100+
visible={visible}
101+
path={path}
102+
uischema={uischema}
103+
schema={schema}
104+
rootSchema={rootSchema}
105+
handleChange={handleChange}
106+
errors={errors}
107+
config={config}
108+
/>
109+
}
110+
/>
111+
</Tooltip>
112+
<FormHelperText error={!isValid && !showDescription}>
113+
{firstFormHelperText}
114+
</FormHelperText>
115+
<FormHelperText error={!isValid}>
116+
{secondFormHelperText}
117+
</FormHelperText>
75118
</Hidden>
76119
);
77120
};

0 commit comments

Comments
 (0)