Grafana-UI: Add disabled state to picker components (#34005)

* TimeRangeInput: add disabled prop

* TimeOfDayPicker: add disabled prop

* TimeZonePicker: add disabled prop

* TagsInput: add disabled prop
This commit is contained in:
Alex Khomenko 2021-05-12 18:33:36 +03:00 committed by GitHub
parent 6200c40160
commit 167bad070b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 47 deletions

View File

@ -145,6 +145,10 @@ export const getInputStyles = stylesFactory(({ theme, invalid = false, width }:
inputDisabled: css`
background-color: ${theme.colors.action.disabledBackground};
color: ${theme.colors.action.disabledText};
border: 1px solid ${theme.colors.action.disabledBackground};
&:focus {
box-shadow: none;
}
`,
addon: css`
label: input-addon;

View File

@ -12,6 +12,7 @@ export interface Props {
onChange: (tags: string[]) => void;
width?: number;
className?: string;
disabled?: boolean;
}
export const TagsInput: FC<Props> = ({
@ -20,6 +21,7 @@ export const TagsInput: FC<Props> = ({
onChange,
width,
className,
disabled,
}) => {
const [newTagName, setNewName] = useState('');
const styles = useStyles(getStyles);
@ -58,6 +60,7 @@ export const TagsInput: FC<Props> = ({
</div>
<div>
<Input
disabled={disabled}
placeholder={placeholder}
onChange={onNameChange}
value={newTagName}

View File

@ -2,7 +2,7 @@ import React, { FC } from 'react';
import RcTimePicker from 'rc-time-picker';
import { css, cx } from '@emotion/css';
import { dateTime, DateTime, dateTimeAsMoment, GrafanaTheme } from '@grafana/data';
import { useTheme, Icon } from '../../index';
import { Icon, useStyles } from '../../index';
import { stylesFactory } from '../../themes';
import { inputSizes } from '../Forms/commonStyles';
import { FormInputSize } from '../Forms/types';
@ -14,8 +14,48 @@ export interface Props {
showHour?: boolean;
minuteStep?: number;
size?: FormInputSize;
disabled?: boolean;
}
export const TimeOfDayPicker: FC<Props> = ({
minuteStep = 1,
showHour = true,
onChange,
value,
size = 'auto',
disabled,
}) => {
const styles = useStyles(getStyles);
return (
<RcTimePicker
className={cx(inputSizes()[size], styles.input)}
popupClassName={styles.picker}
defaultValue={dateTimeAsMoment()}
onChange={(value: any) => onChange(dateTime(value))}
allowEmpty={false}
showSecond={false}
value={dateTimeAsMoment(value)}
showHour={showHour}
minuteStep={minuteStep}
inputIcon={<Caret wrapperStyle={styles.caretWrapper} />}
disabled={disabled}
/>
);
};
interface CaretProps {
wrapperStyle?: string;
}
const Caret: FC<CaretProps> = ({ wrapperStyle = '' }) => {
return (
<div className={wrapperStyle}>
<Icon name="angle-down" />
</div>
);
};
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const bgColor = theme.colors.formInputBg;
const menuShadowColor = theme.colors.dropdownShadow;
@ -79,40 +119,16 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
&:focus {
${focusCss(theme)}
}
&:disabled {
background-color: ${theme.colors.formInputBgDisabled};
color: ${theme.colors.formInputDisabledText};
border: 1px solid ${theme.colors.formInputBgDisabled};
&:focus {
box-shadow: none;
}
}
}
`,
};
});
export const TimeOfDayPicker: FC<Props> = ({ minuteStep = 1, showHour = true, onChange, value, size = 'auto' }) => {
const theme = useTheme();
const styles = getStyles(theme);
return (
<div>
<RcTimePicker
className={cx(inputSizes()[size], styles.input)}
popupClassName={styles.picker}
defaultValue={dateTimeAsMoment()}
onChange={(value: any) => onChange(dateTime(value))}
allowEmpty={false}
showSecond={false}
value={dateTimeAsMoment(value)}
showHour={showHour}
minuteStep={minuteStep}
inputIcon={<Caret wrapperStyle={styles.caretWrapper} />}
/>
</div>
);
};
interface CaretProps {
wrapperStyle?: string;
}
const Caret: FC<CaretProps> = ({ wrapperStyle = '' }) => {
return (
<div className={wrapperStyle}>
<Icon name="angle-down" />
</div>
);
};

