diff --git a/packages/grafana-ui/src/components/Forms/Checkbox.mdx b/packages/grafana-ui/src/components/Forms/Checkbox.mdx
index 836c39381fe..6ae0beee73e 100644
--- a/packages/grafana-ui/src/components/Forms/Checkbox.mdx
+++ b/packages/grafana-ui/src/components/Forms/Checkbox.mdx
@@ -9,22 +9,27 @@ import { Checkbox } from './Checkbox';
Checked represents true, un-checked represent false. So you can use them to select a binary option or multiple options in a set. `Checkbox` can be used in groups, where the single checkboxes have no dependencies. That means that selecting one doesn’t affect any other `Checkbox`. When adding a description to your `Checkbox`, write positive statements so that "checked" means "yes" and not "no". That way, you can avoid confusion.
-**DO:** [ ] Hide options
-**DON'T:** [ ] Do not show options
+- **DO:** [ ] Hide options
+- **DON'T:** [ ] Do not show options
Checkboxes typically only trigger changes after sending a form. If your component should trigger a change immediately, it's better to use a toggle switch instead. Furthermore, checkboxes are not mutually exclusive. That means that selecting one will not disable the others or impact them in any other way. If you want to offer a mutually exclusive choice, use `RadioButtonGroup` or a `Select` dropdown.
-**DO:**
-Show series
-[ ] A-series
-[ ] B-series
-[ ] C-series
+**DO:** Show series
-**DON'T:**
-Show only
-[ ] A-series
-[ ] B-series
-[ ] C-series
+- [ ] A-series
+- [ ] B-series
+- [ ] C-series
+
+**DON'T:** Show only
+
+- [ ] A-series
+- [ ] B-series
+- [ ] C-series
+
+The indeterminate state of the checkbox should be used when there is a group of child checkboxes that are in a mix of checked and unchecked states. For instance when you have a list of checkboxes representing the columns of a table, and you want to allow the user to select which columns to display. If some of the columns are checked, and some are unchecked, then the parent checkbox should be in an indeterminate state. If all the columns are checked, then the parent should be checked. If none of the columns are checked, then the parent should be unchecked.
+It is discouraged to set both `indeterminate` and `checked` state as a checkboxs emit boolean values which can only ever be TRUE or FALSE, and if something is partially true, then it is false.
+
+- **DON'T:** ``
### Usage
diff --git a/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx b/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx
index 3606cc3d9a2..5d43c643df2 100644
--- a/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx
+++ b/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx
@@ -37,6 +37,7 @@ Basic.args = {
label: 'Skip TLS cert validation',
description: 'Set to true if you want to skip TLS cert validation',
disabled: false,
+ indeterminate: false,
};
export const StackedList = () => {
@@ -78,6 +79,33 @@ InAField.args = {
description:
'Annotation queries can be toggled on or of at the top of the dashboard. With this option checked this toggle will be hidden.',
disabled: false,
+ indeterminate: false,
+};
+
+export const AllStates: ComponentStory = (args) => {
+ const [checked, setChecked] = useState(false);
+ const onChange = useCallback(
+ (e: React.FormEvent) => setChecked(e.currentTarget.checked),
+ [setChecked]
+ );
+
+ return (
+
+
+
+
+
+
+
+
+ );
+};
+
+AllStates.args = {
+ label: 'Props set from controls',
+ description: 'Set to true if you want to skip TLS cert validation',
+ disabled: false,
+ indeterminate: false,
};
export default meta;
diff --git a/packages/grafana-ui/src/components/Forms/Checkbox.tsx b/packages/grafana-ui/src/components/Forms/Checkbox.tsx
index b769c514137..af19c3675f6 100644
--- a/packages/grafana-ui/src/components/Forms/Checkbox.tsx
+++ b/packages/grafana-ui/src/components/Forms/Checkbox.tsx
@@ -9,15 +9,20 @@ import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
import { getLabelStyles } from './Label';
export interface CheckboxProps extends Omit, 'value'> {
+ /** Label to display next to checkbox */
label?: string;
+ /** Description to display under the label */
description?: string;
+ /** Current value of the checkbox */
value?: boolean;
- // htmlValue allows to specify the input "value" attribute
+ /** htmlValue allows to specify the input "value" attribute */
htmlValue?: string | number;
+ /** Sets the checkbox into a "mixed" state. This is only a visual change and does not affect the value. */
+ indeterminate?: boolean;
}
export const Checkbox = React.forwardRef(
- ({ label, description, value, htmlValue, onChange, disabled, className, ...inputProps }, ref) => {
+ ({ label, description, value, htmlValue, onChange, disabled, className, indeterminate, ...inputProps }, ref) => {
const handleOnChange = useCallback(
(e: React.ChangeEvent) => {
if (onChange) {
@@ -28,16 +33,19 @@ export const Checkbox = React.forwardRef(
);
const styles = useStyles2(getCheckboxStyles);
+ const ariaChecked = indeterminate ? 'mixed' : undefined;
+
return (