diff --git a/packages/grafana-data/src/types/theme.ts b/packages/grafana-data/src/types/theme.ts
index 6f3ad8ff742..2d7eb3229a7 100644
--- a/packages/grafana-data/src/types/theme.ts
+++ b/packages/grafana-data/src/types/theme.ts
@@ -237,6 +237,10 @@ export interface GrafanaTheme extends GrafanaThemeCommons {
formSwitchBgHover: string;
formSwitchBgDisabled: string;
formSwitchDot: string;
+ formCheckboxBg: string;
+ formCheckboxBgChecked: string;
+ formCheckboxBgCheckedHover: string;
+ formCheckboxCheckmark: string;
};
shadow: {
pageHeader: string;
diff --git a/packages/grafana-ui/src/components/Forms/Checkbox.mdx b/packages/grafana-ui/src/components/Forms/Checkbox.mdx
new file mode 100644
index 00000000000..c74326611d4
--- /dev/null
+++ b/packages/grafana-ui/src/components/Forms/Checkbox.mdx
@@ -0,0 +1,18 @@
+import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
+import { Checkbox } from './Checkbox';
+
+
+
+# Checkbox
+
+### Usage
+
+```jsx
+import { Forms } from '@grafana/ui';
+
+
+```
+
+### Props
+
+
diff --git a/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx b/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx
new file mode 100644
index 00000000000..14f37f09bec
--- /dev/null
+++ b/packages/grafana-ui/src/components/Forms/Checkbox.story.tsx
@@ -0,0 +1,25 @@
+import React, { useState } from 'react';
+import mdx from './Checkbox.mdx';
+import { Checkbox } from './Checkbox';
+
+export default {
+ title: 'UI/Forms/Checkbox',
+ component: Checkbox,
+ parameters: {
+ docs: {
+ page: mdx,
+ },
+ },
+};
+
+export const simple = () => {
+ const [checked, setChecked] = useState(false);
+ return (
+
+ );
+};
diff --git a/packages/grafana-ui/src/components/Forms/Checkbox.tsx b/packages/grafana-ui/src/components/Forms/Checkbox.tsx
new file mode 100644
index 00000000000..13f868ed18a
--- /dev/null
+++ b/packages/grafana-ui/src/components/Forms/Checkbox.tsx
@@ -0,0 +1,129 @@
+import React, { HTMLProps } from 'react';
+import { GrafanaTheme } from '@grafana/data';
+import { getLabelStyles } from './Label';
+import { useTheme, stylesFactory } from '../../themes';
+import { css, cx } from 'emotion';
+import { getFocusCss } from './commonStyles';
+
+export interface CheckboxProps extends Omit, 'onChange' | 'value'> {
+ label?: string;
+ description?: string;
+ value: boolean;
+ onChange?: (checked: boolean) => void;
+}
+
+export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme) => {
+ const labelStyles = getLabelStyles(theme);
+ const checkboxSize = '16px';
+ return {
+ label: cx(
+ labelStyles.label,
+ css`
+ padding-left: ${theme.spacing.formSpacingBase}px;
+ `
+ ),
+ description: cx(
+ labelStyles.description,
+ css`
+ padding-left: ${theme.spacing.formSpacingBase}px;
+ `
+ ),
+ wrapper: css`
+ position: relative;
+ padding-left: ${checkboxSize};
+ `,
+ input: css`
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ &:focus + span {
+ ${getFocusCss(theme)}
+ }
+
+ /**
+ * Using adjacent sibling selector to style checked state.
+ * Primarily to limit the classes necessary to use when these classes will be used
+ * for angular components styling
+ * */
+ &:checked + span {
+ background: blue;
+ background: ${theme.colors.formCheckboxBgChecked};
+ border: none;
+ &:hover {
+ background: ${theme.colors.formCheckboxBgCheckedHover};
+ }
+ &:after {
+ content: '';
+ position: absolute;
+ left: 5px;
+ top: 1px;
+ width: 6px;
+ height: 12px;
+ border: solid ${theme.colors.formCheckboxCheckmark};
+ border-width: 0 3px 3px 0;
+ transform: rotate(45deg);
+ }
+ }
+ `,
+ checkmark: css`
+ display: inline-block;
+ width: ${checkboxSize};
+ height: ${checkboxSize};
+ border-radius: ${theme.border.radius.sm};
+ margin-right: ${theme.spacing.formSpacingBase}px;
+ background: ${theme.colors.formCheckboxBg};
+ border: 1px solid ${theme.colors.formInputBorder};
+ position: absolute;
+ top: 1px;
+ left: 0;
+ &:hover {
+ cursor: pointer;
+ border-color: ${theme.colors.formInputBorderHover};
+ }
+ `,
+ };
+});
+
+export const Checkbox: React.FC = ({
+ label,
+ description,
+ value,
+ onChange,
+ id,
+ disabled,
+ ...inputProps
+}) => {
+ const theme = useTheme();
+ const styles = getCheckboxStyles(theme);
+
+ return (
+
+ );
+};
+
+Checkbox.displayName = 'Checkbox';
diff --git a/packages/grafana-ui/src/components/Forms/Form.story.tsx b/packages/grafana-ui/src/components/Forms/Form.story.tsx
index 8db650c24cc..8396fd60aa3 100644
--- a/packages/grafana-ui/src/components/Forms/Form.story.tsx
+++ b/packages/grafana-ui/src/components/Forms/Form.story.tsx
@@ -9,6 +9,7 @@ import { Button } from './Button';
import { Form } from './Form';
import { Switch } from './Switch';
import { Icon } from '../Icon/Icon';
+import { Checkbox } from './Checkbox';
import { TextArea } from './TextArea/TextArea';
export default {
@@ -22,6 +23,7 @@ export const users = () => {
const [username, setUsername] = useState();
const [password, setPassword] = useState();
const [disabledUser, setDisabledUser] = useState(false);
+ const [checked, setChecked] = useState(false);
return (
<>
@@ -58,6 +60,14 @@ export const users = () => {
setDisabledUser(checked)} />
+
+
+