InlineSwitch: Added missing InlineSwitch component and fixed two places that used unaligned inline switch (#30162)

* InlineSwitch: Added missing InlineSwitch component and fixed two places that used unaligned inline switch

* Fixed e2e tests
This commit is contained in:
Torkel Ödegaard 2021-01-11 10:50:17 +01:00 committed by GitHub
parent 549587a3c1
commit 314865dd88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 97 additions and 81 deletions

View File

@ -66,27 +66,11 @@ describe('Variables - Add variable', () => {
.within(select => {
e2e.components.Select.singleValue().should('have.text', 'Disabled');
});
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsMultiSwitch()
.should('be.visible')
.within(select => {
e2e()
.get('input')
.should('not.be.checked');
});
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsIncludeAllSwitch()
.should('be.visible')
.within(select => {
e2e()
.get('input')
.should('not.be.checked');
});
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.valueGroupsTagsEnabledSwitch()
.should('be.visible')
.within(select => {
e2e()
.get('input')
.should('not.be.checked');
});
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsMultiSwitch().should('not.be.checked');
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsIncludeAllSwitch().should('not.be.checked');
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.valueGroupsTagsEnabledSwitch().should('not.be.checked');
e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().should('not.exist');
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsCustomAllInput().should('not.exist');
});
@ -190,7 +174,7 @@ describe('Variables - Add variable', () => {
.blur();
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsMultiSwitch()
.click()
.click({ force: true })
.within(() => {
e2e()
.get('input')
@ -198,7 +182,7 @@ describe('Variables - Add variable', () => {
});
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsIncludeAllSwitch()
.click()
.click({ force: true })
.within(() => {
e2e()
.get('input')

View File

@ -6,7 +6,6 @@ import { getFieldValidationMessageStyles } from './FieldValidationMessage';
import { getButtonStyles, ButtonVariant } from '../Button';
import { ComponentSize } from '../../types/size';
import { getInputStyles } from '../Input/Input';
import { getSwitchStyles } from '../Switch/Switch';
import { getCheckboxStyles } from './Checkbox';
export const getFormStyles = stylesFactory(
@ -23,7 +22,6 @@ export const getFormStyles = stylesFactory(
hasText: true,
}),
input: getInputStyles({ theme, invalid: options.invalid }),
switch: getSwitchStyles(theme),
checkbox: getCheckboxStyles(theme),
};
}

View File

@ -22,3 +22,9 @@ import { Switch } from '@grafana/ui';
### Props
<Props of={Switch} />
# InlineSwitch
### When to use
Same as for Switch but for inline forms.

View File

@ -1,8 +1,10 @@
import React, { useState, useCallback } from 'react';
import { boolean } from '@storybook/addon-knobs';
import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory';
import { Switch } from '@grafana/ui';
import { InlineField, Switch, InlineSwitch } from '@grafana/ui';
import mdx from './Switch.mdx';
import { InlineFieldRow } from '../Forms/InlineFieldRow';
import { Field } from '../Forms/Field';
export default {
title: 'Forms/Switch',
@ -20,7 +22,23 @@ export const Controlled = () => {
const onChange = useCallback(e => setChecked(e.currentTarget.checked), [setChecked]);
const BEHAVIOUR_GROUP = 'Behaviour props';
const disabled = boolean('Disabled', false, BEHAVIOUR_GROUP);
return <Switch value={checked} disabled={disabled} onChange={onChange} />;
return (
<div>
<p>
<Field label="Normal switch" description="For horizontal forms">
<Switch value={checked} disabled={disabled} onChange={onChange} />
</Field>
</p>
<p>
<InlineFieldRow>
<InlineField label="My switch">
<InlineSwitch value={checked} disabled={disabled} onChange={onChange} />
</InlineField>
</InlineFieldRow>
</p>
</div>
);
};
export const Uncontrolled = () => {

View File

@ -5,11 +5,55 @@ import { GrafanaTheme, deprecationWarning } from '@grafana/data';
import { stylesFactory, useTheme } from '../../themes';
import { focusCss } from '../../themes/mixins';
export interface SwitchProps extends Omit<HTMLProps<HTMLInputElement>, 'value'> {
export interface Props extends Omit<HTMLProps<HTMLInputElement>, 'value'> {
value?: boolean;
}
export const getSwitchStyles = stylesFactory((theme: GrafanaTheme) => {
export const Switch = React.forwardRef<HTMLInputElement, Props>(
({ value, checked, disabled = false, onChange, id, ...inputProps }, ref) => {
if (checked) {
deprecationWarning('Switch', 'checked prop', 'value');
}
const theme = useTheme();
const styles = getSwitchStyles(theme);
const switchIdRef = useRef(id ? id : uniqueId('switch-'));
return (
<div className={cx(styles.switch)}>
<input
type="checkbox"
disabled={disabled}
checked={value}
onChange={event => {
onChange?.(event);
}}
id={switchIdRef.current}
{...inputProps}
ref={ref}
/>
<label htmlFor={switchIdRef.current} />
</div>
);
}
);
Switch.displayName = 'Switch';
export const InlineSwitch = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
const theme = useTheme();
const styles = getSwitchStyles(theme);
return (
<div className={styles.inlineContainer}>
<Switch {...props} ref={ref} />
</div>
);
});
InlineSwitch.displayName = 'Switch';
const getSwitchStyles = stylesFactory((theme: GrafanaTheme) => {
return {
switch: css`
width: 32px;
@ -71,36 +115,14 @@ export const getSwitchStyles = stylesFactory((theme: GrafanaTheme) => {
}
}
`,
inlineContainer: css`
padding: 0 ${theme.spacing.sm};
height: ${theme.spacing.formInputHeight}px;
display: flex;
align-items: center;
background: ${theme.colors.formInputBg};
border: 1px solid ${theme.colors.formInputBorder};
border-radius: ${theme.border.radius.md};
`,
};
});
export const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
({ value, checked, disabled = false, onChange, id, ...inputProps }, ref) => {
if (checked) {
deprecationWarning('Switch', 'checked prop', 'value');
}
const theme = useTheme();
const styles = getSwitchStyles(theme);
const switchIdRef = useRef(id ? id : uniqueId('switch-'));
return (
<div className={cx(styles.switch)}>
<input
type="checkbox"
disabled={disabled}
checked={value}
onChange={event => {
onChange?.(event);
}}
id={switchIdRef.current}
{...inputProps}
ref={ref}
/>
<label htmlFor={switchIdRef.current} />
</div>
);
}
);
Switch.displayName = 'Switch';

View File

@ -168,7 +168,7 @@ export { RadioButtonGroup } from './Forms/RadioButtonGroup/RadioButtonGroup';
export { Input } from './Input/Input';
export { FormInputSize } from './Forms/types';
export { Switch } from './Switch/Switch';
export { Switch, InlineSwitch } from './Switch/Switch';
export { Checkbox } from './Forms/Checkbox';
export { TextArea } from './TextArea/TextArea';

View File

@ -1,8 +1,5 @@
import React, { ChangeEvent, PropsWithChildren, ReactElement } from 'react';
import { InlineField, Switch, useStyles } from '@grafana/ui';
import { GrafanaTheme } from '@grafana/data';
import { css } from 'emotion';
import { InlineField, InlineSwitch } from '@grafana/ui';
interface VariableSwitchFieldProps {
value: boolean;
name: string;
@ -18,22 +15,9 @@ export function VariableSwitchField({
onChange,
ariaLabel,
}: PropsWithChildren<VariableSwitchFieldProps>): ReactElement {
const styles = useStyles(getStyles);
return (
<InlineField label={name} labelWidth={20} tooltip={tooltip}>
<div aria-label={ariaLabel} className={styles.switchContainer}>
<Switch label={name} value={value} onChange={onChange} />
</div>
<InlineSwitch label={name} value={value} onChange={onChange} aria-label={ariaLabel} />
</InlineField>
);
}
function getStyles(theme: GrafanaTheme) {
return {
switchContainer: css`
margin-left: ${theme.spacing.sm};
margin-right: ${theme.spacing.sm};
`,
};
}

View File

@ -1,4 +1,4 @@
import { InlineField, Input, Switch } from '@grafana/ui';
import { InlineField, Input, InlineSwitch } from '@grafana/ui';
import React, { FunctionComponent, ComponentProps, useState } from 'react';
import { extendedStats } from '../../../../query_def';
import { useDispatch } from '../../../../hooks/useStatelessReducer';
@ -132,7 +132,11 @@ const ExtendedStatSetting: FunctionComponent<ExtendedStatSettingProps> = ({ stat
return (
<InlineField label={stat.label} {...inlineFieldProps} key={stat.value}>
<Switch id={id} onChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange(e.target.checked)} value={value} />
<InlineSwitch
id={id}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange(e.target.checked)}
value={value}
/>
</InlineField>
);
};