mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
grafana/ui: Unify disabled styles for input components (#34126)
* Select: Add disabled prop to SingleValue * TagsInput: Disable remove button with disabled prop * Checkbox: Add disabled styles
This commit is contained in:
parent
1367f7171e
commit
65cacd31c2
@ -1,7 +1,7 @@
|
|||||||
import React, { HTMLProps, useCallback } from 'react';
|
import React, { HTMLProps, useCallback } from 'react';
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { getLabelStyles } from './Label';
|
import { getLabelStyles } from './Label';
|
||||||
import { useTheme2, stylesFactory } from '../../themes';
|
import { stylesFactory, useStyles2 } from '../../themes';
|
||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
||||||
|
|
||||||
@ -11,6 +11,37 @@ export interface CheckboxProps extends Omit<HTMLProps<HTMLInputElement>, 'value'
|
|||||||
value?: boolean;
|
value?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
||||||
|
({ label, description, value, onChange, disabled, className, ...inputProps }, ref) => {
|
||||||
|
const handleOnChange = useCallback(
|
||||||
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (onChange) {
|
||||||
|
onChange(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onChange]
|
||||||
|
);
|
||||||
|
const styles = useStyles2(getCheckboxStyles);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label className={cx(styles.wrapper, className)}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className={styles.input}
|
||||||
|
checked={value}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={handleOnChange}
|
||||||
|
{...inputProps}
|
||||||
|
ref={ref}
|
||||||
|
/>
|
||||||
|
<span className={styles.checkmark} />
|
||||||
|
{label && <span className={styles.label}>{label}</span>}
|
||||||
|
{description && <span className={styles.description}>{description}</span>}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||||
const labelStyles = getLabelStyles(theme);
|
const labelStyles = getLabelStyles(theme);
|
||||||
const checkboxSize = '16px';
|
const checkboxSize = '16px';
|
||||||
@ -79,6 +110,18 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:disabled + span {
|
||||||
|
background-color: ${theme.colors.action.disabledBackground};
|
||||||
|
cursor: not-allowed;
|
||||||
|
&:hover {
|
||||||
|
background-color: ${theme.colors.action.disabledBackground};
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
border-color: ${theme.colors.action.disabledText};
|
||||||
|
}
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
checkmark: css`
|
checkmark: css`
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -100,36 +143,4 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
|
||||||
({ label, description, value, onChange, disabled, className, ...inputProps }, ref) => {
|
|
||||||
const theme = useTheme2();
|
|
||||||
const handleOnChange = useCallback(
|
|
||||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
if (onChange) {
|
|
||||||
onChange(e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[onChange]
|
|
||||||
);
|
|
||||||
const styles = getCheckboxStyles(theme);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<label className={cx(styles.wrapper, className)}>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
className={styles.input}
|
|
||||||
checked={value}
|
|
||||||
disabled={disabled}
|
|
||||||
onChange={handleOnChange}
|
|
||||||
{...inputProps}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
<span className={styles.checkmark} />
|
|
||||||
{label && <span className={styles.label}>{label}</span>}
|
|
||||||
{description && <span className={styles.description}>{description}</span>}
|
|
||||||
</label>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Checkbox.displayName = 'Checkbox';
|
Checkbox.displayName = 'Checkbox';
|
||||||
|
@ -314,7 +314,9 @@ export function SelectBase<T>({
|
|||||||
DropdownIndicator(props: any) {
|
DropdownIndicator(props: any) {
|
||||||
return <DropdownIndicator isOpen={props.selectProps.menuIsOpen} />;
|
return <DropdownIndicator isOpen={props.selectProps.menuIsOpen} />;
|
||||||
},
|
},
|
||||||
SingleValue: SingleValue,
|
SingleValue(props: any) {
|
||||||
|
return <SingleValue {...props} disabled={disabled} />;
|
||||||
|
},
|
||||||
MultiValueContainer: MultiValueContainer,
|
MultiValueContainer: MultiValueContainer,
|
||||||
MultiValueRemove: MultiValueRemove,
|
MultiValueRemove: MultiValueRemove,
|
||||||
...components,
|
...components,
|
||||||
|
@ -34,7 +34,11 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return { singleValue, container, item };
|
const disabled = css`
|
||||||
|
color: ${theme.colors.action.disabledText};
|
||||||
|
`;
|
||||||
|
|
||||||
|
return { singleValue, container, item, disabled };
|
||||||
};
|
};
|
||||||
|
|
||||||
type StylesType = ReturnType<typeof getStyles>;
|
type StylesType = ReturnType<typeof getStyles>;
|
||||||
@ -44,17 +48,18 @@ interface Props
|
|||||||
imgUrl?: string;
|
imgUrl?: string;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
hideText?: boolean;
|
hideText?: boolean;
|
||||||
}> {}
|
}> {
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export const SingleValue = (props: Props) => {
|
export const SingleValue = (props: Props) => {
|
||||||
const { children, data } = props;
|
const { children, data, disabled } = props;
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
const loading = useDelayedSwitch(data.loading || false, { delay: 250, duration: 750 });
|
const loading = useDelayedSwitch(data.loading || false, { delay: 250, duration: 750 });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<components.SingleValue {...props}>
|
<components.SingleValue {...props}>
|
||||||
<div className={cx(styles.singleValue)}>
|
<div className={cx(styles.singleValue, disabled && styles.disabled)}>
|
||||||
{data.imgUrl ? (
|
{data.imgUrl ? (
|
||||||
<FadeWithImage loading={loading} imgUrl={data.imgUrl} styles={styles} />
|
<FadeWithImage loading={loading} imgUrl={data.imgUrl} styles={styles} />
|
||||||
) : (
|
) : (
|
||||||
|
@ -32,6 +32,9 @@ export const TagsInput: FC<Props> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onRemove = (tagToRemove: string) => {
|
const onRemove = (tagToRemove: string) => {
|
||||||
|
if (disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
onChange(tags?.filter((x) => x !== tagToRemove));
|
onChange(tags?.filter((x) => x !== tagToRemove));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user