diff --git a/src-docs/src/views/datagrid/_snippets.tsx b/src-docs/src/views/datagrid/_snippets.tsx index fb3921346bc..72b86c826bf 100644 --- a/src-docs/src/views/datagrid/_snippets.tsx +++ b/src-docs/src/views/datagrid/_snippets.tsx @@ -64,7 +64,7 @@ inMemory={{ level: 'sorting' }}`, 'renderFooterCellValue={({ rowIndex, columnId }) => {}}', renderCustomGridBody: `// Optional; advanced usage only. This render function is an escape hatch for consumers who need to opt out of virtualization or otherwise need total custom control over how data grid cells are rendered. -renderCustomDataGridBody={({ visibleColumns, visibleRowData, Cell }) => ( +renderCustomGridBody={({ visibleColumns, visibleRowData, Cell }) => ( )}`, pagination: `pagination={{ diff --git a/src-docs/src/views/description_list/column_widths.tsx b/src-docs/src/views/description_list/column_widths.tsx new file mode 100644 index 00000000000..25f5500aa1c --- /dev/null +++ b/src-docs/src/views/description_list/column_widths.tsx @@ -0,0 +1,28 @@ +import React from 'react'; + +import { EuiDescriptionList } from '../../../../src/components'; + +const listItems = [ + { + title: '25% width', + description: '75% width', + }, + { + title: 'TIE Fighter', + description: + 'The sequel to XWING, join the dark side and fly for the Emperor.', + }, + { + title: 'Quake 2', + description: 'The game that made me drop out of college.', + }, +]; + +export default () => ( + +); diff --git a/src-docs/src/views/description_list/description_list_example.js b/src-docs/src/views/description_list/description_list_example.js index c846252972d..76a50c097b4 100644 --- a/src-docs/src/views/description_list/description_list_example.js +++ b/src-docs/src/views/description_list/description_list_example.js @@ -1,9 +1,10 @@ -import React, { Fragment } from 'react'; +import React from 'react'; import { GuideSectionTypes } from '../../components'; import { EuiCode, + EuiLink, EuiDescriptionList, EuiDescriptionListTitle, EuiDescriptionListDescription, @@ -59,6 +60,13 @@ const descriptionListResponsiveColumnSnippet = ``; +import DescriptionListColumnWidths from './column_widths'; +const descriptionListColumnWidthsSource = require('!!raw-loader!./column_widths'); +const descriptionListColumnWidthsSnippet = ``; + import DescriptionListStyling from './description_list_styling'; const descriptionListStylingSource = require('!!raw-loader!./description_list_styling'); const descriptionListStylingSnippet = [ @@ -181,13 +189,11 @@ export const DescriptionListExample = { }, ], text: ( - -

- Using the prop type set to{' '} - column description lists can be presented in an - inline, column format. -

-
+

