Grafana-UI: Move Select container styles to outer most container (#40611)

* Grafana-UI: Move Select container styles to outer most container

* Update packages/grafana-ui/src/components/Select/Container.tsx

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* Rename file

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
This commit is contained in:
Josh Hunt 2021-10-19 12:29:33 +01:00 committed by GitHub
parent 58360923fd
commit d5a0f719df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 203 additions and 59 deletions

View File

@ -1,4 +1,4 @@
import { css } from '@emotion/css';
import { css, cx } from '@emotion/css';
import { GrafanaTheme, GrafanaTheme2 } from '@grafana/data';
import { focusCss } from '../../themes/mixins';
import { ComponentSize } from '../../types/size';
@ -19,51 +19,59 @@ export const sharedInputStyle = (theme: GrafanaTheme2, invalid = false) => {
// Need to colors without alpha channel
const autoFillBorder = theme.isDark ? '#2e2f35' : '#bab4ca';
return css`
background: ${background};
line-height: ${theme.typography.body.lineHeight};
font-size: ${theme.typography.size.md};
color: ${textColor};
border: 1px solid ${borderColor};
padding: ${theme.spacing(0, 1, 0, 1)};
return cx(
inputPadding(theme),
css`
background: ${background};
line-height: ${theme.typography.body.lineHeight};
font-size: ${theme.typography.size.md};
color: ${textColor};
border: 1px solid ${borderColor};
&:-webkit-autofill,
&:-webkit-autofill:hover {
/* Welcome to 2005. This is a HACK to get rid od Chromes default autofill styling */
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0), inset 0 0 0 100px ${background}!important;
-webkit-text-fill-color: ${textColor} !important;
border-color: ${autoFillBorder};
}
&:-webkit-autofill,
&:-webkit-autofill:hover {
/* Welcome to 2005. This is a HACK to get rid od Chromes default autofill styling */
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0), inset 0 0 0 100px ${background}!important;
-webkit-text-fill-color: ${textColor} !important;
border-color: ${autoFillBorder};
}
&:-webkit-autofill:focus {
/* Welcome to 2005. This is a HACK to get rid od Chromes default autofill styling */
box-shadow: 0 0 0 2px ${theme.colors.background.primary}, 0 0 0px 4px ${theme.colors.primary.main},
inset 0 0 0 1px rgba(255, 255, 255, 0), inset 0 0 0 100px ${background}!important;
-webkit-text-fill-color: ${textColor} !important;
}
&:hover {
border-color: ${borderColorHover};
}
&:focus {
outline: none;
}
&:disabled {
background-color: ${theme.colors.action.disabledBackground};
color: ${theme.colors.action.disabledText};
border: 1px solid ${theme.colors.action.disabledBackground};
&:-webkit-autofill:focus {
/* Welcome to 2005. This is a HACK to get rid od Chromes default autofill styling */
box-shadow: 0 0 0 2px ${theme.colors.background.primary}, 0 0 0px 4px ${theme.colors.primary.main},
inset 0 0 0 1px rgba(255, 255, 255, 0), inset 0 0 0 100px ${background}!important;
-webkit-text-fill-color: ${textColor} !important;
}
&:hover {
border-color: ${borderColor};
border-color: ${borderColorHover};
}
}
&::placeholder {
color: ${theme.colors.text.disabled};
opacity: 1;
}
&:focus {
outline: none;
}
&:disabled {
background-color: ${theme.colors.action.disabledBackground};
color: ${theme.colors.action.disabledText};
border: 1px solid ${theme.colors.action.disabledBackground};
&:hover {
border-color: ${borderColor};
}
}
&::placeholder {
color: ${theme.colors.text.disabled};
opacity: 1;
}
`
);
};
export const inputPadding = (theme: GrafanaTheme2) => {
return css`
padding: ${theme.spacing(0, 1, 0, 1)};
`;
};

View File

@ -0,0 +1,68 @@
import React from 'react';
import { useTheme2 } from '../../themes/ThemeContext';
import { sharedInputStyle } from '../Forms/commonStyles';
import { getInputStyles } from '../Input/Input';
import { css, cx } from '@emotion/css';
import { stylesFactory } from '../../themes';
import { GrafanaTheme2 } from '@grafana/data';
import { focusCss } from '../../themes/mixins';
import { components, ContainerProps, GroupTypeBase } from 'react-select';
export const SelectContainer = <Option, isMulti extends boolean, Group extends GroupTypeBase<Option>>(
props: ContainerProps<Option, isMulti, Group> & { isFocused: boolean }
) => {
const {
isDisabled,
isFocused,
children,
selectProps: { prefix },
} = props;
const theme = useTheme2();
const styles = getSelectContainerStyles(theme, isFocused, isDisabled, !!prefix);
return (
<components.SelectContainer {...props} className={cx(styles.wrapper, props.className)}>
{children}
</components.SelectContainer>
);
};
const getSelectContainerStyles = stylesFactory(
(theme: GrafanaTheme2, focused: boolean, disabled: boolean, withPrefix: boolean) => {
const styles = getInputStyles({ theme, invalid: false });
return {
wrapper: cx(
styles.wrapper,
sharedInputStyle(theme, false),
focused &&
css`
${focusCss(theme.v1)}
`,
disabled && styles.inputDisabled,
css`
position: relative;
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
min-height: 32px;
height: auto;
max-width: 100%;
/* Input padding is applied to the InputControl so the menu is aligned correctly */
padding: 0;
cursor: ${disabled ? 'not-allowed' : 'pointer'};
`,
withPrefix &&
css`
padding-left: 0;
`
),
};
}
);

View File

@ -1,11 +1,10 @@
import React from 'react';
import { useTheme2 } from '../../themes/ThemeContext';
import { sharedInputStyle } from '../Forms/commonStyles';
import { inputPadding } from '../Forms/commonStyles';
import { getInputStyles } from '../Input/Input';
import { css, cx } from '@emotion/css';
import { stylesFactory } from '../../themes';
import { GrafanaTheme2 } from '@grafana/data';
import { focusCss } from '../../themes/mixins';
interface InputControlProps {
/** Show an icon as a prefix in the input */
@ -21,28 +20,22 @@ const getInputControlStyles = stylesFactory(
const styles = getInputStyles({ theme, invalid });
return {
wrapper: cx(
styles.wrapper,
sharedInputStyle(theme, invalid),
focused &&
css`
${focusCss(theme.v1)}
`,
disabled && styles.inputDisabled,
input: cx(
inputPadding(theme),
css`
min-height: 32px;
height: auto;
flex-direction: row;
padding-right: 0;
width: 100%;
max-width: 100%;
align-items: center;
cursor: default;
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
justify-content: space-between;
padding-right: 0;
position: relative;
box-sizing: border-box;
cursor: ${disabled ? 'not-allowed' : 'pointer'};
`,
withPrefix &&
css`
@ -64,7 +57,7 @@ export const InputControl = React.forwardRef<HTMLDivElement, React.PropsWithChil
const theme = useTheme2();
const styles = getInputControlStyles(theme, invalid, focused, disabled, !!prefix);
return (
<div className={styles.wrapper} {...innerProps} ref={ref}>
<div className={styles.input} {...innerProps} ref={ref}>
{prefix && <div className={cx(styles.prefix)}>{prefix}</div>}
{children}
</div>

View File

@ -98,7 +98,6 @@ export const Basic: Story<StoryProps> = (args) => {
setValue(v);
action('onChange')(v);
}}
prefix={getPrefix(args.icon)}
{...args}
/>
</>

