Upgrade EUI to v95.12.0 (#193805)

`v95.11.0``v95.12.0-backport.0`

> [!note]
> A few fun highlights from this release:
> - Content within `EuiDataGrid`, `EuiBasicTable`, and
`EuiInMemoryTable`, when manually selected/highlighted by users, should
now more cleanly copy and paste into various spreadsheet apps
> - `EuiProvider` will now detect the user's system-level dark or light
mode and default to that if no `colorMode` prop is passed manually

_[Questions? Please see our Kibana upgrade
FAQ.](https://github.com/elastic/eui/blob/main/wiki/eui-team-processes/upgrading-kibana.md#faq-for-kibana-teams)_

---

## [`v95.12.0`](https://github.com/elastic/eui/releases/v95.12.0)

- Enhanced `EuiDataGrid` and `EuiBasic/InMemoryTable` to clean content
newlines/tabs when users copy and paste from their tabular data
([#8019](https://github.com/elastic/eui/pull/8019))
- Updated `EuiResizableButton` with a new `accountForScrollbars` prop
([#8021](https://github.com/elastic/eui/pull/8021))
- Updated `EuiProvider` to inherit from the user's OS/system light/dark
mode setting if a `colorMode` prop has not been passed
([#8026](https://github.com/elastic/eui/pull/8026))

**Bug fixes**

- Fixed `EuiDatePicker`'s `onClear` button to not appear when the input
is `disabled` ([#8020](https://github.com/elastic/eui/pull/8020))
- Fixed several `EuiDataGrid` row height bugs:
([#8025](https://github.com/elastic/eui/pull/8025))
- Fixed row heights not recalculating when
`rowHeightOptions.lineHeight`, `gridStyles.fontSize`, or
`gridStyles.cellPadding` changed
- Fixed incorrect height calculations for `rowHeightOptions.rowHeights`
with `lineCount`s
- Fixed control column content to align better with multi-line row
heights, as well as custom line-heights
##
[`v95.12.0-backport.0`](https://github.com/elastic/eui/releases/v95.12.0-backport.0)

**This is a backport release only intended for use by Kibana.**

**Bug fixes**

- Fixed `EuiProvider`'s system color mode detection causing errors
during server-side rendering
([#8040](https://github.com/elastic/eui/pull/8040))
- Fixed an `EuiDataGrid` rendering bug that was causing bouncing
scrollbar issues ([#8041](https://github.com/elastic/eui/pull/8041))
This commit is contained in:
Cee Chen 2024-09-30 16:25:47 -07:00 committed by GitHub
parent 6ed731cad5
commit 8a89c8576d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 126 additions and 169 deletions

View file

@ -115,7 +115,7 @@
"@elastic/ecs": "^8.11.1",
"@elastic/elasticsearch": "^8.15.0",
"@elastic/ems-client": "8.5.3",
"@elastic/eui": "95.11.0",
"@elastic/eui": "95.12.0-backport.0",
"@elastic/filesaver": "1.1.2",
"@elastic/node-crypto": "1.2.1",
"@elastic/numeral": "^2.5.1",

View file

@ -53,22 +53,16 @@ if (!Object.hasOwn(global, 'Worker')) {
if (!Object.hasOwn(global, 'matchMedia')) {
Object.defineProperty(global, 'matchMedia', {
writable: true,
// eslint-disable-next-line no-undef
value: jest.fn().mockImplementation((query) => ({
value: (query) => ({
matches: false,
media: query,
onchange: null,
// eslint-disable-next-line no-undef
addListener: jest.fn(), // deprecated
// eslint-disable-next-line no-undef
removeListener: jest.fn(), // deprecated
// eslint-disable-next-line no-undef
addEventListener: jest.fn(),
// eslint-disable-next-line no-undef
removeEventListener: jest.fn(),
// eslint-disable-next-line no-undef
dispatchEvent: jest.fn(),
})),
addListener: () => {},
removeListener: () => {},
addEventListener: () => {},
removeEventListener: () => {},
dispatchEvent: () => {},
}),
});
}
}

View file

@ -28,7 +28,6 @@ export { popularizeField } from './src/utils/popularize_field';
export { useColumns, type UseColumnsProps } from './src/hooks/use_data_grid_columns';
export { OPEN_DETAILS, SELECT_ROW } from './src/components/data_table_columns'; // TODO: deprecate?
export { DataTableRowControl } from './src/components/data_table_row_control';
export type {
UnifiedDataTableRenderCustomToolbar,

View file

@ -16,7 +16,6 @@ import {
EuiToolTip,
} from '@elastic/eui';
import { RowControlColumn, RowControlProps } from '@kbn/discover-utils';
import { DataTableRowControl, Size } from '../../data_table_row_control';
import { DEFAULT_CONTROL_COLUMN_WIDTH } from '../../../constants';
import { useControlColumn } from '../../../hooks/use_control_column';
@ -40,23 +39,25 @@ export const RowControlCell = ({
tooltipContent,
}) => {
return (
<DataTableRowControl size={Size.normal}>
<EuiToolTip content={tooltipContent ?? label} delay="long">
<EuiButtonIcon
data-test-subj={dataTestSubj ?? `unifiedDataTable_rowControl_${props.columnId}`}
disabled={disabled}
iconSize="s"
iconType={iconType}
color={color ?? 'text'}
aria-label={label}
onClick={() => {
if (record) {
onClick?.({ record, rowIndex });
}
}}
/>
</EuiToolTip>
</DataTableRowControl>
<EuiToolTip
content={tooltipContent ?? label}
delay="long"
anchorClassName="unifiedDataTable__rowControl"
>
<EuiButtonIcon
data-test-subj={dataTestSubj ?? `unifiedDataTable_rowControl_${props.columnId}`}
disabled={disabled}
iconSize="s"
iconType={iconType}
color={color ?? 'text'}
aria-label={label}
onClick={() => {
if (record) {
onClick?.({ record, rowIndex });
}
}}
/>
</EuiToolTip>
);
},
[props.columnId, record, rowIndex]

View file

@ -19,9 +19,7 @@ import {
EuiToolTip,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { css } from '@emotion/react';
import { RowControlColumn, RowControlProps } from '@kbn/discover-utils';
import { DataTableRowControl, Size } from '../../data_table_row_control';
import { DEFAULT_CONTROL_COLUMN_WIDTH } from '../../../constants';
import { useControlColumn } from '../../../hooks/use_control_column';
@ -80,26 +78,20 @@ export const RowMenuControlCell = ({
return (
<EuiPopover
id={`rowMenuActionsPopover_${props.rowIndex}`}
className="unifiedDataTable__rowControl"
button={
<DataTableRowControl size={Size.normal}>
<EuiToolTip content={buttonLabel} delay="long">
<EuiButtonIcon
data-test-subj={`unifiedDataTable_${props.columnId}`}
iconSize="s"
iconType="boxesVertical"
color="text"
aria-label={buttonLabel}
css={css`
.euiDataGridRowCell__content--defaultHeight & {
margin-top: 2px; // to align with other controls
}
`}
onClick={() => {
setIsMoreActionsPopoverOpen(!isMoreActionsPopoverOpen);
}}
/>
</EuiToolTip>
</DataTableRowControl>
<EuiToolTip content={buttonLabel} delay="long">
<EuiButtonIcon
data-test-subj={`unifiedDataTable_${props.columnId}`}
iconSize="s"
iconType="boxesVertical"
color="text"
aria-label={buttonLabel}
onClick={() => {
setIsMoreActionsPopoverOpen(!isMoreActionsPopoverOpen);
}}
/>
</EuiToolTip>
}
isOpen={isMoreActionsPopoverOpen}
closePopover={() => setIsMoreActionsPopoverOpen(false)}

View file

@ -125,16 +125,17 @@
.unifiedDataTable__rowControl {
// fine-tuning the vertical alignment with the text for any row height setting
margin-top: -$euiSizeXS;
.euiDataGridRowCell__content--defaultHeight & { // "Single line" row height setting
margin-top: 0;
margin-top: -1px;
// Compact density - 'auto & custom' row height
.euiDataGrid--fontSizeSmall .euiDataGridRowCell__content:not(.euiDataGridRowCell__content--defaultHeight) & {
margin-top: -2.5px;
}
&--size-normal {
display: inline-block;
width: $euiSizeL;
height: $euiSizeL;
overflow: hidden;
// Compact density - 'single' row height
.euiDataGrid--fontSizeSmall .euiDataGridRowCell__content--defaultHeight & {
align-self: flex-start;
margin-top: -3px;
}
}

View file

@ -50,32 +50,22 @@ export const SelectButton = (props: EuiDataGridCellValueElementProps) => {
}
return (
<EuiFlexGroup
responsive={false}
direction="column"
justifyContent="center"
className="unifiedDataTable__rowControl"
<EuiCheckbox
id={record.id}
aria-label={toggleDocumentSelectionLabel}
checked={isDocSelected(record.id)}
data-test-subj={`dscGridSelectDoc-${record.id}`}
onChange={(event) => {
if ((event.nativeEvent as MouseEvent)?.shiftKey) {
toggleMultipleDocsSelection(record.id);
} else {
toggleDocSelection(record.id);
}
}}
css={css`
padding-block: ${euiTheme.size.xs}; // to have the same height as "openDetails" control
padding-left: ${euiTheme.size.xs}; // space between controls
margin-left: ${euiTheme.size.xs}; /* fine tune horizontal alignment */
`}
>
<EuiFlexItem grow={false}>
<EuiCheckbox
id={record.id}
aria-label={toggleDocumentSelectionLabel}
checked={isDocSelected(record.id)}
data-test-subj={`dscGridSelectDoc-${record.id}`}
onChange={(event) => {
if ((event.nativeEvent as MouseEvent)?.shiftKey) {
toggleMultipleDocsSelection(record.id);
} else {
toggleDocSelection(record.id);
}
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
/>
);
};

View file

@ -11,7 +11,6 @@ import React, { useContext, useEffect, useRef, useState } from 'react';
import { EuiButtonIcon, EuiDataGridCellValueElementProps, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { UnifiedDataTableContext } from '../table_context';
import { DataTableRowControl, Size } from './data_table_row_control';
import { useControlColumn } from '../hooks/use_control_column';
/**
@ -49,25 +48,28 @@ export const ExpandButton = (props: EuiDataGridCellValueElementProps) => {
}
return (
<DataTableRowControl size={Size.normal}>
<EuiToolTip content={buttonLabel} delay="long" ref={toolTipRef}>
<EuiButtonIcon
id={rowIndex === 0 ? tourStep : undefined}
size="xs"
iconSize="s"
aria-label={buttonLabel}
data-test-subj={testSubj}
onClick={() => {
const nextHit = isCurrentRowExpanded ? undefined : record;
toolTipRef.current?.hideToolTip();
setPressed(Boolean(nextHit));
setExpanded?.(nextHit);
}}
color={isCurrentRowExpanded ? 'primary' : 'text'}
iconType={isCurrentRowExpanded ? 'minimize' : 'expand'}
isSelected={isCurrentRowExpanded}
/>
</EuiToolTip>
</DataTableRowControl>
<EuiToolTip
content={buttonLabel}
delay="long"
ref={toolTipRef}
anchorClassName="unifiedDataTable__rowControl"
>
<EuiButtonIcon
id={rowIndex === 0 ? tourStep : undefined}
size="xs"
iconSize="s"
aria-label={buttonLabel}
data-test-subj={testSubj}
onClick={() => {
const nextHit = isCurrentRowExpanded ? undefined : record;
toolTipRef.current?.hideToolTip();
setPressed(Boolean(nextHit));
setExpanded?.(nextHit);
}}
color={isCurrentRowExpanded ? 'primary' : 'text'}
iconType={isCurrentRowExpanded ? 'minimize' : 'expand'}
isSelected={isCurrentRowExpanded}
/>
</EuiToolTip>
);
};

View file

@ -1,26 +0,0 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React from 'react';
import classnames from 'classnames';
export enum Size {
normal = 'normal',
}
export const DataTableRowControl: React.FC<React.PropsWithChildren<{ size?: Size }>> = ({
size,
children,
}) => {
const classes = classnames('unifiedDataTable__rowControl', {
// normalize the size of the control
[`unifiedDataTable__rowControl--size-${size}`]: size,
});
return <span className={classes}>{children}</span>;
};

View file

@ -87,7 +87,7 @@ export const LICENSE_OVERRIDES = {
'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts
'@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint
'@elastic/ems-client@8.5.3': ['Elastic License 2.0'],
'@elastic/eui@95.11.0': ['Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0'],
'@elastic/eui@95.12.0-backport.0': ['Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0'],
'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODCBy license https://github.com/mattcg/language-subtag-registry
'buffers@0.1.1': ['MIT'], // license in importing module https://www.npmjs.com/package/binary
'@bufbuild/protobuf@1.2.1': ['Apache-2.0'], // license (Apache-2.0 AND BSD-3-Clause)

View file

@ -199,7 +199,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 1);
expect(await cell.getVisibleText()).to.be(' - ');
expect(await dataGrid.getHeaders()).to.eql([
"Select columnPress the Enter key to interact with this cell's contents.", // contains screen reader help text
'Select column',
'Control column',
'Access to degraded docs',
'Access to available stacktraces',

View file

@ -9,7 +9,7 @@
import { chunk } from 'lodash';
import { Key } from 'selenium-webdriver';
import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services';
import { WebElementWrapper, CustomCheerioStatic } from '@kbn/ftr-common-functional-ui-services';
import { FtrService } from '../ftr_provider_context';
export interface TabbedGridData {
@ -34,12 +34,10 @@ export class DataGridService extends FtrService {
const table = await this.find.byCssSelector('.euiDataGrid');
const $ = await table.parseDomContent();
const columns = $('.euiDataGridHeaderCell')
.toArray()
.map((cell) => $(cell).text());
const columns = this.getHeaderText($);
const cells = $.findTestSubjects('dataGridRowCell')
.toArray()
.map((cell) => $(cell).text());
.map((cell) => $(cell).find('.euiDataGridRowCell__content').text());
const rows = chunk(cells, columns.length);
@ -76,12 +74,25 @@ export class DataGridService extends FtrService {
/**
* Returns an array of data grid headers names
*/
public async getHeaders() {
const header = await this.testSubjects.find('euiDataGridBody > dataGridHeader');
const $ = await header.parseDomContent();
public getHeaderText(parsedDomContent: CustomCheerioStatic) {
const $ = parsedDomContent;
return $('.euiDataGridHeaderCell')
.toArray()
.map((cell) => $(cell).text());
.map((cell) => {
const content = $(cell).find('.euiDataGridHeaderCell__content');
if (content.length) {
return content.text();
} else {
// Control columns will need hidden text manually stripped
$(cell).find('[hidden], [data-tabular-copy-marker]').remove();
return $(cell).text();
}
});
}
public async getHeaders() {
const header = await this.testSubjects.find('euiDataGridBody > dataGridHeader');
return this.getHeaderText(await header.parseDomContent());
}
public getHeaderElement(field: string) {

View file

@ -577,7 +577,9 @@ describe('Packs - Create and Edit', { tags: ['@ess', '@serverless'] }, () => {
cy.getBySel('docsLoading').should('exist');
cy.getBySel('docsLoading').should('not.exist');
return cy.get('tbody .euiTableRow > td:nth-child(5)').invoke('text');
return cy
.get('tbody .euiTableRow > td:nth-child(5) > .euiTableCellContent')
.invoke('text');
},
(response) => response !== '-',
{

View file

@ -114,13 +114,12 @@ export const getRunningProcesses = (command: string): Cypress.Chainable<number>
.getByTestSubj('processesOutput-processListTable', { timeout: 120000 })
.findByTestSubj('processesOutput-command')
.contains(command)
.parents('td')
.siblings('td')
.eq(1)
.find('span')
.then((span) => {
.parents('tr')
.findByTestSubj('processesOutput-pid')
.find('.euiTableCellContent')
.then((cellContent) => {
// get pid
return Number(span.text());
return Number(cellContent.text());
});
};

View file

@ -40,11 +40,6 @@ exports[`CustomTimelineDataGridBody should render exactly as snapshots 1`] = `
min-height: 34px;
}
.c1 .euiDataGridRowCell .unifiedDataTable__rowControl,
.c1 .euiDataGridRowCell__content .unifiedDataTable__rowControl {
margin-top: -4px;
}
<div>
<div
class="c0 euiDataGridRow "

View file

@ -121,9 +121,6 @@ const CustomGridRowCellWrapper = styled.div.attrs<{
.euiDataGridRowCell,
.euiDataGridRowCell__content {
min-height: ${DEFAULT_UDT_ROW_HEIGHT}px;
.unifiedDataTable__rowControl {
margin-top: -4px;
}
}
`;

View file

@ -41,7 +41,7 @@ export function MachineLearningCommonDataGridProvider({ getService }: FtrProvide
const cells = $.findTestSubjects('dataGridRowCell')
.toArray()
.map((cell) => {
const cellText = $(cell).text();
const cellText = $(cell).find('.euiDataGridRowCell__content').text();
const columnData = $(cell).attr('data-gridcell-column-index');
const rowData = $(cell).attr('data-gridcell-row-index');
return { text: cellText, column: Number(columnData) + 1, row: Number(rowData) };

View file

@ -436,7 +436,7 @@ export function MachineLearningDataFrameAnalyticsTableProvider({
const vars: Record<string, string> = {};
for (const row of $('tr').toArray()) {
const [name, value] = $(row).find('td').toArray();
const [name, value] = $(row).find('td').find('.euiTableCellContent').toArray();
vars[$(name).text().trim()] = $(value).text().trim();
}

View file

@ -32,7 +32,7 @@ describe('All hosts table', { tags: ['@ess'] }, () => {
kqlSearch('host.name: "siem-kibana" {enter}');
cy.get('[data-test-subj="tableHeaderCell_node.risk_4"]').should('exist');
cy.get(`${TABLE_CELL} .euiTableCellContent`).eq(4).should('have.text', 'Low');
cy.get(TABLE_CELL).eq(4).should('have.text', 'Low');
});
});
@ -55,7 +55,7 @@ describe('All hosts table', { tags: ['@ess'] }, () => {
kqlSearch('host.name: "siem-kibana" {enter}');
cy.get('[data-test-subj="tableHeaderCell_node.risk_4"]').should('exist');
cy.get(`${TABLE_CELL} .euiTableCellContent`).eq(4).should('have.text', 'Critical');
cy.get(TABLE_CELL).eq(4).should('have.text', 'Critical');
});
});
});

View file

@ -30,7 +30,7 @@ export const OVERVIEW_STATUS = '[data-test-subj="eventDetails"] [data-test-subj=
export const EVENT_DETAILS_ALERT_STATUS_POPOVER =
'[data-test-subj="event-details-alertStatusPopover"]';
export const TABLE_CELL = '.euiTableRowCell';
export const TABLE_CELL = '.euiTableRowCell .euiTableCellContent';
export const CELL_EXPAND_VALUE = '[data-test-subj="euiDataGridCellExpandButton"]';

View file

@ -202,7 +202,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 1);
expect(await cell.getVisibleText()).to.be(' - ');
expect(await dataGrid.getHeaders()).to.eql([
"Select columnPress the Enter key to interact with this cell's contents.", // contains screen reader help text
'Select column',
'Control column',
'Access to degraded docs',
'Access to available stacktraces',

View file

@ -1741,10 +1741,10 @@
resolved "https://registry.yarnpkg.com/@elastic/eslint-plugin-eui/-/eslint-plugin-eui-0.0.2.tgz#56b9ef03984a05cc213772ae3713ea8ef47b0314"
integrity sha512-IoxURM5zraoQ7C8f+mJb9HYSENiZGgRVcG4tLQxE61yHNNRDXtGDWTZh8N1KIHcsqN1CEPETjuzBXkJYF/fDiQ==
"@elastic/eui@95.11.0":
version "95.11.0"
resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-95.11.0.tgz#40e8124ac54c625ba7160cb84a378507abdeaf40"
integrity sha512-O688EbhrgSrV9j54mnK4xLyhv+imkBv5ti7isqLxJtd0L7Fe2A1d6EaA11Qv5plOwwC+cGsrkrDnlSqi1MtNoQ==
"@elastic/eui@95.12.0-backport.0":
version "95.12.0-backport.0"
resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-95.12.0-backport.0.tgz#de862ded9f23053b24e1f1939de1ff8f8109be60"
integrity sha512-hqhqWdAGw5tQwWTP/hn2VoM8YQE2k9IdMmGh0RdkG+JcD1GZySvSDWdTQgr9iA4/XaulJp9R3OenwDjkLLmjPw==
dependencies:
"@hello-pangea/dnd" "^16.6.0"
"@types/lodash" "^4.14.202"