Chore: Clean up usage of deprecated stylesFactory function (#78419)

pull/78476/head
kay delaney 2 years ago committed by GitHub
parent 165de515cd
commit 9e11779921
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      packages/grafana-ui/src/components/Button/FullWidthButtonContainer.tsx
  2. 39
      packages/grafana-ui/src/components/ButtonCascader/ButtonCascader.tsx
  3. 5
      packages/grafana-ui/src/components/Card/Card.tsx
  4. 17
      packages/grafana-ui/src/components/Card/CardContainer.tsx
  5. 9
      packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx
  6. 9
      packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksListItem.tsx
  7. 9
      packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx
  8. 2
      packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.tsx
  9. 10
      packages/grafana-ui/src/components/DateTimePickers/TimeRangeInput.tsx
  10. 5
      packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx
  11. 4
      packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx
  12. 36
      packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx
  13. 9
      packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerFooter.tsx
  14. 42
      packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeList.tsx
  15. 13
      packages/grafana-ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneOption.tsx
  16. 26
      packages/grafana-ui/src/components/ErrorBoundary/ErrorWithStack.tsx
  17. 5
      packages/grafana-ui/src/components/Forms/Checkbox.tsx
  18. 61
      packages/grafana-ui/src/components/Forms/Field.tsx
  19. 9
      packages/grafana-ui/src/components/Forms/FieldSet.tsx
  20. 37
      packages/grafana-ui/src/components/Forms/FieldValidationMessage.tsx
  21. 55
      packages/grafana-ui/src/components/Forms/Label.tsx
  22. 9
      packages/grafana-ui/src/components/Forms/RadioButtonGroup/RadioButton.tsx
  23. 10
      packages/grafana-ui/src/components/IconButton/IconButton.tsx
  24. 6
      packages/grafana-ui/src/components/InfoBox/InfoBox.tsx
  25. 8
      packages/grafana-ui/src/components/Modal/Modal.tsx
  26. 6
      packages/grafana-ui/src/components/Modal/getModalStyles.ts
  27. 33
      packages/grafana-ui/src/components/Select/InputControl.tsx
  28. 12
      packages/grafana-ui/src/components/Select/SelectContainer.tsx
  29. 5
      packages/grafana-ui/src/components/Slider/RangeSlider.tsx
  30. 5
      packages/grafana-ui/src/components/Slider/Slider.tsx
  31. 6
      packages/grafana-ui/src/components/Slider/styles.ts
  32. 12
      packages/grafana-ui/src/components/Switch/Switch.tsx
  33. 64
      packages/grafana-ui/src/components/TabbedContainer/TabbedContainer.tsx
  34. 20
      packages/grafana-ui/src/components/Table/FilterList.tsx
  35. 26
      packages/grafana-ui/src/components/Tabs/Counter.tsx
  36. 19
      packages/grafana-ui/src/components/Tabs/TabContent.tsx
  37. 9
      packages/grafana-ui/src/components/TextArea/TextArea.tsx
  38. 41
      packages/grafana-ui/src/components/transitions/FadeTransition.tsx
  39. 47
      packages/grafana-ui/src/components/transitions/SlideOutTransition.tsx
  40. 36
      packages/grafana-ui/src/graveyard/Graph/GraphWithLegend.tsx
  41. 11
      public/app/core/navigation/GrafanaRouteError.tsx
  42. 9
      public/app/features/dashboard/components/RowOptions/RowOptionsModal.tsx
  43. 82
      public/app/features/dimensions/editors/ResourceCards.tsx
  44. 80
      public/app/features/explore/ExploreDrawer.tsx
  45. 10
      public/app/features/geo/editor/GazetteerPathEditor.tsx
  46. 8
      public/app/features/inspector/InspectStatsTable.tsx
  47. 13
      public/app/features/inspector/InspectStatsTraceIdsTable.tsx
  48. 6
      public/app/features/live/dashboard/DashboardChangedModal.tsx
  49. 9
      public/app/features/users/TokenRevokedModal.tsx
  50. 9
      public/app/plugins/datasource/azuremonitor/components/Space.tsx
  51. 9
      public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/MultiFilterItem.tsx
  52. 9
      public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.tsx
  53. 55
      public/app/plugins/datasource/elasticsearch/configuration/DataLink.tsx
  54. 9
      public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/EditorField.tsx

@ -1,20 +1,20 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React from 'react'; import React from 'react';
import { stylesFactory } from '../../themes'; import { useStyles2 } from '../../themes';
export interface Props { export interface Props {
className?: string; className?: string;
} }
export const FullWidthButtonContainer = ({ className, children }: React.PropsWithChildren<Props>) => { export const FullWidthButtonContainer = ({ className, children }: React.PropsWithChildren<Props>) => {
const styles = getStyles(); const styles = useStyles2(getStyles);
return <div className={cx(styles, className)}>{children}</div>; return <div className={cx(styles, className)}>{children}</div>;
}; };
const getStyles = stylesFactory(() => { const getStyles = () =>
return css({ css({
display: 'flex', display: 'flex',
button: { button: {
@ -31,4 +31,3 @@ const getStyles = stylesFactory(() => {
textAlign: 'center', textAlign: 'center',
}, },
}); });
});

@ -4,7 +4,7 @@ import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { IconName } from '../../types/icon'; import { IconName } from '../../types/icon';
import { Button, ButtonProps } from '../Button'; import { Button, ButtonProps } from '../Button';
import { CascaderOption } from '../Cascader/Cascader'; import { CascaderOption } from '../Cascader/Cascader';
@ -27,27 +27,9 @@ export interface ButtonCascaderProps {
hideDownIcon?: boolean; hideDownIcon?: boolean;
} }
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
return {
popup: css({
label: 'popup',
zIndex: theme.zIndex.dropdown,
}),
icons: {
right: css({
margin: '1px 0 0 4px',
}),
left: css({
margin: '-1px 4px 0 0',
}),
},
};
});
export const ButtonCascader = (props: ButtonCascaderProps) => { export const ButtonCascader = (props: ButtonCascaderProps) => {
const { onChange, className, loadData, icon, buttonProps, hideDownIcon, variant, disabled, ...rest } = props; const { onChange, className, loadData, icon, buttonProps, hideDownIcon, variant, disabled, ...rest } = props;
const theme = useTheme2(); const styles = useStyles2(getStyles);
const styles = getStyles(theme);
// Weird way to do this bit it goes around a styling issue in Button where even null/undefined child triggers // Weird way to do this bit it goes around a styling issue in Button where even null/undefined child triggers
// styling change which messes up the look if there is only single icon content. // styling change which messes up the look if there is only single icon content.
@ -72,3 +54,20 @@ export const ButtonCascader = (props: ButtonCascaderProps) => {
}; };
ButtonCascader.displayName = 'ButtonCascader'; ButtonCascader.displayName = 'ButtonCascader';
const getStyles = (theme: GrafanaTheme2) => {
return {
popup: css({
label: 'popup',
zIndex: theme.zIndex.dropdown,
}),
icons: {
right: css({
margin: '1px 0 0 4px',
}),
left: css({
margin: '-1px 4px 0 0',
}),
},
};
};

@ -3,7 +3,7 @@ import React, { memo, cloneElement, FC, useMemo, useContext, ReactNode } from 'r
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { getFocusStyles } from '../../themes/mixins'; import { getFocusStyles } from '../../themes/mixins';
import { CardContainer, CardContainerProps, getCardContainerStyles } from './CardContainer'; import { CardContainer, CardContainerProps, getCardContainerStyles } from './CardContainer';
@ -55,8 +55,7 @@ export const Card: CardInterface = ({ disabled, href, onClick, children, isSelec
const disableHover = disabled || (!onClick && !href); const disableHover = disabled || (!onClick && !href);
const onCardClick = onClick && !disabled ? onClick : undefined; const onCardClick = onClick && !disabled ? onClick : undefined;
const theme = useTheme2(); const styles = useStyles2(getCardContainerStyles, disabled, disableHover, isSelected);
const styles = getCardContainerStyles(theme, disabled, disableHover, isSelected);
return ( return (
<CardContainer <CardContainer

@ -3,7 +3,7 @@ import React, { HTMLAttributes } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { styleMixins, stylesFactory, useStyles2, useTheme2 } from '../../themes'; import { styleMixins, useStyles2 } from '../../themes';
/** /**
* @public * @public
@ -57,8 +57,8 @@ export const CardContainer = ({
href, href,
...props ...props
}: CardContainerProps) => { }: CardContainerProps) => {
const theme = useTheme2(); const { oldContainer } = useStyles2(getCardContainerStyles, disableEvents, disableHover, isSelected);
const { oldContainer } = getCardContainerStyles(theme, disableEvents, disableHover, isSelected);
return ( return (
<div {...props} className={cx(oldContainer, className)}> <div {...props} className={cx(oldContainer, className)}>
<CardInner href={href}>{children}</CardInner> <CardInner href={href}>{children}</CardInner>
@ -66,8 +66,12 @@ export const CardContainer = ({
); );
}; };
export const getCardContainerStyles = stylesFactory( export const getCardContainerStyles = (
(theme: GrafanaTheme2, disabled = false, disableHover = false, isSelected) => { theme: GrafanaTheme2,
disabled = false,
disableHover = false,
isSelected?: boolean
) => {
const isSelectable = isSelected !== undefined; const isSelectable = isSelected !== undefined;
return { return {
@ -132,5 +136,4 @@ export const getCardContainerStyles = stylesFactory(
}), }),
}), }),
}; };
} };
);

@ -4,7 +4,7 @@ import React, { useState } from 'react';
import { DataFrame, DataLink, GrafanaTheme2, VariableSuggestion } from '@grafana/data'; import { DataFrame, DataLink, GrafanaTheme2, VariableSuggestion } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../../themes'; import { useStyles2 } from '../../../themes';
import { Button } from '../../Button/Button'; import { Button } from '../../Button/Button';
import { Modal } from '../../Modal/Modal'; import { Modal } from '../../Modal/Modal';
@ -19,11 +19,10 @@ interface DataLinksInlineEditorProps {
} }
export const DataLinksInlineEditor = ({ links, onChange, getSuggestions, data }: DataLinksInlineEditorProps) => { export const DataLinksInlineEditor = ({ links, onChange, getSuggestions, data }: DataLinksInlineEditorProps) => {
const theme = useTheme2();
const [editIndex, setEditIndex] = useState<number | null>(null); const [editIndex, setEditIndex] = useState<number | null>(null);
const [isNew, setIsNew] = useState(false); const [isNew, setIsNew] = useState(false);
const styles = getDataLinksInlineEditorStyles(theme); const styles = useStyles2(getDataLinksInlineEditorStyles);
const linksSafe: DataLink[] = links ?? []; const linksSafe: DataLink[] = links ?? [];
const isEditing = editIndex !== null; const isEditing = editIndex !== null;
@ -110,10 +109,8 @@ export const DataLinksInlineEditor = ({ links, onChange, getSuggestions, data }:
); );
}; };
const getDataLinksInlineEditorStyles = stylesFactory((theme: GrafanaTheme2) => { const getDataLinksInlineEditorStyles = (theme: GrafanaTheme2) => ({
return {
wrapper: css({ wrapper: css({
marginBottom: theme.spacing(2), marginBottom: theme.spacing(2),
}), }),
};
}); });

@ -3,7 +3,7 @@ import React from 'react';
import { DataFrame, DataLink, GrafanaTheme2 } from '@grafana/data'; import { DataFrame, DataLink, GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../../themes'; import { useStyles2 } from '../../../themes';
import { isCompactUrl } from '../../../utils/dataLinks'; import { isCompactUrl } from '../../../utils/dataLinks';
import { FieldValidationMessage } from '../../Forms/FieldValidationMessage'; import { FieldValidationMessage } from '../../Forms/FieldValidationMessage';
import { IconButton } from '../../IconButton/IconButton'; import { IconButton } from '../../IconButton/IconButton';
@ -19,8 +19,7 @@ export interface DataLinksListItemProps {
} }
export const DataLinksListItem = ({ link, onEdit, onRemove }: DataLinksListItemProps) => { export const DataLinksListItem = ({ link, onEdit, onRemove }: DataLinksListItemProps) => {
const theme = useTheme2(); const styles = useStyles2(getDataLinkListItemStyles);
const styles = getDataLinkListItemStyles(theme);
const { title = '', url = '' } = link; const { title = '', url = '' } = link;
const hasTitle = title.trim() !== ''; const hasTitle = title.trim() !== '';
@ -52,7 +51,7 @@ export const DataLinksListItem = ({ link, onEdit, onRemove }: DataLinksListItemP
); );
}; };
const getDataLinkListItemStyles = stylesFactory((theme: GrafanaTheme2) => { const getDataLinkListItemStyles = (theme: GrafanaTheme2) => {
return { return {
wrapper: css({ wrapper: css({
marginBottom: theme.spacing(2), marginBottom: theme.spacing(2),
@ -95,4 +94,4 @@ const getDataLinkListItemStyles = stylesFactory((theme: GrafanaTheme2) => {
maxWidth: '90%', maxWidth: '90%',
}), }),
}; };
}); };

@ -4,7 +4,7 @@ import React, { PureComponent } from 'react';
import { DataSourceSettings } from '@grafana/data'; import { DataSourceSettings } from '@grafana/data';
import { stylesFactory } from '../../themes'; import { useStyles2 } from '../../themes';
import { Button } from '../Button'; import { Button } from '../Button';
import { FormField } from '../FormField/FormField'; import { FormField } from '../FormField/FormField';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';
@ -36,8 +36,7 @@ interface CustomHeaderRowProps {
onBlur: () => void; onBlur: () => void;
} }
const getCustomHeaderRowStyles = stylesFactory(() => { const getCustomHeaderRowStyles = () => ({
return {
layout: css({ layout: css({
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
@ -51,11 +50,11 @@ const getCustomHeaderRowStyles = stylesFactory(() => {
}, },
}, },
}), }),
};
}); });
const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }: CustomHeaderRowProps) => { const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }: CustomHeaderRowProps) => {
const styles = getCustomHeaderRowStyles(); const styles = useStyles2(getCustomHeaderRowStyles);
return ( return (
<div className={styles.layout}> <div className={styles.layout}>
<FormField <FormField

@ -72,7 +72,7 @@ export const DateTimePicker = ({
const { dialogProps } = useDialog({}, ref); const { dialogProps } = useDialog({}, ref);
const theme = useTheme2(); const theme = useTheme2();
const { modalBackdrop } = getModalStyles(theme); const { modalBackdrop } = useStyles2(getModalStyles);
const isFullscreen = useMedia(`(min-width: ${theme.breakpoints.values.lg}px)`); const isFullscreen = useMedia(`(min-width: ${theme.breakpoints.values.lg}px)`);
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);

@ -4,8 +4,7 @@ import React, { FormEvent, MouseEvent, useState } from 'react';
import { dateTime, getDefaultTimeRange, GrafanaTheme2, TimeRange, TimeZone } from '@grafana/data'; import { dateTime, getDefaultTimeRange, GrafanaTheme2, TimeRange, TimeZone } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { stylesFactory } from '../../themes'; import { useStyles2 } from '../../themes/ThemeContext';
import { useTheme2 } from '../../themes/ThemeContext';
import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper'; import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';
import { getInputStyles } from '../Input/Input'; import { getInputStyles } from '../Input/Input';
@ -47,8 +46,7 @@ export const TimeRangeInput = ({
showIcon = false, showIcon = false,
}: TimeRangeInputProps) => { }: TimeRangeInputProps) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const theme = useTheme2(); const styles = useStyles2(getStyles, disabled);
const styles = getStyles(theme, disabled);
const onOpen = (event: FormEvent<HTMLButtonElement>) => { const onOpen = (event: FormEvent<HTMLButtonElement>) => {
event.stopPropagation(); event.stopPropagation();
@ -115,7 +113,7 @@ export const TimeRangeInput = ({
); );
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2, disabled = false) => { const getStyles = (theme: GrafanaTheme2, disabled = false) => {
const inputStyles = getInputStyles({ theme, invalid: false }); const inputStyles = getInputStyles({ theme, invalid: false });
return { return {
container: css({ container: css({
@ -163,4 +161,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, disabled = false) => {
marginRight: theme.spacing(0.5), marginRight: theme.spacing(0.5),
}), }),
}; };
}); };

@ -16,7 +16,7 @@ import {
} from '@grafana/data'; } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { useStyles2, useTheme2 } from '../../themes/ThemeContext'; import { useStyles2 } from '../../themes/ThemeContext';
import { t, Trans } from '../../utils/i18n'; import { t, Trans } from '../../utils/i18n';
import { ButtonGroup } from '../Button'; import { ButtonGroup } from '../Button';
import { getModalStyles } from '../Modal/getModalStyles'; import { getModalStyles } from '../Modal/getModalStyles';
@ -106,9 +106,8 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
); );
const { dialogProps } = useDialog({}, overlayRef); const { dialogProps } = useDialog({}, overlayRef);
const theme = useTheme2();
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const { modalBackdrop } = getModalStyles(theme); const { modalBackdrop } = useStyles2(getModalStyles);
const hasAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to); const hasAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to);
const variant = isSynced ? 'active' : isOnCanvas ? 'canvas' : 'default'; const variant = isSynced ? 'active' : isOnCanvas ? 'canvas' : 'default';

@ -7,7 +7,7 @@ import React, { FormEvent, memo } from 'react';
import { DateTime, GrafanaTheme2, TimeZone } from '@grafana/data'; import { DateTime, GrafanaTheme2, TimeZone } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { useTheme2 } from '../../../themes'; import { useStyles2, useTheme2 } from '../../../themes';
import { getModalStyles } from '../../Modal/getModalStyles'; import { getModalStyles } from '../../Modal/getModalStyles';
import { Body } from './CalendarBody'; import { Body } from './CalendarBody';
@ -68,7 +68,7 @@ export interface TimePickerCalendarProps {
function TimePickerCalendar(props: TimePickerCalendarProps) { function TimePickerCalendar(props: TimePickerCalendarProps) {
const theme = useTheme2(); const theme = useTheme2();
const { modalBackdrop } = getModalStyles(theme); const { modalBackdrop } = useStyles2(getModalStyles);
const styles = getStyles(theme, props.isReversed); const styles = getStyles(theme, props.isReversed);
const { isOpen, isFullscreen, onClose } = props; const { isOpen, isFullscreen, onClose } = props;
const ref = React.createRef<HTMLElement>(); const ref = React.createRef<HTMLElement>();

@ -4,7 +4,7 @@ import React, { memo, useMemo, useState } from 'react';
import { GrafanaTheme2, isDateTime, rangeUtil, RawTimeRange, TimeOption, TimeRange, TimeZone } from '@grafana/data'; import { GrafanaTheme2, isDateTime, rangeUtil, RawTimeRange, TimeOption, TimeRange, TimeZone } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { stylesFactory, useTheme2 } from '../../../themes'; import { useStyles2, useTheme2 } from '../../../themes';
import { getFocusStyles } from '../../../themes/mixins'; import { getFocusStyles } from '../../../themes/mixins';
import { t, Trans } from '../../../utils/i18n'; import { t, Trans } from '../../../utils/i18n';
import { CustomScrollbar } from '../../CustomScrollbar/CustomScrollbar'; import { CustomScrollbar } from '../../CustomScrollbar/CustomScrollbar';
@ -63,8 +63,7 @@ export const TimePickerContentWithScreenSize = (props: PropsWithScreenSize) => {
const isHistoryEmpty = !history?.length; const isHistoryEmpty = !history?.length;
const isContainerTall = const isContainerTall =
(isFullscreen && showHistory) || (!isFullscreen && ((showHistory && !isHistoryEmpty) || !hideQuickRanges)); (isFullscreen && showHistory) || (!isFullscreen && ((showHistory && !isHistoryEmpty) || !hideQuickRanges));
const theme = useTheme2(); const styles = useStyles2(getStyles, isReversed, hideQuickRanges, isContainerTall, isFullscreen);
const styles = getStyles(theme, isReversed, hideQuickRanges, isContainerTall, isFullscreen);
const historyOptions = mapToHistoryOptions(history, timeZone); const historyOptions = mapToHistoryOptions(history, timeZone);
const timeOption = useTimeOption(value.raw, quickOptions); const timeOption = useTimeOption(value.raw, quickOptions);
const [searchTerm, setSearchQuery] = useState(''); const [searchTerm, setSearchQuery] = useState('');
@ -124,8 +123,7 @@ export const TimePickerContent = (props: Props) => {
const NarrowScreenForm = (props: FormProps) => { const NarrowScreenForm = (props: FormProps) => {
const { value, hideQuickRanges, onChange, timeZone, historyOptions = [], showHistory } = props; const { value, hideQuickRanges, onChange, timeZone, historyOptions = [], showHistory } = props;
const theme = useTheme2(); const styles = useStyles2(getNarrowScreenStyles);
const styles = getNarrowScreenStyles(theme);
const isAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to); const isAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to);
const [collapsedFlag, setCollapsedFlag] = useState(!isAbsolute); const [collapsedFlag, setCollapsedFlag] = useState(!isAbsolute);
const collapsed = hideQuickRanges ? false : collapsedFlag; const collapsed = hideQuickRanges ? false : collapsedFlag;
@ -176,8 +174,7 @@ const NarrowScreenForm = (props: FormProps) => {
const FullScreenForm = (props: FormProps) => { const FullScreenForm = (props: FormProps) => {
const { onChange, value, timeZone, fiscalYearStartMonth, isReversed, historyOptions } = props; const { onChange, value, timeZone, fiscalYearStartMonth, isReversed, historyOptions } = props;
const theme = useTheme2(); const styles = useStyles2(getFullScreenStyles, props.hideQuickRanges);
const styles = getFullScreenStyles(theme, props.hideQuickRanges);
const onChangeTimeOption = (timeOption: TimeOption) => { const onChangeTimeOption = (timeOption: TimeOption) => {
return onChange(mapOptionToTimeRange(timeOption, timeZone)); return onChange(mapOptionToTimeRange(timeOption, timeZone));
}; };
@ -214,8 +211,7 @@ const FullScreenForm = (props: FormProps) => {
}; };
const EmptyRecentList = memo(() => { const EmptyRecentList = memo(() => {
const theme = useTheme2(); const styles = useStyles2(getEmptyListStyles);
const styles = getEmptyListStyles(theme);
const emptyRecentListText = t( const emptyRecentListText = t(
'time-picker.content.empty-recent-list-info', 'time-picker.content.empty-recent-list-info',
"It looks like you haven't used this time picker before. As soon as you enter some time intervals, recently used intervals will appear here." "It looks like you haven't used this time picker before. As soon as you enter some time intervals, recently used intervals will appear here."
@ -263,8 +259,13 @@ const useTimeOption = (raw: RawTimeRange, quickOptions: TimeOption[]): TimeOptio
}, [raw, quickOptions]); }, [raw, quickOptions]);
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2, isReversed, hideQuickRanges, isContainerTall, isFullscreen) => { const getStyles = (
return { theme: GrafanaTheme2,
isReversed?: boolean,
hideQuickRanges?: boolean,
isContainerTall?: boolean,
isFullscreen?: boolean
) => ({
container: css({ container: css({
background: theme.colors.background.primary, background: theme.colors.background.primary,
boxShadow: theme.shadows.z3, boxShadow: theme.shadows.z3,
@ -299,11 +300,9 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, isReversed, hideQuickRang
spacing: css({ spacing: css({
marginTop: '16px', marginTop: '16px',
}), }),
};
}); });
const getNarrowScreenStyles = stylesFactory((theme: GrafanaTheme2) => { const getNarrowScreenStyles = (theme: GrafanaTheme2) => ({
return {
header: css({ header: css({
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
@ -326,11 +325,9 @@ const getNarrowScreenStyles = stylesFactory((theme: GrafanaTheme2) => {
form: css({ form: css({
padding: '7px 9px 7px 9px', padding: '7px 9px 7px 9px',
}), }),
};
}); });
const getFullScreenStyles = stylesFactory((theme: GrafanaTheme2, hideQuickRanges?: boolean) => { const getFullScreenStyles = (theme: GrafanaTheme2, hideQuickRanges?: boolean) => ({
return {
container: css({ container: css({
paddingTop: '9px', paddingTop: '9px',
paddingLeft: '11px', paddingLeft: '11px',
@ -346,11 +343,9 @@ const getFullScreenStyles = stylesFactory((theme: GrafanaTheme2, hideQuickRanges
justifyContent: 'flex-end', justifyContent: 'flex-end',
paddingTop: theme.spacing(1), paddingTop: theme.spacing(1),
}), }),
};
}); });
const getEmptyListStyles = stylesFactory((theme: GrafanaTheme2) => { const getEmptyListStyles = (theme: GrafanaTheme2) => ({
return {
container: css({ container: css({
padding: '12px', padding: '12px',
margin: '12px', margin: '12px',
@ -362,5 +357,4 @@ const getEmptyListStyles = stylesFactory((theme: GrafanaTheme2) => {
link: css({ link: css({
color: theme.colors.text.link, color: theme.colors.text.link,
}), }),
};
}); });

@ -5,7 +5,7 @@ import React, { useCallback, useState } from 'react';
import { getTimeZoneInfo, GrafanaTheme2, TimeZone } from '@grafana/data'; import { getTimeZoneInfo, GrafanaTheme2, TimeZone } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { stylesFactory, useTheme2 } from '../../../themes'; import { useStyles2 } from '../../../themes';
import { t, Trans } from '../../../utils/i18n'; import { t, Trans } from '../../../utils/i18n';
import { Button } from '../../Button'; import { Button } from '../../Button';
import { Field } from '../../Forms/Field'; import { Field } from '../../Forms/Field';
@ -46,8 +46,7 @@ export const TimePickerFooter = (props: Props) => {
[isEditing, setEditing] [isEditing, setEditing]
); );
const theme = useTheme2(); const style = useStyles2(getStyle);
const style = getStyle(theme);
if (!isString(timeZone)) { if (!isString(timeZone)) {
return null; return null;
@ -136,8 +135,7 @@ export const TimePickerFooter = (props: Props) => {
); );
}; };
const getStyle = stylesFactory((theme: GrafanaTheme2) => { const getStyle = (theme: GrafanaTheme2) => ({
return {
container: css({ container: css({
borderTop: `1px solid ${theme.colors.border.weak}`, borderTop: `1px solid ${theme.colors.border.weak}`,
padding: '11px', padding: '11px',
@ -174,5 +172,4 @@ const getStyle = stylesFactory((theme: GrafanaTheme2) => {
alignItems: 'baseline', alignItems: 'baseline',
flexGrow: 1, flexGrow: 1,
}), }),
};
}); });

@ -3,32 +3,12 @@ import React, { ReactNode } from 'react';
import { TimeOption } from '@grafana/data'; import { TimeOption } from '@grafana/data';
import { stylesFactory } from '../../../themes'; import { useStyles2 } from '../../../themes';
import { t } from '../../../utils/i18n'; import { t } from '../../../utils/i18n';
import { TimePickerTitle } from './TimePickerTitle'; import { TimePickerTitle } from './TimePickerTitle';
import { TimeRangeOption } from './TimeRangeOption'; import { TimeRangeOption } from './TimeRangeOption';
const getStyles = stylesFactory(() => {
return {
title: css({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '8px 16px 5px 9px',
}),
};
});
const getOptionsStyles = stylesFactory(() => {
return {
grow: css({
flexGrow: 1,
alignItems: 'flex-start',
}),
};
});
interface Props { interface Props {
title?: string; title?: string;
options: TimeOption[]; options: TimeOption[];
@ -38,7 +18,7 @@ interface Props {
} }
export const TimeRangeList = (props: Props) => { export const TimeRangeList = (props: Props) => {
const styles = getStyles(); const styles = useStyles2(getStyles);
const { title, options, placeholderEmpty } = props; const { title, options, placeholderEmpty } = props;
if (typeof placeholderEmpty !== 'undefined' && options.length <= 0) { if (typeof placeholderEmpty !== 'undefined' && options.length <= 0) {
@ -62,7 +42,7 @@ export const TimeRangeList = (props: Props) => {
}; };
const Options = ({ options, value, onChange, title }: Props) => { const Options = ({ options, value, onChange, title }: Props) => {
const styles = getOptionsStyles(); const styles = useStyles2(getOptionsStyles);
return ( return (
<> <>
@ -92,3 +72,19 @@ function isEqual(x: TimeOption, y?: TimeOption): boolean {
} }
return y.from === x.from && y.to === x.to; return y.from === x.from && y.to === x.to;
} }
const getStyles = () => ({
title: css({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '8px 16px 5px 9px',
}),
});
const getOptionsStyles = () => ({
grow: css({
flexGrow: 1,
alignItems: 'flex-start',
}),
});

@ -4,8 +4,7 @@ import React, { PropsWithChildren, RefCallback } from 'react';
import { GrafanaTheme2, SelectableValue, getTimeZoneInfo } from '@grafana/data'; import { GrafanaTheme2, SelectableValue, getTimeZoneInfo } from '@grafana/data';
import { useTheme2 } from '../../../themes/ThemeContext'; import { useStyles2 } from '../../../themes';
import { stylesFactory } from '../../../themes/stylesFactory';
import { Icon } from '../../Icon/Icon'; import { Icon } from '../../Icon/Icon';
import { TimeZoneDescription } from './TimeZoneDescription'; import { TimeZoneDescription } from './TimeZoneDescription';
@ -28,8 +27,7 @@ export interface SelectableZone extends SelectableValue<string> {
export const WideTimeZoneOption = (props: PropsWithChildren<Props>) => { export const WideTimeZoneOption = (props: PropsWithChildren<Props>) => {
const { children, innerProps, innerRef, data, isSelected, isFocused } = props; const { children, innerProps, innerRef, data, isSelected, isFocused } = props;
const theme = useTheme2(); const styles = useStyles2(getStyles);
const styles = getStyles(theme);
const timestamp = Date.now(); const timestamp = Date.now();
const containerStyles = cx(styles.container, isFocused && styles.containerFocused); const containerStyles = cx(styles.container, isFocused && styles.containerFocused);
@ -68,8 +66,7 @@ export const WideTimeZoneOption = (props: PropsWithChildren<Props>) => {
export const CompactTimeZoneOption = (props: React.PropsWithChildren<Props>) => { export const CompactTimeZoneOption = (props: React.PropsWithChildren<Props>) => {
const { children, innerProps, innerRef, data, isSelected, isFocused } = props; const { children, innerProps, innerRef, data, isSelected, isFocused } = props;
const theme = useTheme2(); const styles = useStyles2(getStyles);
const styles = getStyles(theme);
const timestamp = Date.now(); const timestamp = Date.now();
const containerStyles = cx(styles.container, isFocused && styles.containerFocused); const containerStyles = cx(styles.container, isFocused && styles.containerFocused);
@ -113,8 +110,7 @@ export const CompactTimeZoneOption = (props: React.PropsWithChildren<Props>) =>
); );
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2) => { const getStyles = (theme: GrafanaTheme2) => ({
return {
container: css({ container: css({
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
@ -157,5 +153,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
spacer: css({ spacer: css({
marginLeft: '6px', marginLeft: '6px',
}), }),
};
}); });

@ -1,23 +1,19 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React from 'react'; import React from 'react';
import { stylesFactory } from '../../themes'; import { useStyles2 } from '../../themes';
import { ErrorBoundaryApi } from './ErrorBoundary'; import { ErrorBoundaryApi } from './ErrorBoundary';
const getStyles = stylesFactory(() => {
return css({
width: '500px',
margin: '64px auto',
});
});
export interface Props extends ErrorBoundaryApi { export interface Props extends ErrorBoundaryApi {
title: string; title: string;
} }
export const ErrorWithStack = ({ error, errorInfo, title }: Props) => ( export const ErrorWithStack = ({ error, errorInfo, title }: Props) => {
<div className={getStyles()}> const style = useStyles2(getStyles);
return (
<div className={style}>
<h2>{title}</h2> <h2>{title}</h2>
<details style={{ whiteSpace: 'pre-wrap' }}> <details style={{ whiteSpace: 'pre-wrap' }}>
{error && error.toString()} {error && error.toString()}
@ -25,6 +21,14 @@ export const ErrorWithStack = ({ error, errorInfo, title }: Props) => (
{errorInfo && errorInfo.componentStack} {errorInfo && errorInfo.componentStack}
</details> </details>
</div> </div>
); );
};
ErrorWithStack.displayName = 'ErrorWithStack'; ErrorWithStack.displayName = 'ErrorWithStack';
const getStyles = () => {
return css({
width: '500px',
margin: '64px auto',
});
};

@ -3,7 +3,7 @@ import React, { HTMLProps, useCallback } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins'; import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
import { getLabelStyles } from './Label'; import { getLabelStyles } from './Label';
@ -36,8 +36,7 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
}, },
[onChange] [onChange]
); );
const theme = useTheme2(); const styles = useStyles2(getCheckboxStyles, invalid);
const styles = getCheckboxStyles(theme, invalid);
const ariaChecked = indeterminate ? 'mixed' : undefined; const ariaChecked = indeterminate ? 'mixed' : undefined;

@ -3,7 +3,7 @@ import React, { HTMLAttributes } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { getChildId } from '../../utils/reactUtils'; import { getChildId } from '../../utils/reactUtils';
import { FieldValidationMessage } from './FieldValidationMessage'; import { FieldValidationMessage } from './FieldValidationMessage';
@ -40,35 +40,6 @@ export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
htmlFor?: string; htmlFor?: string;
} }
export const getFieldStyles = stylesFactory((theme: GrafanaTheme2) => {
return {
field: css({
display: 'flex',
flexDirection: 'column',
marginBottom: theme.spacing(2),
}),
fieldHorizontal: css({
flexDirection: 'row',
justifyContent: 'space-between',
flexWrap: 'wrap',
}),
fieldValidationWrapper: css({
marginTop: theme.spacing(0.5),
}),
fieldValidationWrapperHorizontal: css({
flex: '1 1 100%',
}),
validationMessageHorizontalOverflow: css({
width: 0,
overflowX: 'visible',
'& > *': {
whiteSpace: 'nowrap',
},
}),
};
});
export const Field = React.forwardRef<HTMLDivElement, FieldProps>( export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
( (
{ {
@ -88,8 +59,7 @@ export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
}: FieldProps, }: FieldProps,
ref ref
) => { ) => {
const theme = useTheme2(); const styles = useStyles2(getFieldStyles);
const styles = getFieldStyles(theme);
const inputId = htmlFor ?? getChildId(children); const inputId = htmlFor ?? getChildId(children);
const labelElement = const labelElement =
@ -143,3 +113,30 @@ function deleteUndefinedProps<T extends Object>(obj: T): Partial<T> {
return obj; return obj;
} }
export const getFieldStyles = (theme: GrafanaTheme2) => ({
field: css({
display: 'flex',
flexDirection: 'column',
marginBottom: theme.spacing(2),
}),
fieldHorizontal: css({
flexDirection: 'row',
justifyContent: 'space-between',
flexWrap: 'wrap',
}),
fieldValidationWrapper: css({
marginTop: theme.spacing(0.5),
}),
fieldValidationWrapperHorizontal: css({
flex: '1 1 100%',
}),
validationMessageHorizontalOverflow: css({
width: 0,
overflowX: 'visible',
'& > *': {
whiteSpace: 'nowrap',
},
}),
});

@ -3,7 +3,7 @@ import React, { HTMLProps } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { Legend } from './Legend'; import { Legend } from './Legend';
@ -14,8 +14,7 @@ export interface Props extends Omit<HTMLProps<HTMLFieldSetElement>, 'label'> {
} }
export const FieldSet = ({ label, children, className, ...rest }: Props) => { export const FieldSet = ({ label, children, className, ...rest }: Props) => {
const theme = useTheme2(); const styles = useStyles2(getStyles);
const styles = getStyles(theme);
return ( return (
<fieldset className={cx(styles.wrapper, className)} {...rest}> <fieldset className={cx(styles.wrapper, className)} {...rest}>
@ -25,8 +24,7 @@ export const FieldSet = ({ label, children, className, ...rest }: Props) => {
); );
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2) => { const getStyles = (theme: GrafanaTheme2) => ({
return {
wrapper: css({ wrapper: css({
marginBottom: theme.spacing(4), marginBottom: theme.spacing(4),
@ -34,5 +32,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
marginBottom: 0, marginBottom: 0,
}, },
}), }),
};
}); });

@ -3,7 +3,7 @@ import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';
export interface FieldValidationMessageProps { export interface FieldValidationMessageProps {
@ -12,7 +12,23 @@ export interface FieldValidationMessageProps {
horizontal?: boolean; horizontal?: boolean;
} }
export const getFieldValidationMessageStyles = stylesFactory((theme: GrafanaTheme2) => { export const FieldValidationMessage = ({
children,
horizontal,
className,
}: React.PropsWithChildren<FieldValidationMessageProps>) => {
const styles = useStyles2(getFieldValidationMessageStyles);
const cssName = cx(horizontal ? styles.horizontal : styles.vertical, className);
return (
<div role="alert" className={cssName}>
<Icon className={styles.fieldValidationMessageIcon} name="exclamation-triangle" />
{children}
</div>
);
};
export const getFieldValidationMessageStyles = (theme: GrafanaTheme2) => {
const baseStyle = ` const baseStyle = `
font-size: ${theme.typography.size.sm}; font-size: ${theme.typography.size.sm};
font-weight: ${theme.typography.fontWeightMedium}; font-weight: ${theme.typography.fontWeightMedium};
@ -69,21 +85,4 @@ export const getFieldValidationMessageStyles = stylesFactory((theme: GrafanaThem
marginRight: theme.spacing(), marginRight: theme.spacing(),
}), }),
}; };
});
export const FieldValidationMessage = ({
children,
horizontal,
className,
}: React.PropsWithChildren<FieldValidationMessageProps>) => {
const theme = useTheme2();
const styles = getFieldValidationMessageStyles(theme);
const cssName = cx(horizontal ? styles.horizontal : styles.vertical, className);
return (
<div role="alert" className={cssName}>
<Icon className={styles.fieldValidationMessageIcon} name="exclamation-triangle" />
{children}
</div>
);
}; };

@ -3,7 +3,7 @@ import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { useTheme2, stylesFactory } from '../../themes'; import { useStyles2 } from '../../themes';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';
export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> { export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
@ -12,8 +12,31 @@ export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement>
category?: React.ReactNode[]; category?: React.ReactNode[];
} }
export const getLabelStyles = stylesFactory((theme: GrafanaTheme2) => { export const Label = ({ children, description, className, category, ...labelProps }: LabelProps) => {
return { const styles = useStyles2(getLabelStyles);
const categories = category?.map((c, i) => {
return (
<span className={styles.categories} key={`${c}/${i}`}>
<span>{c}</span>
<Icon name="angle-right" className={styles.chevron} />
</span>
);
});
return (
<div className={cx(styles.label, className)}>
<label {...labelProps}>
<div className={styles.labelContent}>
{categories}
{children}
</div>
{description && <span className={styles.description}>{description}</span>}
</label>
</div>
);
};
export const getLabelStyles = (theme: GrafanaTheme2) => ({
label: css({ label: css({
label: 'Label', label: 'Label',
fontSize: theme.typography.size.sm, fontSize: theme.typography.size.sm,
@ -43,30 +66,4 @@ export const getLabelStyles = stylesFactory((theme: GrafanaTheme2) => {
chevron: css({ chevron: css({
margin: theme.spacing(0, 0.25), margin: theme.spacing(0, 0.25),
}), }),
};
}); });
export const Label = ({ children, description, className, category, ...labelProps }: LabelProps) => {
const theme = useTheme2();
const styles = getLabelStyles(theme);
const categories = category?.map((c, i) => {
return (
<span className={styles.categories} key={`${c}/${i}`}>
<span>{c}</span>
<Icon name="angle-right" className={styles.chevron} />
</span>
);
});
return (
<div className={cx(styles.label, className)}>
<label {...labelProps}>
<div className={styles.labelContent}>
{categories}
{children}
</div>
{description && <span className={styles.description}>{description}</span>}
</label>
</div>
);
};

@ -4,7 +4,7 @@ import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { StringSelector } from '@grafana/e2e-selectors'; import { StringSelector } from '@grafana/e2e-selectors';
import { useTheme2, stylesFactory } from '../../../themes'; import { useStyles2 } from '../../../themes';
import { getFocusStyles, getMouseFocusStyles } from '../../../themes/mixins'; import { getFocusStyles, getMouseFocusStyles } from '../../../themes/mixins';
import { getPropertiesForButtonSize } from '../commonStyles'; import { getPropertiesForButtonSize } from '../commonStyles';
@ -41,8 +41,7 @@ export const RadioButton = React.forwardRef<HTMLInputElement, RadioButtonProps>(
}, },
ref ref
) => { ) => {
const theme = useTheme2(); const styles = useStyles2(getRadioButtonStyles, size, fullWidth);
const styles = getRadioButtonStyles(theme, size, fullWidth);
return ( return (
<div className={styles.radioOption}> <div className={styles.radioOption}>
@ -68,7 +67,7 @@ export const RadioButton = React.forwardRef<HTMLInputElement, RadioButtonProps>(
RadioButton.displayName = 'RadioButton'; RadioButton.displayName = 'RadioButton';
const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme2, size: RadioButtonSize, fullWidth?: boolean) => { const getRadioButtonStyles = (theme: GrafanaTheme2, size: RadioButtonSize, fullWidth?: boolean) => {
const { fontSize, height, padding } = getPropertiesForButtonSize(size, theme); const { fontSize, height, padding } = getPropertiesForButtonSize(size, theme);
const textColor = theme.colors.text.secondary; const textColor = theme.colors.text.secondary;
@ -130,4 +129,4 @@ const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme2, size: RadioBut
}, },
}), }),
}; };
}); };

@ -3,7 +3,7 @@ import React from 'react';
import { GrafanaTheme2, colorManipulator, deprecationWarning } from '@grafana/data'; import { GrafanaTheme2, colorManipulator, deprecationWarning } from '@grafana/data';
import { useTheme2, stylesFactory } from '../../themes'; import { useStyles2 } from '../../themes';
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins'; import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
import { ComponentSize } from '../../types'; import { ComponentSize } from '../../types';
import { IconName, IconSize, IconType } from '../../types/icon'; import { IconName, IconSize, IconType } from '../../types/icon';
@ -44,8 +44,6 @@ export type Props = BasePropsWithTooltip | BasePropsWithAriaLabel;
export const IconButton = React.forwardRef<HTMLButtonElement, Props>((props, ref) => { export const IconButton = React.forwardRef<HTMLButtonElement, Props>((props, ref) => {
const { size = 'md', variant = 'secondary' } = props; const { size = 'md', variant = 'secondary' } = props;
const theme = useTheme2();
let limitedIconSize: LimitedIconSize; let limitedIconSize: LimitedIconSize;
// very large icons (xl to xxxl) are unified to size xl // very large icons (xl to xxxl) are unified to size xl
@ -56,7 +54,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, Props>((props, ref
limitedIconSize = size; limitedIconSize = size;
} }
const styles = getStyles(theme, limitedIconSize, variant); const styles = useStyles2(getStyles, limitedIconSize, variant);
let ariaLabel: string | undefined; let ariaLabel: string | undefined;
let buttonRef: typeof ref | undefined; let buttonRef: typeof ref | undefined;
@ -104,7 +102,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, Props>((props, ref
IconButton.displayName = 'IconButton'; IconButton.displayName = 'IconButton';
const getStyles = stylesFactory((theme: GrafanaTheme2, size, variant: IconButtonVariant) => { const getStyles = (theme: GrafanaTheme2, size: IconSize, variant: IconButtonVariant) => {
// overall size of the IconButton on hover // overall size of the IconButton on hover
// theme.spacing.gridSize originates from 2*4px for padding and letting the IconSize generally decide on the hoverSize // theme.spacing.gridSize originates from 2*4px for padding and letting the IconSize generally decide on the hoverSize
const hoverSize = getSvgSize(size) + theme.spacing.gridSize; const hoverSize = getSvgSize(size) + theme.spacing.gridSize;
@ -166,4 +164,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, size, variant: IconButton
verticalAlign: 'baseline', verticalAlign: 'baseline',
}), }),
}; };
}); };

@ -3,7 +3,7 @@ import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useStyles2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { Alert, AlertVariant } from '../Alert/Alert'; import { Alert, AlertVariant } from '../Alert/Alert';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';
@ -45,11 +45,9 @@ export const InfoBox = React.memo(
InfoBox.displayName = 'InfoBox'; InfoBox.displayName = 'InfoBox';
const getStyles = stylesFactory((theme: GrafanaTheme2) => { const getStyles = (theme: GrafanaTheme2) => ({
return {
docsLink: css({ docsLink: css({
display: 'inline-block', display: 'inline-block',
marginTop: theme.spacing(2), marginTop: theme.spacing(2),
}), }),
};
}); });

@ -4,7 +4,7 @@ import { FocusScope } from '@react-aria/focus';
import { OverlayContainer, useOverlay } from '@react-aria/overlays'; import { OverlayContainer, useOverlay } from '@react-aria/overlays';
import React, { PropsWithChildren, useRef } from 'react'; import React, { PropsWithChildren, useRef } from 'react';
import { useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { IconName } from '../../types'; import { IconName } from '../../types';
import { t } from '../../utils/i18n'; import { t } from '../../utils/i18n';
import { IconButton } from '../IconButton/IconButton'; import { IconButton } from '../IconButton/IconButton';
@ -46,8 +46,7 @@ export function Modal(props: PropsWithChildren<Props>) {
onClickBackdrop, onClickBackdrop,
trapFocus = true, trapFocus = true,
} = props; } = props;
const theme = useTheme2(); const styles = useStyles2(getModalStyles);
const styles = getModalStyles(theme);
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
@ -101,8 +100,7 @@ export function Modal(props: PropsWithChildren<Props>) {
} }
function ModalButtonRow({ leftItems, children }: { leftItems?: React.ReactNode; children: React.ReactNode }) { function ModalButtonRow({ leftItems, children }: { leftItems?: React.ReactNode; children: React.ReactNode }) {
const theme = useTheme2(); const styles = useStyles2(getModalStyles);
const styles = getModalStyles(theme);
if (leftItems) { if (leftItems) {
return ( return (

@ -2,9 +2,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory } from '../../themes'; export const getModalStyles = (theme: GrafanaTheme2) => {
export const getModalStyles = stylesFactory((theme: GrafanaTheme2) => {
const borderRadius = theme.shape.radius.default; const borderRadius = theme.shape.radius.default;
return { return {
@ -80,4 +78,4 @@ export const getModalStyles = stylesFactory((theme: GrafanaTheme2) => {
paddingTop: theme.spacing(3), paddingTop: theme.spacing(3),
}), }),
}; };
}); };

@ -3,8 +3,7 @@ import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory } from '../../themes'; import { useStyles2 } from '../../themes/ThemeContext';
import { useTheme2 } from '../../themes/ThemeContext';
import { inputPadding } from '../Forms/commonStyles'; import { inputPadding } from '../Forms/commonStyles';
import { getInputStyles } from '../Input/Input'; import { getInputStyles } from '../Input/Input';
@ -17,7 +16,20 @@ interface InputControlProps {
innerProps: JSX.IntrinsicElements['div']; innerProps: JSX.IntrinsicElements['div'];
} }
const getInputControlStyles = stylesFactory((theme: GrafanaTheme2, invalid: boolean, withPrefix: boolean) => { export const InputControl = React.forwardRef<HTMLDivElement, React.PropsWithChildren<InputControlProps>>(
function InputControl({ focused, invalid, disabled, children, innerProps, prefix, ...otherProps }, ref) {
const styles = useStyles2(getInputControlStyles, invalid, !!prefix);
return (
<div className={styles.input} {...innerProps} ref={ref}>
{prefix && <div className={cx(styles.prefix)}>{prefix}</div>}
{children}
</div>
);
}
);
const getInputControlStyles = (theme: GrafanaTheme2, invalid: boolean, withPrefix: boolean) => {
const styles = getInputStyles({ theme, invalid }); const styles = getInputStyles({ theme, invalid });
return { return {
@ -47,17 +59,4 @@ const getInputControlStyles = stylesFactory((theme: GrafanaTheme2, invalid: bool
}) })
), ),
}; };
}); };
export const InputControl = React.forwardRef<HTMLDivElement, React.PropsWithChildren<InputControlProps>>(
function InputControl({ focused, invalid, disabled, children, innerProps, prefix, ...otherProps }, ref) {
const theme = useTheme2();
const styles = getInputControlStyles(theme, invalid, !!prefix);
return (
<div className={styles.input} {...innerProps} ref={ref}>
{prefix && <div className={cx(styles.prefix)}>{prefix}</div>}
{children}
</div>
);
}
);

@ -4,8 +4,7 @@ import { components, ContainerProps as BaseContainerProps, GroupBase } from 'rea
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory } from '../../themes'; import { useStyles2 } from '../../themes/ThemeContext';
import { useTheme2 } from '../../themes/ThemeContext';
import { getFocusStyles } from '../../themes/mixins'; import { getFocusStyles } from '../../themes/mixins';
import { sharedInputStyle } from '../Forms/commonStyles'; import { sharedInputStyle } from '../Forms/commonStyles';
import { getInputStyles } from '../Input/Input'; import { getInputStyles } from '../Input/Input';
@ -26,8 +25,7 @@ export const SelectContainer = <Option, isMulti extends boolean, Group extends G
selectProps: { invalid = false }, selectProps: { invalid = false },
} = props; } = props;
const theme = useTheme2(); const styles = useStyles2(getSelectContainerStyles, isFocused, isDisabled, invalid);
const styles = getSelectContainerStyles(theme, isFocused, isDisabled, invalid);
return ( return (
<components.SelectContainer {...props} className={cx(styles.wrapper, props.className)}> <components.SelectContainer {...props} className={cx(styles.wrapper, props.className)}>
@ -36,8 +34,7 @@ export const SelectContainer = <Option, isMulti extends boolean, Group extends G
); );
}; };
const getSelectContainerStyles = stylesFactory( const getSelectContainerStyles = (theme: GrafanaTheme2, focused: boolean, disabled: boolean, invalid: boolean) => {
(theme: GrafanaTheme2, focused: boolean, disabled: boolean, invalid: boolean) => {
const styles = getInputStyles({ theme, invalid }); const styles = getInputStyles({ theme, invalid });
return { return {
@ -64,5 +61,4 @@ const getSelectContainerStyles = stylesFactory(
}) })
), ),
}; };
} };
);

@ -3,7 +3,7 @@ import { Global } from '@emotion/react';
import Slider, { SliderProps } from 'rc-slider'; import Slider, { SliderProps } from 'rc-slider';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTheme2 } from '../../themes/ThemeContext'; import { useStyles2 } from '../../themes/ThemeContext';
import HandleTooltip from './HandleTooltip'; import HandleTooltip from './HandleTooltip';
import { getStyles } from './styles'; import { getStyles } from './styles';
@ -43,8 +43,7 @@ export const RangeSlider = ({
); );
const isHorizontal = orientation === 'horizontal'; const isHorizontal = orientation === 'horizontal';
const theme = useTheme2(); const styles = useStyles2(getStyles, isHorizontal);
const styles = getStyles(theme, isHorizontal);
const tipHandleRender: SliderProps['handleRender'] = (node, handleProps) => { const tipHandleRender: SliderProps['handleRender'] = (node, handleProps) => {
return ( return (

@ -3,7 +3,7 @@ import { Global } from '@emotion/react';
import SliderComponent from 'rc-slider'; import SliderComponent from 'rc-slider';
import React, { useState, useCallback, ChangeEvent, FocusEvent } from 'react'; import React, { useState, useCallback, ChangeEvent, FocusEvent } from 'react';
import { useTheme2 } from '../../themes/ThemeContext'; import { useStyles2 } from '../../themes/ThemeContext';
import { Input } from '../Input/Input'; import { Input } from '../Input/Input';
import { getStyles } from './styles'; import { getStyles } from './styles';
@ -26,8 +26,7 @@ export const Slider = ({
included, included,
}: SliderProps) => { }: SliderProps) => {
const isHorizontal = orientation === 'horizontal'; const isHorizontal = orientation === 'horizontal';
const theme = useTheme2(); const styles = useStyles2(getStyles, isHorizontal, Boolean(marks));
const styles = getStyles(theme, isHorizontal, Boolean(marks));
const SliderWithTooltip = SliderComponent; const SliderWithTooltip = SliderComponent;
const [sliderValue, setSliderValue] = useState<number>(value ?? min); const [sliderValue, setSliderValue] = useState<number>(value ?? min);

@ -3,9 +3,7 @@ import { css as cssCore } from '@emotion/react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory } from '../../themes'; export const getStyles = (theme: GrafanaTheme2, isHorizontal: boolean, hasMarks = false) => {
export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: boolean, hasMarks = false) => {
const { spacing } = theme; const { spacing } = theme;
const railColor = theme.colors.border.strong; const railColor = theme.colors.border.strong;
const trackColor = theme.colors.primary.main; const trackColor = theme.colors.primary.main;
@ -127,4 +125,4 @@ export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: bool
order: 1, order: 1,
}), }),
}; };
}); };

@ -4,7 +4,7 @@ import React, { HTMLProps, useRef } from 'react';
import { GrafanaTheme2, deprecationWarning } from '@grafana/data'; import { GrafanaTheme2, deprecationWarning } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins'; import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
export interface Props extends Omit<HTMLProps<HTMLInputElement>, 'value'> { export interface Props extends Omit<HTMLProps<HTMLInputElement>, 'value'> {
@ -21,8 +21,7 @@ export const Switch = React.forwardRef<HTMLInputElement, Props>(
deprecationWarning('Switch', 'checked prop', 'value'); deprecationWarning('Switch', 'checked prop', 'value');
} }
const theme = useTheme2(); const styles = useStyles2(getSwitchStyles);
const styles = getSwitchStyles(theme);
const switchIdRef = useRef(id ? id : uniqueId('switch-')); const switchIdRef = useRef(id ? id : uniqueId('switch-'));
return ( return (
@ -52,8 +51,7 @@ export interface InlineSwitchProps extends Props {
export const InlineSwitch = React.forwardRef<HTMLInputElement, InlineSwitchProps>( export const InlineSwitch = React.forwardRef<HTMLInputElement, InlineSwitchProps>(
({ transparent, className, showLabel, label, value, id, invalid, ...props }, ref) => { ({ transparent, className, showLabel, label, value, id, invalid, ...props }, ref) => {
const theme = useTheme2(); const styles = useStyles2(getSwitchStyles, transparent);
const styles = getSwitchStyles(theme, transparent);
return ( return (
<div <div
@ -75,8 +73,7 @@ export const InlineSwitch = React.forwardRef<HTMLInputElement, InlineSwitchProps
InlineSwitch.displayName = 'Switch'; InlineSwitch.displayName = 'Switch';
const getSwitchStyles = stylesFactory((theme: GrafanaTheme2, transparent?: boolean) => { const getSwitchStyles = (theme: GrafanaTheme2, transparent?: boolean) => ({
return {
switch: css({ switch: css({
width: '32px', width: '32px',
height: '16px', height: '16px',
@ -180,5 +177,4 @@ const getSwitchStyles = stylesFactory((theme: GrafanaTheme2, transparent?: boole
border: `1px solid ${theme.colors.error.border}`, border: `1px solid ${theme.colors.error.border}`,
}, },
}), }),
};
}); });

@ -5,7 +5,7 @@ import { SelectableValue, GrafanaTheme2 } from '@grafana/data';
import { IconButton } from '../../components/IconButton/IconButton'; import { IconButton } from '../../components/IconButton/IconButton';
import { TabsBar, Tab, TabContent } from '../../components/Tabs'; import { TabsBar, Tab, TabContent } from '../../components/Tabs';
import { stylesFactory, useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { IconName } from '../../types/icon'; import { IconName } from '../../types/icon';
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar'; import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
@ -23,45 +23,14 @@ export interface TabbedContainerProps {
onClose: () => void; onClose: () => void;
} }
const getStyles = stylesFactory((theme: GrafanaTheme2) => { export function TabbedContainer({ tabs, defaultTab, closeIconTooltip, onClose }: TabbedContainerProps) {
return { const [activeTab, setActiveTab] = useState(tabs.some((tab) => tab.value === defaultTab) ? defaultTab : tabs[0].value);
container: css({
height: '100%',
}),
tabContent: css({
padding: theme.spacing(2),
backgroundColor: theme.colors.background.primary,
height: `calc(100% - ${theme.components.menuTabs.height}px)`,
}),
close: css({
position: 'absolute',
right: '16px',
top: '5px',
cursor: 'pointer',
fontSize: theme.typography.size.lg,
}),
tabs: css({
paddingTop: theme.spacing(1),
borderColor: theme.colors.border.weak,
ul: {
marginLeft: theme.spacing(2),
},
}),
};
});
export function TabbedContainer(props: TabbedContainerProps) {
const [activeTab, setActiveTab] = useState(
props.tabs.some((tab) => tab.value === props.defaultTab) ? props.defaultTab : props.tabs?.[0].value
);
const onSelectTab = (item: SelectableValue<string>) => { const onSelectTab = (item: SelectableValue<string>) => {
setActiveTab(item.value!); setActiveTab(item.value!);
}; };
const { tabs, onClose, closeIconTooltip } = props; const styles = useStyles2(getStyles);
const theme = useTheme2();
const styles = getStyles(theme);
return ( return (
<div className={styles.container}> <div className={styles.container}>
@ -83,3 +52,28 @@ export function TabbedContainer(props: TabbedContainerProps) {
</div> </div>
); );
} }
const getStyles = (theme: GrafanaTheme2) => ({
container: css({
height: '100%',
}),
tabContent: css({
padding: theme.spacing(2),
backgroundColor: theme.colors.background.primary,
height: `calc(100% - ${theme.components.menuTabs.height}px)`,
}),
close: css({
position: 'absolute',
right: '16px',
top: '5px',
cursor: 'pointer',
fontSize: theme.typography.size.lg,
}),
tabs: css({
paddingTop: theme.spacing(1),
borderColor: theme.colors.border.weak,
ul: {
marginLeft: theme.spacing(2),
},
}),
});

@ -5,7 +5,7 @@ import { FixedSizeList as List } from 'react-window';
import { GrafanaTheme2, SelectableValue } from '@grafana/data'; import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { Checkbox, FilterInput, Label, VerticalGroup } from '..'; import { Checkbox, FilterInput, Label, VerticalGroup } from '..';
import { stylesFactory, useTheme2 } from '../../themes'; import { useStyles2, useTheme2 } from '../../themes';
interface Props { interface Props {
values: SelectableValue[]; values: SelectableValue[];
@ -18,8 +18,6 @@ const ITEM_HEIGHT = 28;
const MIN_HEIGHT = ITEM_HEIGHT * 5; const MIN_HEIGHT = ITEM_HEIGHT * 5;
export const FilterList = ({ options, values, caseSensitive, onChange }: Props) => { export const FilterList = ({ options, values, caseSensitive, onChange }: Props) => {
const theme = useTheme2();
const styles = getStyles(theme);
const [searchFilter, setSearchFilter] = useState(''); const [searchFilter, setSearchFilter] = useState('');
const regex = useMemo(() => new RegExp(searchFilter, caseSensitive ? undefined : 'i'), [searchFilter, caseSensitive]); const regex = useMemo(() => new RegExp(searchFilter, caseSensitive ? undefined : 'i'), [searchFilter, caseSensitive]);
const items = useMemo( const items = useMemo(
@ -32,16 +30,12 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props)
}), }),
[options, regex] [options, regex]
); );
const styles = useStyles2(getStyles);
const theme = useTheme2();
const gutter = theme.spacing.gridSize; const gutter = theme.spacing.gridSize;
const height = useMemo(() => Math.min(items.length * ITEM_HEIGHT, MIN_HEIGHT) + gutter, [gutter, items.length]); const height = useMemo(() => Math.min(items.length * ITEM_HEIGHT, MIN_HEIGHT) + gutter, [gutter, items.length]);
const onInputChange = useCallback(
(v: string) => {
setSearchFilter(v);
},
[setSearchFilter]
);
const onCheckedChanged = useCallback( const onCheckedChanged = useCallback(
(option: SelectableValue) => (event: React.FormEvent<HTMLInputElement>) => { (option: SelectableValue) => (event: React.FormEvent<HTMLInputElement>) => {
const newValues = event.currentTarget.checked const newValues = event.currentTarget.checked
@ -55,7 +49,7 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props)
return ( return (
<VerticalGroup spacing="md"> <VerticalGroup spacing="md">
<FilterInput placeholder="Filter values" onChange={onInputChange} value={searchFilter} /> <FilterInput placeholder="Filter values" onChange={setSearchFilter} value={searchFilter} />
{!items.length && <Label>No values</Label>} {!items.length && <Label>No values</Label>}
{items.length && ( {items.length && (
<List <List
@ -82,7 +76,7 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props)
); );
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2) => ({ const getStyles = (theme: GrafanaTheme2) => ({
filterList: css({ filterList: css({
label: 'filterList', label: 'filterList',
}), }),
@ -98,4 +92,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => ({
backgroundColor: theme.colors.action.hover, backgroundColor: theme.colors.action.hover,
}, },
}), }),
})); });

@ -3,10 +3,19 @@ import React from 'react';
import { GrafanaTheme2, locale } from '@grafana/data'; import { GrafanaTheme2, locale } from '@grafana/data';
import { stylesFactory, useStyles2 } from '../../themes'; import { useStyles2 } from '../../themes';
const getStyles = stylesFactory((theme: GrafanaTheme2) => { export interface CounterProps {
return { value: number;
}
export const Counter = ({ value }: CounterProps) => {
const styles = useStyles2(getStyles);
return <span className={styles.counter}>{locale(value, 0).text}</span>;
};
const getStyles = (theme: GrafanaTheme2) => ({
counter: css({ counter: css({
label: 'counter', label: 'counter',
marginLeft: theme.spacing(1), marginLeft: theme.spacing(1),
@ -17,15 +26,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
fontWeight: theme.typography.fontWeightMedium, fontWeight: theme.typography.fontWeightMedium,
fontSize: theme.typography.size.sm, fontSize: theme.typography.size.sm,
}), }),
};
}); });
export interface CounterProps {
value: number;
}
export const Counter = ({ value }: CounterProps) => {
const styles = useStyles2(getStyles);
return <span className={styles.counter}>{locale(value, 0).text}</span>;
};

@ -3,23 +3,14 @@ import React, { HTMLAttributes, ReactNode } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
interface Props extends HTMLAttributes<HTMLDivElement> { interface Props extends HTMLAttributes<HTMLDivElement> {
children: ReactNode; children: ReactNode;
} }
const getTabContentStyle = stylesFactory((theme: GrafanaTheme2) => {
return {
tabContent: css({
background: theme.colors.background.primary,
}),
};
});
export const TabContent = ({ children, className, ...restProps }: Props) => { export const TabContent = ({ children, className, ...restProps }: Props) => {
const theme = useTheme2(); const styles = useStyles2(getTabContentStyle);
const styles = getTabContentStyle(theme);
return ( return (
<div {...restProps} className={cx(styles.tabContent, className)}> <div {...restProps} className={cx(styles.tabContent, className)}>
@ -27,3 +18,9 @@ export const TabContent = ({ children, className, ...restProps }: Props) => {
</div> </div>
); );
}; };
const getTabContentStyle = (theme: GrafanaTheme2) => ({
tabContent: css({
background: theme.colors.background.primary,
}),
});

@ -3,7 +3,7 @@ import React, { HTMLProps } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { getFocusStyle, sharedInputStyle } from '../Forms/commonStyles'; import { getFocusStyle, sharedInputStyle } from '../Forms/commonStyles';
export interface Props extends Omit<HTMLProps<HTMLTextAreaElement>, 'size'> { export interface Props extends Omit<HTMLProps<HTMLTextAreaElement>, 'size'> {
@ -12,14 +12,12 @@ export interface Props extends Omit<HTMLProps<HTMLTextAreaElement>, 'size'> {
} }
export const TextArea = React.forwardRef<HTMLTextAreaElement, Props>(({ invalid, className, ...props }, ref) => { export const TextArea = React.forwardRef<HTMLTextAreaElement, Props>(({ invalid, className, ...props }, ref) => {
const theme = useTheme2(); const styles = useStyles2(getTextAreaStyle, invalid);
const styles = getTextAreaStyle(theme, invalid);
return <textarea {...props} className={cx(styles.textarea, className)} ref={ref} />; return <textarea {...props} className={cx(styles.textarea, className)} ref={ref} />;
}); });
const getTextAreaStyle = stylesFactory((theme: GrafanaTheme2, invalid = false) => { const getTextAreaStyle = (theme: GrafanaTheme2, invalid = false) => ({
return {
textarea: cx( textarea: cx(
sharedInputStyle(theme), sharedInputStyle(theme),
getFocusStyle(theme), getFocusStyle(theme),
@ -31,7 +29,6 @@ const getTextAreaStyle = stylesFactory((theme: GrafanaTheme2, invalid = false) =
borderColor: invalid ? theme.colors.error.border : theme.components.input.borderColor, borderColor: invalid ? theme.colors.error.border : theme.components.input.borderColor,
}) })
), ),
};
}); });
TextArea.displayName = 'TextArea'; TextArea.displayName = 'TextArea';

@ -2,10 +2,28 @@ import { css } from '@emotion/css';
import React from 'react'; import React from 'react';
import { CSSTransition } from 'react-transition-group'; import { CSSTransition } from 'react-transition-group';
import { stylesFactory } from '../../themes'; import { GrafanaTheme2 } from '@grafana/data';
const getStyles = stylesFactory((duration: number) => { import { useStyles2 } from '../../themes';
return {
type Props = {
children: React.ReactNode;
visible: boolean;
duration?: number;
};
export function FadeTransition(props: Props) {
const { visible, children, duration = 250 } = props;
const styles = useStyles2(getStyles, duration);
return (
<CSSTransition in={visible} mountOnEnter={true} unmountOnExit={true} timeout={duration} classNames={styles}>
{children}
</CSSTransition>
);
}
const getStyles = (_theme: GrafanaTheme2, duration: number) => ({
enter: css({ enter: css({
label: 'enter', label: 'enter',
opacity: 0, opacity: 0,
@ -24,21 +42,4 @@ const getStyles = stylesFactory((duration: number) => {
opacity: 0, opacity: 0,
transition: `opacity ${duration}ms ease-out`, transition: `opacity ${duration}ms ease-out`,
}), }),
};
}); });
type Props = {
children: React.ReactNode;
visible: boolean;
duration?: number;
};
export function FadeTransition(props: Props) {
const { visible, children, duration = 250 } = props;
const styles = getStyles(duration);
return (
<CSSTransition in={visible} mountOnEnter={true} unmountOnExit={true} timeout={duration} classNames={styles}>
{children}
</CSSTransition>
);
}

@ -2,10 +2,31 @@ import { css } from '@emotion/css';
import React from 'react'; import React from 'react';
import { CSSTransition } from 'react-transition-group'; import { CSSTransition } from 'react-transition-group';
import { stylesFactory } from '../../themes'; import { GrafanaTheme2 } from '@grafana/data';
const getStyles = stylesFactory((duration: number, measurement: 'width' | 'height', size: number) => { import { useStyles2 } from '../../themes';
return {
type Props = {
children: React.ReactNode;
visible: boolean;
size: number;
duration?: number;
horizontal?: boolean;
};
export function SlideOutTransition(props: Props) {
const { visible, children, duration = 250, horizontal, size } = props;
const styles = useStyles2(getStyles, duration, horizontal ? 'width' : 'height', size);
return (
<CSSTransition in={visible} mountOnEnter={true} unmountOnExit={true} timeout={duration} classNames={styles}>
{children}
</CSSTransition>
);
}
const getStyles = (_theme: GrafanaTheme2, duration: number, measurement: 'width' | 'height', size: number) => ({
enter: css({ enter: css({
label: 'enter', label: 'enter',
[`${measurement}`]: 0, [`${measurement}`]: 0,
@ -28,24 +49,4 @@ const getStyles = stylesFactory((duration: number, measurement: 'width' | 'heigh
[`${measurement}`]: 0, [`${measurement}`]: 0,
transition: `opacity ${duration}ms ease-out, ${measurement} ${duration}ms ease-out`, transition: `opacity ${duration}ms ease-out, ${measurement} ${duration}ms ease-out`,
}), }),
};
}); });
type Props = {
children: React.ReactNode;
visible: boolean;
size: number;
duration?: number;
horizontal?: boolean;
};
export function SlideOutTransition(props: Props) {
const { visible, children, duration = 250, horizontal, size } = props;
const styles = getStyles(duration, horizontal ? 'width' : 'height', size);
return (
<CSSTransition in={visible} mountOnEnter={true} unmountOnExit={true} timeout={duration} classNames={styles}>
{children}
</CSSTransition>
);
}

@ -3,13 +3,13 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React from 'react'; import React from 'react';
import { GraphSeriesValue } from '@grafana/data'; import { GrafanaTheme2, GraphSeriesValue } from '@grafana/data';
import { LegendDisplayMode, LegendPlacement } from '@grafana/schema'; import { LegendDisplayMode, LegendPlacement } from '@grafana/schema';
import { CustomScrollbar } from '../../components/CustomScrollbar/CustomScrollbar'; import { CustomScrollbar } from '../../components/CustomScrollbar/CustomScrollbar';
import { VizLegend } from '../../components/VizLegend/VizLegend'; import { VizLegend } from '../../components/VizLegend/VizLegend';
import { VizLegendItem } from '../../components/VizLegend/types'; import { VizLegendItem } from '../../components/VizLegend/types';
import { stylesFactory } from '../../themes'; import { useStyles2 } from '../../themes';
import { Graph, GraphProps } from './Graph'; import { Graph, GraphProps } from './Graph';
@ -25,21 +25,6 @@ export interface GraphWithLegendProps extends GraphProps {
onToggleSort: (sortBy: string) => void; onToggleSort: (sortBy: string) => void;
} }
const getGraphWithLegendStyles = stylesFactory(({ placement }: GraphWithLegendProps) => ({
wrapper: css({
display: 'flex',
flexDirection: placement === 'bottom' ? 'column' : 'row',
}),
graphContainer: css({
minHeight: '65%',
flexGrow: 1,
}),
legendContainer: css({
padding: '10px 0',
maxHeight: placement === 'bottom' ? '35%' : 'none',
}),
}));
const shouldHideLegendItem = (data: GraphSeriesValue[][], hideEmpty = false, hideZero = false) => { const shouldHideLegendItem = (data: GraphSeriesValue[][], hideEmpty = false, hideZero = false) => {
const isZeroOnlySeries = data.reduce((acc, current) => acc + (current[1] || 0), 0) === 0; const isZeroOnlySeries = data.reduce((acc, current) => acc + (current[1] || 0), 0) === 0;
const isNullOnlySeries = !data.reduce((acc, current) => acc && current[1] !== null, true); const isNullOnlySeries = !data.reduce((acc, current) => acc && current[1] !== null, true);
@ -72,7 +57,7 @@ export const GraphWithLegend = (props: GraphWithLegendProps) => {
children, children,
ariaLabel, ariaLabel,
} = props; } = props;
const { graphContainer, wrapper, legendContainer } = getGraphWithLegendStyles(props); const { graphContainer, wrapper, legendContainer } = useStyles2(getGraphWithLegendStyles, props.placement);
const legendItems = series.reduce<VizLegendItem[]>((acc, s) => { const legendItems = series.reduce<VizLegendItem[]>((acc, s) => {
return shouldHideLegendItem(s.data, hideEmpty, hideZero) return shouldHideLegendItem(s.data, hideEmpty, hideZero)
@ -130,3 +115,18 @@ export const GraphWithLegend = (props: GraphWithLegendProps) => {
</div> </div>
); );
}; };
const getGraphWithLegendStyles = (_theme: GrafanaTheme2, placement: LegendPlacement) => ({
wrapper: css({
display: 'flex',
flexDirection: placement === 'bottom' ? 'column' : 'row',
}),
graphContainer: css({
minHeight: '65%',
flexGrow: 1,
}),
legendContainer: css({
padding: '10px 0',
maxHeight: placement === 'bottom' ? '35%' : 'none',
}),
});

@ -3,7 +3,7 @@ import React, { ErrorInfo, useEffect } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { locationUtil, PageLayoutType } from '@grafana/data'; import { locationUtil, PageLayoutType } from '@grafana/data';
import { Button, ErrorWithStack, stylesFactory } from '@grafana/ui'; import { Button, ErrorWithStack, useStyles2 } from '@grafana/ui';
import { Page } from '../components/Page/Page'; import { Page } from '../components/Page/Page';
@ -15,6 +15,7 @@ interface Props {
export function GrafanaRouteError({ error, errorInfo }: Props) { export function GrafanaRouteError({ error, errorInfo }: Props) {
const location = useLocation(); const location = useLocation();
const isChunkLoadingError = error?.name === 'ChunkLoadError'; const isChunkLoadingError = error?.name === 'ChunkLoadError';
const style = useStyles2(getStyles);
useEffect(() => { useEffect(() => {
// Auto reload page 1 time if we have a chunk load error // Auto reload page 1 time if we have a chunk load error
@ -27,7 +28,7 @@ export function GrafanaRouteError({ error, errorInfo }: Props) {
return ( return (
<Page navId="error" layout={PageLayoutType.Canvas}> <Page navId="error" layout={PageLayoutType.Canvas}>
<div className={getStyles()}> <div className={style}>
{isChunkLoadingError && ( {isChunkLoadingError && (
<div> <div>
<h2>Unable to find application file</h2> <h2>Unable to find application file</h2>
@ -50,9 +51,7 @@ export function GrafanaRouteError({ error, errorInfo }: Props) {
); );
} }
const getStyles = stylesFactory(() => { const getStyles = () => css`
return css`
width: 500px; width: 500px;
margin: 64px auto; margin: 64px auto;
`; `;
});

@ -1,7 +1,7 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React from 'react'; import React from 'react';
import { Modal, stylesFactory } from '@grafana/ui'; import { Modal, useStyles2 } from '@grafana/ui';
import { OnRowOptionsUpdate, RowOptionsForm } from './RowOptionsForm'; import { OnRowOptionsUpdate, RowOptionsForm } from './RowOptionsForm';
@ -14,7 +14,8 @@ export interface RowOptionsModalProps {
} }
export const RowOptionsModal = ({ repeat, title, onDismiss, onUpdate, warning }: RowOptionsModalProps) => { export const RowOptionsModal = ({ repeat, title, onDismiss, onUpdate, warning }: RowOptionsModalProps) => {
const styles = getStyles(); const styles = useStyles2(getStyles);
return ( return (
<Modal isOpen={true} title="Row options" icon="copy" onDismiss={onDismiss} className={styles.modal}> <Modal isOpen={true} title="Row options" icon="copy" onDismiss={onDismiss} className={styles.modal}>
<RowOptionsForm repeat={repeat} title={title} onCancel={onDismiss} onUpdate={onUpdate} warning={warning} /> <RowOptionsForm repeat={repeat} title={title} onCancel={onDismiss} onUpdate={onUpdate} warning={warning} />
@ -22,11 +23,9 @@ export const RowOptionsModal = ({ repeat, title, onDismiss, onUpdate, warning }:
); );
}; };
const getStyles = stylesFactory(() => { const getStyles = () => ({
return {
modal: css` modal: css`
label: RowOptionsModal; label: RowOptionsModal;
width: 500px; width: 500px;
`, `,
};
}); });

@ -4,7 +4,7 @@ import AutoSizer from 'react-virtualized-auto-sizer';
import { areEqual, FixedSizeGrid as Grid } from 'react-window'; import { areEqual, FixedSizeGrid as Grid } from 'react-window';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { useTheme2, stylesFactory } from '@grafana/ui'; import { useStyles2 } from '@grafana/ui';
import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG'; import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG';
import { ResourceItem } from './FolderPickerTab'; import { ResourceItem } from './FolderPickerTab';
@ -26,8 +26,7 @@ const MemoizedCell = memo(function Cell(props: CellProps) {
const { cards, columnCount, onChange, selected } = data; const { cards, columnCount, onChange, selected } = data;
const singleColumnIndex = columnIndex + rowIndex * columnCount; const singleColumnIndex = columnIndex + rowIndex * columnCount;
const card = cards[singleColumnIndex]; const card = cards[singleColumnIndex];
const theme = useTheme2(); const styles = useStyles2(getStyles);
const styles = getStyles(theme);
return ( return (
<div style={style}> <div style={style}>
@ -56,8 +55,43 @@ const MemoizedCell = memo(function Cell(props: CellProps) {
); );
}, areEqual); }, areEqual);
const getStyles = stylesFactory((theme: GrafanaTheme2) => { interface CardProps {
return { onChange: (value: string) => void;
cards: ResourceItem[];
value?: string;
}
export const ResourceCards = (props: CardProps) => {
const { onChange, cards, value } = props;
const styles = useStyles2(getStyles);
return (
<AutoSizer defaultWidth={680}>
{({ width, height }) => {
const cardWidth = 90;
const cardHeight = 90;
const columnCount = Math.floor(width / cardWidth);
const rowCount = Math.ceil(cards.length / columnCount);
return (
<Grid
width={width}
height={height}
columnCount={columnCount}
columnWidth={cardWidth}
rowCount={rowCount}
rowHeight={cardHeight}
itemData={{ cards, columnCount, onChange, selected: value }}
className={styles.grid}
>
{MemoizedCell}
</Grid>
);
}}
</AutoSizer>
);
};
const getStyles = (theme: GrafanaTheme2) => ({
card: css` card: css`
display: inline-block; display: inline-block;
width: 90px; width: 90px;
@ -100,42 +134,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
grid: css` grid: css`
border: 1px solid ${theme.colors.border.medium}; border: 1px solid ${theme.colors.border.medium};
`, `,
};
}); });
interface CardProps {
onChange: (value: string) => void;
cards: ResourceItem[];
value?: string;
}
export const ResourceCards = (props: CardProps) => {
const { onChange, cards, value } = props;
const theme = useTheme2();
const styles = getStyles(theme);
return (
<AutoSizer defaultWidth={680}>
{({ width, height }) => {
const cardWidth = 90;
const cardHeight = 90;
const columnCount = Math.floor(width / cardWidth);
const rowCount = Math.ceil(cards.length / columnCount);
return (
<Grid
width={width}
height={height}
columnCount={columnCount}
columnWidth={cardWidth}
rowCount={rowCount}
rowHeight={cardHeight}
itemData={{ cards, columnCount, onChange, selected: value }}
className={styles.grid}
>
{MemoizedCell}
</Grid>
);
}}
</AutoSizer>
);
};

@ -5,9 +5,44 @@ import React from 'react';
// Services & Utils // Services & Utils
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '@grafana/ui'; import { useStyles2, useTheme2 } from '@grafana/ui';
// Types export interface Props {
width: number;
children: React.ReactNode;
onResize?: ResizeCallback;
}
export function ExploreDrawer(props: Props) {
const { width, children, onResize } = props;
const theme = useTheme2();
const styles = useStyles2(getStyles);
const drawerWidth = `${width + 31.5}px`;
return (
<Resizable
className={cx(styles.container, styles.drawerActive)}
defaultSize={{ width: drawerWidth, height: `${theme.components.horizontalDrawer.defaultHeight}px` }}
handleClasses={{ top: styles.rzHandle }}
enable={{
top: true,
right: false,
bottom: false,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
}}
maxHeight="100vh"
maxWidth={drawerWidth}
minWidth={drawerWidth}
onResize={onResize}
>
{children}
</Resizable>
);
}
const drawerSlide = (theme: GrafanaTheme2) => keyframes` const drawerSlide = (theme: GrafanaTheme2) => keyframes`
0% { 0% {
@ -19,8 +54,7 @@ const drawerSlide = (theme: GrafanaTheme2) => keyframes`
} }
`; `;
const getStyles = stylesFactory((theme: GrafanaTheme2) => { const getStyles = (theme: GrafanaTheme2) => ({
return {
container: css` container: css`
position: fixed !important; position: fixed !important;
bottom: 0; bottom: 0;
@ -48,42 +82,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
background: ${theme.colors.secondary.shade}; background: ${theme.colors.secondary.shade};
} }
`, `,
};
}); });
export interface Props {
width: number;
children: React.ReactNode;
onResize?: ResizeCallback;
}
export function ExploreDrawer(props: Props) {
const { width, children, onResize } = props;
const theme = useTheme2();
const styles = getStyles(theme);
const drawerWidth = `${width + 31.5}px`;
return (
<Resizable
className={cx(styles.container, styles.drawerActive)}
defaultSize={{ width: drawerWidth, height: `${theme.components.horizontalDrawer.defaultHeight}px` }}
handleClasses={{ top: styles.rzHandle }}
enable={{
top: true,
right: false,
bottom: false,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
}}
maxHeight="100vh"
maxWidth={drawerWidth}
minWidth={drawerWidth}
onResize={onResize}
>
{children}
</Resizable>
);
}

@ -1,8 +1,8 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { useMemo, useState, useEffect } from 'react'; import React, { useMemo, useState, useEffect } from 'react';
import { StandardEditorProps, SelectableValue, GrafanaTheme2 } from '@grafana/data'; import { StandardEditorProps, SelectableValue } from '@grafana/data';
import { Alert, Select, stylesFactory, useTheme2 } from '@grafana/ui'; import { Alert, Select, useStyles2 } from '@grafana/ui';
import { COUNTRIES_GAZETTEER_PATH, Gazetteer, getGazetteer } from '../gazetteer/gazetteer'; import { COUNTRIES_GAZETTEER_PATH, Gazetteer, getGazetteer } from '../gazetteer/gazetteer';
@ -34,7 +34,7 @@ export const GazetteerPathEditor = ({
context, context,
item, item,
}: StandardEditorProps<string, GazetteerPathEditorConfigSettings>) => { }: StandardEditorProps<string, GazetteerPathEditorConfigSettings>) => {
const styles = getStyles(useTheme2()); const styles = useStyles2(getStyles);
const [gaz, setGaz] = useState<Gazetteer>(); const [gaz, setGaz] = useState<Gazetteer>();
const settings = item.settings; const settings = item.settings;
@ -86,8 +86,7 @@ export const GazetteerPathEditor = ({
); );
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2) => { const getStyles = () => ({
return {
keys: css` keys: css`
margin-top: 4px; margin-top: 4px;
text-overflow: ellipsis; text-overflow: ellipsis;
@ -98,5 +97,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
margin-left: 4px; margin-left: 4px;
} }
`, `,
};
}); });

@ -9,7 +9,7 @@ import {
QueryResultMetaStat, QueryResultMetaStat,
TimeZone, TimeZone,
} from '@grafana/data'; } from '@grafana/data';
import { stylesFactory, useTheme2 } from '@grafana/ui'; import { useStyles2, useTheme2 } from '@grafana/ui';
interface InspectStatsTableProps { interface InspectStatsTableProps {
timeZone: TimeZone; timeZone: TimeZone;
@ -19,7 +19,7 @@ interface InspectStatsTableProps {
export const InspectStatsTable = ({ timeZone, name, stats }: InspectStatsTableProps) => { export const InspectStatsTable = ({ timeZone, name, stats }: InspectStatsTableProps) => {
const theme = useTheme2(); const theme = useTheme2();
const styles = getStyles(theme); const styles = useStyles2(getStyles);
if (!stats || !stats.length) { if (!stats || !stats.length) {
return null; return null;
@ -56,13 +56,11 @@ function formatStat(stat: QueryResultMetaStat, timeZone: TimeZone, theme: Grafan
return formattedValueToString(display(stat.value)); return formattedValueToString(display(stat.value));
} }
const getStyles = stylesFactory((theme: GrafanaTheme2) => { const getStyles = (theme: GrafanaTheme2) => ({
return {
wrapper: css` wrapper: css`
padding-bottom: ${theme.spacing(2)}; padding-bottom: ${theme.spacing(2)};
`, `,
cell: css` cell: css`
text-align: right; text-align: right;
`, `,
};
}); });

@ -2,16 +2,15 @@ import { css } from '@emotion/css';
import React from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '@grafana/ui'; import { useStyles2 } from '@grafana/ui';
type Props = { interface Props {
name: string; name: string;
traceIds: string[]; traceIds: string[];
}; }
export const InspectStatsTraceIdsTable = ({ name, traceIds }: Props) => { export const InspectStatsTraceIdsTable = ({ name, traceIds }: Props) => {
const theme = useTheme2(); const styles = useStyles2(getStyles);
const styles = getStyles(theme);
if (traceIds.length === 0) { if (traceIds.length === 0) {
return null; return null;
@ -35,13 +34,11 @@ export const InspectStatsTraceIdsTable = ({ name, traceIds }: Props) => {
); );
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2) => { const getStyles = (theme: GrafanaTheme2) => ({
return {
wrapper: css` wrapper: css`
padding-bottom: ${theme.spacing(2)}; padding-bottom: ${theme.spacing(2)};
`, `,
cell: css` cell: css`
text-align: right; text-align: right;
`, `,
};
}); });

@ -3,7 +3,7 @@ import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { locationService } from '@grafana/runtime'; import { locationService } from '@grafana/runtime';
import { Button, Modal, stylesFactory, useStyles2 } from '@grafana/ui'; import { Button, Modal, useStyles2 } from '@grafana/ui';
import { dashboardWatcher } from './dashboardWatcher'; import { dashboardWatcher } from './dashboardWatcher';
import { DashboardEvent, DashboardEventAction } from './types'; import { DashboardEvent, DashboardEventAction } from './types';
@ -50,12 +50,10 @@ export function DashboardChangedModal({ onDismiss, event }: Props) {
); );
} }
const getStyles = stylesFactory((theme: GrafanaTheme2) => { const getStyles = (theme: GrafanaTheme2) => ({
return {
modal: css({ width: '600px' }), modal: css({ width: '600px' }),
description: css({ description: css({
color: theme.colors.text.secondary, color: theme.colors.text.secondary,
paddingBottom: theme.spacing(1), paddingBottom: theme.spacing(1),
}), }),
};
}); });

@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
import React from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { Button, InfoBox, Portal, stylesFactory, useTheme2 } from '@grafana/ui'; import { Button, InfoBox, Portal, useStyles2, useTheme2 } from '@grafana/ui';
import { getModalStyles } from '@grafana/ui/src/components/Modal/getModalStyles'; import { getModalStyles } from '@grafana/ui/src/components/Modal/getModalStyles';
interface Props { interface Props {
@ -10,9 +10,8 @@ interface Props {
} }
export const TokenRevokedModal = (props: Props) => { export const TokenRevokedModal = (props: Props) => {
const styles = useStyles2(getStyles);
const theme = useTheme2(); const theme = useTheme2();
const styles = getStyles(theme);
const modalStyles = getModalStyles(theme); const modalStyles = getModalStyles(theme);
const showMaxConcurrentSessions = Boolean(props.maxConcurrentSessions); const showMaxConcurrentSessions = Boolean(props.maxConcurrentSessions);
@ -51,8 +50,7 @@ export const TokenRevokedModal = (props: Props) => {
); );
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2) => { const getStyles = (theme: GrafanaTheme2) => ({
return {
infobox: css` infobox: css`
margin-bottom: 0; margin-bottom: 0;
`, `,
@ -63,5 +61,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
background-color: ${theme.colors.background.canvas}; background-color: ${theme.colors.background.canvas};
opacity: 0.8; opacity: 0.8;
`, `,
};
}); });

@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
import React from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '@grafana/ui'; import { useStyles2 } from '@grafana/ui';
export interface SpaceProps { export interface SpaceProps {
v?: number; v?: number;
@ -11,8 +11,7 @@ export interface SpaceProps {
} }
export const Space = (props: SpaceProps) => { export const Space = (props: SpaceProps) => {
const theme = useTheme2(); const styles = useStyles2(getStyles, props);
const styles = getStyles(theme, props);
return <span className={cx(styles.wrapper)} />; return <span className={cx(styles.wrapper)} />;
}; };
@ -23,7 +22,7 @@ Space.defaultProps = {
layout: 'block', layout: 'block',
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2, props: SpaceProps) => ({ const getStyles = (theme: GrafanaTheme2, props: SpaceProps) => ({
wrapper: css([ wrapper: css([
{ {
paddingRight: theme.spacing(props.h ?? 0), paddingRight: theme.spacing(props.h ?? 0),
@ -36,4 +35,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, props: SpaceProps) => ({
display: 'block', display: 'block',
}, },
]), ]),
})); });

@ -3,7 +3,7 @@ import React, { useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { AccessoryButton, InputGroup } from '@grafana/experimental'; import { AccessoryButton, InputGroup } from '@grafana/experimental';
import { Input, stylesFactory, useTheme2 } from '@grafana/ui'; import { Input, useStyles2 } from '@grafana/ui';
import { MultiFilterCondition } from './MultiFilter'; import { MultiFilterCondition } from './MultiFilter';
@ -17,8 +17,7 @@ export interface Props {
export const MultiFilterItem = ({ filter, onChange, onDelete, keyPlaceholder }: Props) => { export const MultiFilterItem = ({ filter, onChange, onDelete, keyPlaceholder }: Props) => {
const [localKey, setLocalKey] = useState(filter.key || ''); const [localKey, setLocalKey] = useState(filter.key || '');
const [localValue, setLocalValue] = useState(filter.value?.join(', ') || ''); const [localValue, setLocalValue] = useState(filter.value?.join(', ') || '');
const theme = useTheme2(); const styles = useStyles2(getOperatorStyles);
const styles = getOperatorStyles(theme);
return ( return (
<div data-testid="cloudwatch-multifilter-item"> <div data-testid="cloudwatch-multifilter-item">
@ -59,9 +58,9 @@ export const MultiFilterItem = ({ filter, onChange, onDelete, keyPlaceholder }:
); );
}; };
const getOperatorStyles = stylesFactory((theme: GrafanaTheme2) => ({ const getOperatorStyles = (theme: GrafanaTheme2) => ({
root: css({ root: css({
padding: theme.spacing(0, 1), padding: theme.spacing(0, 1),
alignSelf: 'center', alignSelf: 'center',
}), }),
})); });

@ -4,7 +4,7 @@ import { useAsyncFn } from 'react-use';
import { GrafanaTheme2, SelectableValue, toOption } from '@grafana/data'; import { GrafanaTheme2, SelectableValue, toOption } from '@grafana/data';
import { AccessoryButton, InputGroup } from '@grafana/experimental'; import { AccessoryButton, InputGroup } from '@grafana/experimental';
import { Select, stylesFactory, useTheme2 } from '@grafana/ui'; import { Select, useStyles2 } from '@grafana/ui';
import { CloudWatchDatasource } from '../../../datasource'; import { CloudWatchDatasource } from '../../../datasource';
import { Dimensions, MetricStat } from '../../../types'; import { Dimensions, MetricStat } from '../../../types';
@ -76,8 +76,7 @@ export const FilterItem = ({
metricName, metricName,
accountId, accountId,
]); ]);
const theme = useTheme2(); const styles = useStyles2(getOperatorStyles);
const styles = getOperatorStyles(theme);
return ( return (
<div data-testid="cloudwatch-dimensions-filter-item"> <div data-testid="cloudwatch-dimensions-filter-item">
@ -119,9 +118,9 @@ export const FilterItem = ({
); );
}; };
const getOperatorStyles = stylesFactory((theme: GrafanaTheme2) => ({ const getOperatorStyles = (theme: GrafanaTheme2) => ({
root: css({ root: css({
padding: theme.spacing(0, 1), padding: theme.spacing(0, 1),
alignSelf: 'center', alignSelf: 'center',
}), }),
})); });

@ -6,50 +6,28 @@ import { DataSourceInstanceSettings, VariableSuggestion } from '@grafana/data';
import { import {
Button, Button,
DataLinkInput, DataLinkInput,
stylesFactory,
InlineField, InlineField,
InlineSwitch, InlineSwitch,
InlineFieldRow, InlineFieldRow,
InlineLabel, InlineLabel,
Input, Input,
useStyles2,
} from '@grafana/ui'; } from '@grafana/ui';
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker'; import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
import { DataLinkConfig } from '../types'; import { DataLinkConfig } from '../types';
const getStyles = stylesFactory(() => ({ interface Props {
firstRow: css`
display: flex;
`,
nameField: css`
flex: 2;
`,
regexField: css`
flex: 3;
`,
row: css`
display: flex;
align-items: baseline;
`,
urlField: css`
display: flex;
flex: 1;
`,
urlDisplayLabelField: css`
flex: 1;
`,
}));
type Props = {
value: DataLinkConfig; value: DataLinkConfig;
onChange: (value: DataLinkConfig) => void; onChange: (value: DataLinkConfig) => void;
onDelete: () => void; onDelete: () => void;
suggestions: VariableSuggestion[]; suggestions: VariableSuggestion[];
className?: string; className?: string;
}; }
export const DataLink = (props: Props) => { export const DataLink = (props: Props) => {
const { value, onChange, onDelete, suggestions, className } = props; const { value, onChange, onDelete, suggestions, className } = props;
const styles = getStyles(); const styles = useStyles2(getStyles);
const [showInternalLink, setShowInternalLink] = useInternalLink(value.datasourceUid); const [showInternalLink, setShowInternalLink] = useInternalLink(value.datasourceUid);
const handleChange = (field: keyof typeof value) => (event: React.ChangeEvent<HTMLInputElement>) => { const handleChange = (field: keyof typeof value) => (event: React.ChangeEvent<HTMLInputElement>) => {
@ -173,3 +151,26 @@ function useInternalLink(datasourceUid?: string): [boolean, Dispatch<SetStateAct
return [showInternalLink, setShowInternalLink]; return [showInternalLink, setShowInternalLink];
} }
const getStyles = () => ({
firstRow: css`
display: flex;
`,
nameField: css`
flex: 2;
`,
regexField: css`
flex: 3;
`,
row: css`
display: flex;
align-items: baseline;
`,
urlField: css`
display: flex;
flex: 1;
`,
urlDisplayLabelField: css`
flex: 1;
`,
});

@ -2,7 +2,7 @@ import { css } from '@emotion/css';
import React, { ComponentProps } from 'react'; import React, { ComponentProps } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { Field, Icon, PopoverContent, ReactUtils, stylesFactory, Tooltip, useTheme2 } from '@grafana/ui'; import { Field, Icon, PopoverContent, ReactUtils, Tooltip, useStyles2 } from '@grafana/ui';
interface EditorFieldProps extends ComponentProps<typeof Field> { interface EditorFieldProps extends ComponentProps<typeof Field> {
label: string; label: string;
@ -15,8 +15,7 @@ interface EditorFieldProps extends ComponentProps<typeof Field> {
export const EditorField = (props: EditorFieldProps) => { export const EditorField = (props: EditorFieldProps) => {
const { label, optional, tooltip, children, width, ...fieldProps } = props; const { label, optional, tooltip, children, width, ...fieldProps } = props;
const theme = useTheme2(); const styles = useStyles2(getStyles, width);
const styles = getStyles(theme, width);
// Null check for backward compatibility // Null check for backward compatibility
const childInputId = fieldProps?.htmlFor || ReactUtils?.getChildId(children); const childInputId = fieldProps?.htmlFor || ReactUtils?.getChildId(children);
@ -45,8 +44,7 @@ export const EditorField = (props: EditorFieldProps) => {
); );
}; };
const getStyles = stylesFactory((theme: GrafanaTheme2, width?: number | string) => { const getStyles = (theme: GrafanaTheme2, width?: number | string) => ({
return {
space: css({ space: css({
paddingRight: theme.spacing(0), paddingRight: theme.spacing(0),
paddingBottom: theme.spacing(0.5), paddingBottom: theme.spacing(0.5),
@ -72,5 +70,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, width?: number | string)
color: theme.colors.text.primary, color: theme.colors.text.primary,
}, },
}), }),
};
}); });

Loading…
Cancel
Save