View File

@ -12,6 +12,7 @@ import { SelectMenu, SelectMenuOptions } from './SelectMenu';
import { IndicatorsContainer } from './IndicatorsContainer';
import { ValueContainer } from './ValueContainer';
import { InputControl } from './InputControl';
import { SelectContainer } from './SelectContainer';
import { DropdownIndicator } from './DropdownIndicator';
import { SelectOptionGroup } from './SelectOptionGroup';
import { SingleValue } from './SingleValue';
@ -334,6 +335,7 @@ export function SelectBase<T>({
},
MultiValueContainer: MultiValueContainer,
MultiValueRemove: MultiValueRemove,
SelectContainer,
...components,
}}
styles={{

View File

@ -0,0 +1,74 @@
import React from 'react';
import { useTheme2 } from '../../themes/ThemeContext';
import { sharedInputStyle } from '../Forms/commonStyles';
import { getInputStyles } from '../Input/Input';
import { css, cx } from '@emotion/css';
import { stylesFactory } from '../../themes';
import { GrafanaTheme2 } from '@grafana/data';
import { focusCss } from '../../themes/mixins';
import { components, ContainerProps, GroupTypeBase } from 'react-select';
// isFocus prop is actually available, but its not in the types for the version we have.
interface CorrectContainerProps<Option, isMulti extends boolean, Group extends GroupTypeBase<Option>>
extends ContainerProps<Option, isMulti, Group> {
isFocused: boolean;
}
export const SelectContainer = <Option, isMulti extends boolean, Group extends GroupTypeBase<Option>>(
props: CorrectContainerProps<Option, isMulti, Group>
) => {
const {
isDisabled,
isFocused,
children,
selectProps: { prefix },
} = props;
const theme = useTheme2();
const styles = getSelectContainerStyles(theme, isFocused, isDisabled, !!prefix);
return (
<components.SelectContainer {...props} className={cx(styles.wrapper, props.className)}>
{children}
</components.SelectContainer>
);
};
const getSelectContainerStyles = stylesFactory(
(theme: GrafanaTheme2, focused: boolean, disabled: boolean, withPrefix: boolean) => {
const styles = getInputStyles({ theme, invalid: false });
return {
wrapper: cx(
styles.wrapper,
sharedInputStyle(theme, false),
focused &&
css`
${focusCss(theme.v1)}
`,
disabled && styles.inputDisabled,
css`
position: relative;
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
min-height: 32px;
height: auto;
max-width: 100%;
/* Input padding is applied to the InputControl so the menu is aligned correctly */
padding: 0;
cursor: ${disabled ? 'not-allowed' : 'pointer'};
`,
withPrefix &&
css`
padding-left: 0;
`
),
};
}
);