@@ -52,7 +52,7 @@ exports[`EuiAvatar props color as null is rendered 1`] = `
exports[`EuiAvatar props color as plain is rendered 1`] = `
@@ -67,7 +67,7 @@ exports[`EuiAvatar props color as plain is rendered 1`] = `
exports[`EuiAvatar props color as string is rendered 1`] = `
+
+ n
+
+
+`;
diff --git a/src/components/avatar/_avatar.scss b/src/components/avatar/_avatar.scss
deleted file mode 100644
index 60f5c478a22..00000000000
--- a/src/components/avatar/_avatar.scss
+++ /dev/null
@@ -1,58 +0,0 @@
-.euiAvatar {
- flex-shrink: 0; // Ensures it never scales down below its intended size
- display: inline-flex;
- justify-content: center;
- align-items: center;
- background-size: cover;
- text-align: center;
- vertical-align: middle;
- overflow-x: hidden;
- font-weight: $euiFontWeightMedium; // Explicitly state so it doesn't get overridden by inheritance
-}
-
-.euiAvatar--user {
- @include innerBorder('dark', 50%, .05);
- border-radius: 50%;
-}
-
-.euiAvatar--space {
- @include innerBorder('dark', $euiBorderRadius, .05);
- border-radius: $euiBorderRadius;
-}
-
-.euiAvatar-isDisabled {
- cursor: not-allowed;
- filter: grayscale(100%);
-}
-
-.euiAvatar--plain {
- background-color: $euiColorEmptyShade;
-}
-
-// Modifiers for sizing.
-$avatarSizing: (
- s: (
- size: $euiSizeL,
- font-size: $euiSizeM
- ),
- m: (
- size: $euiSizeXL,
- font-size: $euiSize*.9
- ),
- l: (
- size: $euiSizeXXL,
- font-size: $euiSizeL*.8
- ),
- xl: (
- size: ($euiSize * 4),
- font-size: $euiSizeXL*.8
- ),
-);
-
-@each $size, $map in $avatarSizing {
- .euiAvatar--#{$size} {
- @include size(map-get($map, 'size'));
- line-height: map-get($map, 'size');
- font-size: map-get($map, 'font-size');
- }
-}
diff --git a/src/components/avatar/_index.scss b/src/components/avatar/_index.scss
deleted file mode 100644
index 50653a82668..00000000000
--- a/src/components/avatar/_index.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import 'avatar';
diff --git a/src/components/avatar/avatar.styles.ts b/src/components/avatar/avatar.styles.ts
new file mode 100644
index 00000000000..e10f591400e
--- /dev/null
+++ b/src/components/avatar/avatar.styles.ts
@@ -0,0 +1,82 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { css } from '@emotion/react';
+import { UseEuiTheme } from '../../services';
+
+const _avatarSize = ({
+ size,
+ fontSize,
+}: {
+ size: string;
+ fontSize: string;
+}) => {
+ return `
+ width: ${size};
+ height: ${size};
+ line-height: ${size};
+ font-size: ${fontSize};
+ `;
+};
+
+export const euiAvatarStyles = ({ euiTheme }: UseEuiTheme) => ({
+ // Base
+ euiAvatar: css`
+ // Ensures it never scales down below its intended size
+ flex-shrink: 0;
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ background-size: cover;
+ text-align: center;
+ vertical-align: middle;
+ overflow-x: hidden;
+ // Explicitly state weight so it doesn't get overridden by inheritance
+ font-weight: ${euiTheme.font.weight.medium};
+ `,
+ // Variants
+ plain: css`
+ background-color: ${euiTheme.colors.emptyShade};
+ `,
+ user: css`
+ border-radius: 50%;
+ `,
+ space: css`
+ border-radius: ${euiTheme.border.radius.medium};
+ `,
+ // States
+ isDisabled: css`
+ cursor: not-allowed;
+ filter: grayscale(100%);
+ `,
+ // Sizes
+ s: css(
+ _avatarSize({
+ size: euiTheme.size.l,
+ fontSize: euiTheme.size.m,
+ })
+ ),
+ m: css(
+ _avatarSize({
+ size: euiTheme.size.xl,
+ fontSize: `calc(${euiTheme.size.base} * 0.9)`,
+ })
+ ),
+ l: css(
+ _avatarSize({
+ size: euiTheme.size.xxl,
+ fontSize: `calc(${euiTheme.size.l} * 0.8)`,
+ })
+ ),
+ xl: css(
+ _avatarSize({
+ size: `calc(${euiTheme.size.base} * 4)`,
+ fontSize: `calc(${euiTheme.size.xl} * 0.8)`,
+ })
+ ),
+});
diff --git a/src/components/avatar/avatar.test.tsx b/src/components/avatar/avatar.test.tsx
index c4297d814ce..d9f95138631 100644
--- a/src/components/avatar/avatar.test.tsx
+++ b/src/components/avatar/avatar.test.tsx
@@ -9,10 +9,13 @@
import React from 'react';
import { render } from 'enzyme';
import { requiredProps } from '../../test/required_props';
+import { renderWithStyles } from '../../test/internal';
import { EuiAvatar, SIZES } from './avatar';
describe('EuiAvatar', () => {
+ renderWithStyles(
);
+
test('is rendered', () => {
const component = render(
);
diff --git a/src/components/avatar/avatar.tsx b/src/components/avatar/avatar.tsx
index e526f626759..87592a14f8b 100644
--- a/src/components/avatar/avatar.tsx
+++ b/src/components/avatar/avatar.tsx
@@ -11,9 +11,15 @@ import { CommonProps, ExclusiveUnion, keysOf } from '../common';
import classNames from 'classnames';
import { isColorDark, hexToRgb, isValidHex } from '../../services/color';
-import { euiPaletteColorBlindBehindText, toInitials } from '../../services';
+import {
+ euiPaletteColorBlindBehindText,
+ toInitials,
+ useEuiTheme,
+} from '../../services';
import { IconType, EuiIcon, IconSize, IconColor } from '../icon';
+import { euiAvatarStyles } from './avatar.styles';
+
const sizeToClassNameMap = {
s: 'euiAvatar--s',
m: 'euiAvatar--m',
@@ -118,25 +124,37 @@ export const EuiAvatar: FunctionComponent
= ({
style,
...rest
}) => {
+ const euiTheme = useEuiTheme();
+ const styles = euiAvatarStyles(euiTheme);
+
const visColors = euiPaletteColorBlindBehindText();
+ const isPlain = color === 'plain';
+
const classes = classNames(
'euiAvatar',
sizeToClassNameMap[size],
typeToClassNameMap[type],
{
'euiAvatar-isDisabled': isDisabled,
- 'euiAvatar--plain': color === 'plain',
},
className
);
+ const cssStyles = [
+ styles.euiAvatar,
+ styles[size],
+ styles[type],
+ isPlain && styles.plain,
+ isDisabled && styles.isDisabled,
+ ];
+
checkValidInitials(initials);
const avatarStyle: CSSProperties = style || {};
let iconCustomColor = iconColor;
- const isNamedColor = color === 'plain' || color === null;
+ const isNamedColor = isPlain || color === null;
if (!isNamedColor) {
checkValidColor(color);
@@ -177,6 +195,7 @@ export const EuiAvatar: FunctionComponent = ({
return (
{
const theme = useEuiTheme();
- const styles = euiComponentStyles(theme);
+ const componentStyles = euiComponentStyles(theme);
+ const styles = [componentStyles]
return (
-
+
);
};
```
+## Style helpers
+
+EUI components often have style variants that use a similar patterns. In these cases, consider creating a helper function to create repetitive styles.
+
+```ts
+const _componentSize = ({
+ size,
+ fontSize,
+}: {
+ size: string;
+ fontSize: string;
+}) => {
+ return `
+ width: ${size};
+ height: ${size};
+ line-height: ${size};
+ font-size: ${fontSize};
+ `;
+};
+```
+
+The helper function can then be used in the exported style block:
+
+```ts
+export const euiComponentStyles = ({ euiTheme }: UseEuiTheme) => ({
+ // Sizes
+ s: css(
+ _componentSize({
+ size: euiTheme.size.l,
+ fontSize: euiTheme.size.m,
+ })
+ ),
+ m: css(
+ _componentSize({
+ size: euiTheme.size.xl,
+ fontSize: `calc(${euiTheme.size.base} * 0.9)`,
+ })
+ ),
+ l: css(
+ _componentSize({
+ size: euiTheme.size.xxl,
+ fontSize: `calc(${euiTheme.size.l} * 0.8)`,
+ })
+ ),
+});
+```
+
+Note that the helper function returns a string literal instead of a `css` method from `@emotion/react`. This reduces the serialization work at runtime and makes the helper more flexible (e.g., could be used with a `style` attribute). Also note that the `css` method from `@emotion/react` can be [called as a normal function](https://emotion.sh/docs/@emotion/css#css) instead of as a template literal.
+
## Conditional styles
Styles can be added conditionally based on environment variables, such as the active theme, using nested string template literals.
@@ -57,5 +107,8 @@ _Work in progress_
* Use an array inside of the `css` prop for optimal style composition and class name generation. This is relevant even if only a single style object is passed.
```tsx
-
+const styles = [componentStyles.default, componentStyles.stateful];
+return (
+
+);
```