diff --git a/packages/grafana-ui/src/components/Button/FullWidthButtonContainer.tsx b/packages/grafana-ui/src/components/Button/FullWidthButtonContainer.tsx index 446c9a2cbed..9c3fcfa7ca7 100644 --- a/packages/grafana-ui/src/components/Button/FullWidthButtonContainer.tsx +++ b/packages/grafana-ui/src/components/Button/FullWidthButtonContainer.tsx @@ -1,20 +1,20 @@ import { css, cx } from '@emotion/css'; import React from 'react'; -import { stylesFactory } from '../../themes'; +import { useStyles2 } from '../../themes'; export interface Props { className?: string; } export const FullWidthButtonContainer = ({ className, children }: React.PropsWithChildren) => { - const styles = getStyles(); + const styles = useStyles2(getStyles); return
{children}
; }; -const getStyles = stylesFactory(() => { - return css({ +const getStyles = () => + css({ display: 'flex', button: { @@ -31,4 +31,3 @@ const getStyles = stylesFactory(() => { textAlign: 'center', }, }); -}); diff --git a/packages/grafana-ui/src/components/ButtonCascader/ButtonCascader.tsx b/packages/grafana-ui/src/components/ButtonCascader/ButtonCascader.tsx index c849c8edbfc..3fe1450c51c 100644 --- a/packages/grafana-ui/src/components/ButtonCascader/ButtonCascader.tsx +++ b/packages/grafana-ui/src/components/ButtonCascader/ButtonCascader.tsx @@ -4,7 +4,7 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory, useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { IconName } from '../../types/icon'; import { Button, ButtonProps } from '../Button'; import { CascaderOption } from '../Cascader/Cascader'; @@ -27,27 +27,9 @@ export interface ButtonCascaderProps { 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) => { const { onChange, className, loadData, icon, buttonProps, hideDownIcon, variant, disabled, ...rest } = props; - const theme = useTheme2(); - const styles = getStyles(theme); + const styles = useStyles2(getStyles); // 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. @@ -72,3 +54,20 @@ export const ButtonCascader = (props: ButtonCascaderProps) => { }; 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', + }), + }, + }; +}; diff --git a/packages/grafana-ui/src/components/Card/Card.tsx b/packages/grafana-ui/src/components/Card/Card.tsx index 858d985383f..45b7683c623 100644 --- a/packages/grafana-ui/src/components/Card/Card.tsx +++ b/packages/grafana-ui/src/components/Card/Card.tsx @@ -3,7 +3,7 @@ import React, { memo, cloneElement, FC, useMemo, useContext, ReactNode } from 'r import { GrafanaTheme2 } from '@grafana/data'; -import { useStyles2, useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { getFocusStyles } from '../../themes/mixins'; 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 onCardClick = onClick && !disabled ? onClick : undefined; - const theme = useTheme2(); - const styles = getCardContainerStyles(theme, disabled, disableHover, isSelected); + const styles = useStyles2(getCardContainerStyles, disabled, disableHover, isSelected); return ( { - const theme = useTheme2(); - const { oldContainer } = getCardContainerStyles(theme, disableEvents, disableHover, isSelected); + const { oldContainer } = useStyles2(getCardContainerStyles, disableEvents, disableHover, isSelected); + return (
{children} @@ -66,71 +66,74 @@ export const CardContainer = ({ ); }; -export const getCardContainerStyles = stylesFactory( - (theme: GrafanaTheme2, disabled = false, disableHover = false, isSelected) => { - const isSelectable = isSelected !== undefined; +export const getCardContainerStyles = ( + theme: GrafanaTheme2, + disabled = false, + disableHover = false, + isSelected?: boolean +) => { + const isSelectable = isSelected !== undefined; - return { - container: css({ - display: 'grid', - position: 'relative', - gridTemplateColumns: 'auto 1fr auto', - gridTemplateRows: '1fr auto auto auto', - gridAutoColumns: '1fr', - gridAutoFlow: 'row', - gridTemplateAreas: ` + return { + container: css({ + display: 'grid', + position: 'relative', + gridTemplateColumns: 'auto 1fr auto', + gridTemplateRows: '1fr auto auto auto', + gridAutoColumns: '1fr', + gridAutoFlow: 'row', + gridTemplateAreas: ` "Figure Heading Tags" "Figure Meta Tags" "Figure Description Tags" "Figure Actions Secondary"`, - width: '100%', - padding: theme.spacing(2), - background: theme.colors.background.secondary, - borderRadius: theme.shape.radius.default, - marginBottom: '8px', - pointerEvents: disabled ? 'none' : 'auto', - transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], { - duration: theme.transitions.duration.short, - }), - - ...(!disableHover && { - '&:hover': { - background: theme.colors.emphasize(theme.colors.background.secondary, 0.03), - cursor: 'pointer', - zIndex: 1, - }, - '&:focus': styleMixins.getFocusStyles(theme), - }), + width: '100%', + padding: theme.spacing(2), + background: theme.colors.background.secondary, + borderRadius: theme.shape.radius.default, + marginBottom: '8px', + pointerEvents: disabled ? 'none' : 'auto', + transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], { + duration: theme.transitions.duration.short, + }), - ...(isSelectable && { + ...(!disableHover && { + '&:hover': { + background: theme.colors.emphasize(theme.colors.background.secondary, 0.03), cursor: 'pointer', - }), + zIndex: 1, + }, + '&:focus': styleMixins.getFocusStyles(theme), + }), - ...(isSelected && { - outline: `solid 2px ${theme.colors.primary.border}`, - }), + ...(isSelectable && { + cursor: 'pointer', }), - oldContainer: css({ - display: 'flex', - width: '100%', - background: theme.colors.background.secondary, - borderRadius: theme.shape.radius.default, - position: 'relative', - pointerEvents: disabled ? 'none' : 'auto', - marginBottom: theme.spacing(1), - transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], { - duration: theme.transitions.duration.short, - }), - ...(!disableHover && { - '&:hover': { - background: theme.colors.emphasize(theme.colors.background.secondary, 0.03), - cursor: 'pointer', - zIndex: 1, - }, - '&:focus': styleMixins.getFocusStyles(theme), - }), + ...(isSelected && { + outline: `solid 2px ${theme.colors.primary.border}`, + }), + }), + oldContainer: css({ + display: 'flex', + width: '100%', + background: theme.colors.background.secondary, + borderRadius: theme.shape.radius.default, + position: 'relative', + pointerEvents: disabled ? 'none' : 'auto', + marginBottom: theme.spacing(1), + transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], { + duration: theme.transitions.duration.short, }), - }; - } -); + + ...(!disableHover && { + '&:hover': { + background: theme.colors.emphasize(theme.colors.background.secondary, 0.03), + cursor: 'pointer', + zIndex: 1, + }, + '&:focus': styleMixins.getFocusStyles(theme), + }), + }), + }; +}; diff --git a/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx b/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx index ca69016f404..99914a5a4c3 100644 --- a/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx +++ b/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx @@ -4,7 +4,7 @@ import React, { useState } from 'react'; import { DataFrame, DataLink, GrafanaTheme2, VariableSuggestion } from '@grafana/data'; -import { stylesFactory, useTheme2 } from '../../../themes'; +import { useStyles2 } from '../../../themes'; import { Button } from '../../Button/Button'; import { Modal } from '../../Modal/Modal'; @@ -19,11 +19,10 @@ interface DataLinksInlineEditorProps { } export const DataLinksInlineEditor = ({ links, onChange, getSuggestions, data }: DataLinksInlineEditorProps) => { - const theme = useTheme2(); const [editIndex, setEditIndex] = useState(null); const [isNew, setIsNew] = useState(false); - const styles = getDataLinksInlineEditorStyles(theme); + const styles = useStyles2(getDataLinksInlineEditorStyles); const linksSafe: DataLink[] = links ?? []; const isEditing = editIndex !== null; @@ -110,10 +109,8 @@ export const DataLinksInlineEditor = ({ links, onChange, getSuggestions, data }: ); }; -const getDataLinksInlineEditorStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - wrapper: css({ - marginBottom: theme.spacing(2), - }), - }; +const getDataLinksInlineEditorStyles = (theme: GrafanaTheme2) => ({ + wrapper: css({ + marginBottom: theme.spacing(2), + }), }); diff --git a/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksListItem.tsx b/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksListItem.tsx index 86044da8782..97a23834fe7 100644 --- a/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksListItem.tsx +++ b/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksListItem.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { DataFrame, DataLink, GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory, useTheme2 } from '../../../themes'; +import { useStyles2 } from '../../../themes'; import { isCompactUrl } from '../../../utils/dataLinks'; import { FieldValidationMessage } from '../../Forms/FieldValidationMessage'; import { IconButton } from '../../IconButton/IconButton'; @@ -19,8 +19,7 @@ export interface DataLinksListItemProps { } export const DataLinksListItem = ({ link, onEdit, onRemove }: DataLinksListItemProps) => { - const theme = useTheme2(); - const styles = getDataLinkListItemStyles(theme); + const styles = useStyles2(getDataLinkListItemStyles); const { title = '', url = '' } = link; 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 { wrapper: css({ marginBottom: theme.spacing(2), @@ -95,4 +94,4 @@ const getDataLinkListItemStyles = stylesFactory((theme: GrafanaTheme2) => { maxWidth: '90%', }), }; -}); +}; diff --git a/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx b/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx index 8802e321939..0751890d5a0 100644 --- a/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx +++ b/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx @@ -4,7 +4,7 @@ import React, { PureComponent } from 'react'; import { DataSourceSettings } from '@grafana/data'; -import { stylesFactory } from '../../themes'; +import { useStyles2 } from '../../themes'; import { Button } from '../Button'; import { FormField } from '../FormField/FormField'; import { Icon } from '../Icon/Icon'; @@ -36,26 +36,25 @@ interface CustomHeaderRowProps { onBlur: () => void; } -const getCustomHeaderRowStyles = stylesFactory(() => { - return { - layout: css({ - display: 'flex', - alignItems: 'center', - marginBottom: '4px', - '> *': { - marginLeft: '4px', - marginBottom: 0, - height: '100%', - '&:first-child, &:last-child': { - marginLeft: 0, - }, +const getCustomHeaderRowStyles = () => ({ + layout: css({ + display: 'flex', + alignItems: 'center', + marginBottom: '4px', + '> *': { + marginLeft: '4px', + marginBottom: 0, + height: '100%', + '&:first-child, &:last-child': { + marginLeft: 0, }, - }), - }; + }, + }), }); const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }: CustomHeaderRowProps) => { - const styles = getCustomHeaderRowStyles(); + const styles = useStyles2(getCustomHeaderRowStyles); + return (
{ const [isOpen, setIsOpen] = useState(false); - const theme = useTheme2(); - const styles = getStyles(theme, disabled); + const styles = useStyles2(getStyles, disabled); const onOpen = (event: FormEvent) => { 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 }); return { container: css({ @@ -163,4 +161,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, disabled = false) => { marginRight: theme.spacing(0.5), }), }; -}); +}; diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx index 40679f0ea27..3c3b2d4b830 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx @@ -16,7 +16,7 @@ import { } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { useStyles2, useTheme2 } from '../../themes/ThemeContext'; +import { useStyles2 } from '../../themes/ThemeContext'; import { t, Trans } from '../../utils/i18n'; import { ButtonGroup } from '../Button'; import { getModalStyles } from '../Modal/getModalStyles'; @@ -106,9 +106,8 @@ export function TimeRangePicker(props: TimeRangePickerProps) { ); const { dialogProps } = useDialog({}, overlayRef); - const theme = useTheme2(); const styles = useStyles2(getStyles); - const { modalBackdrop } = getModalStyles(theme); + const { modalBackdrop } = useStyles2(getModalStyles); const hasAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to); const variant = isSynced ? 'active' : isOnCanvas ? 'canvas' : 'default'; diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx index 2e32795301e..71b56bd5425 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx @@ -7,7 +7,7 @@ import React, { FormEvent, memo } from 'react'; import { DateTime, GrafanaTheme2, TimeZone } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { useTheme2 } from '../../../themes'; +import { useStyles2, useTheme2 } from '../../../themes'; import { getModalStyles } from '../../Modal/getModalStyles'; import { Body } from './CalendarBody'; @@ -68,7 +68,7 @@ export interface TimePickerCalendarProps { function TimePickerCalendar(props: TimePickerCalendarProps) { const theme = useTheme2(); - const { modalBackdrop } = getModalStyles(theme); + const { modalBackdrop } = useStyles2(getModalStyles); const styles = getStyles(theme, props.isReversed); const { isOpen, isFullscreen, onClose } = props; const ref = React.createRef(); diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx index 48d28f1e2fe..a0bc70b19cc 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx @@ -4,7 +4,7 @@ import React, { memo, useMemo, useState } from 'react'; import { GrafanaTheme2, isDateTime, rangeUtil, RawTimeRange, TimeOption, TimeRange, TimeZone } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { stylesFactory, useTheme2 } from '../../../themes'; +import { useStyles2, useTheme2 } from '../../../themes'; import { getFocusStyles } from '../../../themes/mixins'; import { t, Trans } from '../../../utils/i18n'; import { CustomScrollbar } from '../../CustomScrollbar/CustomScrollbar'; @@ -63,8 +63,7 @@ export const TimePickerContentWithScreenSize = (props: PropsWithScreenSize) => { const isHistoryEmpty = !history?.length; const isContainerTall = (isFullscreen && showHistory) || (!isFullscreen && ((showHistory && !isHistoryEmpty) || !hideQuickRanges)); - const theme = useTheme2(); - const styles = getStyles(theme, isReversed, hideQuickRanges, isContainerTall, isFullscreen); + const styles = useStyles2(getStyles, isReversed, hideQuickRanges, isContainerTall, isFullscreen); const historyOptions = mapToHistoryOptions(history, timeZone); const timeOption = useTimeOption(value.raw, quickOptions); const [searchTerm, setSearchQuery] = useState(''); @@ -124,8 +123,7 @@ export const TimePickerContent = (props: Props) => { const NarrowScreenForm = (props: FormProps) => { const { value, hideQuickRanges, onChange, timeZone, historyOptions = [], showHistory } = props; - const theme = useTheme2(); - const styles = getNarrowScreenStyles(theme); + const styles = useStyles2(getNarrowScreenStyles); const isAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to); const [collapsedFlag, setCollapsedFlag] = useState(!isAbsolute); const collapsed = hideQuickRanges ? false : collapsedFlag; @@ -176,8 +174,7 @@ const NarrowScreenForm = (props: FormProps) => { const FullScreenForm = (props: FormProps) => { const { onChange, value, timeZone, fiscalYearStartMonth, isReversed, historyOptions } = props; - const theme = useTheme2(); - const styles = getFullScreenStyles(theme, props.hideQuickRanges); + const styles = useStyles2(getFullScreenStyles, props.hideQuickRanges); const onChangeTimeOption = (timeOption: TimeOption) => { return onChange(mapOptionToTimeRange(timeOption, timeZone)); }; @@ -214,8 +211,7 @@ const FullScreenForm = (props: FormProps) => { }; const EmptyRecentList = memo(() => { - const theme = useTheme2(); - const styles = getEmptyListStyles(theme); + const styles = useStyles2(getEmptyListStyles); const emptyRecentListText = t( '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." @@ -263,104 +259,102 @@ const useTimeOption = (raw: RawTimeRange, quickOptions: TimeOption[]): TimeOptio }, [raw, quickOptions]); }; -const getStyles = stylesFactory((theme: GrafanaTheme2, isReversed, hideQuickRanges, isContainerTall, isFullscreen) => { - return { - container: css({ - background: theme.colors.background.primary, - boxShadow: theme.shadows.z3, - width: `${isFullscreen ? '546px' : '262px'}`, - borderRadius: theme.shape.radius.default, - border: `1px solid ${theme.colors.border.weak}`, - [`${isReversed ? 'left' : 'right'}`]: 0, - }), - body: css({ - display: 'flex', - flexDirection: 'row-reverse', - height: `${isContainerTall ? '381px' : '217px'}`, - maxHeight: '100vh', - }), - leftSide: css({ - display: 'flex', - flexDirection: 'column', - borderRight: `${isReversed ? 'none' : `1px solid ${theme.colors.border.weak}`}`, - width: `${!hideQuickRanges ? '60%' : '100%'}`, - overflow: 'hidden', - order: isReversed ? 1 : 0, - }), - rightSide: css({ - width: `${isFullscreen ? '40%' : '100%'}; !important`, - borderRight: isReversed ? `1px solid ${theme.colors.border.weak}` : 'none', - display: 'flex', - flexDirection: 'column', - }), - timeRangeFilter: css({ - padding: theme.spacing(1), - }), - spacing: css({ - marginTop: '16px', - }), - }; +const getStyles = ( + theme: GrafanaTheme2, + isReversed?: boolean, + hideQuickRanges?: boolean, + isContainerTall?: boolean, + isFullscreen?: boolean +) => ({ + container: css({ + background: theme.colors.background.primary, + boxShadow: theme.shadows.z3, + width: `${isFullscreen ? '546px' : '262px'}`, + borderRadius: theme.shape.radius.default, + border: `1px solid ${theme.colors.border.weak}`, + [`${isReversed ? 'left' : 'right'}`]: 0, + }), + body: css({ + display: 'flex', + flexDirection: 'row-reverse', + height: `${isContainerTall ? '381px' : '217px'}`, + maxHeight: '100vh', + }), + leftSide: css({ + display: 'flex', + flexDirection: 'column', + borderRight: `${isReversed ? 'none' : `1px solid ${theme.colors.border.weak}`}`, + width: `${!hideQuickRanges ? '60%' : '100%'}`, + overflow: 'hidden', + order: isReversed ? 1 : 0, + }), + rightSide: css({ + width: `${isFullscreen ? '40%' : '100%'}; !important`, + borderRight: isReversed ? `1px solid ${theme.colors.border.weak}` : 'none', + display: 'flex', + flexDirection: 'column', + }), + timeRangeFilter: css({ + padding: theme.spacing(1), + }), + spacing: css({ + marginTop: '16px', + }), }); -const getNarrowScreenStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - header: css({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - borderBottom: `1px solid ${theme.colors.border.weak}`, - padding: '7px 9px 7px 9px', - }), - expandButton: css({ - backgroundColor: 'transparent', - border: 'none', - display: 'flex', - width: '100%', +const getNarrowScreenStyles = (theme: GrafanaTheme2) => ({ + header: css({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + borderBottom: `1px solid ${theme.colors.border.weak}`, + padding: '7px 9px 7px 9px', + }), + expandButton: css({ + backgroundColor: 'transparent', + border: 'none', + display: 'flex', + width: '100%', - '&:focus-visible': getFocusStyles(theme), - }), - body: css({ - borderBottom: `1px solid ${theme.colors.border.weak}`, - }), - form: css({ - padding: '7px 9px 7px 9px', - }), - }; + '&:focus-visible': getFocusStyles(theme), + }), + body: css({ + borderBottom: `1px solid ${theme.colors.border.weak}`, + }), + form: css({ + padding: '7px 9px 7px 9px', + }), }); -const getFullScreenStyles = stylesFactory((theme: GrafanaTheme2, hideQuickRanges?: boolean) => { - return { - container: css({ - paddingTop: '9px', - paddingLeft: '11px', - paddingRight: !hideQuickRanges ? '20%' : '11px', - }), - title: css({ - marginBottom: '11px', - }), - recent: css({ - flexGrow: 1, - display: 'flex', - flexDirection: 'column', - justifyContent: 'flex-end', - paddingTop: theme.spacing(1), - }), - }; +const getFullScreenStyles = (theme: GrafanaTheme2, hideQuickRanges?: boolean) => ({ + container: css({ + paddingTop: '9px', + paddingLeft: '11px', + paddingRight: !hideQuickRanges ? '20%' : '11px', + }), + title: css({ + marginBottom: '11px', + }), + recent: css({ + flexGrow: 1, + display: 'flex', + flexDirection: 'column', + justifyContent: 'flex-end', + paddingTop: theme.spacing(1), + }), }); -const getEmptyListStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - container: css({ - padding: '12px', - margin: '12px', +const getEmptyListStyles = (theme: GrafanaTheme2) => ({ + container: css({ + padding: '12px', + margin: '12px', - 'a, span': { - fontSize: '13px', - }, - }), - link: css({ - color: theme.colors.text.link, - }), - }; + 'a, span': { + fontSize: '13px', + }, + }), + link: css({ + color: theme.colors.text.link, + }), }); diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerFooter.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerFooter.tsx index 3286314f7ef..a750b66d9e8 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerFooter.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerFooter.tsx @@ -5,7 +5,7 @@ import React, { useCallback, useState } from 'react'; import { getTimeZoneInfo, GrafanaTheme2, TimeZone } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { stylesFactory, useTheme2 } from '../../../themes'; +import { useStyles2 } from '../../../themes'; import { t, Trans } from '../../../utils/i18n'; import { Button } from '../../Button'; import { Field } from '../../Forms/Field'; @@ -46,8 +46,7 @@ export const TimePickerFooter = (props: Props) => { [isEditing, setEditing] ); - const theme = useTheme2(); - const style = getStyle(theme); + const style = useStyles2(getStyle); if (!isString(timeZone)) { return null; @@ -136,43 +135,41 @@ export const TimePickerFooter = (props: Props) => { ); }; -const getStyle = stylesFactory((theme: GrafanaTheme2) => { - return { - container: css({ - borderTop: `1px solid ${theme.colors.border.weak}`, - padding: '11px', - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - }), - editContainer: css({ - borderTop: `1px solid ${theme.colors.border.weak}`, - padding: '11px', - justifyContent: 'space-between', - alignItems: 'center', - }), - spacer: css({ - marginLeft: '7px', - }), - timeSettingContainer: css({ - paddingTop: theme.spacing(1), - }), - fiscalYearField: css({ - marginBottom: 0, - }), - timeZoneContainer: css({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - flexGrow: 1, - }), - timeZone: css({ - display: 'flex', - flexDirection: 'row', - alignItems: 'baseline', - flexGrow: 1, - }), - }; +const getStyle = (theme: GrafanaTheme2) => ({ + container: css({ + borderTop: `1px solid ${theme.colors.border.weak}`, + padding: '11px', + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }), + editContainer: css({ + borderTop: `1px solid ${theme.colors.border.weak}`, + padding: '11px', + justifyContent: 'space-between', + alignItems: 'center', + }), + spacer: css({ + marginLeft: '7px', + }), + timeSettingContainer: css({ + paddingTop: theme.spacing(1), + }), + fiscalYearField: css({ + marginBottom: 0, + }), + timeZoneContainer: css({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + flexGrow: 1, + }), + timeZone: css({ + display: 'flex', + flexDirection: 'row', + alignItems: 'baseline', + flexGrow: 1, + }), }); diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeList.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeList.tsx index ea834651bff..0833e099046 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeList.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeList.tsx @@ -3,32 +3,12 @@ import React, { ReactNode } from 'react'; import { TimeOption } from '@grafana/data'; -import { stylesFactory } from '../../../themes'; +import { useStyles2 } from '../../../themes'; import { t } from '../../../utils/i18n'; import { TimePickerTitle } from './TimePickerTitle'; 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 { title?: string; options: TimeOption[]; @@ -38,7 +18,7 @@ interface Props { } export const TimeRangeList = (props: Props) => { - const styles = getStyles(); + const styles = useStyles2(getStyles); const { title, options, placeholderEmpty } = props; if (typeof placeholderEmpty !== 'undefined' && options.length <= 0) { @@ -62,7 +42,7 @@ export const TimeRangeList = (props: Props) => { }; const Options = ({ options, value, onChange, title }: Props) => { - const styles = getOptionsStyles(); + const styles = useStyles2(getOptionsStyles); return ( <> @@ -92,3 +72,19 @@ function isEqual(x: TimeOption, y?: TimeOption): boolean { } 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', + }), +}); diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneOption.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneOption.tsx index d48fbcf964b..0db448f3606 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneOption.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneOption.tsx @@ -4,8 +4,7 @@ import React, { PropsWithChildren, RefCallback } from 'react'; import { GrafanaTheme2, SelectableValue, getTimeZoneInfo } from '@grafana/data'; -import { useTheme2 } from '../../../themes/ThemeContext'; -import { stylesFactory } from '../../../themes/stylesFactory'; +import { useStyles2 } from '../../../themes'; import { Icon } from '../../Icon/Icon'; import { TimeZoneDescription } from './TimeZoneDescription'; @@ -28,8 +27,7 @@ export interface SelectableZone extends SelectableValue { export const WideTimeZoneOption = (props: PropsWithChildren) => { const { children, innerProps, innerRef, data, isSelected, isFocused } = props; - const theme = useTheme2(); - const styles = getStyles(theme); + const styles = useStyles2(getStyles); const timestamp = Date.now(); const containerStyles = cx(styles.container, isFocused && styles.containerFocused); @@ -68,8 +66,7 @@ export const WideTimeZoneOption = (props: PropsWithChildren) => { export const CompactTimeZoneOption = (props: React.PropsWithChildren) => { const { children, innerProps, innerRef, data, isSelected, isFocused } = props; - const theme = useTheme2(); - const styles = getStyles(theme); + const styles = useStyles2(getStyles); const timestamp = Date.now(); const containerStyles = cx(styles.container, isFocused && styles.containerFocused); @@ -113,49 +110,47 @@ export const CompactTimeZoneOption = (props: React.PropsWithChildren) => ); }; -const getStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - container: css({ - display: 'flex', - alignItems: 'center', - flexDirection: 'row', - flexShrink: 0, - whiteSpace: 'nowrap', - cursor: 'pointer', - padding: '6px 8px 4px', - - '&:hover': { - background: theme.colors.action.hover, - }, - }), - containerFocused: css({ +const getStyles = (theme: GrafanaTheme2) => ({ + container: css({ + display: 'flex', + alignItems: 'center', + flexDirection: 'row', + flexShrink: 0, + whiteSpace: 'nowrap', + cursor: 'pointer', + padding: '6px 8px 4px', + + '&:hover': { background: theme.colors.action.hover, - }), - body: css({ - display: 'flex', - fontWeight: theme.typography.fontWeightMedium, - flexDirection: 'column', - flexGrow: 1, - }), - row: css({ - display: 'flex', - flexDirection: 'row', - }), - leftColumn: css({ - flexGrow: 1, - textOverflow: 'ellipsis', - }), - rightColumn: css({ - justifyContent: 'flex-end', - alignItems: 'center', - }), - wideRow: css({ - display: 'flex', - flexDirection: 'row', - alignItems: 'baseline', - }), - spacer: css({ - marginLeft: '6px', - }), - }; + }, + }), + containerFocused: css({ + background: theme.colors.action.hover, + }), + body: css({ + display: 'flex', + fontWeight: theme.typography.fontWeightMedium, + flexDirection: 'column', + flexGrow: 1, + }), + row: css({ + display: 'flex', + flexDirection: 'row', + }), + leftColumn: css({ + flexGrow: 1, + textOverflow: 'ellipsis', + }), + rightColumn: css({ + justifyContent: 'flex-end', + alignItems: 'center', + }), + wideRow: css({ + display: 'flex', + flexDirection: 'row', + alignItems: 'baseline', + }), + spacer: css({ + marginLeft: '6px', + }), }); diff --git a/packages/grafana-ui/src/components/ErrorBoundary/ErrorWithStack.tsx b/packages/grafana-ui/src/components/ErrorBoundary/ErrorWithStack.tsx index 5009b8f5df4..f5d2395e834 100644 --- a/packages/grafana-ui/src/components/ErrorBoundary/ErrorWithStack.tsx +++ b/packages/grafana-ui/src/components/ErrorBoundary/ErrorWithStack.tsx @@ -1,30 +1,34 @@ import { css } from '@emotion/css'; import React from 'react'; -import { stylesFactory } from '../../themes'; +import { useStyles2 } from '../../themes'; import { ErrorBoundaryApi } from './ErrorBoundary'; -const getStyles = stylesFactory(() => { - return css({ - width: '500px', - margin: '64px auto', - }); -}); - export interface Props extends ErrorBoundaryApi { title: string; } -export const ErrorWithStack = ({ error, errorInfo, title }: Props) => ( -
-

{title}

-
- {error && error.toString()} -
- {errorInfo && errorInfo.componentStack} -
-
-); +export const ErrorWithStack = ({ error, errorInfo, title }: Props) => { + const style = useStyles2(getStyles); + + return ( +
+

{title}

+
+ {error && error.toString()} +
+ {errorInfo && errorInfo.componentStack} +
+
+ ); +}; ErrorWithStack.displayName = 'ErrorWithStack'; + +const getStyles = () => { + return css({ + width: '500px', + margin: '64px auto', + }); +}; diff --git a/packages/grafana-ui/src/components/Forms/Checkbox.tsx b/packages/grafana-ui/src/components/Forms/Checkbox.tsx index 97ee940235b..1802382d588 100644 --- a/packages/grafana-ui/src/components/Forms/Checkbox.tsx +++ b/packages/grafana-ui/src/components/Forms/Checkbox.tsx @@ -3,7 +3,7 @@ import React, { HTMLProps, useCallback } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins'; import { getLabelStyles } from './Label'; @@ -36,8 +36,7 @@ export const Checkbox = React.forwardRef( }, [onChange] ); - const theme = useTheme2(); - const styles = getCheckboxStyles(theme, invalid); + const styles = useStyles2(getCheckboxStyles, invalid); const ariaChecked = indeterminate ? 'mixed' : undefined; diff --git a/packages/grafana-ui/src/components/Forms/Field.tsx b/packages/grafana-ui/src/components/Forms/Field.tsx index 72fd2a45ee0..9b6e6ef5a7c 100644 --- a/packages/grafana-ui/src/components/Forms/Field.tsx +++ b/packages/grafana-ui/src/components/Forms/Field.tsx @@ -3,7 +3,7 @@ import React, { HTMLAttributes } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory, useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { getChildId } from '../../utils/reactUtils'; import { FieldValidationMessage } from './FieldValidationMessage'; @@ -40,35 +40,6 @@ export interface FieldProps extends HTMLAttributes { 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( ( { @@ -88,8 +59,7 @@ export const Field = React.forwardRef( }: FieldProps, ref ) => { - const theme = useTheme2(); - const styles = getFieldStyles(theme); + const styles = useStyles2(getFieldStyles); const inputId = htmlFor ?? getChildId(children); const labelElement = @@ -143,3 +113,30 @@ function deleteUndefinedProps(obj: T): Partial { 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', + }, + }), +}); diff --git a/packages/grafana-ui/src/components/Forms/FieldSet.tsx b/packages/grafana-ui/src/components/Forms/FieldSet.tsx index c062021e20c..3d3c0986092 100644 --- a/packages/grafana-ui/src/components/Forms/FieldSet.tsx +++ b/packages/grafana-ui/src/components/Forms/FieldSet.tsx @@ -3,7 +3,7 @@ import React, { HTMLProps } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory, useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { Legend } from './Legend'; @@ -14,8 +14,7 @@ export interface Props extends Omit, 'label'> { } export const FieldSet = ({ label, children, className, ...rest }: Props) => { - const theme = useTheme2(); - const styles = getStyles(theme); + const styles = useStyles2(getStyles); return (
@@ -25,14 +24,12 @@ export const FieldSet = ({ label, children, className, ...rest }: Props) => { ); }; -const getStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - wrapper: css({ - marginBottom: theme.spacing(4), +const getStyles = (theme: GrafanaTheme2) => ({ + wrapper: css({ + marginBottom: theme.spacing(4), - '&:last-child': { - marginBottom: 0, - }, - }), - }; + '&:last-child': { + marginBottom: 0, + }, + }), }); diff --git a/packages/grafana-ui/src/components/Forms/FieldValidationMessage.tsx b/packages/grafana-ui/src/components/Forms/FieldValidationMessage.tsx index 55f460653bf..8d8dc832b66 100644 --- a/packages/grafana-ui/src/components/Forms/FieldValidationMessage.tsx +++ b/packages/grafana-ui/src/components/Forms/FieldValidationMessage.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory, useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { Icon } from '../Icon/Icon'; export interface FieldValidationMessageProps { @@ -12,7 +12,23 @@ export interface FieldValidationMessageProps { horizontal?: boolean; } -export const getFieldValidationMessageStyles = stylesFactory((theme: GrafanaTheme2) => { +export const FieldValidationMessage = ({ + children, + horizontal, + className, +}: React.PropsWithChildren) => { + const styles = useStyles2(getFieldValidationMessageStyles); + const cssName = cx(horizontal ? styles.horizontal : styles.vertical, className); + + return ( +
+ + {children} +
+ ); +}; + +export const getFieldValidationMessageStyles = (theme: GrafanaTheme2) => { const baseStyle = ` font-size: ${theme.typography.size.sm}; font-weight: ${theme.typography.fontWeightMedium}; @@ -69,21 +85,4 @@ export const getFieldValidationMessageStyles = stylesFactory((theme: GrafanaThem marginRight: theme.spacing(), }), }; -}); - -export const FieldValidationMessage = ({ - children, - horizontal, - className, -}: React.PropsWithChildren) => { - const theme = useTheme2(); - const styles = getFieldValidationMessageStyles(theme); - const cssName = cx(horizontal ? styles.horizontal : styles.vertical, className); - - return ( -
- - {children} -
- ); }; diff --git a/packages/grafana-ui/src/components/Forms/Label.tsx b/packages/grafana-ui/src/components/Forms/Label.tsx index a8f6826f901..6abadee2fd9 100644 --- a/packages/grafana-ui/src/components/Forms/Label.tsx +++ b/packages/grafana-ui/src/components/Forms/Label.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { useTheme2, stylesFactory } from '../../themes'; +import { useStyles2 } from '../../themes'; import { Icon } from '../Icon/Icon'; export interface LabelProps extends React.LabelHTMLAttributes { @@ -12,43 +12,8 @@ export interface LabelProps extends React.LabelHTMLAttributes category?: React.ReactNode[]; } -export const getLabelStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - label: css({ - label: 'Label', - fontSize: theme.typography.size.sm, - fontWeight: theme.typography.fontWeightMedium, - lineHeight: 1.25, - marginBottom: theme.spacing(0.5), - color: theme.colors.text.primary, - maxWidth: '480px', - }), - labelContent: css({ - display: 'flex', - alignItems: 'center', - }), - description: css({ - label: 'Label-description', - color: theme.colors.text.secondary, - fontSize: theme.typography.size.sm, - fontWeight: theme.typography.fontWeightRegular, - marginTop: theme.spacing(0.25), - display: 'block', - }), - categories: css({ - label: 'Label-categories', - display: 'inline-flex', - alignItems: 'center', - }), - chevron: css({ - margin: theme.spacing(0, 0.25), - }), - }; -}); - export const Label = ({ children, description, className, category, ...labelProps }: LabelProps) => { - const theme = useTheme2(); - const styles = getLabelStyles(theme); + const styles = useStyles2(getLabelStyles); const categories = category?.map((c, i) => { return ( @@ -70,3 +35,35 @@ export const Label = ({ children, description, className, category, ...labelProp
); }; + +export const getLabelStyles = (theme: GrafanaTheme2) => ({ + label: css({ + label: 'Label', + fontSize: theme.typography.size.sm, + fontWeight: theme.typography.fontWeightMedium, + lineHeight: 1.25, + marginBottom: theme.spacing(0.5), + color: theme.colors.text.primary, + maxWidth: '480px', + }), + labelContent: css({ + display: 'flex', + alignItems: 'center', + }), + description: css({ + label: 'Label-description', + color: theme.colors.text.secondary, + fontSize: theme.typography.size.sm, + fontWeight: theme.typography.fontWeightRegular, + marginTop: theme.spacing(0.25), + display: 'block', + }), + categories: css({ + label: 'Label-categories', + display: 'inline-flex', + alignItems: 'center', + }), + chevron: css({ + margin: theme.spacing(0, 0.25), + }), +}); diff --git a/packages/grafana-ui/src/components/Forms/RadioButtonGroup/RadioButton.tsx b/packages/grafana-ui/src/components/Forms/RadioButtonGroup/RadioButton.tsx index 4009b6039de..9360b560686 100644 --- a/packages/grafana-ui/src/components/Forms/RadioButtonGroup/RadioButton.tsx +++ b/packages/grafana-ui/src/components/Forms/RadioButtonGroup/RadioButton.tsx @@ -4,7 +4,7 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { StringSelector } from '@grafana/e2e-selectors'; -import { useTheme2, stylesFactory } from '../../../themes'; +import { useStyles2 } from '../../../themes'; import { getFocusStyles, getMouseFocusStyles } from '../../../themes/mixins'; import { getPropertiesForButtonSize } from '../commonStyles'; @@ -41,8 +41,7 @@ export const RadioButton = React.forwardRef( }, ref ) => { - const theme = useTheme2(); - const styles = getRadioButtonStyles(theme, size, fullWidth); + const styles = useStyles2(getRadioButtonStyles, size, fullWidth); return (
@@ -68,7 +67,7 @@ export const RadioButton = React.forwardRef( 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 textColor = theme.colors.text.secondary; @@ -130,4 +129,4 @@ const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme2, size: RadioBut }, }), }; -}); +}; diff --git a/packages/grafana-ui/src/components/IconButton/IconButton.tsx b/packages/grafana-ui/src/components/IconButton/IconButton.tsx index a1f52a15758..ca40fd8c8fd 100644 --- a/packages/grafana-ui/src/components/IconButton/IconButton.tsx +++ b/packages/grafana-ui/src/components/IconButton/IconButton.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { GrafanaTheme2, colorManipulator, deprecationWarning } from '@grafana/data'; -import { useTheme2, stylesFactory } from '../../themes'; +import { useStyles2 } from '../../themes'; import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins'; import { ComponentSize } from '../../types'; import { IconName, IconSize, IconType } from '../../types/icon'; @@ -44,8 +44,6 @@ export type Props = BasePropsWithTooltip | BasePropsWithAriaLabel; export const IconButton = React.forwardRef((props, ref) => { const { size = 'md', variant = 'secondary' } = props; - - const theme = useTheme2(); let limitedIconSize: LimitedIconSize; // very large icons (xl to xxxl) are unified to size xl @@ -56,7 +54,7 @@ export const IconButton = React.forwardRef((props, ref limitedIconSize = size; } - const styles = getStyles(theme, limitedIconSize, variant); + const styles = useStyles2(getStyles, limitedIconSize, variant); let ariaLabel: string | undefined; let buttonRef: typeof ref | undefined; @@ -104,7 +102,7 @@ export const IconButton = React.forwardRef((props, ref 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 // 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; @@ -166,4 +164,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, size, variant: IconButton verticalAlign: 'baseline', }), }; -}); +}; diff --git a/packages/grafana-ui/src/components/InfoBox/InfoBox.tsx b/packages/grafana-ui/src/components/InfoBox/InfoBox.tsx index 9ed71a53e9d..3ce7197a9c9 100644 --- a/packages/grafana-ui/src/components/InfoBox/InfoBox.tsx +++ b/packages/grafana-ui/src/components/InfoBox/InfoBox.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory, useStyles2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { Alert, AlertVariant } from '../Alert/Alert'; import { Icon } from '../Icon/Icon'; @@ -45,11 +45,9 @@ export const InfoBox = React.memo( InfoBox.displayName = 'InfoBox'; -const getStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - docsLink: css({ - display: 'inline-block', - marginTop: theme.spacing(2), - }), - }; +const getStyles = (theme: GrafanaTheme2) => ({ + docsLink: css({ + display: 'inline-block', + marginTop: theme.spacing(2), + }), }); diff --git a/packages/grafana-ui/src/components/Modal/Modal.tsx b/packages/grafana-ui/src/components/Modal/Modal.tsx index 53040b267d6..af41c8cc78b 100644 --- a/packages/grafana-ui/src/components/Modal/Modal.tsx +++ b/packages/grafana-ui/src/components/Modal/Modal.tsx @@ -4,7 +4,7 @@ import { FocusScope } from '@react-aria/focus'; import { OverlayContainer, useOverlay } from '@react-aria/overlays'; import React, { PropsWithChildren, useRef } from 'react'; -import { useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { IconName } from '../../types'; import { t } from '../../utils/i18n'; import { IconButton } from '../IconButton/IconButton'; @@ -46,8 +46,7 @@ export function Modal(props: PropsWithChildren) { onClickBackdrop, trapFocus = true, } = props; - const theme = useTheme2(); - const styles = getModalStyles(theme); + const styles = useStyles2(getModalStyles); const ref = useRef(null); @@ -101,8 +100,7 @@ export function Modal(props: PropsWithChildren) { } function ModalButtonRow({ leftItems, children }: { leftItems?: React.ReactNode; children: React.ReactNode }) { - const theme = useTheme2(); - const styles = getModalStyles(theme); + const styles = useStyles2(getModalStyles); if (leftItems) { return ( diff --git a/packages/grafana-ui/src/components/Modal/getModalStyles.ts b/packages/grafana-ui/src/components/Modal/getModalStyles.ts index c9b115736da..ede316fbd32 100644 --- a/packages/grafana-ui/src/components/Modal/getModalStyles.ts +++ b/packages/grafana-ui/src/components/Modal/getModalStyles.ts @@ -2,9 +2,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory } from '../../themes'; - -export const getModalStyles = stylesFactory((theme: GrafanaTheme2) => { +export const getModalStyles = (theme: GrafanaTheme2) => { const borderRadius = theme.shape.radius.default; return { @@ -80,4 +78,4 @@ export const getModalStyles = stylesFactory((theme: GrafanaTheme2) => { paddingTop: theme.spacing(3), }), }; -}); +}; diff --git a/packages/grafana-ui/src/components/Select/InputControl.tsx b/packages/grafana-ui/src/components/Select/InputControl.tsx index 14b979ed8d8..c4a3e4b90f2 100644 --- a/packages/grafana-ui/src/components/Select/InputControl.tsx +++ b/packages/grafana-ui/src/components/Select/InputControl.tsx @@ -3,8 +3,7 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory } from '../../themes'; -import { useTheme2 } from '../../themes/ThemeContext'; +import { useStyles2 } from '../../themes/ThemeContext'; import { inputPadding } from '../Forms/commonStyles'; import { getInputStyles } from '../Input/Input'; @@ -17,7 +16,20 @@ interface InputControlProps { innerProps: JSX.IntrinsicElements['div']; } -const getInputControlStyles = stylesFactory((theme: GrafanaTheme2, invalid: boolean, withPrefix: boolean) => { +export const InputControl = React.forwardRef>( + function InputControl({ focused, invalid, disabled, children, innerProps, prefix, ...otherProps }, ref) { + const styles = useStyles2(getInputControlStyles, invalid, !!prefix); + + return ( +
+ {prefix &&
{prefix}
} + {children} +
+ ); + } +); + +const getInputControlStyles = (theme: GrafanaTheme2, invalid: boolean, withPrefix: boolean) => { const styles = getInputStyles({ theme, invalid }); return { @@ -47,17 +59,4 @@ const getInputControlStyles = stylesFactory((theme: GrafanaTheme2, invalid: bool }) ), }; -}); - -export const InputControl = React.forwardRef>( - function InputControl({ focused, invalid, disabled, children, innerProps, prefix, ...otherProps }, ref) { - const theme = useTheme2(); - const styles = getInputControlStyles(theme, invalid, !!prefix); - return ( -
- {prefix &&
{prefix}
} - {children} -
- ); - } -); +}; diff --git a/packages/grafana-ui/src/components/Select/SelectContainer.tsx b/packages/grafana-ui/src/components/Select/SelectContainer.tsx index 95a3d0c3d8b..8e6f4ff895d 100644 --- a/packages/grafana-ui/src/components/Select/SelectContainer.tsx +++ b/packages/grafana-ui/src/components/Select/SelectContainer.tsx @@ -4,8 +4,7 @@ import { components, ContainerProps as BaseContainerProps, GroupBase } from 'rea import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory } from '../../themes'; -import { useTheme2 } from '../../themes/ThemeContext'; +import { useStyles2 } from '../../themes/ThemeContext'; import { getFocusStyles } from '../../themes/mixins'; import { sharedInputStyle } from '../Forms/commonStyles'; import { getInputStyles } from '../Input/Input'; @@ -26,8 +25,7 @@ export const SelectContainer = @@ -36,33 +34,31 @@ export const SelectContainer = { - const styles = getInputStyles({ theme, invalid }); +const getSelectContainerStyles = (theme: GrafanaTheme2, focused: boolean, disabled: boolean, invalid: boolean) => { + const styles = getInputStyles({ theme, invalid }); - return { - wrapper: cx( - styles.wrapper, - sharedInputStyle(theme, invalid), - focused && css(getFocusStyles(theme)), - disabled && styles.inputDisabled, - css({ - position: 'relative', - boxSizing: 'border-box', - /* The display property is set by the styles prop in SelectBase because it's dependant on the width prop */ - flexDirection: 'row', - flexWrap: 'wrap', - alignItems: 'stretch', - justifyContent: 'space-between', - minHeight: '32px', - height: 'auto', - maxWidth: '100%', + return { + wrapper: cx( + styles.wrapper, + sharedInputStyle(theme, invalid), + focused && css(getFocusStyles(theme)), + disabled && styles.inputDisabled, + css({ + position: 'relative', + boxSizing: 'border-box', + /* The display property is set by the styles prop in SelectBase because it's dependant on the width prop */ + flexDirection: 'row', + flexWrap: 'wrap', + alignItems: 'stretch', + justifyContent: 'space-between', + minHeight: '32px', + height: 'auto', + maxWidth: '100%', - /* Input padding is applied to the InputControl so the menu is aligned correctly */ - padding: 0, - cursor: disabled ? 'not-allowed' : 'pointer', - }) - ), - }; - } -); + /* Input padding is applied to the InputControl so the menu is aligned correctly */ + padding: 0, + cursor: disabled ? 'not-allowed' : 'pointer', + }) + ), + }; +}; diff --git a/packages/grafana-ui/src/components/Slider/RangeSlider.tsx b/packages/grafana-ui/src/components/Slider/RangeSlider.tsx index dcd0df00e16..83e97e58f9c 100644 --- a/packages/grafana-ui/src/components/Slider/RangeSlider.tsx +++ b/packages/grafana-ui/src/components/Slider/RangeSlider.tsx @@ -3,7 +3,7 @@ import { Global } from '@emotion/react'; import Slider, { SliderProps } from 'rc-slider'; import React, { useCallback } from 'react'; -import { useTheme2 } from '../../themes/ThemeContext'; +import { useStyles2 } from '../../themes/ThemeContext'; import HandleTooltip from './HandleTooltip'; import { getStyles } from './styles'; @@ -43,8 +43,7 @@ export const RangeSlider = ({ ); const isHorizontal = orientation === 'horizontal'; - const theme = useTheme2(); - const styles = getStyles(theme, isHorizontal); + const styles = useStyles2(getStyles, isHorizontal); const tipHandleRender: SliderProps['handleRender'] = (node, handleProps) => { return ( diff --git a/packages/grafana-ui/src/components/Slider/Slider.tsx b/packages/grafana-ui/src/components/Slider/Slider.tsx index ca442bd440a..7f7dc200ceb 100644 --- a/packages/grafana-ui/src/components/Slider/Slider.tsx +++ b/packages/grafana-ui/src/components/Slider/Slider.tsx @@ -3,7 +3,7 @@ import { Global } from '@emotion/react'; import SliderComponent from 'rc-slider'; import React, { useState, useCallback, ChangeEvent, FocusEvent } from 'react'; -import { useTheme2 } from '../../themes/ThemeContext'; +import { useStyles2 } from '../../themes/ThemeContext'; import { Input } from '../Input/Input'; import { getStyles } from './styles'; @@ -26,8 +26,7 @@ export const Slider = ({ included, }: SliderProps) => { const isHorizontal = orientation === 'horizontal'; - const theme = useTheme2(); - const styles = getStyles(theme, isHorizontal, Boolean(marks)); + const styles = useStyles2(getStyles, isHorizontal, Boolean(marks)); const SliderWithTooltip = SliderComponent; const [sliderValue, setSliderValue] = useState(value ?? min); diff --git a/packages/grafana-ui/src/components/Slider/styles.ts b/packages/grafana-ui/src/components/Slider/styles.ts index e5d78736986..0b422da66ba 100644 --- a/packages/grafana-ui/src/components/Slider/styles.ts +++ b/packages/grafana-ui/src/components/Slider/styles.ts @@ -3,9 +3,7 @@ import { css as cssCore } from '@emotion/react'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory } from '../../themes'; - -export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: boolean, hasMarks = false) => { +export const getStyles = (theme: GrafanaTheme2, isHorizontal: boolean, hasMarks = false) => { const { spacing } = theme; const railColor = theme.colors.border.strong; const trackColor = theme.colors.primary.main; @@ -127,4 +125,4 @@ export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: bool order: 1, }), }; -}); +}; diff --git a/packages/grafana-ui/src/components/Switch/Switch.tsx b/packages/grafana-ui/src/components/Switch/Switch.tsx index aa9cbd60262..95c401201c2 100644 --- a/packages/grafana-ui/src/components/Switch/Switch.tsx +++ b/packages/grafana-ui/src/components/Switch/Switch.tsx @@ -4,7 +4,7 @@ import React, { HTMLProps, useRef } from 'react'; import { GrafanaTheme2, deprecationWarning } from '@grafana/data'; -import { stylesFactory, useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins'; export interface Props extends Omit, 'value'> { @@ -21,8 +21,7 @@ export const Switch = React.forwardRef( deprecationWarning('Switch', 'checked prop', 'value'); } - const theme = useTheme2(); - const styles = getSwitchStyles(theme); + const styles = useStyles2(getSwitchStyles); const switchIdRef = useRef(id ? id : uniqueId('switch-')); return ( @@ -52,8 +51,7 @@ export interface InlineSwitchProps extends Props { export const InlineSwitch = React.forwardRef( ({ transparent, className, showLabel, label, value, id, invalid, ...props }, ref) => { - const theme = useTheme2(); - const styles = getSwitchStyles(theme, transparent); + const styles = useStyles2(getSwitchStyles, transparent); return (
{ - return { - switch: css({ - width: '32px', - height: '16px', - position: 'relative', - - input: { - opacity: 0, - left: '-100vw', - zIndex: -1000, - position: 'absolute', - - '&:disabled + label': { - background: theme.colors.action.disabledBackground, - cursor: 'not-allowed', - }, - - '&:checked + label': { - background: theme.colors.primary.main, - borderColor: theme.colors.primary.main, - - '&:hover': { - background: theme.colors.primary.shade, - }, - - '&::after': { - transform: 'translate3d(18px, -50%, 0)', - background: theme.colors.primary.contrastText, - }, - }, - - '&:focus + label, &:focus-visible + label': getFocusStyles(theme), - - '&:focus:not(:focus-visible) + label': getMouseFocusStyles(theme), +const getSwitchStyles = (theme: GrafanaTheme2, transparent?: boolean) => ({ + switch: css({ + width: '32px', + height: '16px', + position: 'relative', + + input: { + opacity: 0, + left: '-100vw', + zIndex: -1000, + position: 'absolute', + + '&:disabled + label': { + background: theme.colors.action.disabledBackground, + cursor: 'not-allowed', }, - label: { - width: '100%', - height: '100%', - cursor: 'pointer', - borderRadius: theme.shape.radius.pill, - background: theme.components.input.background, - border: `1px solid ${theme.components.input.borderColor}`, - transition: 'all 0.3s ease', + '&:checked + label': { + background: theme.colors.primary.main, + borderColor: theme.colors.primary.main, '&:hover': { - borderColor: theme.components.input.borderHover, + background: theme.colors.primary.shade, }, '&::after': { - position: 'absolute', - display: 'block', - content: '""', - width: '12px', - height: '12px', - borderRadius: theme.shape.radius.circle, - background: theme.colors.text.secondary, - boxShadow: theme.shadows.z1, - top: '50%', - transform: 'translate3d(2px, -50%, 0)', - transition: 'transform 0.2s cubic-bezier(0.19, 1, 0.22, 1)', - - '@media (forced-colors: active)': { - border: '1px solid transparent', - }, + transform: 'translate3d(18px, -50%, 0)', + background: theme.colors.primary.contrastText, }, }, - }), - inlineContainer: css({ - padding: theme.spacing(0, 1), - height: theme.spacing(theme.components.height.md), - display: 'inline-flex', - alignItems: 'center', - background: transparent ? 'transparent' : theme.components.input.background, - border: `1px solid ${transparent ? 'transparent' : theme.components.input.borderColor}`, - borderRadius: theme.shape.radius.default, + + '&:focus + label, &:focus-visible + label': getFocusStyles(theme), + + '&:focus:not(:focus-visible) + label': getMouseFocusStyles(theme), + }, + + label: { + width: '100%', + height: '100%', + cursor: 'pointer', + borderRadius: theme.shape.radius.pill, + background: theme.components.input.background, + border: `1px solid ${theme.components.input.borderColor}`, + transition: 'all 0.3s ease', '&:hover': { - border: `1px solid ${transparent ? 'transparent' : theme.components.input.borderHover}`, + borderColor: theme.components.input.borderHover, + }, - '.inline-switch-label': { - color: theme.colors.text.primary, + '&::after': { + position: 'absolute', + display: 'block', + content: '""', + width: '12px', + height: '12px', + borderRadius: theme.shape.radius.circle, + background: theme.colors.text.secondary, + boxShadow: theme.shadows.z1, + top: '50%', + transform: 'translate3d(2px, -50%, 0)', + transition: 'transform 0.2s cubic-bezier(0.19, 1, 0.22, 1)', + + '@media (forced-colors: active)': { + border: '1px solid transparent', }, }, - }), - disabled: css({ - backgroundColor: 'rgba(204, 204, 220, 0.04)', - color: 'rgba(204, 204, 220, 0.6)', - border: '1px solid rgba(204, 204, 220, 0.04)', - }), - inlineLabel: css({ - cursor: 'pointer', - paddingRight: theme.spacing(1), - color: theme.colors.text.secondary, - whiteSpace: 'nowrap', - }), - inlineLabelEnabled: css({ - color: theme.colors.text.primary, - }), - invalid: css({ - 'input + label, input:checked + label, input:hover + label': { - border: `1px solid ${theme.colors.error.border}`, + }, + }), + inlineContainer: css({ + padding: theme.spacing(0, 1), + height: theme.spacing(theme.components.height.md), + display: 'inline-flex', + alignItems: 'center', + background: transparent ? 'transparent' : theme.components.input.background, + border: `1px solid ${transparent ? 'transparent' : theme.components.input.borderColor}`, + borderRadius: theme.shape.radius.default, + + '&:hover': { + border: `1px solid ${transparent ? 'transparent' : theme.components.input.borderHover}`, + + '.inline-switch-label': { + color: theme.colors.text.primary, }, - }), - }; + }, + }), + disabled: css({ + backgroundColor: 'rgba(204, 204, 220, 0.04)', + color: 'rgba(204, 204, 220, 0.6)', + border: '1px solid rgba(204, 204, 220, 0.04)', + }), + inlineLabel: css({ + cursor: 'pointer', + paddingRight: theme.spacing(1), + color: theme.colors.text.secondary, + whiteSpace: 'nowrap', + }), + inlineLabelEnabled: css({ + color: theme.colors.text.primary, + }), + invalid: css({ + 'input + label, input:checked + label, input:hover + label': { + border: `1px solid ${theme.colors.error.border}`, + }, + }), }); diff --git a/packages/grafana-ui/src/components/TabbedContainer/TabbedContainer.tsx b/packages/grafana-ui/src/components/TabbedContainer/TabbedContainer.tsx index 86973201467..1794b1a96da 100644 --- a/packages/grafana-ui/src/components/TabbedContainer/TabbedContainer.tsx +++ b/packages/grafana-ui/src/components/TabbedContainer/TabbedContainer.tsx @@ -5,7 +5,7 @@ import { SelectableValue, GrafanaTheme2 } from '@grafana/data'; import { IconButton } from '../../components/IconButton/IconButton'; import { TabsBar, Tab, TabContent } from '../../components/Tabs'; -import { stylesFactory, useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { IconName } from '../../types/icon'; import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar'; @@ -23,45 +23,14 @@ export interface TabbedContainerProps { onClose: () => void; } -const getStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - 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 - ); +export function TabbedContainer({ tabs, defaultTab, closeIconTooltip, onClose }: TabbedContainerProps) { + const [activeTab, setActiveTab] = useState(tabs.some((tab) => tab.value === defaultTab) ? defaultTab : tabs[0].value); const onSelectTab = (item: SelectableValue) => { setActiveTab(item.value!); }; - const { tabs, onClose, closeIconTooltip } = props; - const theme = useTheme2(); - const styles = getStyles(theme); + const styles = useStyles2(getStyles); return (
@@ -83,3 +52,28 @@ export function TabbedContainer(props: TabbedContainerProps) {
); } + +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), + }, + }), +}); diff --git a/packages/grafana-ui/src/components/Table/FilterList.tsx b/packages/grafana-ui/src/components/Table/FilterList.tsx index 1900aae00ad..2ff6d26bb41 100644 --- a/packages/grafana-ui/src/components/Table/FilterList.tsx +++ b/packages/grafana-ui/src/components/Table/FilterList.tsx @@ -5,7 +5,7 @@ import { FixedSizeList as List } from 'react-window'; import { GrafanaTheme2, SelectableValue } from '@grafana/data'; import { Checkbox, FilterInput, Label, VerticalGroup } from '..'; -import { stylesFactory, useTheme2 } from '../../themes'; +import { useStyles2, useTheme2 } from '../../themes'; interface Props { values: SelectableValue[]; @@ -18,8 +18,6 @@ const ITEM_HEIGHT = 28; const MIN_HEIGHT = ITEM_HEIGHT * 5; export const FilterList = ({ options, values, caseSensitive, onChange }: Props) => { - const theme = useTheme2(); - const styles = getStyles(theme); const [searchFilter, setSearchFilter] = useState(''); const regex = useMemo(() => new RegExp(searchFilter, caseSensitive ? undefined : 'i'), [searchFilter, caseSensitive]); const items = useMemo( @@ -32,16 +30,12 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props) }), [options, regex] ); + + const styles = useStyles2(getStyles); + const theme = useTheme2(); const gutter = theme.spacing.gridSize; 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( (option: SelectableValue) => (event: React.FormEvent) => { const newValues = event.currentTarget.checked @@ -55,7 +49,7 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props) return ( - + {!items.length && } {items.length && ( ({ +const getStyles = (theme: GrafanaTheme2) => ({ filterList: css({ label: 'filterList', }), @@ -98,4 +92,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => ({ backgroundColor: theme.colors.action.hover, }, }), -})); +}); diff --git a/packages/grafana-ui/src/components/Tabs/Counter.tsx b/packages/grafana-ui/src/components/Tabs/Counter.tsx index 351863c7cf4..8a8c507bff2 100644 --- a/packages/grafana-ui/src/components/Tabs/Counter.tsx +++ b/packages/grafana-ui/src/components/Tabs/Counter.tsx @@ -3,22 +3,7 @@ import React from 'react'; import { GrafanaTheme2, locale } from '@grafana/data'; -import { stylesFactory, useStyles2 } from '../../themes'; - -const getStyles = stylesFactory((theme: GrafanaTheme2) => { - return { - counter: css({ - label: 'counter', - marginLeft: theme.spacing(1), - borderRadius: theme.spacing(3), - backgroundColor: theme.colors.action.hover, - padding: theme.spacing(0.25, 1), - color: theme.colors.text.secondary, - fontWeight: theme.typography.fontWeightMedium, - fontSize: theme.typography.size.sm, - }), - }; -}); +import { useStyles2 } from '../../themes'; export interface CounterProps { value: number; @@ -29,3 +14,16 @@ export const Counter = ({ value }: CounterProps) => { return {locale(value, 0).text}; }; + +const getStyles = (theme: GrafanaTheme2) => ({ + counter: css({ + label: 'counter', + marginLeft: theme.spacing(1), + borderRadius: theme.spacing(3), + backgroundColor: theme.colors.action.hover, + padding: theme.spacing(0.25, 1), + color: theme.colors.text.secondary, + fontWeight: theme.typography.fontWeightMedium, + fontSize: theme.typography.size.sm, + }), +}); diff --git a/packages/grafana-ui/src/components/Tabs/TabContent.tsx b/packages/grafana-ui/src/components/Tabs/TabContent.tsx index 929c7f854dd..76c7b88f182 100644 --- a/packages/grafana-ui/src/components/Tabs/TabContent.tsx +++ b/packages/grafana-ui/src/components/Tabs/TabContent.tsx @@ -3,23 +3,14 @@ import React, { HTMLAttributes, ReactNode } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory, useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; interface Props extends HTMLAttributes { children: ReactNode; } -const getTabContentStyle = stylesFactory((theme: GrafanaTheme2) => { - return { - tabContent: css({ - background: theme.colors.background.primary, - }), - }; -}); - export const TabContent = ({ children, className, ...restProps }: Props) => { - const theme = useTheme2(); - const styles = getTabContentStyle(theme); + const styles = useStyles2(getTabContentStyle); return (
@@ -27,3 +18,9 @@ export const TabContent = ({ children, className, ...restProps }: Props) => {
); }; + +const getTabContentStyle = (theme: GrafanaTheme2) => ({ + tabContent: css({ + background: theme.colors.background.primary, + }), +}); diff --git a/packages/grafana-ui/src/components/TextArea/TextArea.tsx b/packages/grafana-ui/src/components/TextArea/TextArea.tsx index bae097216e1..5f438b9982c 100644 --- a/packages/grafana-ui/src/components/TextArea/TextArea.tsx +++ b/packages/grafana-ui/src/components/TextArea/TextArea.tsx @@ -3,7 +3,7 @@ import React, { HTMLProps } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { stylesFactory, useTheme2 } from '../../themes'; +import { useStyles2 } from '../../themes'; import { getFocusStyle, sharedInputStyle } from '../Forms/commonStyles'; export interface Props extends Omit, 'size'> { @@ -12,26 +12,23 @@ export interface Props extends Omit, 'size'> { } export const TextArea = React.forwardRef(({ invalid, className, ...props }, ref) => { - const theme = useTheme2(); - const styles = getTextAreaStyle(theme, invalid); + const styles = useStyles2(getTextAreaStyle, invalid); return