diff --git a/src/components/badge/badge.tsx b/src/components/badge/badge.tsx index 03cfcc0f9f2..3e3bac321f2 100644 --- a/src/components/badge/badge.tsx +++ b/src/components/badge/badge.tsx @@ -16,15 +16,17 @@ import React, { useMemo, } from 'react'; import classNames from 'classnames'; -import { CommonProps, ExclusiveUnion, PropsOf } from '../common'; + import { useEuiTheme, + useEuiMemoizedStyles, getSecureRelForTarget, wcagContrastMin, } from '../../services'; +import { validateHref } from '../../services/security/href_validator'; +import { CommonProps, ExclusiveUnion, PropsOf } from '../common'; import { EuiInnerText } from '../inner_text'; import { EuiIcon, IconType } from '../icon'; -import { validateHref } from '../../services/security/href_validator'; import { getTextColor, getColorContrast, getIsValidColor } from './color_utils'; import { euiBadgeStyles } from './badge.styles'; @@ -124,12 +126,11 @@ export const EuiBadge: FunctionComponent = ({ style, ...rest }) => { - const euiTheme = useEuiTheme(); - const isHrefValid = !href || validateHref(href); const isDisabled = _isDisabled || !isHrefValid; const isNamedColor = COLORS.includes(color as BadgeColor); + const euiTheme = useEuiTheme(); const customColorStyles = useMemo(() => { // Named colors set their styles via Emotion CSS and not inline styles if (isNamedColor) return style; @@ -165,7 +166,7 @@ export const EuiBadge: FunctionComponent = ({ } }, [color, isNamedColor, style, euiTheme]); - const styles = euiBadgeStyles(euiTheme); + const styles = useEuiMemoizedStyles(euiBadgeStyles); const cssStyles = [ styles.euiBadge, isNamedColor && styles[color as BadgeColor], diff --git a/src/components/badge/badge_group/badge_group.tsx b/src/components/badge/badge_group/badge_group.tsx index 83099b899ce..9a5c03e1bac 100644 --- a/src/components/badge/badge_group/badge_group.tsx +++ b/src/components/badge/badge_group/badge_group.tsx @@ -8,8 +8,9 @@ import React, { forwardRef, HTMLAttributes, Ref, ReactNode } from 'react'; import classNames from 'classnames'; + +import { useEuiMemoizedStyles } from '../../../services'; import { CommonProps } from '../../common'; -import { useEuiTheme } from '../../../services'; import { euiBadgeGroupStyles } from './badge_group.styles'; @@ -35,13 +36,11 @@ export const EuiBadgeGroup = forwardRef< { children, className, gutterSize = 'xs', ...rest }, ref: Ref ) => { - const euiTheme = useEuiTheme(); + const classes = classNames('euiBadgeGroup', className); - const styles = euiBadgeGroupStyles(euiTheme); + const styles = useEuiMemoizedStyles(euiBadgeGroupStyles); const cssStyles = [styles.euiBadgeGroup, styles[gutterSize]]; - const classes = classNames('euiBadgeGroup', className); - return (
{children} diff --git a/src/components/badge/beta_badge/beta_badge.tsx b/src/components/badge/beta_badge/beta_badge.tsx index 89f60ccce68..6cf6484be6c 100644 --- a/src/components/badge/beta_badge/beta_badge.tsx +++ b/src/components/badge/beta_badge/beta_badge.tsx @@ -14,12 +14,10 @@ import React, { ReactNode, } from 'react'; import classNames from 'classnames'; -import { CommonProps, ExclusiveUnion } from '../../common'; - -import { getSecureRelForTarget, useEuiTheme } from '../../../services'; +import { getSecureRelForTarget, useEuiMemoizedStyles } from '../../../services'; +import { CommonProps, ExclusiveUnion } from '../../common'; import { EuiToolTip, EuiToolTipProps, ToolTipPositions } from '../../tool_tip'; - import { EuiIcon, IconType } from '../../icon'; import { euiBetaBadgeStyles } from './beta_badge.styles'; @@ -146,14 +144,12 @@ export const EuiBetaBadge: FunctionComponent = ({ alignment = 'baseline', ...rest }) => { - const euiTheme = useEuiTheme(); - const singleLetter = !!(typeof label === 'string' && label.length === 1); const isCircular = iconType || singleLetter; const classes = classNames('euiBetaBadge', className); - const styles = euiBetaBadgeStyles(euiTheme); + const styles = useEuiMemoizedStyles(euiBetaBadgeStyles); const cssStyles = [ styles.euiBetaBadge, styles[color], diff --git a/src/components/badge/notification_badge/badge_notification.tsx b/src/components/badge/notification_badge/badge_notification.tsx index 7a1ea13b684..c68cfa21510 100644 --- a/src/components/badge/notification_badge/badge_notification.tsx +++ b/src/components/badge/notification_badge/badge_notification.tsx @@ -8,8 +8,9 @@ import React, { HTMLAttributes, ReactNode, FunctionComponent } from 'react'; import classNames from 'classnames'; + +import { useEuiMemoizedStyles } from '../../../services'; import { CommonProps } from '../../common'; -import { useEuiTheme } from '../../../services'; import { euiNotificationBadgeStyles } from './badge_notification.styles'; @@ -33,13 +34,11 @@ export interface EuiNotificationBadgeProps export const EuiNotificationBadge: FunctionComponent< EuiNotificationBadgeProps > = ({ children, className, size = 's', color = 'accent', ...rest }) => { - const euiTheme = useEuiTheme(); + const classes = classNames('euiNotificationBadge', className); - const styles = euiNotificationBadgeStyles(euiTheme); + const styles = useEuiMemoizedStyles(euiNotificationBadgeStyles); const cssStyles = [styles.euiNotificationBadge, styles[size], styles[color]]; - const classes = classNames('euiNotificationBadge', className); - return ( {children} diff --git a/src/components/call_out/call_out.styles.ts b/src/components/call_out/call_out.styles.ts index a6164f8d951..59e4cd4cc04 100644 --- a/src/components/call_out/call_out.styles.ts +++ b/src/components/call_out/call_out.styles.ts @@ -45,15 +45,10 @@ export const euiCallOutStyles = ({ euiTheme }: UseEuiTheme) => { ${logicalCSS('right', euiTheme.size.s)} `, }, - euiCallOut__icon: css` - position: relative; - ${logicalCSS('top', '-1px')} - ${logicalCSS('margin-right', euiTheme.size.s)} - `, }; }; -export const euiCallOutHeadingStyles = ({ euiTheme }: UseEuiTheme) => { +export const euiCallOutHeaderStyles = ({ euiTheme }: UseEuiTheme) => { return { euiCallOutHeader: css` font-weight: ${euiTheme.font.weight.medium}; @@ -75,5 +70,10 @@ export const euiCallOutHeadingStyles = ({ euiTheme }: UseEuiTheme) => { danger: css` color: ${euiTheme.colors.dangerText}; `, + euiCallOut__icon: css` + position: relative; + ${logicalCSS('top', '-1px')} + ${logicalCSS('margin-right', euiTheme.size.s)} + `, }; }; diff --git a/src/components/call_out/call_out.tsx b/src/components/call_out/call_out.tsx index 728848b099f..4abcacb253d 100644 --- a/src/components/call_out/call_out.tsx +++ b/src/components/call_out/call_out.tsx @@ -6,22 +6,21 @@ * Side Public License, v 1. */ -import React, { forwardRef, HTMLAttributes, ReactNode } from 'react'; +import React, { forwardRef, HTMLAttributes, ReactNode, useMemo } from 'react'; import classNames from 'classnames'; +import { useEuiMemoizedStyles } from '../../services'; import { CommonProps } from '../common'; import { IconType, EuiIcon } from '../icon'; - import { EuiButtonIcon } from '../button'; import { EuiText } from '../text'; -import { useEuiTheme } from '../../services'; import { EuiPanel } from '../panel'; import { EuiSpacer } from '../spacer'; import { EuiTitle } from '../title'; import { EuiI18n } from '../i18n'; -import { euiCallOutStyles, euiCallOutHeadingStyles } from './call_out.styles'; +import { euiCallOutStyles, euiCallOutHeaderStyles } from './call_out.styles'; export const COLORS = ['primary', 'success', 'warning', 'danger'] as const; export type Color = (typeof COLORS)[number]; @@ -63,22 +62,12 @@ export const EuiCallOut = forwardRef( }, ref ) => { - const theme = useEuiTheme(); - const styles = euiCallOutStyles(theme); + const styles = useEuiMemoizedStyles(euiCallOutStyles); const cssStyles = [ styles.euiCallOut, onDismiss && styles.hasDismissButton.hasDimissButton, onDismiss && styles.hasDismissButton[size], ]; - const cssDismissButtonStyles = [ - styles.dismissButton.euiCallOut__dismissButton, - styles.dismissButton[size], - ]; - const headerStyles = euiCallOutHeadingStyles(theme); - const cssHeaderStyles = [ - headerStyles.euiCallOutHeader, - headerStyles[color], - ]; const classes = classNames( 'euiCallOut', @@ -88,42 +77,57 @@ export const EuiCallOut = forwardRef( className ); - const dismissButton = onDismiss && ( - - {(dismissAriaLabel: string) => ( - - )} - - ); - - const headerIcon = iconType && ( -

@@ -168,7 +168,7 @@ exports[`EuiContextMenu renders isSeparator items 1`] = `
{ static defaultProps: Partial = { @@ -199,7 +202,7 @@ export class EuiContextMenuClass extends Component< return null; } - constructor(props: WithEuiThemeProps & EuiContextMenuProps) { + constructor(props: WithEuiStylesMemoizerProps & EuiContextMenuProps) { super(props); this.state = { @@ -429,7 +432,7 @@ export class EuiContextMenuClass extends Component< render() { const { - theme, + stylesMemoizer, panels, onPanelChange, className, @@ -453,12 +456,11 @@ export class EuiContextMenuClass extends Component< const classes = classNames('euiContextMenu', className); - const styles = euiContextMenuStyles(theme); - const cssStyles = [styles.euiContextMenu]; + const styles = stylesMemoizer(euiContextMenuStyles); return (
(EuiContextMenuClass); + withEuiStylesMemoizer(EuiContextMenuClass); diff --git a/src/components/context_menu/context_menu_panel.tsx b/src/components/context_menu/context_menu_panel.tsx index bf928459f59..578d42cd49c 100644 --- a/src/components/context_menu/context_menu_panel.tsx +++ b/src/components/context_menu/context_menu_panel.tsx @@ -17,7 +17,11 @@ import React, { import classNames from 'classnames'; import { tabbable, FocusableElement } from 'tabbable'; -import { withEuiTheme, WithEuiThemeProps, keys } from '../../services'; +import { + withEuiStylesMemoizer, + WithEuiStylesMemoizerProps, + keys, +} from '../../services'; import { CommonProps, NoArgCallback } from '../common'; import { EuiResizeObserver } from '../observer/resize_observer'; @@ -74,7 +78,7 @@ interface State { } export class EuiContextMenuPanelClass extends Component< - WithEuiThemeProps & Props, + WithEuiStylesMemoizerProps & Props, State > { static defaultProps: Partial = { @@ -86,7 +90,7 @@ export class EuiContextMenuPanelClass extends Component< private panel?: HTMLElement | null = null; private initialPopoverParent?: HTMLElement | null = null; - constructor(props: WithEuiThemeProps & Props) { + constructor(props: WithEuiStylesMemoizerProps & Props) { super(props); this.state = { @@ -394,7 +398,7 @@ export class EuiContextMenuPanelClass extends Component< render() { const { - theme, + stylesMemoizer, children, className, onClose, @@ -414,7 +418,7 @@ export class EuiContextMenuPanelClass extends Component< const classes = classNames('euiContextMenuPanel', className); - const styles = euiContextMenuPanelStyles(theme); + const styles = stylesMemoizer(euiContextMenuPanelStyles); const cssStyles = [ styles.euiContextMenuPanel, transitionDirection && @@ -472,6 +476,5 @@ export class EuiContextMenuPanelClass extends Component< } } -export const EuiContextMenuPanel = withEuiTheme( - EuiContextMenuPanelClass -); +export const EuiContextMenuPanel = + withEuiStylesMemoizer(EuiContextMenuPanelClass); diff --git a/src/components/description_list/description_list.tsx b/src/components/description_list/description_list.tsx index 1b0ebba7edb..579fd198c44 100644 --- a/src/components/description_list/description_list.tsx +++ b/src/components/description_list/description_list.tsx @@ -9,7 +9,7 @@ import React, { HTMLAttributes, FunctionComponent, useMemo } from 'react'; import classNames from 'classnames'; -import { useEuiTheme, useIsWithinBreakpoints } from '../../services'; +import { useEuiMemoizedStyles, useIsWithinBreakpoints } from '../../services'; import { CommonProps } from '../common'; import { EuiDescriptionListProps } from './description_list_types'; @@ -45,8 +45,7 @@ export const EuiDescriptionList: FunctionComponent< } }, [_type, showResponsiveColumns]); - const euiTheme = useEuiTheme(); - const styles = euiDescriptionListStyles(euiTheme); + const styles = useEuiMemoizedStyles(euiDescriptionListStyles); const cssStyles = [ styles.euiDescriptionList, @@ -74,26 +73,24 @@ export const EuiDescriptionList: FunctionComponent< const classes = classNames('euiDescriptionList', className); - let childrenOrListItems = null; + const renderedListItems = useMemo(() => { + if (listItems) { + return listItems.map((item, index) => { + return [ + + {item.title} + , - if (listItems) { - childrenOrListItems = listItems.map((item, index) => { - return [ - - {item.title} - , - - - {item.description} - , - ]; - }); - } else { - childrenOrListItems = children; - } + + {item.description} + , + ]; + }); + } + }, [listItems, descriptionProps, titleProps]); return ( - {childrenOrListItems} + {listItems ? renderedListItems : children} ); diff --git a/src/components/description_list/description_list_description.tsx b/src/components/description_list/description_list_description.tsx index e39881d1978..747d2264ed0 100644 --- a/src/components/description_list/description_list_description.tsx +++ b/src/components/description_list/description_list_description.tsx @@ -9,8 +9,8 @@ import React, { HTMLAttributes, FunctionComponent, useContext } from 'react'; import classNames from 'classnames'; +import { useEuiMemoizedStyles } from '../../services'; import { CommonProps } from '../common'; -import { useEuiTheme } from '../../services'; import { EuiDescriptionListContext } from './description_list_context'; import { euiDescriptionListDescriptionStyles } from './description_list_description.styles'; @@ -27,8 +27,7 @@ export const EuiDescriptionListDescription: FunctionComponent< EuiDescriptionListContext ); - const theme = useEuiTheme(); - const styles = euiDescriptionListDescriptionStyles(theme); + const styles = useEuiMemoizedStyles(euiDescriptionListDescriptionStyles); let conditionalStyles = compressed && textStyle === 'reverse' diff --git a/src/components/description_list/description_list_title.tsx b/src/components/description_list/description_list_title.tsx index 7f5167693c9..a69d2a4d2c2 100644 --- a/src/components/description_list/description_list_title.tsx +++ b/src/components/description_list/description_list_title.tsx @@ -9,8 +9,8 @@ import React, { HTMLAttributes, FunctionComponent, useContext } from 'react'; import classNames from 'classnames'; +import { useEuiMemoizedStyles } from '../../services'; import { CommonProps } from '../common'; -import { useEuiTheme } from '../../services'; import { EuiDescriptionListContext } from './description_list_context'; import { euiDescriptionListTitleStyles } from './description_list_title.styles'; @@ -27,8 +27,7 @@ export const EuiDescriptionListTitle: FunctionComponent< EuiDescriptionListContext ); - const theme = useEuiTheme(); - const styles = euiDescriptionListTitleStyles(theme); + const styles = useEuiMemoizedStyles(euiDescriptionListTitleStyles); let conditionalStyles = compressed && textStyle !== 'reverse' diff --git a/src/components/empty_prompt/empty_prompt.tsx b/src/components/empty_prompt/empty_prompt.tsx index fb919eecbf7..d16fe9539fc 100644 --- a/src/components/empty_prompt/empty_prompt.tsx +++ b/src/components/empty_prompt/empty_prompt.tsx @@ -14,7 +14,7 @@ import React, { } from 'react'; import classNames from 'classnames'; -import { useEuiTheme } from '../../services'; +import { useEuiMemoizedStyles } from '../../services'; import { CommonProps } from '../common'; import { EuiTitle, EuiTitleSize } from '../title'; import { EuiFlexGroup, EuiFlexItem } from '../flex'; @@ -97,8 +97,7 @@ export const EuiEmptyPrompt: FunctionComponent = ({ ...rest }) => { const classes = classNames('euiEmptyPrompt', className); - const euiTheme = useEuiTheme(); - const styles = useMemo(() => euiEmptyPromptStyles(euiTheme), [euiTheme]); + const styles = useEuiMemoizedStyles(euiEmptyPromptStyles); const cssStyles = [styles.euiEmptyPrompt, styles[layout]]; const mainStyles = [ styles.main.euiEmptyPrompt__main, diff --git a/src/components/horizontal_rule/__snapshots__/horizontal_rule.test.tsx.snap b/src/components/horizontal_rule/__snapshots__/horizontal_rule.test.tsx.snap index 6258794c6f6..122adf20d6f 100644 --- a/src/components/horizontal_rule/__snapshots__/horizontal_rule.test.tsx.snap +++ b/src/components/horizontal_rule/__snapshots__/horizontal_rule.test.tsx.snap @@ -3,7 +3,7 @@ exports[`EuiHorizontalRule is rendered 1`] = `
`; diff --git a/src/components/horizontal_rule/horizontal_rule.tsx b/src/components/horizontal_rule/horizontal_rule.tsx index 297af7d8378..9313d960911 100644 --- a/src/components/horizontal_rule/horizontal_rule.tsx +++ b/src/components/horizontal_rule/horizontal_rule.tsx @@ -10,7 +10,7 @@ import React, { FunctionComponent, HTMLAttributes } from 'react'; import classNames from 'classnames'; import { CommonProps } from '../common'; -import { useEuiTheme } from '../../services'; +import { useEuiMemoizedStyles } from '../../services'; import { euiHorizontalRuleStyles } from './horizontal_rule.styles'; export const SIZES = ['full', 'half', 'quarter'] as const; @@ -29,37 +29,15 @@ export interface EuiHorizontalRuleProps margin?: EuiHorizontalRuleMargin; } -const marginToClassNameMap: { - [value in EuiHorizontalRuleMargin]: string | null; -} = { - none: null, - xs: 'marginXSmall', - s: 'marginSmall', - m: 'marginMedium', - l: 'marginLarge', - xl: 'marginXLarge', - xxl: 'marginXXLarge', -}; - export const EuiHorizontalRule: FunctionComponent = ({ className, size = 'full', margin = 'l', ...rest }) => { - const euiTheme = useEuiTheme(); - const styles = euiHorizontalRuleStyles(euiTheme); - - const classes = classNames( - 'euiHorizontalRule', - { - [`euiHorizontalRule--${size}`]: size, - [`euiHorizontalRule--${marginToClassNameMap[margin]}`]: - margin && margin !== 'none', - }, - className - ); + const classes = classNames('euiHorizontalRule', className); + const styles = useEuiMemoizedStyles(euiHorizontalRuleStyles); const cssStyles = [styles.euiHorizontalRule, styles[size], styles[margin]]; return
; diff --git a/src/components/tabs/tab.tsx b/src/components/tabs/tab.tsx index 7ae9ac2adcf..98281510769 100644 --- a/src/components/tabs/tab.tsx +++ b/src/components/tabs/tab.tsx @@ -15,8 +15,9 @@ import React, { useContext, } from 'react'; import classNames from 'classnames'; + +import { getSecureRelForTarget, useEuiMemoizedStyles } from '../../services'; import { CommonProps, ExclusiveUnion } from '../common'; -import { getSecureRelForTarget, useEuiTheme } from '../../services'; import { validateHref } from '../../services/security/href_validator'; import { euiTabStyles, euiTabContentStyles } from './tab.styles'; @@ -63,7 +64,6 @@ export const EuiTab: FunctionComponent = ({ ...rest }) => { const { size, expand } = useContext(EuiTabsContext); - const euiTheme = useEuiTheme(); const isHrefValid = !href || validateHref(href); const disabled = _disabled || !isHrefValid; @@ -72,7 +72,7 @@ export const EuiTab: FunctionComponent = ({ 'euiTab-isSelected': isSelected, }); - const tabStyles = euiTabStyles(euiTheme); + const tabStyles = useEuiMemoizedStyles(euiTabStyles); const cssTabStyles = [ tabStyles.euiTab, expand && tabStyles.expanded, @@ -80,7 +80,7 @@ export const EuiTab: FunctionComponent = ({ isSelected && (disabled ? tabStyles.disabled.selected : tabStyles.selected), ]; - const tabContentStyles = euiTabContentStyles(euiTheme); + const tabContentStyles = useEuiMemoizedStyles(euiTabContentStyles); const cssTabContentStyles = [ tabContentStyles.euiTab__content, size && tabContentStyles[size], diff --git a/src/components/tabs/tabs.tsx b/src/components/tabs/tabs.tsx index adeaae1a597..ae9cb409ffb 100644 --- a/src/components/tabs/tabs.tsx +++ b/src/components/tabs/tabs.tsx @@ -13,8 +13,8 @@ import React, { ReactNode, } from 'react'; import classNames from 'classnames'; +import { useEuiMemoizedStyles } from '../../services'; import { CommonProps } from '../common'; -import { useEuiTheme } from '../../services'; import { euiTabsStyles } from './tabs.styles'; import { EuiTabsContext } from './tabs_context'; @@ -58,12 +58,9 @@ export const EuiTabs = forwardRef( }: EuiTabsProps, ref ) => { - const euiTheme = useEuiTheme(); - const classes = classNames('euiTabs', className); - const styles = euiTabsStyles(euiTheme); - + const styles = useEuiMemoizedStyles(euiTabsStyles); const cssStyles = [ styles.euiTabs, styles[size],