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 { GrafanaTheme2 } from '@grafana/data';
|
||||
import { getLabelStyles } from './Label';
|
||||
import { useTheme2, stylesFactory } from '../../themes';
|
||||
import { stylesFactory, useStyles2 } from '../../themes';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
||||
|
||||
@ -11,6 +11,37 @@ export interface CheckboxProps extends Omit<HTMLProps<HTMLInputElement>, 'value'
|
||||
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) => {
|
||||
const labelStyles = getLabelStyles(theme);
|
||||
const checkboxSize = '16px';
|
||||
@ -79,6 +110,18 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
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`
|
||||
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';
|
||||
|
@ -314,7 +314,9 @@ export function SelectBase<T>({
|
||||
DropdownIndicator(props: any) {
|
||||
return <DropdownIndicator isOpen={props.selectProps.menuIsOpen} />;
|
||||
},
|
||||
SingleValue: SingleValue,
|
||||
SingleValue(props: any) {
|
||||
return <SingleValue {...props} disabled={disabled} />;
|
||||
},
|
||||
MultiValueContainer: MultiValueContainer,
|
||||
MultiValueRemove: MultiValueRemove,
|
||||
...components,
|
||||
|
@ -34,7 +34,11 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
position: absolute;
|
||||
`;
|
||||
|
||||
return { singleValue, container, item };
|
||||
const disabled = css`
|
||||
color: ${theme.colors.action.disabledText};
|
||||
`;
|
||||
|
||||
return { singleValue, container, item, disabled };
|
||||
};
|
||||
|
||||
type StylesType = ReturnType<typeof getStyles>;
|
||||
@ -44,17 +48,18 @@ interface Props
|
||||
imgUrl?: string;
|
||||
loading?: boolean;
|
||||
hideText?: boolean;
|
||||
}> {}
|
||||
}> {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export const SingleValue = (props: Props) => {
|
||||
const { children, data } = props;
|
||||
const { children, data, disabled } = props;
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const loading = useDelayedSwitch(data.loading || false, { delay: 250, duration: 750 });
|
||||
|
||||
return (
|
||||
<components.SingleValue {...props}>
|
||||
<div className={cx(styles.singleValue)}>
|
||||
<div className={cx(styles.singleValue, disabled && styles.disabled)}>
|
||||
{data.imgUrl ? (
|
||||
<FadeWithImage loading={loading} imgUrl={data.imgUrl} styles={styles} />
|
||||
) : (
|
||||
|
@ -32,6 +32,9 @@ export const TagsInput: FC<Props> = ({
|
||||
};
|
||||
|
||||
const onRemove = (tagToRemove: string) => {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
onChange(tags?.filter((x) => x !== tagToRemove));
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user