+ Using the prop type set to{' '} + column description lists can be presented in an + inline, column format. +

), snippet: descriptionListColumnSnippet, demo: , @@ -200,17 +206,53 @@ export const DescriptionListExample = { }, ], text: ( - -

- To return to the typical row format on smaller screens set{' '} - type to responsiveColumn. The - following list will only show the column format on larger screens. -

-
+

+ To return to the typical row format on smaller screens set{' '} + type to responsiveColumn. The + following list will only show the column format on larger screens. +

), snippet: descriptionListResponsiveColumnSnippet, demo: , }, + { + source: [ + { + type: GuideSectionTypes.TSX, + code: descriptionListColumnWidthsSource, + }, + ], + text: ( + <> +

+ The optional columnWidths prop allows customizing + specific column widths (e.g.{' '} + {"['100px', '200px']"}). The first array value + applies to the title column, and the second applies to the + description column. +

+

+ Passing numbers instead of CSS width strings will use a ratio of + widths. For example, [1, 3] will render a + description column 3x the width of the title column. In other words, + titles will have a width of 25% descriptions will have a width of + 75%. +

+

+ For advanced usage, column width strings also accept{' '} + + CSS grid special units, sizing, keywords, and sizing functions + + . +

+ + ), + snippet: descriptionListColumnWidthsSnippet, + demo: , + }, { title: 'Inline', source: [ diff --git a/src/components/datagrid/controls/__snapshots__/keyboard_shortcuts.test.tsx.snap b/src/components/datagrid/controls/__snapshots__/keyboard_shortcuts.test.tsx.snap index a920547560e..10f17a05ef2 100644 --- a/src/components/datagrid/controls/__snapshots__/keyboard_shortcuts.test.tsx.snap +++ b/src/components/datagrid/controls/__snapshots__/keyboard_shortcuts.test.tsx.snap @@ -86,6 +86,7 @@ exports[`useDataGridKeyboardShortcuts returns a popover containing a list of key aria-labelledby="generated-id" class="euiDescriptionList emotion-euiDescriptionList-column-center-s-s" data-type="column" + style="grid-template-columns: 1fr 3fr;" >
`; -exports[`EuiDescriptionList props column gap m is rendered 1`] = ` +exports[`EuiDescriptionList props columnGutterSize m is rendered 1`] = `
`; -exports[`EuiDescriptionList props column gap s is rendered 1`] = ` +exports[`EuiDescriptionList props columnGutterSize s is rendered 1`] = `
`; -exports[`EuiDescriptionList props gutter m is rendered 1`] = ` -
-`; - -exports[`EuiDescriptionList props gutter s is rendered 1`] = ` -
-`; - exports[`EuiDescriptionList props listItems descriptionProps is rendered 1`] = `
`; +exports[`EuiDescriptionList props rowGutterSize m is rendered 1`] = ` +
+`; + +exports[`EuiDescriptionList props rowGutterSize s is rendered 1`] = ` +
+`; + exports[`EuiDescriptionList props type column is rendered 1`] = `
{ description: 'Description 3', }, ]; + describe('props', () => { describe('listItems', () => { const { container } = render( @@ -145,7 +146,7 @@ describe('EuiDescriptionList', () => { }); }); - describe('gutter', () => { + describe('rowGutterSize', () => { ROW_GUTTER_SIZES.forEach((gutter) => { test(`${gutter} is rendered`, () => { const { container } = render( @@ -157,7 +158,7 @@ describe('EuiDescriptionList', () => { }); }); - describe('column gap', () => { + describe('columnGutterSize', () => { COLUMN_GUTTER_SIZES.forEach((columnGutterSize) => { test(`${columnGutterSize} is rendered`, () => { const { container } = render( @@ -170,6 +171,55 @@ describe('EuiDescriptionList', () => { expect(container.firstChild).toMatchSnapshot(); }); }); + + describe('columnWidths', () => { + it('renders the passed values as an inline css grid style', () => { + const { container } = render( + + ); + expect(container.firstChild).toHaveStyle( + 'grid-template-columns: 100px minmax(200px, auto)' + ); + }); + + it('converts numbers into fr grid units', () => { + const { container } = render( + + ); + expect(container.firstChild).toHaveStyle( + 'grid-template-columns: 1fr 2fr' + ); + }); + + it('respects custom styles', () => { + const { container } = render( + + ); + expect(container.firstChild).toHaveStyle('color: red'); + }); + + it('correctly removes inline styles when responsive columns collapse to rows', () => { + const { container, rerender } = render( + + ); + expect(container.firstChild).toHaveStyle( + 'grid-template-columns: 3fr 4fr' + ); + + mockUseIsWithinBreakpoints.mockReturnValue(true); + rerender( + + ); + expect(container.firstChild).toHaveAttribute('style', ''); + }); + }); }); }); }); diff --git a/src/components/description_list/description_list.tsx b/src/components/description_list/description_list.tsx index 75862b8a883..1b0ebba7edb 100644 --- a/src/components/description_list/description_list.tsx +++ b/src/components/description_list/description_list.tsx @@ -24,6 +24,7 @@ export const EuiDescriptionList: FunctionComponent< align = 'left', children, className, + style, compressed = false, descriptionProps, listItems, @@ -32,6 +33,7 @@ export const EuiDescriptionList: FunctionComponent< type: _type = 'row', rowGutterSize = 's', columnGutterSize = 's', + columnWidths, ...rest }) => { const showResponsiveColumns = useIsWithinBreakpoints(['xs', 's']); @@ -54,6 +56,22 @@ export const EuiDescriptionList: FunctionComponent< type === 'column' && styles.columnGap[columnGutterSize], ]; + const inlineStyles = useMemo(() => { + if (type === 'column' && columnWidths) { + // Leave string values as is - e.g. if a consumer passes in a specific '200px' or 'minmax()' + const convertNumbersToFr = (value: number | string) => + typeof value === 'number' ? `${value}fr` : value; + + const titleWidth = convertNumbersToFr(columnWidths[0]); + const descriptionWidth = convertNumbersToFr(columnWidths[1]); + return { + gridTemplateColumns: `${titleWidth} ${descriptionWidth}`, + ...style, + }; + } + return style; + }, [style, type, columnWidths]); + const classes = classNames('euiDescriptionList', className); let childrenOrListItems = null; @@ -81,7 +99,13 @@ export const EuiDescriptionList: FunctionComponent< -
+
{childrenOrListItems}
diff --git a/src/components/description_list/description_list_types.ts b/src/components/description_list/description_list_types.ts index 0f5ad635f35..6debbdcbe9f 100644 --- a/src/components/description_list/description_list_types.ts +++ b/src/components/description_list/description_list_types.ts @@ -49,6 +49,20 @@ export interface EuiDescriptionListProps { * Only applies to `column` and `responsiveColumn` types. */ columnGutterSize?: EuiDescriptionListColumnGapSizes; + /** + * Allows customizing specific column widths (e.g. `['100px', '200px']`). The first + * array value applies to the title column, and the second applies to the description column. + * + * Passing numbers instead of CSS width strings will use a ratio of widths. + * For example, [1, 3] will render a description column 3x the width of the title column. + * In other words, descriptions will have a width of `75%` and titles will have a width of `25%`. + * + * Only applies to `column` and `responsiveColumn` types. + * + * _Advanced usage note:_ column width strings also accept [CSS grid special units, + * sizing, keywords, and sizing functions](https://css-tricks.com/snippets/css/complete-guide-grid/#aa-special-units-functions). + */ + columnWidths?: [number | string, number | string]; } export const CHILD_TYPES = ['row', 'inline', 'column'] as const; diff --git a/upcoming_changelogs/7146.md b/upcoming_changelogs/7146.md new file mode 100644 index 00000000000..06c4f4078a4 --- /dev/null +++ b/upcoming_changelogs/7146.md @@ -0,0 +1,6 @@ +- Updated `EuiDescriptionList` with new `columnWidths` prop + +**Bug fixes** + +- Fixed `EuiDataGrid`'s keyboard shortcuts popover display +