From b2ac7f6cd4edf74f9cc61bf84282bd16d048b668 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 2 Sep 2024 16:27:10 +0200 Subject: [PATCH 1/6] feat: adds support for component prop on EuiText --- .../eui/src/components/text/text.stories.tsx | 1 + .../eui/src/components/text/text.test.tsx | 10 ++++++++ packages/eui/src/components/text/text.tsx | 24 +++++++++++++++---- .../src/components/text/text_align.test.tsx | 10 ++++++++ .../eui/src/components/text/text_align.tsx | 7 +++++- .../src/components/text/text_color.test.tsx | 10 ++++++++ .../eui/src/components/text/text_color.tsx | 5 ++-- 7 files changed, 59 insertions(+), 8 deletions(-) diff --git a/packages/eui/src/components/text/text.stories.tsx b/packages/eui/src/components/text/text.stories.tsx index b3cf2b479a9..e8a613c1ea5 100644 --- a/packages/eui/src/components/text/text.stories.tsx +++ b/packages/eui/src/components/text/text.stories.tsx @@ -25,6 +25,7 @@ const meta: Meta = { grow: true, color: 'default', textAlign: 'left', + component: 'div', }, }; moveStorybookControlsToCategory(meta, ['color'], 'EuiTextColor props'); diff --git a/packages/eui/src/components/text/text.test.tsx b/packages/eui/src/components/text/text.test.tsx index 25fd808ec06..e1806621661 100644 --- a/packages/eui/src/components/text/text.test.tsx +++ b/packages/eui/src/components/text/text.test.tsx @@ -64,5 +64,15 @@ describe('EuiText', () => { expect(container.firstChild).toMatchSnapshot(); }); + + test('component', () => { + const { container } = render( + + Content + + ); + + expect(container.firstChild?.nodeName).toBe('SPAN'); + }); }); }); diff --git a/packages/eui/src/components/text/text.tsx b/packages/eui/src/components/text/text.tsx index e264e6c9ca3..a510a4ca8d8 100644 --- a/packages/eui/src/components/text/text.tsx +++ b/packages/eui/src/components/text/text.tsx @@ -22,6 +22,10 @@ export type TextSize = (typeof TEXT_SIZES)[number]; export type EuiTextProps = CommonProps & Omit, 'color'> & { + /** + * Determines the root element + */ + component?: 'div' | 'span' | 'p'; textAlign?: TextAlignment; /** * Determines the text size. Choose `relative` to control the `font-size` based on the value of a parent container. @@ -36,6 +40,7 @@ export type EuiTextProps = CommonProps & }; export const EuiText: FunctionComponent = ({ + component = 'div', size = 'm', color, grow = true, @@ -52,16 +57,22 @@ export const EuiText: FunctionComponent = ({ ]; const classes = classNames('euiText', className); + const Component = component; let text = ( -
+ {children} -
+ ); if (color) { text = ( - + {text} ); @@ -69,7 +80,12 @@ export const EuiText: FunctionComponent = ({ if (textAlign) { text = ( - + {text} ); diff --git a/packages/eui/src/components/text/text_align.test.tsx b/packages/eui/src/components/text/text_align.test.tsx index ea99b3358ef..e31bb5c3641 100644 --- a/packages/eui/src/components/text/text_align.test.tsx +++ b/packages/eui/src/components/text/text_align.test.tsx @@ -50,5 +50,15 @@ describe('EuiTextAlign', () => { shouldRenderCustomStyles(); }); + + test('component', () => { + const { container } = render( + + Content + + ); + + expect(container.firstChild?.nodeName).toBe('SPAN'); + }); }); }); diff --git a/packages/eui/src/components/text/text_align.tsx b/packages/eui/src/components/text/text_align.tsx index 5b3c44736c4..cdf7591a653 100644 --- a/packages/eui/src/components/text/text_align.tsx +++ b/packages/eui/src/components/text/text_align.tsx @@ -21,6 +21,10 @@ export type TextAlignment = (typeof ALIGNMENTS)[number]; export type EuiTextAlignProps = CommonProps & HTMLAttributes & { + /** + * Determines the root element + */ + component?: 'div' | 'span' | 'p'; textAlign?: TextAlignment; /** * Applies text styling to the child element instead of rendering a parent wrapper `div`. @@ -31,6 +35,7 @@ export type EuiTextAlignProps = CommonProps & export const EuiTextAlign: FunctionComponent = ({ children, + component: Component = 'div', textAlign = 'left', cloneElement = false, ...rest @@ -42,6 +47,6 @@ export const EuiTextAlign: FunctionComponent = ({ if (isValidElement(children) && cloneElement) { return cloneElementWithCss(children, props); } else { - return
{children}
; + return {children}; } }; diff --git a/packages/eui/src/components/text/text_color.test.tsx b/packages/eui/src/components/text/text_color.test.tsx index 876d94ce14c..ba0bf2f4f3d 100644 --- a/packages/eui/src/components/text/text_color.test.tsx +++ b/packages/eui/src/components/text/text_color.test.tsx @@ -62,5 +62,15 @@ describe('EuiTextColor', () => {
); }); + + test('component', () => { + const { container } = render( + + Content + + ); + + expect(container.firstChild?.nodeName).toBe('SPAN'); + }); }); }); diff --git a/packages/eui/src/components/text/text_color.tsx b/packages/eui/src/components/text/text_color.tsx index bbc5ef2fb30..e7a8647f034 100644 --- a/packages/eui/src/components/text/text_color.tsx +++ b/packages/eui/src/components/text/text_color.tsx @@ -44,7 +44,7 @@ export type EuiTextColorProps = CommonProps & /** * Determines the root element */ - component?: 'div' | 'span'; + component?: 'div' | 'span' | 'p'; /** * Applies text styling to the child element instead of rendering a parent wrapper `span`/`div`. * Can only be used when wrapping a *single* child element/tag, and not raw text. @@ -55,7 +55,7 @@ export type EuiTextColorProps = CommonProps & export const EuiTextColor: FunctionComponent = ({ children, color = 'default', - component = 'span', + component: Component = 'span', cloneElement = false, style, ...rest @@ -84,7 +84,6 @@ export const EuiTextColor: FunctionComponent = ({ const childrenStyle = { ...children.props.style, ...euiTextStyle }; return cloneElementWithCss(children, { ...props, style: childrenStyle }); } else { - const Component = component; return {children}; } }; From 60f9ab42559f0315dd52c99182938771b3037864 Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Mon, 2 Sep 2024 16:44:36 +0200 Subject: [PATCH 2/6] chore: add changelog --- packages/eui/changelogs/upcoming/7993.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/eui/changelogs/upcoming/7993.md diff --git a/packages/eui/changelogs/upcoming/7993.md b/packages/eui/changelogs/upcoming/7993.md new file mode 100644 index 00000000000..3f259cd9246 --- /dev/null +++ b/packages/eui/changelogs/upcoming/7993.md @@ -0,0 +1,3 @@ +- Added `component` prop on `EuiText` and `EuiTextAlign` +- Updated `component` prop values for `EuiTextColor` + From 8b61b90dd6ff6d04b1e14ff10c3803e05d1d626b Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Tue, 3 Sep 2024 18:35:08 +0200 Subject: [PATCH 3/6] style: update JSDoc comments --- packages/eui/src/components/text/text.tsx | 2 +- packages/eui/src/components/text/text_align.tsx | 2 +- packages/eui/src/components/text/text_color.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/eui/src/components/text/text.tsx b/packages/eui/src/components/text/text.tsx index a510a4ca8d8..06f3a8eb02b 100644 --- a/packages/eui/src/components/text/text.tsx +++ b/packages/eui/src/components/text/text.tsx @@ -23,7 +23,7 @@ export type TextSize = (typeof TEXT_SIZES)[number]; export type EuiTextProps = CommonProps & Omit, 'color'> & { /** - * Determines the root element + * The HTML element/tag to render */ component?: 'div' | 'span' | 'p'; textAlign?: TextAlignment; diff --git a/packages/eui/src/components/text/text_align.tsx b/packages/eui/src/components/text/text_align.tsx index cdf7591a653..c775360fc8f 100644 --- a/packages/eui/src/components/text/text_align.tsx +++ b/packages/eui/src/components/text/text_align.tsx @@ -22,7 +22,7 @@ export type TextAlignment = (typeof ALIGNMENTS)[number]; export type EuiTextAlignProps = CommonProps & HTMLAttributes & { /** - * Determines the root element + * The HTML element/tag to render */ component?: 'div' | 'span' | 'p'; textAlign?: TextAlignment; diff --git a/packages/eui/src/components/text/text_color.tsx b/packages/eui/src/components/text/text_color.tsx index e7a8647f034..e76cf54207b 100644 --- a/packages/eui/src/components/text/text_color.tsx +++ b/packages/eui/src/components/text/text_color.tsx @@ -42,7 +42,7 @@ export type EuiTextColorProps = CommonProps & */ color?: TextColor | CSSProperties['color']; /** - * Determines the root element + * The HTML element/tag to render */ component?: 'div' | 'span' | 'p'; /** From 8a0af411bf23e4a5c727a25a7f5209bf87e3ebcb Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Wed, 4 Sep 2024 13:47:12 +0200 Subject: [PATCH 4/6] styles: enhance component prop JSDoc to add information about valid usage --- packages/eui/src/components/text/text.tsx | 5 ++++- packages/eui/src/components/text/text_align.tsx | 3 +++ packages/eui/src/components/text/text_color.tsx | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/eui/src/components/text/text.tsx b/packages/eui/src/components/text/text.tsx index 06f3a8eb02b..3ccb7052e4f 100644 --- a/packages/eui/src/components/text/text.tsx +++ b/packages/eui/src/components/text/text.tsx @@ -23,7 +23,10 @@ export type TextSize = (typeof TEXT_SIZES)[number]; export type EuiTextProps = CommonProps & Omit, 'color'> & { /** - * The HTML element/tag to render + * The HTML element/tag to render. + * Use with care when nesting multiple components to ensure valid html. + * Block elements can't be nested inside inline elements: `

` and `

` are not valid inside ``. + * Additionally `
` is not valid to use inside `

`. */ component?: 'div' | 'span' | 'p'; textAlign?: TextAlignment; diff --git a/packages/eui/src/components/text/text_align.tsx b/packages/eui/src/components/text/text_align.tsx index c775360fc8f..e6cee796be6 100644 --- a/packages/eui/src/components/text/text_align.tsx +++ b/packages/eui/src/components/text/text_align.tsx @@ -23,6 +23,9 @@ export type EuiTextAlignProps = CommonProps & HTMLAttributes & { /** * The HTML element/tag to render + * Use with care when nesting multiple components to ensure valid html. + * Block elements can't be nested inside inline elements. (

and

are not valid inside ) + * Additionally
is not valid to use inside

. */ component?: 'div' | 'span' | 'p'; textAlign?: TextAlignment; diff --git a/packages/eui/src/components/text/text_color.tsx b/packages/eui/src/components/text/text_color.tsx index e76cf54207b..2a04509bf3c 100644 --- a/packages/eui/src/components/text/text_color.tsx +++ b/packages/eui/src/components/text/text_color.tsx @@ -43,6 +43,9 @@ export type EuiTextColorProps = CommonProps & color?: TextColor | CSSProperties['color']; /** * The HTML element/tag to render + * Use with care when nesting multiple components to ensure valid html. + * Block elements can't be nested inside inline elements. (

and

are not valid inside ) + * Additionally
is not valid to use inside

. */ component?: 'div' | 'span' | 'p'; /** From 9e6e9c9b223424e6716ee72af3af14f0128fbac8 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Thu, 5 Sep 2024 19:40:51 -0700 Subject: [PATCH 5/6] [PR feedback] DRY out prop types/docs + copy tweaks, clarify valid usage --- packages/eui/changelogs/upcoming/7993.md | 4 +- packages/eui/src/components/text/text.tsx | 29 ++++------- .../eui/src/components/text/text_align.tsx | 28 ++--------- .../eui/src/components/text/text_color.tsx | 34 ++----------- packages/eui/src/components/text/types.ts | 48 +++++++++++++++++++ 5 files changed, 65 insertions(+), 78 deletions(-) create mode 100644 packages/eui/src/components/text/types.ts diff --git a/packages/eui/changelogs/upcoming/7993.md b/packages/eui/changelogs/upcoming/7993.md index 3f259cd9246..41df76e3168 100644 --- a/packages/eui/changelogs/upcoming/7993.md +++ b/packages/eui/changelogs/upcoming/7993.md @@ -1,3 +1 @@ -- Added `component` prop on `EuiText` and `EuiTextAlign` -- Updated `component` prop values for `EuiTextColor` - +- Updated `EuiText`, `EuiTextColor`, and `EuiTextAlign` with a new `component` prop that allows changing the default rendered `

` wrapper to a `` or `

` tag. diff --git a/packages/eui/src/components/text/text.tsx b/packages/eui/src/components/text/text.tsx index 3ccb7052e4f..bc675e7cb91 100644 --- a/packages/eui/src/components/text/text.tsx +++ b/packages/eui/src/components/text/text.tsx @@ -6,39 +6,26 @@ * Side Public License, v 1. */ -import React, { FunctionComponent, HTMLAttributes, CSSProperties } from 'react'; +import React, { FunctionComponent } from 'react'; import classNames from 'classnames'; -import { CommonProps } from '../common'; import { useEuiMemoizedStyles } from '../../services'; -import { euiTextStyles } from './text.styles'; - -import { TextColor, EuiTextColor } from './text_color'; -import { EuiTextAlign, TextAlignment } from './text_align'; +import type { SharedTextProps, EuiTextColors, EuiTextAlignment } from './types'; +import { EuiTextColor } from './text_color'; +import { EuiTextAlign } from './text_align'; +import { euiTextStyles } from './text.styles'; export const TEXT_SIZES = ['xs', 's', 'm', 'relative'] as const; export type TextSize = (typeof TEXT_SIZES)[number]; -export type EuiTextProps = CommonProps & - Omit, 'color'> & { - /** - * The HTML element/tag to render. - * Use with care when nesting multiple components to ensure valid html. - * Block elements can't be nested inside inline elements: `

` and `

` are not valid inside ``. - * Additionally `
` is not valid to use inside `

`. - */ - component?: 'div' | 'span' | 'p'; - textAlign?: TextAlignment; +export type EuiTextProps = SharedTextProps & + EuiTextColors & + EuiTextAlignment & { /** * Determines the text size. Choose `relative` to control the `font-size` based on the value of a parent container. */ size?: TextSize; - /** - * Any of our named colors or a `hex`, `rgb` or `rgba` value. - * @default inherit - */ - color?: TextColor | CSSProperties['color']; grow?: boolean; }; diff --git a/packages/eui/src/components/text/text_align.tsx b/packages/eui/src/components/text/text_align.tsx index e6cee796be6..aa8fbad54a6 100644 --- a/packages/eui/src/components/text/text_align.tsx +++ b/packages/eui/src/components/text/text_align.tsx @@ -6,35 +6,17 @@ * Side Public License, v 1. */ -import React, { - FunctionComponent, - HTMLAttributes, - isValidElement, -} from 'react'; -import { CommonProps } from '../common'; +import React, { FunctionComponent, isValidElement } from 'react'; import { cloneElementWithCss } from '../../services'; - +import type { SharedTextProps, CloneElement, EuiTextAlignment } from './types'; import { euiTextAlignStyles as styles } from './text_align.styles'; export const ALIGNMENTS = ['left', 'right', 'center'] as const; export type TextAlignment = (typeof ALIGNMENTS)[number]; -export type EuiTextAlignProps = CommonProps & - HTMLAttributes & { - /** - * The HTML element/tag to render - * Use with care when nesting multiple components to ensure valid html. - * Block elements can't be nested inside inline elements. (

and

are not valid inside ) - * Additionally
is not valid to use inside

. - */ - component?: 'div' | 'span' | 'p'; - textAlign?: TextAlignment; - /** - * Applies text styling to the child element instead of rendering a parent wrapper `div`. - * Can only be used when wrapping a *single* child element/tag, and not raw text. - */ - cloneElement?: boolean; - }; +export type EuiTextAlignProps = SharedTextProps & + CloneElement & + EuiTextAlignment; export const EuiTextAlign: FunctionComponent = ({ children, diff --git a/packages/eui/src/components/text/text_color.tsx b/packages/eui/src/components/text/text_color.tsx index 2a04509bf3c..a31615eb40e 100644 --- a/packages/eui/src/components/text/text_color.tsx +++ b/packages/eui/src/components/text/text_color.tsx @@ -6,16 +6,9 @@ * Side Public License, v 1. */ -import React, { - FunctionComponent, - HTMLAttributes, - CSSProperties, - isValidElement, -} from 'react'; - -import { CommonProps } from '../common'; +import React, { FunctionComponent, isValidElement } from 'react'; import { useEuiMemoizedStyles, cloneElementWithCss } from '../../services'; - +import type { SharedTextProps, CloneElement, EuiTextColors } from './types'; import { euiTextColorStyles } from './text_color.styles'; export const COLORS = [ @@ -32,28 +25,7 @@ export type TextColor = (typeof COLORS)[number]; export const _isNamedColor = (color: any): color is TextColor => COLORS.includes(color); -export type EuiTextColorProps = CommonProps & - Omit< - HTMLAttributes & HTMLAttributes, - 'color' - > & { - /** - * Any of our named colors or a `hex`, `rgb` or `rgba` value. - */ - color?: TextColor | CSSProperties['color']; - /** - * The HTML element/tag to render - * Use with care when nesting multiple components to ensure valid html. - * Block elements can't be nested inside inline elements. (

and

are not valid inside ) - * Additionally
is not valid to use inside

. - */ - component?: 'div' | 'span' | 'p'; - /** - * Applies text styling to the child element instead of rendering a parent wrapper `span`/`div`. - * Can only be used when wrapping a *single* child element/tag, and not raw text. - */ - cloneElement?: boolean; - }; +export type EuiTextColorProps = SharedTextProps & CloneElement & EuiTextColors; export const EuiTextColor: FunctionComponent = ({ children, diff --git a/packages/eui/src/components/text/types.ts b/packages/eui/src/components/text/types.ts new file mode 100644 index 00000000000..26b37508c7d --- /dev/null +++ b/packages/eui/src/components/text/types.ts @@ -0,0 +1,48 @@ +/* + * 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 type { HTMLAttributes, CSSProperties } from 'react'; +import type { CommonProps } from '../common'; + +import type { TextColor } from './text_color'; +import type { TextAlignment } from './text_align'; + +export type SharedTextProps = CommonProps & + Omit, 'color'> & { + /** + * The HTML element/tag to render. + * Use with care when nesting multiple components to ensure valid XHTML: + * - `

` and other block tags are not valid to use inside `

`. If using the `

` tag, we recommend passing strings/text only. + * - `` is valid to be nested in any tag, and can have any tag nested within it. + */ + component?: 'div' | 'span' | 'p'; + }; + +export type CloneElement = { + /** + * Applies text styling to the child element instead of rendering a parent wrapper. + * Can only be used when wrapping a *single* child element/tag, and not raw text. + */ + cloneElement?: boolean; +}; + +export type EuiTextColors = { + /** + * Any of our named colors or a `hex`, `rgb` or `rgba` value. + * @default inherit + */ + color?: TextColor | CSSProperties['color']; +}; + +export type EuiTextAlignment = { + /** + * Applies horizontal text alignment + * @default left + */ + textAlign?: TextAlignment; +}; From 0f91cfa31da2e9c1928c8803e51c7902a6f90fec Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Thu, 5 Sep 2024 19:48:04 -0700 Subject: [PATCH 6/6] Missing EuiTextAlign control in Storybook --- packages/eui/src/components/text/text_align.stories.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/eui/src/components/text/text_align.stories.tsx b/packages/eui/src/components/text/text_align.stories.tsx index 67f1fb4ad9d..8adcaab5226 100644 --- a/packages/eui/src/components/text/text_align.stories.tsx +++ b/packages/eui/src/components/text/text_align.stories.tsx @@ -21,6 +21,7 @@ const meta: Meta = { args: { textAlign: 'left', cloneElement: false, + component: 'div', }, }; hideStorybookControls(meta, ['aria-label']);