Skip to content

Commit

Permalink
Upgrade EUI to v94.1.0 (major EuiTable refactors) (#180514)
Browse files Browse the repository at this point in the history
`v93.6.0` ⏩ `v94.1.0`

> [!important]
> 👋 Hello everyone - this is a special release containing `EuiTable`'s
conversion to Emotion, several long-overdue cleanups and breaking
changes, and one or two fun new features. First, let's address the big
questions:

### Q: I'm listed as a codeowner, how much should I manually QA/review?

Answer: It depends on what exactly in your code changed, but _in
general_ I would strongly suggest at least pulling this branch down and
doing a quick visual smoke test of all tables (_note: **not**
datagrids_) in your apps/plugins. You should not expect to see any major
visual regressions.

If your table contained any kind of custom styling or behavior (e.g.
custom CSS, etc.) I **strongly** recommend taking more time to QA
thoroughly to ensure your table still looks and behaves as expected.
Teams with very manual or specific updates will be flagged below in
comment threads.

### Q: When do I need to review by?

This PR will be merged **after** 8.14FF. Because this upgrade touches so
many files and teams, we're aiming for asking for an admin merge by EOD
4/18 regardless of full approval status.

As always, you're welcome to ping us after merge if you find any issues
later ([see our
FAQ](https://github.com/elastic/eui/blob/main/wiki/eui-team-processes/upgrading-kibana.md#faq-for-kibana-teams)),
as you will have until 8.15FF to catch any bugs.

### Q: What breaking changes were made, and why?

Here's a quick shortlist of all the changes made that affected the
majority of the commits in this PR:

#### <u>Removed several top-level table props</u>
- The `responsive` prop has been removed in favor of the new
`responsiveBreakpoint` prop (same `false` behavior as before)
- The following props were removed from basic and in-memory tables:
  - `hasActions`, `isSelectable`, and `isExpandable`
- These props were not used for functionality and were only used for
styling tables in mobile/responsive views, which is not a best practice
pattern we wanted for our APIs. Mobile tables are now styled correctly
without needing consumers to pass these extra props.
  - `textOnly`
- This prop was unused and had no meaningful impact on tables or table
content.

#### Removed hidden mobile vs. desktop DOM

Previously, EUI would set classes that applied `display: none` CSS for
content that was hidden for mobile vs. desktop. This is no longer the
case, and content that only displays for mobile or only displays for
desktop will no longer render to the DOM at all if the table is not in
that responsive state.

This is both more performant when rendering large quantities of
cells/content, and simpler to write test assertions for when comparing
what the user actually sees vs. what the DOM ‘sees’.
(c3eeb08441e4b6efe6505e7cddaa87b540ddb259,
78cefcd954a7b46eaccd05e431b5e24dc86071a3)

#### Removed direct usages of table `className`s

EuiTable `classNames` no longer have any styles attached to them, so
some instances where Kibana usages were applying the `className` for
styles have been replaced with direct component usage or removed
entirely (86ce80b).

#### Custom table cell styles

Any custom CSS for table cells was previously being applied to the inner
`div.euiTableCellContent` wrapper. As of this latest release, the
`className` and `css` props will now be applied directly to the outer
`td.euiTableRowCell` element. If you were targeting custom styles table
cells, please re-QA your styles to ensure everything still looks as
expected.

---

<details open><summary>Full changelog (click to collapse)</summary>

##
[`v94.1.0-backport.0`](https://github.com/elastic/eui/releases/v94.1.0-backport.0)

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

**Bug fixes**

- Fixed a visual text alignment regression in `EuiTableRowCell`s with
the `row` header scope
([#7681](elastic/eui#7681))

**Accessibility**

- Improved `EuiBasicTable` and `EuiInMemoryTable`'s selection checkboxes
to have unique aria-labels per row
([#7672](elastic/eui#7672))

## [`v94.1.0`](https://github.com/elastic/eui/releases/v94.1.0)

- Updated `EuiTableHeaderCell` to show a subdued `sortable` icon for
columns that are not currently sorted but can be
([#7656](elastic/eui#7656))
- Updated `EuiBasicTable` and `EuiInMemoryTable`'s
`columns[].actions[]`'s to pass back click events to `onClick` callbacks
as the second callback
([#7667](elastic/eui#7667))

## [`v94.0.0`](https://github.com/elastic/eui/releases/v94.0.0)

- Updated `EuiTable`, `EuiBasicTable`, and `EuiInMemoryTable` with a new
`responsiveBreakpoint` prop, which allows customizing the point at which
the table collapses into a mobile-friendly view with cards
([#7625](elastic/eui#7625))
- Updated `EuiProvider`'s `componentDefaults` prop to allow configuring
`EuiTable.responsiveBreakpoint`
([#7625](elastic/eui#7625))

**Bug fixes**

- `EuiBasicTable` & `EuiInMemoryTable` `isPrimary` actions are now
correctly shown on mobile views
([#7640](elastic/eui#7640))
- Table `mobileOptions`:
([#7642](elastic/eui#7642))
- `mobileOptions.align` is now respected instead of all cells being
forced to left alignment
- `textTruncate` and `textOnly` are now respected even if a `render`
function is not passed

**Breaking changes**

- Removed unused `EuiTableHeaderButton` component
([#7621](elastic/eui#7621))
- Removed the `responsive` prop from `EuiTable`, `EuiBasicTable`, and
`EuiInMemoryTable`. Use the new `responsiveBreakpoint` prop instead
([#7625](elastic/eui#7625))
- The following props are no longer needed by `EuiBasicTable` or
`EuiInMemoryTable` for responsive table behavior to work correctly, and
can be removed: ([#7632](elastic/eui#7632))
  - `isSelectable`
  - `isExpandable`
  - `hasActions`
- Removed the `showOnHover` prop from `EuiTableRowCell` /
`EuiBasicTable`/`EuiInMemoryTable`'s `columns` API. Use the new actions
`columns[].actions[].showOnHover` API instead.
([#7640](elastic/eui#7640))
- Removed top-level `textOnly` prop from `EuiBasicTable` and
`EuiInMemoryTable`. Use `columns[].textOnly` instead.
([#7642](elastic/eui#7642))

**DOM changes**

- `EuiTable` mobile headers no longer render in the DOM when not visible
(previously rendered with `display: none`). This may affect DOM testing
assertions. ([#7625](elastic/eui#7625))
- `EuiTableRowCell` now applies passed `className`s to the parent `<td>`
element, instead of to the inner cell content `<div>`.
([#7631](elastic/eui#7631))
- `EuiTableRow`s rendered by basic and memory tables now only render a
`.euiTableRow-isSelectable` className if the selection checkbox is not
disabled ([#7632](elastic/eui#7632))
- `EuiTableRowCell`s with `textOnly` set to `false` will no longer
attempt to apply the `.euiTableCellContent__text` className to child
elements. ([#7641](elastic/eui#7641))
- `EuiTableRowCell` no longer renders mobile headers to the DOM unless
the current table is displaying its responsive view.
([#7642](elastic/eui#7642))
- `EuiTableHeaderCell` and `EuiTableRowCell` will no longer render in
the DOM at all on mobile if their columns' `mobileOptions.show` is set
to `false`. ([#7642](elastic/eui#7642))
- `EuiTableHeaderCell` and `EuiTableRowCell` will no longer render in
the DOM at all on desktop if their columns' `mobileOptions.only` is set
to `true`. ([#7642](elastic/eui#7642))

**CSS-in-JS conversions**

- Converted `EuiTable`, `EuiTableRow`, `EuiTableRowCell`, and all other
table subcomponents to Emotion
([#7654](elastic/eui#7654))
- Removed the following `EuiTable` Sass variables:
([#7654](elastic/eui#7654))
  - `$euiTableCellContentPadding`
  - `$euiTableCellContentPaddingCompressed`
  - `$euiTableCellCheckboxWidth`
  - `$euiTableHoverColor`
  - `$euiTableSelectedColor`
  - `$euiTableHoverSelectedColor`
  - `$euiTableActionsBorderColor`
  - `$euiTableHoverClickableColor`
  - `$euiTableFocusClickableColor`
- Removed the following `EuiTable` Sass mixins:
([#7654](elastic/eui#7654))
  - `euiTableActionsBackgroundMobile`
  - `euiTableCellCheckbox`
  - `euiTableCell`
</details>
  • Loading branch information
cee-chen authored Apr 18, 2024
1 parent 8f23f23 commit cbc68cd
Show file tree
Hide file tree
Showing 214 changed files with 1,068 additions and 1,656 deletions.
12 changes: 7 additions & 5 deletions examples/data_view_field_editor_example/public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import {
EuiProvider,
DefaultItemAction,
EuiButton,
EuiCheckbox,
Expand Down Expand Up @@ -121,7 +122,6 @@ const DataViewFieldEditorExample = ({ dataView, dataViewFieldEditor }: Props) =>
items={fields}
columns={columns}
pagination={true}
hasActions={true}
sorting={{
sort: {
field: 'name',
Expand All @@ -135,10 +135,12 @@ const DataViewFieldEditorExample = ({ dataView, dataViewFieldEditor }: Props) =>
);

return (
<EuiPageTemplate offset={0}>
<EuiPageTemplate.Header pageTitle="Data view field editor demo" />
<EuiPageTemplate.Section>{content}</EuiPageTemplate.Section>
</EuiPageTemplate>
<EuiProvider>
<EuiPageTemplate offset={0}>
<EuiPageTemplate.Header pageTitle="Data view field editor demo" />
<EuiPageTemplate.Section>{content}</EuiPageTemplate.Section>
</EuiPageTemplate>
</EuiProvider>
);
};

Expand Down
53 changes: 27 additions & 26 deletions examples/field_formats_example/public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
EuiCodeBlock,
EuiLink,
EuiPageTemplate,
EuiProvider,
EuiSpacer,
EuiText,
EuiTitle,
Expand Down Expand Up @@ -61,7 +62,6 @@ const UsingAnExistingFieldFormatExample: React.FC<{ deps: Deps }> = (props) => {
<EuiBasicTable
data-test-subj={'example1 sample table'}
items={sample}
textOnly={true}
columns={[
{
field: 'raw',
Expand Down Expand Up @@ -100,7 +100,6 @@ const CreatingCustomFieldFormat: React.FC<{ deps: Deps }> = (props) => {
<EuiSpacer size={'s'} />
<EuiBasicTable
items={sample}
textOnly={true}
data-test-subj={'example2 sample table'}
columns={[
{
Expand Down Expand Up @@ -168,29 +167,31 @@ const CreatingCustomFieldFormatEditor: React.FC<{ deps: Deps }> = (props) => {

export const App: React.FC<{ deps: Deps }> = (props) => {
return (
<EuiPageTemplate offset={0}>
<EuiPageTemplate.Header pageTitle="Field formats examples" />
<EuiPageTemplate.Section grow={false}>
<EuiTitle size="m">
<h2>Using an existing field format</h2>
</EuiTitle>
<EuiSpacer />
<UsingAnExistingFieldFormatExample deps={props.deps} />
</EuiPageTemplate.Section>
<EuiPageTemplate.Section grow={false}>
<EuiTitle size="m">
<h2>Creating a custom field format</h2>
</EuiTitle>
<EuiSpacer />
<CreatingCustomFieldFormat deps={props.deps} />
</EuiPageTemplate.Section>
<EuiPageTemplate.Section grow={false}>
<EuiTitle size="m">
<h2>Creating a custom field format editor</h2>
</EuiTitle>
<EuiSpacer />
<CreatingCustomFieldFormatEditor deps={props.deps} />
</EuiPageTemplate.Section>
</EuiPageTemplate>
<EuiProvider>
<EuiPageTemplate offset={0}>
<EuiPageTemplate.Header pageTitle="Field formats examples" />
<EuiPageTemplate.Section grow={false}>
<EuiTitle size="m">
<h2>Using an existing field format</h2>
</EuiTitle>
<EuiSpacer />
<UsingAnExistingFieldFormatExample deps={props.deps} />
</EuiPageTemplate.Section>
<EuiPageTemplate.Section grow={false}>
<EuiTitle size="m">
<h2>Creating a custom field format</h2>
</EuiTitle>
<EuiSpacer />
<CreatingCustomFieldFormat deps={props.deps} />
</EuiPageTemplate.Section>
<EuiPageTemplate.Section grow={false}>
<EuiTitle size="m">
<h2>Creating a custom field format editor</h2>
</EuiTitle>
<EuiSpacer />
<CreatingCustomFieldFormatEditor deps={props.deps} />
</EuiPageTemplate.Section>
</EuiPageTemplate>
</EuiProvider>
);
};
5 changes: 3 additions & 2 deletions examples/files_example/public/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { FileJSON } from '@kbn/files-plugin/common';
import type { FilesClientResponses } from '@kbn/files-plugin/public';

import {
EuiProvider,
EuiPageTemplate,
EuiInMemoryTable,
EuiInMemoryTableProps,
Expand Down Expand Up @@ -131,7 +132,7 @@ export const FilesExampleApp = ({ files, notifications }: FilesExampleAppDeps) =
];

return (
<>
<EuiProvider>
<EuiPageTemplate restrictWidth>
<EuiPageTemplate.Header pageTitle="Files example" />
<EuiPageTemplate.Section>
Expand Down Expand Up @@ -185,6 +186,6 @@ export const FilesExampleApp = ({ files, notifications }: FilesExampleAppDeps) =
}}
/>
)}
</>
</EuiProvider>
);
};
62 changes: 32 additions & 30 deletions examples/partial_results_example/public/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import React, { useContext, useEffect, useState } from 'react';
import { pluck } from 'rxjs';
import {
EuiProvider,
EuiBasicTable,
EuiCallOut,
EuiCodeBlock,
Expand Down Expand Up @@ -40,35 +41,36 @@ export function App() {
}, [expressions]);

return (
<EuiPageTemplate offset={0}>
<EuiPageTemplate.Header pageTitle="Partial Results Demo" />
<EuiPageTemplate.Section>
<EuiText data-test-subj="example-help">
<p>
This example listens for the window events and adds them to the table along with a
trigger counter.
</p>
</EuiText>
<EuiSpacer size={'m'} />
<EuiCodeBlock>{expression}</EuiCodeBlock>
<EuiSpacer size={'m'} />
{datatable ? (
<EuiBasicTable
textOnly={true}
data-test-subj={'example-table'}
columns={datatable.columns?.map(({ id: field, name }) => ({
field,
name,
'data-test-subj': `example-column-${field.toLowerCase()}`,
}))}
items={datatable.rows ?? []}
/>
) : (
<EuiCallOut color="success">
<p>Click or press any key.</p>
</EuiCallOut>
)}
</EuiPageTemplate.Section>
</EuiPageTemplate>
<EuiProvider>
<EuiPageTemplate offset={0}>
<EuiPageTemplate.Header pageTitle="Partial Results Demo" />
<EuiPageTemplate.Section>
<EuiText data-test-subj="example-help">
<p>
This example listens for the window events and adds them to the table along with a
trigger counter.
</p>
</EuiText>
<EuiSpacer size={'m'} />
<EuiCodeBlock>{expression}</EuiCodeBlock>
<EuiSpacer size={'m'} />
{datatable ? (
<EuiBasicTable
data-test-subj={'example-table'}
columns={datatable.columns?.map(({ id: field, name }) => ({
field,
name,
'data-test-subj': `example-column-${field.toLowerCase()}`,
}))}
items={datatable.rows ?? []}
/>
) : (
<EuiCallOut color="success">
<p>Click or press any key.</p>
</EuiCallOut>
)}
</EuiPageTemplate.Section>
</EuiPageTemplate>
</EuiProvider>
);
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"@elastic/ecs": "^8.11.1",
"@elastic/elasticsearch": "^8.13.0",
"@elastic/ems-client": "8.5.1",
"@elastic/eui": "93.6.0",
"@elastic/eui": "94.1.0-backport.0",
"@elastic/filesaver": "1.1.2",
"@elastic/node-crypto": "1.2.1",
"@elastic/numeral": "^2.5.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ export function Table<T extends UserContentCommonSchema>({
data-test-subj="itemsInMemTable"
rowHeader="attributes.title"
tableCaption={tableCaption}
isSelectable
/>
);
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ export const StatusTable: FunctionComponent<StatusTableProps> = ({ statuses }) =
columns={tableColumns}
itemId={(item) => item.id}
items={statuses}
isExpandable={true}
itemIdToExpandedRowMap={itemIdToExpandedRowMap}
rowProps={({ state }) => ({
className: `status-table-row-${state.uiColor}`,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ export const getEuiContextMapping = (): EuiTokensObject => {
defaultMessage: 'Select all rows',
description: 'ARIA and displayed label on a checkbox to select all table rows',
}),
'euiBasicTable.selectThisRow': i18n.translate('core.euiBasicTable.selectThisRow', {
defaultMessage: 'Select this row',
description: 'ARIA and displayed label on a checkbox to select a single table row',
}),
'euiBasicTable.selectThisRow': ({ index }: EuiValues) =>
i18n.translate('core.euiBasicTable.selectThisRow', {
defaultMessage: 'Select row {index}',
values: { index },
description: 'ARIA and displayed label on a checkbox to select a single table row',
}),
'euiBasicTable.tableCaptionWithPagination': ({ tableCaption, page, pageCount }: EuiValues) =>
i18n.translate('core.euiBasicTable.tableCaptionWithPagination', {
defaultMessage: '{tableCaption}; Page {page} of {pageCount}.',
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ export const SyncJobsTable: React.FC<SyncJobHistoryTableProps> = ({
data-test-subj={`entSearchContent-index-${type}-syncJobs-table`}
items={syncJobs}
columns={columns}
hasActions
onChange={onPaginate}
pagination={pagination}
tableLayout="fixed"
Expand Down
4 changes: 2 additions & 2 deletions packages/kbn-test-jest-helpers/src/testbed/testbed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,11 @@ export function registerTestBed<T extends string = string, P extends object = an
.slice(1) // we remove the first row as it is the table header
.map((row) => ({
reactWrapper: row,
columns: row.find('.euiTableCellContent').map((col) => ({
columns: row.find('div.euiTableCellContent').map((col) => ({
reactWrapper: col,
// We can't access the td value with col.text() because
// eui adds an extra div in td on mobile => (.euiTableRowCell__mobileHeader)
value: col.find('.euiTableCellContent').text(),
value: col.find('div.euiTableCellContent').text(),
})),
}));

Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-text-based-editor/src/query_history.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe('QueryHistory', () => {
/>
);
expect(screen.getByRole('table')).toHaveTextContent(
'Time ranRecent queriesLast durationTime ranMar. 25, 24 08:45:27Recent queriesfrom kibana_sample_data_flights | limit 10Last duration2ms'
'Time ranRecent queriesLast durationMar. 25, 24 08:45:27from kibana_sample_data_flights | limit 102ms'
);
});
});
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-text-based-editor/src/query_history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ export function QueryHistory({
defaultMessage: 'Queries history table',
}
)}
responsive={false}
responsiveBreakpoint={false}
items={historyItems}
columns={columns}
sorting={sorting}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export const FieldNumberSummary: React.FC<FieldNumberSummaryProps> = ({
columns={summaryTableColumns}
tableCaption={summaryTableTitle}
data-test-subj={`${dataTestSubject}-numberSummary`}
responsive={false}
responsiveBreakpoint={false}
css={css`
& .euiTableHeaderCell {
${euiScreenReaderOnly()}
Expand Down
2 changes: 1 addition & 1 deletion src/dev/license_checker/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export const LICENSE_OVERRIDES = {
'[email protected]': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts
'@mapbox/[email protected]': ['MIT'], // license in readme https://github.com/tmcw/jsonlint
'@elastic/[email protected]': ['Elastic License 2.0'],
'@elastic/eui@93.6.0': ['SSPL-1.0 OR Elastic License 2.0'],
'@elastic/eui@94.1.0-backport.0': ['SSPL-1.0 OR Elastic License 2.0'],
'[email protected]': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry
'[email protected]': ['MIT'], // license in importing module https://www.npmjs.com/package/binary
'@bufbuild/[email protected]': ['Apache-2.0'], // license (Apache-2.0 AND BSD-3-Clause)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ describe('Background Search Session Management Table', () => {
);
});

expect(table.find('thead th .euiTableCellContent__text').map((node) => node.text()))
.toMatchInlineSnapshot(`
expect(table.find('thead th').map((node) => node.text())).toMatchInlineSnapshot(`
Array [
"App",
"Name",
Expand Down Expand Up @@ -136,12 +135,12 @@ describe('Background Search Session Management Table', () => {

expect(table.find('tbody td').map((node) => node.text())).toMatchInlineSnapshot(`
Array [
"App",
"Namevery background search Info",
"# Searches0",
"StatusExpired",
"Created2 Dec, 2020, 00:19:32",
"Expiration--",
"",
"very background search Info",
"0",
"Expired",
"2 Dec, 2020, 00:19:32",
"--",
"",
"",
]
Expand Down
Loading

0 comments on commit cbc68cd

Please sign in to comment.