Commit da6056d5 by Tobias Skarhed Committed by GitHub

Form migrations: Forms/switch move folders (#23430)

* Move legacy Switch

* Move from Forms folder

* Fix prettify issue

* Fix prettify issue
parent ab98a8be
...@@ -2,7 +2,7 @@ import React, { FunctionComponent } from 'react'; ...@@ -2,7 +2,7 @@ import React, { FunctionComponent } from 'react';
import { ColorPickerPopover, ColorPickerProps } from './ColorPickerPopover'; import { ColorPickerPopover, ColorPickerProps } from './ColorPickerPopover';
import { PopoverContentProps } from '../Tooltip/Tooltip'; import { PopoverContentProps } from '../Tooltip/Tooltip';
import { Switch } from '../Switch/Switch'; import { Switch } from '../Forms/Legacy/Switch/Switch';
import { withTheme } from '../../themes/ThemeContext'; import { withTheme } from '../../themes/ThemeContext';
export interface SeriesColorPickerPopoverProps extends ColorPickerProps, PopoverContentProps { export interface SeriesColorPickerPopoverProps extends ColorPickerProps, PopoverContentProps {
......
import React, { ChangeEvent, useContext } from 'react'; import React, { ChangeEvent, useContext } from 'react';
import { DataLink, VariableSuggestion, GrafanaTheme } from '@grafana/data'; import { DataLink, VariableSuggestion, GrafanaTheme } from '@grafana/data';
import { FormField } from '../index'; import { FormField } from '../index';
import { Switch } from '../Switch/Switch'; import { Switch } from '../Forms/Legacy/Switch/Switch';
import { css } from 'emotion'; import { css } from 'emotion';
import { ThemeContext, stylesFactory } from '../../themes/index'; import { ThemeContext, stylesFactory } from '../../themes/index';
import { DataLinkInput } from './DataLinkInput'; import { DataLinkInput } from './DataLinkInput';
......
...@@ -13,7 +13,7 @@ import { Input } from '../Forms/Legacy/Input/Input'; ...@@ -13,7 +13,7 @@ import { Input } from '../Forms/Legacy/Input/Input';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';
import { FormField } from '../FormField/FormField'; import { FormField } from '../FormField/FormField';
import { FormLabel } from '../FormLabel/FormLabel'; import { FormLabel } from '../FormLabel/FormLabel';
import { Switch } from '../Switch/Switch'; import { Switch } from '../Forms/Legacy/Switch/Switch';
import { TagsInput } from '../TagsInput/TagsInput'; import { TagsInput } from '../TagsInput/TagsInput';
const ACCESS_OPTIONS: Array<SelectableValue<string>> = [ const ACCESS_OPTIONS: Array<SelectableValue<string>> = [
......
import React from 'react'; import React from 'react';
import { HttpSettingsBaseProps } from './types'; import { HttpSettingsBaseProps } from './types';
import { Switch } from '../Switch/Switch'; import { Switch } from '../Forms/Legacy/Switch/Switch';
export const HttpProxySettings: React.FC<HttpSettingsBaseProps> = ({ dataSourceConfig, onChange }) => { export const HttpProxySettings: React.FC<HttpSettingsBaseProps> = ({ dataSourceConfig, onChange }) => {
return ( return (
......
...@@ -2,7 +2,7 @@ import React, { useState, useCallback } from 'react'; ...@@ -2,7 +2,7 @@ import React, { useState, useCallback } from 'react';
import { boolean, number, text } from '@storybook/addon-knobs'; import { boolean, number, text } from '@storybook/addon-knobs';
import { Field } from './Field'; import { Field } from './Field';
import { Input } from '../Input/Input'; import { Input } from '../Input/Input';
import { Switch } from './Switch'; import { Switch } from '../Switch/Switch';
import mdx from './Field.mdx'; import mdx from './Field.mdx';
export default { export default {
......
...@@ -7,7 +7,7 @@ import { Field } from './Field'; ...@@ -7,7 +7,7 @@ import { Field } from './Field';
import { Input } from '../Input/Input'; import { Input } from '../Input/Input';
import { Button } from '../Button'; import { Button } from '../Button';
import { Form } from './Form'; import { Form } from './Form';
import { Switch } from './Switch'; import { Switch } from '../Switch/Switch';
import { Checkbox } from './Checkbox'; import { Checkbox } from './Checkbox';
import { RadioButtonGroup } from './RadioButtonGroup/RadioButtonGroup'; import { RadioButtonGroup } from './RadioButtonGroup/RadioButtonGroup';
......
import React, { PureComponent } from 'react';
import uniqueId from 'lodash/uniqueId';
import { Tooltip } from '../../../Tooltip/Tooltip';
import * as PopperJS from 'popper.js';
export interface Props {
label: string;
checked: boolean;
className?: string;
labelClass?: string;
switchClass?: string;
tooltip?: string;
tooltipPlacement?: PopperJS.Placement;
transparent?: boolean;
onChange: (event?: React.SyntheticEvent<HTMLInputElement>) => void;
}
export interface State {
id: string;
}
export class Switch extends PureComponent<Props, State> {
state = {
id: uniqueId(),
};
internalOnChange = (event: React.FormEvent<HTMLInputElement>) => {
event.stopPropagation();
this.props.onChange(event);
};
render() {
const {
labelClass = '',
switchClass = '',
label,
checked,
transparent,
className,
tooltip,
tooltipPlacement,
} = this.props;
const labelId = this.state.id;
const labelClassName = `gf-form-label ${labelClass} ${transparent ? 'gf-form-label--transparent' : ''} pointer`;
const switchClassName = `gf-form-switch ${switchClass} ${transparent ? 'gf-form-switch--transparent' : ''}`;
return (
<div className="gf-form-switch-container-react">
<label htmlFor={labelId} className={`gf-form gf-form-switch-container ${className || ''}`}>
{label && (
<div className={labelClassName}>
{label}
{tooltip && (
<Tooltip placement={tooltipPlacement ? tooltipPlacement : 'auto'} content={tooltip} theme={'info'}>
<div className="gf-form-help-icon gf-form-help-icon--right-normal">
<i className="fa fa-info-circle" />
</div>
</Tooltip>
)}
</div>
)}
<div className={switchClassName}>
<input id={labelId} type="checkbox" checked={checked} onChange={this.internalOnChange} />
<span className="gf-form-switch__slider" />
</div>
</label>
</div>
);
}
}
import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
import { Switch } from "./Switch";
<Meta title="MDX|Switch" component={Switch} />
# Switch
### When to use
`Switch` is a representation of an on-off state – like a light switch. So you can use `Switch` to toggle binary states.
Switches trigger changes immediately. If your component should trigger a change only after sending a form, it's better to use either `RadioButtonGroup` or `Checkbox` instead. Furthermore, switches cannot be grouped – each `Switch` triggers an independent state. If you want multiple mutually exclusive choices, the `RadioButtonGroup` is the better option. To offer multiple choices within the same group or context which are not mutually exclusive, use `Checkbox` instead.
### Usage
```jsx
import { Switch } from '@grafana/ui';
<Switch disabled={...} checked={...} onChange={...} />
```
### Props
<Props of={Switch} />
import React, { HTMLProps } from 'react';
import { css, cx } from 'emotion';
import uniqueId from 'lodash/uniqueId';
import { GrafanaTheme } from '@grafana/data';
import { stylesFactory, useTheme } from '../../themes';
import { getFocusCss } from './commonStyles';
export interface SwitchProps extends Omit<HTMLProps<HTMLInputElement>, 'value'> {
value?: boolean;
}
export const getSwitchStyles = stylesFactory((theme: GrafanaTheme) => {
return {
switch: css`
width: 32px;
height: 16px;
position: relative;
input {
opacity: 0;
left: -100vw;
z-index: -1000;
position: absolute;
&:disabled + label {
background: ${theme.colors.formSwitchBgDisabled};
cursor: not-allowed;
}
&:checked + label {
background: ${theme.colors.formSwitchBgActive};
&:hover {
background: ${theme.colors.formSwitchBgActiveHover};
}
&::after {
transform: translate3d(18px, -50%, 0);
}
}
&:focus + label {
${getFocusCss(theme)};
}
}
label {
width: 100%;
height: 100%;
cursor: pointer;
border: none;
border-radius: 50px;
background: ${theme.colors.formSwitchBg};
transition: all 0.3s ease;
&:hover {
background: ${theme.colors.formSwitchBgHover};
}
&::after {
position: absolute;
display: block;
content: '';
width: 12px;
height: 12px;
border-radius: 6px;
background: ${theme.colors.formSwitchDot};
top: 50%;
transform: translate3d(2px, -50%, 0);
transition: transform 0.2s cubic-bezier(0.19, 1, 0.22, 1);
}
}
}
`,
};
});
export const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
({ value, checked, disabled = false, onChange, ...inputProps }, ref) => {
const theme = useTheme();
const styles = getSwitchStyles(theme);
const switchId = uniqueId('switch-');
return (
<div className={cx(styles.switch)}>
<input
type="checkbox"
disabled={disabled}
checked={value}
onChange={event => {
onChange?.(event);
}}
id={switchId}
{...inputProps}
ref={ref}
/>
<label htmlFor={switchId} />
</div>
);
}
);
...@@ -6,7 +6,7 @@ import { getFieldValidationMessageStyles } from './FieldValidationMessage'; ...@@ -6,7 +6,7 @@ import { getFieldValidationMessageStyles } from './FieldValidationMessage';
import { getButtonStyles, ButtonVariant } from '../Button'; import { getButtonStyles, ButtonVariant } from '../Button';
import { ComponentSize } from '../../types/size'; import { ComponentSize } from '../../types/size';
import { getInputStyles } from '../Input/Input'; import { getInputStyles } from '../Input/Input';
import { getSwitchStyles } from './Switch'; import { getSwitchStyles } from '../Switch/Switch';
import { getCheckboxStyles } from './Checkbox'; import { getCheckboxStyles } from './Checkbox';
export const getFormStyles = stylesFactory( export const getFormStyles = stylesFactory(
......
import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
import { Switch } from "./Switch";
<Meta title="MDX|Switch" component={Switch} />
# Switch # Switch
A basic docs for Switch component ### When to use
`Switch` is a representation of an on-off state – like a light switch. So you can use `Switch` to toggle binary states.
Switches trigger changes immediately. If your component should trigger a change only after sending a form, it's better to use either `RadioButtonGroup` or `Checkbox` instead. Furthermore, switches cannot be grouped – each `Switch` triggers an independent state. If you want multiple mutually exclusive choices, the `RadioButtonGroup` is the better option. To offer multiple choices within the same group or context which are not mutually exclusive, use `Checkbox` instead.
### Usage
```jsx
import { Switch } from '@grafana/ui';
<Switch disabled={...} checked={...} onChange={...} />
```
### Props
<Props of={Switch} />
import React, { PureComponent } from 'react'; import React, { HTMLProps } from 'react';
import { css, cx } from 'emotion';
import uniqueId from 'lodash/uniqueId'; import uniqueId from 'lodash/uniqueId';
import { Tooltip } from '../Tooltip/Tooltip'; import { GrafanaTheme } from '@grafana/data';
import { Icon } from '../Icon/Icon'; import { stylesFactory, useTheme } from '../../themes';
import * as PopperJS from 'popper.js'; import { getFocusCss } from '../Forms/commonStyles';
export interface Props { export interface SwitchProps extends Omit<HTMLProps<HTMLInputElement>, 'value'> {
label: string; value?: boolean;
checked: boolean;
className?: string;
labelClass?: string;
switchClass?: string;
tooltip?: string;
tooltipPlacement?: PopperJS.Placement;
transparent?: boolean;
onChange: (event?: React.SyntheticEvent<HTMLInputElement>) => void;
} }
export interface State { export const getSwitchStyles = stylesFactory((theme: GrafanaTheme) => {
id: string; return {
} switch: css`
width: 32px;
height: 16px;
position: relative;
export class Switch extends PureComponent<Props, State> { input {
state = { opacity: 0;
id: uniqueId(), left: -100vw;
}; z-index: -1000;
position: absolute;
internalOnChange = (event: React.FormEvent<HTMLInputElement>) => { &:disabled + label {
event.stopPropagation(); background: ${theme.colors.formSwitchBgDisabled};
this.props.onChange(event); cursor: not-allowed;
}; }
&:checked + label {
background: ${theme.colors.formSwitchBgActive};
&:hover {
background: ${theme.colors.formSwitchBgActiveHover};
}
&::after {
transform: translate3d(18px, -50%, 0);
}
}
render() { &:focus + label {
const { ${getFocusCss(theme)};
labelClass = '', }
switchClass = '', }
label,
checked,
transparent,
className,
tooltip,
tooltipPlacement,
} = this.props;
const labelId = this.state.id; label {
const labelClassName = `gf-form-label ${labelClass} ${transparent ? 'gf-form-label--transparent' : ''} pointer`; width: 100%;
const switchClassName = `gf-form-switch ${switchClass} ${transparent ? 'gf-form-switch--transparent' : ''}`; height: 100%;
cursor: pointer;
border: none;
border-radius: 50px;
background: ${theme.colors.formSwitchBg};
transition: all 0.3s ease;
&:hover {
background: ${theme.colors.formSwitchBgHover};
}
&::after {
position: absolute;
display: block;
content: '';
width: 12px;
height: 12px;
border-radius: 6px;
background: ${theme.colors.formSwitchDot};
top: 50%;
transform: translate3d(2px, -50%, 0);
transition: transform 0.2s cubic-bezier(0.19, 1, 0.22, 1);
}
}
}
`,
};
});
export const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
({ value, checked, disabled = false, onChange, ...inputProps }, ref) => {
const theme = useTheme();
const styles = getSwitchStyles(theme);
const switchId = uniqueId('switch-');
return ( return (
<div className="gf-form-switch-container-react"> <div className={cx(styles.switch)}>
<label htmlFor={labelId} className={`gf-form gf-form-switch-container ${className || ''}`}> <input
{label && ( type="checkbox"
<div className={labelClassName}> disabled={disabled}
{label} checked={value}
{tooltip && ( onChange={event => {
<Tooltip placement={tooltipPlacement ? tooltipPlacement : 'auto'} content={tooltip} theme={'info'}> onChange?.(event);
<div className="gf-form-help-icon gf-form-help-icon--right-normal"> }}
<Icon name="info-circle" /> id={switchId}
</div> {...inputProps}
</Tooltip> ref={ref}
)} />
</div> <label htmlFor={switchId} />
)}
<div className={switchClassName}>
<input id={labelId} type="checkbox" checked={checked} onChange={this.internalOnChange} />
<span className="gf-form-switch__slider" />
</div>
</label>
</div> </div>
); );
} }
} );
...@@ -143,8 +143,10 @@ export { HorizontalGroup, VerticalGroup, Container } from './Layout/Layout'; ...@@ -143,8 +143,10 @@ export { HorizontalGroup, VerticalGroup, Container } from './Layout/Layout';
export { RadioButtonGroup } from './Forms/RadioButtonGroup/RadioButtonGroup'; export { RadioButtonGroup } from './Forms/RadioButtonGroup/RadioButtonGroup';
export { Input } from './Input/Input'; export { Input } from './Input/Input';
export { Switch } from './Forms/Switch';
export { Switch } from './Switch/Switch';
export { Checkbox } from './Forms/Checkbox'; export { Checkbox } from './Forms/Checkbox';
export { TextArea } from './TextArea/TextArea'; export { TextArea } from './TextArea/TextArea';
// Legacy forms // Legacy forms
...@@ -158,7 +160,7 @@ import { ButtonSelect } from './Forms/Legacy/Select/ButtonSelect'; ...@@ -158,7 +160,7 @@ import { ButtonSelect } from './Forms/Legacy/Select/ButtonSelect';
//Input //Input
import { Input, LegacyInputStatus } from './Forms/Legacy/Input/Input'; import { Input, LegacyInputStatus } from './Forms/Legacy/Input/Input';
import { Switch } from './Switch/Switch'; import { Switch } from './Forms/Legacy/Switch/Switch';
const LegacyForms = { const LegacyForms = {
Select, Select,
......
...@@ -19,8 +19,9 @@ import { ...@@ -19,8 +19,9 @@ import {
valueMappingsOverrideProcessor, valueMappingsOverrideProcessor,
ThresholdsMode, ThresholdsMode,
} from '@grafana/data'; } from '@grafana/data';
import { Switch } from '../components/Switch/Switch';
import { NumberValueEditor, RadioButtonGroup, StringValueEditor, Select } from '../components'; import { NumberValueEditor, RadioButtonGroup, StringValueEditor, Select } from '../components';
import { Switch } from '../components/Forms/Switch';
import { ValueMappingsValueEditor } from '../components/OptionsUI/mappings'; import { ValueMappingsValueEditor } from '../components/OptionsUI/mappings';
import { ThresholdsValueEditor } from '../components/OptionsUI/thresholds'; import { ThresholdsValueEditor } from '../components/OptionsUI/thresholds';
import { UnitValueEditor } from '../components/OptionsUI/units'; import { UnitValueEditor } from '../components/OptionsUI/units';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment