Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EuiTable] New responsiveBreakpoint prop + initial setup for mobile vs desktop styles #7625

Merged
merged 11 commits into from
Mar 27, 2024
Merged
7 changes: 7 additions & 0 deletions changelogs/upcoming/7625.md
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,7 @@
- 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
- Updated `EuiProvider`'s `componentDefaults` prop to allow configuring `EuiTable.responsiveBreakpoint`

**Deprecations**

- Deprecated the `responsive` prop from `EuiTable`, `EuiBasicTable`, and `EuiInMemoryTable`. Use the new `responsiveBreakpoint` prop instead
- `EuiTable` mobile headers no longer render in the DOM when not visible (previously rendered with `display: none`). This may affect DOM testing assertions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const EuiComponentDefaultsProps: FunctionComponent<
// Exported in one place for DRYness // Exported in one place for DRYness
export const euiProviderComponentDefaultsSnippet = `<EuiProvider export const euiProviderComponentDefaultsSnippet = `<EuiProvider
componentDefaults={{ componentDefaults={{
EuiTable: { responsiveBreakpoint: 's', },
EuiTablePagination: { itemsPerPage: 20, }, EuiTablePagination: { itemsPerPage: 20, },
EuiFocusTrap: { crossFrame: true }, EuiFocusTrap: { crossFrame: true },
EuiPortal: { insert }, EuiPortal: { insert },
Expand Down
2 changes: 1 addition & 1 deletion src-docs/src/views/tables/mobile/mobile.tsx
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ export default () => {
selection={selection} selection={selection}
isSelectable={true} isSelectable={true}
hasActions={true} hasActions={true}
responsive={isResponsive} responsiveBreakpoint={isResponsive}
onChange={onTableChange} onChange={onTableChange}
/> />
</> </>
Expand Down
25 changes: 19 additions & 6 deletions src-docs/src/views/tables/mobile/mobile_section.js
Original file line number Original file line Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom';
import { GuideSectionTypes } from '../../../components'; import { GuideSectionTypes } from '../../../components';


import Table from './mobile'; import Table from './mobile';
Expand Down Expand Up @@ -32,14 +33,26 @@ export const section = {
text: ( text: (
<> <>
<p> <p>
Allowing a table to be responsive means breaking each row down into its Tables will be mobile-responsive by default, breaking down each row into
own section and individually displaying each table header above the cell its own card section and individually displaying each table header above
contents. There are few times when you may want to exclude this behavior the cell contents. The default breakpoint at which the table will
from your table, for instance, when the table has very few columns or responsively shift into cards is the{' '}
the table does not break down easily into this format. For these use <Link to="/theming/breakpoints/values">
cases, you may set <EuiCode language="js">responsive=false</EuiCode>. <EuiCode>m</EuiCode> window size
</Link>
, which can be customized with the{' '}
<EuiCode>responsiveBreakpoint</EuiCode> prop (e.g.,{' '}
<EuiCode language="js">{'responsiveBreakpoint="s"'}</EuiCode>).
</p> </p>
<p> <p>
To never render your table responsively (e.g. for tables with very few
columns), you may set{' '}
<EuiCode language="js">{'responsiveBreakpoint={false}'}</EuiCode>.
Inversely, if you always want your table to render in a mobile-friendly
manner, pass <EuiCode>true</EuiCode>.
</p>
<p>
{/* TODO: This shouldn't be true by the end of the Emotion conversion */}
To make your table work responsively, please make sure you add the To make your table work responsively, please make sure you add the
following <EuiTextColor color="danger">additional</EuiTextColor> props following <EuiTextColor color="danger">additional</EuiTextColor> props
to the top level table component (<strong>EuiBasicTable</strong> or{' '} to the top level table component (<strong>EuiBasicTable</strong> or{' '}
Expand Down
83 changes: 2 additions & 81 deletions src/components/basic_table/__snapshots__/basic_table.test.tsx.snap
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -6,23 +6,8 @@ exports[`EuiBasicTable renders (bare-bones) 1`] = `
class="euiBasicTable testClass1 testClass2 emotion-euiTestCss" class="euiBasicTable testClass1 testClass2 emotion-euiTestCss"
data-test-subj="test subject string" data-test-subj="test subject string"
> >
<div>
<div
class="euiTableHeaderMobile"
>
<div
class="euiFlexGroup emotion-euiFlexGroup-l-spaceBetween-baseline-row"
>
<div
class="euiFlexItem emotion-euiFlexItem-growZero"
/>
<div
class="euiFlexItem emotion-euiFlexItem-growZero"
/>
</div>
</div>
<table <table
class="euiTable euiTable--responsive emotion-euiTable-fixed-uncompressed" class="euiTable euiTable--responsive emotion-euiTable-fixed-uncompressed-desktop"
id="__table_generated-id" id="__table_generated-id"
tabindex="-1" tabindex="-1"
> >
Expand Down Expand Up @@ -127,77 +112,14 @@ exports[`EuiBasicTable renders (bare-bones) 1`] = `
</tbody> </tbody>
</table> </table>
</div> </div>
</div>
`; `;


exports[`EuiBasicTable renders (kitchen sink) with pagination, selection, sorting, actions, and footer 1`] = ` exports[`EuiBasicTable renders (kitchen sink) with pagination, selection, sorting, actions, and footer 1`] = `
<div <div
class="euiBasicTable" class="euiBasicTable"
> >
<div>
<div
class="euiTableHeaderMobile"
>
<div
class="euiFlexGroup emotion-euiFlexGroup-l-spaceBetween-baseline-row"
>
<div
class="euiFlexItem emotion-euiFlexItem-growZero"
>
<div
class="euiCheckbox emotion-euiCheckbox"
>
<input
aria-label="Select all rows"
class="euiCheckbox__input"
id="_selection_column-checkbox_generated-id_mobile"
type="checkbox"
/>
<div
class="euiCheckbox__square"
/>
<label
class="euiCheckbox__label"
for="_selection_column-checkbox_generated-id_mobile"
>
Select all rows
</label>
</div>
</div>
<div
class="euiFlexItem emotion-euiFlexItem-growZero"
>
<div
class="euiTableSortMobile"
>
<div
class="euiPopover emotion-euiPopover-inline-block"
>
<button
class="euiButtonEmpty emotion-euiButtonDisplay-euiButtonEmpty-xs-empty-primary-flush-right"
type="button"
>
<span
class="euiButtonEmpty__content emotion-euiButtonDisplayContent"
>
<span
class="eui-textTruncate euiButtonEmpty__text"
>
Sorting
</span>
<span
color="inherit"
data-euiicon-type="arrowDown"
/>
</span>
</button>
</div>
</div>
</div>
</div>
</div>
<table <table
class="euiTable euiTable--responsive emotion-euiTable-fixed-uncompressed" class="euiTable euiTable--responsive emotion-euiTable-fixed-uncompressed-desktop"
id="__table_generated-id" id="__table_generated-id"
tabindex="-1" tabindex="-1"
> >
Expand Down Expand Up @@ -757,7 +679,6 @@ exports[`EuiBasicTable renders (kitchen sink) with pagination, selection, sortin
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
</div>
<div> <div>
<div <div
class="euiSpacer euiSpacer--m emotion-euiSpacer-m" class="euiSpacer euiSpacer--m emotion-euiSpacer-m"
Expand Down
Original file line number Original file line Diff line number Diff line change
@@ -1,5 +1,57 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP


exports[`EuiInMemoryTable behavior mobile header 1`] = `
<div
class="euiTableHeaderMobile emotion-euiTableHeaderMobile"
>
<div
class="euiCheckbox emotion-euiCheckbox"
>
<input
aria-label="Select all rows"
class="euiCheckbox__input"
id="_selection_column-checkbox_generated-id_mobile"
type="checkbox"
/>
<div
class="euiCheckbox__square"
/>
<label
class="euiCheckbox__label"
for="_selection_column-checkbox_generated-id_mobile"
>
Select all rows
</label>
</div>
<div
class="euiTableSortMobile emotion-euiTableSortMobile"
>
<div
class="euiPopover emotion-euiPopover-inline-block"
>
<button
class="euiButtonEmpty emotion-euiButtonDisplay-euiButtonEmpty-xs-empty-primary-flush-right"
type="button"
>
<span
class="euiButtonEmpty__content emotion-euiButtonDisplayContent"
>
<span
class="eui-textTruncate euiButtonEmpty__text"
>
Sorting
</span>
<span
color="inherit"
data-euiicon-type="arrowDown"
/>
</span>
</button>
</div>
</div>
</div>
`;

exports[`EuiInMemoryTable behavior pagination 1`] = ` exports[`EuiInMemoryTable behavior pagination 1`] = `
<nav <nav
aria-label="Pagination for table: " aria-label="Pagination for table: "
Expand Down Expand Up @@ -102,23 +154,8 @@ exports[`EuiInMemoryTable empty array 1`] = `
class="euiBasicTable testClass1 testClass2 emotion-euiTestCss" class="euiBasicTable testClass1 testClass2 emotion-euiTestCss"
data-test-subj="test subject string" data-test-subj="test subject string"
> >
<div>
<div
class="euiTableHeaderMobile"
>
<div
class="euiFlexGroup emotion-euiFlexGroup-l-spaceBetween-baseline-row"
>
<div
class="euiFlexItem emotion-euiFlexItem-growZero"
/>
<div
class="euiFlexItem emotion-euiFlexItem-growZero"
/>
</div>
</div>
<table <table
class="euiTable euiTable--responsive emotion-euiTable-fixed-uncompressed" class="euiTable euiTable--responsive emotion-euiTable-fixed-uncompressed-desktop"
id="__table_generated-id" id="__table_generated-id"
tabindex="-1" tabindex="-1"
> >
Expand Down Expand Up @@ -175,7 +212,6 @@ exports[`EuiInMemoryTable empty array 1`] = `
</tbody> </tbody>
</table> </table>
</div> </div>
</div>
`; `;


exports[`EuiInMemoryTable with executeQueryOptions 1`] = ` exports[`EuiInMemoryTable with executeQueryOptions 1`] = `
Expand Down Expand Up @@ -211,23 +247,8 @@ exports[`EuiInMemoryTable with items 1`] = `
class="euiBasicTable testClass1 testClass2 emotion-euiTestCss" class="euiBasicTable testClass1 testClass2 emotion-euiTestCss"
data-test-subj="test subject string" data-test-subj="test subject string"
> >
<div>
<div
class="euiTableHeaderMobile"
>
<div
class="euiFlexGroup emotion-euiFlexGroup-l-spaceBetween-baseline-row"
>
<div
class="euiFlexItem emotion-euiFlexItem-growZero"
/>
<div
class="euiFlexItem emotion-euiFlexItem-growZero"
/>
</div>
</div>
<table <table
class="euiTable euiTable--responsive emotion-euiTable-fixed-uncompressed" class="euiTable euiTable--responsive emotion-euiTable-fixed-uncompressed-desktop"
id="__table_generated-id" id="__table_generated-id"
tabindex="-1" tabindex="-1"
> >
Expand Down Expand Up @@ -332,5 +353,4 @@ exports[`EuiInMemoryTable with items 1`] = `
</tbody> </tbody>
</table> </table>
</div> </div>
</div>
`; `;
53 changes: 23 additions & 30 deletions src/components/basic_table/basic_table.tsx
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {
import { CommonProps } from '../common'; import { CommonProps } from '../common';
import { isFunction } from '../../services/predicate'; import { isFunction } from '../../services/predicate';
import { get } from '../../services/objects'; import { get } from '../../services/objects';
import { EuiFlexGroup, EuiFlexItem } from '../flex';
import { EuiCheckbox } from '../form'; import { EuiCheckbox } from '../form';


import { EuiComponentDefaultsContext } from '../provider/component_defaults'; import { EuiComponentDefaultsContext } from '../provider/component_defaults';
Expand Down Expand Up @@ -261,10 +260,6 @@ interface BasicTableProps<T extends object>
* Configures #Pagination * Configures #Pagination
*/ */
pagination?: undefined; pagination?: undefined;
/**
* If true, will convert table to cards in mobile view
*/
responsive?: boolean;
/** /**
* Applied to `EuiTableRow` * Applied to `EuiTableRow`
*/ */
Expand Down Expand Up @@ -529,6 +524,7 @@ export class EuiBasicTable<T extends object = any> extends Component<
compressed, compressed,
itemIdToExpandedRowMap, itemIdToExpandedRowMap,
responsive, responsive,
responsiveBreakpoint,
isSelectable, isSelectable,
isExpandable, isExpandable,
hasActions, hasActions,
Expand Down Expand Up @@ -558,40 +554,37 @@ export class EuiBasicTable<T extends object = any> extends Component<
} }


renderTable() { renderTable() {
const { compressed, responsive, tableLayout, loading } = this.props; const {

compressed,
const mobileHeader = responsive ? ( responsive,
<EuiTableHeaderMobile> responsiveBreakpoint,
<EuiFlexGroup tableLayout,
responsive={false} loading,
justifyContent="spaceBetween" } = this.props;
alignItems="baseline"
>
<EuiFlexItem grow={false}>{this.renderSelectAll(true)}</EuiFlexItem>
<EuiFlexItem grow={false}>{this.renderTableMobileSort()}</EuiFlexItem>
</EuiFlexGroup>
</EuiTableHeaderMobile>
) : undefined;
const caption = this.renderTableCaption();
const head = this.renderTableHead();
const body = this.renderTableBody();
const footer = this.renderTableFooter();
return ( return (
<div> <>
{mobileHeader} {/* TODO: Remove conditional once `responsive` prop is deprecated */}
{responsive && (
<EuiTableHeaderMobile responsiveBreakpoint={responsiveBreakpoint}>
{this.renderSelectAll(true)}
{this.renderTableMobileSort()}
</EuiTableHeaderMobile>
)}
<EuiTable <EuiTable
id={this.tableId} id={this.tableId}
tableLayout={tableLayout} tableLayout={tableLayout}
responsiveBreakpoint={responsiveBreakpoint}
responsive={responsive} responsive={responsive}
compressed={compressed} compressed={compressed}
css={loading && safariLoadingWorkaround} css={loading && safariLoadingWorkaround}
> >
{caption} {this.renderTableCaption()}
{head} {this.renderTableHead()}
{body} {this.renderTableBody()}
{footer} {this.renderTableFooter()}
</EuiTable> </EuiTable>
</div> </>
); );
} }


Expand Down
Loading