mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Grafana UI: Add invalid state to Checkbox component (#68242)
This commit is contained in:
parent
f515d2efac
commit
4cf77424fd
@ -38,6 +38,7 @@ Basic.args = {
|
||||
description: 'Set to true if you want to skip TLS cert validation',
|
||||
disabled: false,
|
||||
indeterminate: false,
|
||||
invalid: false,
|
||||
};
|
||||
|
||||
export const StackedList = () => {
|
||||
@ -80,6 +81,7 @@ InAField.args = {
|
||||
'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,
|
||||
invalid: false,
|
||||
};
|
||||
|
||||
export const AllStates: StoryFn<typeof Checkbox> = (args) => {
|
||||
@ -96,6 +98,8 @@ export const AllStates: StoryFn<typeof Checkbox> = (args) => {
|
||||
<Checkbox value={true} label="Checked" />
|
||||
<Checkbox value={false} label="Unchecked" />
|
||||
<Checkbox value={false} indeterminate={true} label="Interdeterminate" />
|
||||
<Checkbox value={false} invalid={true} label="Invalid and unchecked" />
|
||||
<Checkbox value={true} invalid={true} label="Invalid and checked" />
|
||||
</VerticalGroup>
|
||||
</div>
|
||||
);
|
||||
@ -106,6 +110,7 @@ AllStates.args = {
|
||||
description: 'Set to true if you want to skip TLS cert validation',
|
||||
disabled: false,
|
||||
indeterminate: false,
|
||||
invalid: false,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
@ -3,7 +3,7 @@ import React, { HTMLProps, useCallback } from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import { stylesFactory, useStyles2 } from '../../themes';
|
||||
import { useTheme2 } from '../../themes';
|
||||
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
||||
|
||||
import { getLabelStyles } from './Label';
|
||||
@ -19,10 +19,15 @@ export interface CheckboxProps extends Omit<HTMLProps<HTMLInputElement>, 'value'
|
||||
htmlValue?: string | number;
|
||||
/** Sets the checkbox into a "mixed" state. This is only a visual change and does not affect the value. */
|
||||
indeterminate?: boolean;
|
||||
/** Show an invalid state around the input */
|
||||
invalid?: boolean;
|
||||
}
|
||||
|
||||
export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
({ label, description, value, htmlValue, onChange, disabled, className, indeterminate, ...inputProps }, ref) => {
|
||||
(
|
||||
{ label, description, value, htmlValue, onChange, disabled, className, indeterminate, invalid, ...inputProps },
|
||||
ref
|
||||
) => {
|
||||
const handleOnChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (onChange) {
|
||||
@ -31,7 +36,8 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
const styles = useStyles2(getCheckboxStyles);
|
||||
const theme = useTheme2();
|
||||
const styles = getCheckboxStyles(theme, invalid);
|
||||
|
||||
const ariaChecked = indeterminate ? 'mixed' : undefined;
|
||||
|
||||
@ -58,11 +64,15 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
}
|
||||
);
|
||||
|
||||
export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
export const getCheckboxStyles = (theme: GrafanaTheme2, invalid = false) => {
|
||||
const labelStyles = getLabelStyles(theme);
|
||||
const checkboxSize = 2;
|
||||
const labelPadding = 1;
|
||||
|
||||
const getBorderColor = (color: string) => {
|
||||
return invalid ? theme.colors.error.border : color;
|
||||
};
|
||||
|
||||
return {
|
||||
wrapper: css`
|
||||
display: inline-grid;
|
||||
@ -96,7 +106,7 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
* */
|
||||
&:checked + span {
|
||||
background: ${theme.colors.primary.main};
|
||||
border: none;
|
||||
border: 1px solid ${getBorderColor(theme.colors.primary.main)};
|
||||
|
||||
&:hover {
|
||||
background: ${theme.colors.primary.shade};
|
||||
@ -106,8 +116,8 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
left: 5px;
|
||||
top: 1px;
|
||||
left: 4px;
|
||||
top: 0px;
|
||||
width: 6px;
|
||||
height: 12px;
|
||||
border: solid ${theme.colors.primary.contrastText};
|
||||
@ -119,6 +129,7 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
&:disabled + span {
|
||||
background-color: ${theme.colors.action.disabledBackground};
|
||||
cursor: not-allowed;
|
||||
border: 1px solid ${getBorderColor(theme.colors.action.disabledBackground)};
|
||||
|
||||
&:hover {
|
||||
background-color: ${theme.colors.action.disabledBackground};
|
||||
@ -132,7 +143,7 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
|
||||
inputIndeterminate: css`
|
||||
&[aria-checked='mixed'] + span {
|
||||
border: none;
|
||||
border: 1px solid ${getBorderColor(theme.colors.primary.main)};
|
||||
background: ${theme.colors.primary.main};
|
||||
|
||||
&:hover {
|
||||
@ -143,8 +154,8 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
left: 3px;
|
||||
right: 3px;
|
||||
left: 2px;
|
||||
right: 2px;
|
||||
top: calc(50% - 1.5px);
|
||||
height: 3px;
|
||||
border: 1.5px solid ${theme.colors.primary.contrastText};
|
||||
@ -155,6 +166,7 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
}
|
||||
&:disabled[aria-checked='mixed'] + span {
|
||||
background-color: ${theme.colors.action.disabledBackground};
|
||||
border: 1px solid ${getBorderColor(theme.colors.error.transparent)};
|
||||
|
||||
&:after {
|
||||
border-color: ${theme.colors.action.disabledText};
|
||||
@ -176,11 +188,11 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
height: ${theme.spacing(checkboxSize)};
|
||||
border-radius: ${theme.shape.borderRadius()};
|
||||
background: ${theme.components.input.background};
|
||||
border: 1px solid ${theme.components.input.borderColor};
|
||||
border: 1px solid ${getBorderColor(theme.components.input.borderColor)};
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
border-color: ${theme.components.input.borderHover};
|
||||
border-color: ${getBorderColor(theme.components.input.borderHover)};
|
||||
}
|
||||
`,
|
||||
label: cx(
|
||||
@ -206,6 +218,6 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
`
|
||||
),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
Checkbox.displayName = 'Checkbox';
|
||||
|
Loading…
Reference in New Issue
Block a user