View File

@ -1,15 +1,15 @@
import React, { FC, FormEvent, MouseEvent, useState } from 'react';
import { css, cx } from '@emotion/css';
import { dateMath, dateTime, getDefaultTimeRange, GrafanaTheme2, TimeRange, TimeZone } from '@grafana/data';
import { useStyles2 } from '../../themes/ThemeContext';
import { useTheme2 } from '../../themes/ThemeContext';
import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper';
import { Icon } from '../Icon/Icon';
import { getInputStyles } from '../Input/Input';
import { getFocusStyle } from '../Forms/commonStyles';
import { TimePickerButtonLabel } from './TimeRangePicker';
import { TimePickerContent } from './TimeRangePicker/TimePickerContent';
import { otherOptions, quickOptions } from './rangeOptions';
import { selectors } from '@grafana/e2e-selectors';
import { stylesFactory } from '../../themes';
const isValidTimeRange = (range: any) => {
return dateMath.isValid(range.from) && dateMath.isValid(range.to);
@ -25,6 +25,7 @@ export interface TimeRangeInputProps {
clearable?: boolean;
isReversed?: boolean;
hideQuickRanges?: boolean;
disabled?: boolean;
}
const noop = () => {};
@ -39,13 +40,18 @@ export const TimeRangeInput: FC<TimeRangeInputProps> = ({
placeholder = 'Select time range',
isReversed = true,
hideQuickRanges = false,
disabled = false,
}) => {
const [isOpen, setIsOpen] = useState(false);
const styles = useStyles2(getStyles);
const theme = useTheme2();
const styles = getStyles(theme, disabled);
const onOpen = (event: FormEvent<HTMLDivElement>) => {
event.stopPropagation();
event.preventDefault();
if (disabled) {
return;
}
setIsOpen(!isOpen);
};
@ -79,12 +85,14 @@ export const TimeRangeInput: FC<TimeRangeInputProps> = ({
<span className={styles.placeholder}>{placeholder}</span>
)}
{!disabled && (
<span className={styles.caretIcon}>
{isValidTimeRange(value) && clearable && (
<Icon className={styles.clearIcon} name="times" size="lg" onClick={onRangeClear} />
)}
<Icon name={isOpen ? 'angle-up' : 'angle-down'} size="lg" />
</span>
)}
</div>
{isOpen && (
<ClickOutsideWrapper includeButtonPress={false} onClick={onClose}>
@ -106,7 +114,7 @@ export const TimeRangeInput: FC<TimeRangeInputProps> = ({
);
};
const getStyles = (theme: GrafanaTheme2) => {
const getStyles = stylesFactory((theme: GrafanaTheme2, disabled = false) => {
const inputStyles = getInputStyles({ theme, invalid: false });
return {
container: css`
@ -118,6 +126,7 @@ const getStyles = (theme: GrafanaTheme2) => {
`,
pickerInput: cx(
inputStyles.input,
disabled && inputStyles.inputDisabled,
inputStyles.wrapper,
css`
display: flex;
@ -126,7 +135,6 @@ const getStyles = (theme: GrafanaTheme2) => {
cursor: pointer;
padding-right: 0;
line-height: ${theme.v1.spacing.formInputHeight - 2}px;
${getFocusStyle(theme.v1)};
`
),
caretIcon: cx(
@ -147,4 +155,4 @@ const getStyles = (theme: GrafanaTheme2) => {
opacity: 1;
`,
};
};
});

View File

@ -21,10 +21,11 @@ export interface Props {
autoFocus?: boolean;
onBlur?: () => void;
includeInternal?: boolean;
disabled?: boolean;
}
export const TimeZonePicker: React.FC<Props> = (props) => {
const { onChange, width, autoFocus = false, onBlur, value, includeInternal = false } = props;
const { onChange, width, autoFocus = false, onBlur, value, includeInternal = false, disabled = false } = props;
const groupedTimeZones = useTimeZones(includeInternal);
const selected = useSelectedTimeZone(groupedTimeZones, value);
const filterBySearchIndex = useFilterBySearchIndex();
@ -52,6 +53,7 @@ export const TimeZonePicker: React.FC<Props> = (props) => {
onChange={onChangeTz}
onBlur={onBlur}
components={{ Option: TimeZoneOption, Group: TimeZoneGroup }}
disabled={disabled}
/>
);
};