mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
58360923fd
commit
d5a0f719df
@ -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)};
|
||||
`;
|
||||
};
|
||||
|
||||
|
68
packages/grafana-ui/src/components/Select/Container.tsx
Normal file
68
packages/grafana-ui/src/components/Select/Container.tsx
Normal 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;
|
||||
`
|
||||
),
|
||||
};
|
||||
}
|
||||
);
|
@ -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>
|
||||
|
@ -98,7 +98,6 @@ export const Basic: Story<StoryProps> = (args) => {
|
||||
setValue(v);
|
||||
action('onChange')(v);
|
||||
}}
|
||||
prefix={getPrefix(args.icon)}
|
||||
{...args}
|
||||
/>
|
||||
</>
|
||||
|
@ -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={{
|
||||
|
@ -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…
Reference in New Issue
Block a user