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>
pull/40303/head
Josh Hunt 4 years ago committed by GitHub
parent 58360923fd
commit d5a0f719df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      packages/grafana-ui/src/components/Forms/commonStyles.ts
  2. 68
      packages/grafana-ui/src/components/Select/Container.tsx
  3. 29
      packages/grafana-ui/src/components/Select/InputControl.tsx
  4. 1
      packages/grafana-ui/src/components/Select/Select.story.tsx
  5. 2
      packages/grafana-ui/src/components/Select/SelectBase.tsx
  6. 74
      packages/grafana-ui/src/components/Select/SelectContainer.tsx

@ -1,4 +1,4 @@
import { css } from '@emotion/css'; import { css, cx } from '@emotion/css';
import { GrafanaTheme, GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme, GrafanaTheme2 } from '@grafana/data';
import { focusCss } from '../../themes/mixins'; import { focusCss } from '../../themes/mixins';
import { ComponentSize } from '../../types/size'; import { ComponentSize } from '../../types/size';
@ -19,13 +19,14 @@ export const sharedInputStyle = (theme: GrafanaTheme2, invalid = false) => {
// Need to colors without alpha channel // Need to colors without alpha channel
const autoFillBorder = theme.isDark ? '#2e2f35' : '#bab4ca'; const autoFillBorder = theme.isDark ? '#2e2f35' : '#bab4ca';
return css` return cx(
inputPadding(theme),
css`
background: ${background}; background: ${background};
line-height: ${theme.typography.body.lineHeight}; line-height: ${theme.typography.body.lineHeight};
font-size: ${theme.typography.size.md}; font-size: ${theme.typography.size.md};
color: ${textColor}; color: ${textColor};
border: 1px solid ${borderColor}; border: 1px solid ${borderColor};
padding: ${theme.spacing(0, 1, 0, 1)};
&:-webkit-autofill, &:-webkit-autofill,
&:-webkit-autofill:hover { &:-webkit-autofill:hover {
@ -64,6 +65,13 @@ export const sharedInputStyle = (theme: GrafanaTheme2, invalid = false) => {
color: ${theme.colors.text.disabled}; color: ${theme.colors.text.disabled};
opacity: 1; opacity: 1;
} }
`
);
};
export const inputPadding = (theme: GrafanaTheme2) => {
return css`
padding: ${theme.spacing(0, 1, 0, 1)};
`; `;
}; };

@ -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;
`
),
};
}
);

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

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

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

@ -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;
`
),
};
}
);
Loading…
Cancel
Save