Design cleanup details panel (#85044)

* cleanup overlay panel. fixed sizes, variable panel height, responsive breakpoint

* cleanup metrics tab. use EuiFlexGrid + ChartSizeArray for chart sizing + fixed responsive issues on flex items

* cleanup metadata tab. disabled responsive table and fixed alignment of filter icon + value

* cleanup logs search. adjusted button size + spacing

* fix responsivness on array values

* remove responsive behavior on search + view-in-logs button

* fix typecheck
This commit is contained in:
Henry Harding 2020-12-04 15:05:13 -05:00 committed by GitHub
parent c85f2545da
commit c6ef1ae30b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 290 additions and 309 deletions

View file

@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { EuiPortal, EuiTabs, EuiTab, EuiPanel, EuiTitle } from '@elastic/eui';
import { EuiPortal, EuiTabs, EuiTab, EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { CSSProperties, useMemo, useState } from 'react';
import React, { useMemo, useState } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
import { euiStyled } from '../../../../../../../observability/public';
import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../../../../lib/lib';
@ -15,7 +15,7 @@ import { MetricsTab } from './tabs/metrics/metrics';
import { LogsTab } from './tabs/logs';
import { ProcessesTab } from './tabs/processes';
import { PropertiesTab } from './tabs/properties/index';
import { OVERLAY_Y_START, OVERLAY_BOTTOM_MARGIN, OVERLAY_HEADER_SIZE } from './tabs/shared';
import { OVERLAY_Y_START, OVERLAY_BOTTOM_MARGIN } from './tabs/shared';
import { useLinkProps } from '../../../../../hooks/use_link_props';
import { getNodeDetailUrl } from '../../../../link_to';
import { findInventoryModel } from '../../../../../../common/inventory_models';
@ -70,21 +70,23 @@ export const NodeContextPopover = ({
return (
<EuiPortal>
<EuiPanel hasShadow={true} paddingSize={'none'} style={panelStyle}>
<OverlayPanel>
<OverlayHeader>
<OverlayHeaderTitleWrapper>
<EuiFlexGroup responsive={false} gutterSize="m">
<EuiFlexItem grow={true}>
<EuiTitle size="s">
<EuiTitle size="xs">
<h4>{node.name}</h4>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize={'xs'} alignItems={'flexEnd'}>
<EuiFlexGroup gutterSize="m" responsive={false}>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
size="xs"
iconSide={'left'}
iconType={'popout'}
href={nodeDetailMenuItemLinkProps.href}
flush="both"
>
<FormattedMessage
id="xpack.infra.infra.nodeDetails.openAsPage"
@ -93,7 +95,7 @@ export const NodeContextPopover = ({
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty onClick={onClose} iconType={'cross'}>
<EuiButtonEmpty size="xs" onClick={onClose} iconType="cross" flush="both">
<FormattedMessage
id="xpack.infra.infra.nodeDetails.close"
defaultMessage="Close"
@ -102,8 +104,9 @@ export const NodeContextPopover = ({
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</OverlayHeaderTitleWrapper>
<EuiTabs>
</EuiFlexGroup>
<EuiSpacer size="s" />
<EuiTabs size="s">
{tabs.map((tab, i) => (
<EuiTab key={tab.id} isSelected={i === selectedTab} onClick={() => setSelectedTab(i)}>
{tab.name}
@ -112,32 +115,38 @@ export const NodeContextPopover = ({
</EuiTabs>
</OverlayHeader>
{tabs[selectedTab].content}
</EuiPanel>
</OverlayPanel>
</EuiPortal>
);
};
const OverlayHeader = euiStyled.div`
border-color: ${(props) => props.theme.eui.euiBorderColor};
border-bottom-width: ${(props) => props.theme.eui.euiBorderWidthThick};
padding-bottom: 0;
padding-top: ${(props) => props.theme.eui.paddingSizes.m};
padding-right: ${(props) => props.theme.eui.paddingSizes.m};
padding-left: ${(props) => props.theme.eui.paddingSizes.m};
background-color: ${(props) => props.theme.eui.euiPageBackgroundColor};
box-shadow: inset 0 -1px ${(props) => props.theme.eui.euiBorderColor};
`;
const OverlayPanel = euiStyled(EuiPanel).attrs({ paddingSize: 'none' })`
display: flex;
flex-direction: column;
position: absolute;
right: 16px;
top: ${OVERLAY_Y_START}px;
width: 100%;
max-width: 720px;
z-index: 2;
max-height: calc(100vh - ${OVERLAY_Y_START + OVERLAY_BOTTOM_MARGIN}px);
overflow: hidden;
background-color: ${(props) => props.theme.eui.euiColorLightestShade};
height: ${OVERLAY_HEADER_SIZE}px;
`;
const OverlayHeaderTitleWrapper = euiStyled(EuiFlexGroup).attrs({ alignItems: 'center' })`
padding: ${(props) => props.theme.eui.paddingSizes.s} ${(props) =>
props.theme.eui.paddingSizes.m} 0;
@media (max-width: 752px) {
border-radius: 0px !important;
left: 0px;
right: 0px;
top: 97px;
bottom: 0;
max-height: calc(100vh - 97px);
max-width: 100%;
}
`;
const panelStyle: CSSProperties = {
position: 'absolute',
right: 10,
top: OVERLAY_Y_START,
width: '50%',
maxWidth: 730,
zIndex: 2,
height: `calc(100vh - ${OVERLAY_Y_START + OVERLAY_BOTTOM_MARGIN}px)`,
overflow: 'hidden',
};

View file

@ -15,7 +15,6 @@ import { TabContent, TabProps } from './shared';
import { LogStream } from '../../../../../../components/log_stream';
import { useWaffleOptionsContext } from '../../../hooks/use_waffle_options';
import { findInventoryFields } from '../../../../../../../common/inventory_models';
import { euiStyled } from '../../../../../../../../observability/public';
import { useLinkProps } from '../../../../../../hooks/use_link_props';
import { getNodeLogsUrl } from '../../../../../link_to';
@ -51,22 +50,25 @@ const TabComponent = (props: TabProps) => {
return (
<TabContent>
<EuiFlexGroup gutterSize={'none'} alignItems="center">
<EuiFlexGroup gutterSize={'m'} alignItems={'center'} responsive={false}>
<EuiFlexItem>
<QueryWrapper>
<EuiFieldSearch
fullWidth
placeholder={i18n.translate('xpack.infra.nodeDetails.logs.textFieldPlaceholder', {
defaultMessage: 'Search for log entries...',
})}
value={textQuery}
isClearable
onChange={onQueryChange}
/>
</QueryWrapper>
<EuiFieldSearch
fullWidth
placeholder={i18n.translate('xpack.infra.nodeDetails.logs.textFieldPlaceholder', {
defaultMessage: 'Search for log entries...',
})}
value={textQuery}
isClearable
onChange={onQueryChange}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty iconType={'popout'} {...nodeLogsMenuItemLinkProps}>
<EuiButtonEmpty
size={'xs'}
flush={'both'}
iconType={'popout'}
{...nodeLogsMenuItemLinkProps}
>
<FormattedMessage
id="xpack.infra.nodeDetails.logs.openLogsLink"
defaultMessage="Open in Logs"
@ -79,11 +81,6 @@ const TabComponent = (props: TabProps) => {
);
};
const QueryWrapper = euiStyled.div`
padding: ${(props) => props.theme.eui.paddingSizes.m};
padding-right: 0;
`;
export const LogsTab = {
id: 'logs',
name: i18n.translate('xpack.infra.nodeDetails.tabs.logs', {

View file

@ -11,7 +11,6 @@ import { EuiFlexGroup } from '@elastic/eui';
import { EuiIcon } from '@elastic/eui';
import { colorTransformer } from '../../../../../../../../common/color_palette';
import { MetricsExplorerOptionsMetric } from '../../../../../metrics_explorer/hooks/use_metrics_explorer_options';
import { euiStyled } from '../../../../../../../../../observability/public';
interface Props {
title: string;
@ -20,33 +19,33 @@ interface Props {
export const ChartHeader = ({ title, metrics }: Props) => {
return (
<ChartHeaderWrapper>
<EuiFlexGroup gutterSize={'s'} responsive={false}>
<EuiFlexItem grow={1}>
<EuiText>
<strong>{title}</strong>
<EuiText size={'s'}>
<h4>{title}</h4>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize={'s'} alignItems={'center'}>
<EuiFlexGroup gutterSize={'s'} alignItems={'center'} responsive={false}>
{metrics.map((chartMetric) => (
<EuiFlexGroup key={chartMetric.label!} gutterSize={'s'} alignItems={'center'}>
<EuiFlexItem grow={false}>
<EuiIcon color={colorTransformer(chartMetric.color!)} type={'dot'} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size={'xs'}>{chartMetric.label}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexItem key={chartMetric.label!}>
<EuiFlexGroup
key={chartMetric.label!}
gutterSize={'xs'}
alignItems={'center'}
responsive={false}
>
<EuiFlexItem grow={false}>
<EuiIcon color={colorTransformer(chartMetric.color!)} type={'dot'} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size={'xs'}>{chartMetric.label}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
))}
</EuiFlexGroup>
</EuiFlexItem>
</ChartHeaderWrapper>
</EuiFlexGroup>
);
};
const ChartHeaderWrapper = euiStyled.div`
display: flex;
width: 100%;
padding: ${(props) => props.theme.eui.paddingSizes.s} ${(props) =>
props.theme.eui.paddingSizes.m};
`;

View file

@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n';
import {
Axis,
Chart,
ChartSizeArray,
niceTimeFormatter,
Position,
Settings,
@ -17,7 +18,7 @@ import {
PointerEvent,
} from '@elastic/charts';
import moment from 'moment';
import { EuiLoadingChart } from '@elastic/eui';
import { EuiLoadingChart, EuiSpacer, EuiFlexGrid, EuiFlexItem } from '@elastic/eui';
import { TabContent, TabProps } from '../shared';
import { useSnapshot } from '../../../../hooks/use_snaphot';
import { useWaffleOptionsContext } from '../../../../hooks/use_waffle_options';
@ -39,7 +40,6 @@ import { createInventoryMetricFormatter } from '../../../../lib/create_inventory
import { calculateDomain } from '../../../../../metrics_explorer/components/helpers/calculate_domain';
import { getTimelineChartTheme } from '../../../../../metrics_explorer/components/helpers/get_chart_theme';
import { useUiSetting } from '../../../../../../../../../../../src/plugins/kibana_react/public';
import { euiStyled } from '../../../../../../../../../observability/public';
import { ChartHeader } from './chart_header';
import {
SYSTEM_METRIC_NAME,
@ -56,6 +56,8 @@ import {
import { TimeDropdown } from './time_dropdown';
const ONE_HOUR = 60 * 60 * 1000;
const CHART_SIZE: ChartSizeArray = ['100%', 160];
const TabComponent = (props: TabProps) => {
const cpuChartRef = useRef<Chart>(null);
const networkChartRef = useRef<Chart>(null);
@ -282,217 +284,184 @@ const TabComponent = (props: TabProps) => {
return (
<TabContent>
<TimepickerWrapper>
<TimeDropdown value={time} onChange={updateTime} />
</TimepickerWrapper>
<ChartsContainer>
<ChartContainerWrapper>
<TimeDropdown value={time} onChange={updateTime} />
<EuiSpacer size={'l'} />
<EuiFlexGrid columns={2} gutterSize={'l'} responsive={false}>
<EuiFlexItem>
<ChartHeader title={CPU_CHART_TITLE} metrics={cpuChartMetrics} />
<ChartContainer>
<Chart ref={cpuChartRef}>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={cpuChartMetrics[0]}
id={'0'}
series={systemMetricsTs!}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={cpuChartMetrics[1]}
id={'0'}
series={userMetricsTs}
stack={false}
/>
<Axis
id={'timestamp'}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={formatter}
/>
<Axis
id={'values'}
position={Position.Left}
tickFormat={cpuFormatter}
domain={getDomain(cpuTimeseries, cpuChartMetrics)}
ticks={6}
showGridLines
/>
<Settings
onPointerUpdate={pointerUpdate}
tooltip={tooltipProps}
theme={getTimelineChartTheme(isDarkMode)}
/>
</Chart>
</ChartContainer>
</ChartContainerWrapper>
<Chart ref={cpuChartRef} size={CHART_SIZE}>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={cpuChartMetrics[0]}
id={'0'}
series={systemMetricsTs!}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={cpuChartMetrics[1]}
id={'0'}
series={userMetricsTs}
stack={false}
/>
<Axis
id={'timestamp'}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={formatter}
/>
<Axis
id={'values'}
position={Position.Left}
tickFormat={cpuFormatter}
domain={getDomain(cpuTimeseries, cpuChartMetrics)}
ticks={6}
showGridLines
/>
<Settings
onPointerUpdate={pointerUpdate}
tooltip={tooltipProps}
theme={getTimelineChartTheme(isDarkMode)}
/>
</Chart>
</EuiFlexItem>
<ChartContainerWrapper>
<EuiFlexItem>
<ChartHeader title={LOAD_CHART_TITLE} metrics={loadChartMetrics} />
<ChartContainer>
<Chart ref={loadChartRef}>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={loadChartMetrics[0]}
id="0"
series={load1mMetricsTs}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={loadChartMetrics[1]}
id="0"
series={load5mMetricsTs}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={loadChartMetrics[2]}
id="0"
series={load15mMetricsTs}
stack={false}
/>
<Axis
id={'timestamp'}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={formatter}
/>
<Axis
id={'values1'}
position={Position.Left}
tickFormat={loadFormatter}
domain={getDomain(loadTimeseries, loadChartMetrics)}
ticks={6}
showGridLines
/>
<Settings
onPointerUpdate={pointerUpdate}
tooltip={tooltipProps}
theme={getTimelineChartTheme(isDarkMode)}
/>
</Chart>
</ChartContainer>
</ChartContainerWrapper>
<Chart ref={loadChartRef} size={CHART_SIZE}>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={loadChartMetrics[0]}
id="0"
series={load1mMetricsTs}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={loadChartMetrics[1]}
id="0"
series={load5mMetricsTs}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={loadChartMetrics[2]}
id="0"
series={load15mMetricsTs}
stack={false}
/>
<Axis
id={'timestamp'}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={formatter}
/>
<Axis
id={'values1'}
position={Position.Left}
tickFormat={loadFormatter}
domain={getDomain(loadTimeseries, loadChartMetrics)}
ticks={6}
showGridLines
/>
<Settings
onPointerUpdate={pointerUpdate}
tooltip={tooltipProps}
theme={getTimelineChartTheme(isDarkMode)}
/>
</Chart>
</EuiFlexItem>
<ChartContainerWrapper>
<EuiFlexItem>
<ChartHeader title={MEMORY_CHART_TITLE} metrics={memoryChartMetrics} />
<ChartContainer>
<Chart ref={memoryChartRef}>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={memoryChartMetrics[0]}
id="0"
series={usedMemoryMetricsTs}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={memoryChartMetrics[1]}
id="0"
series={freeMemoryMetricsTs}
stack={false}
/>
<Axis
id={'timestamp'}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={formatter}
/>
<Axis
id={'values'}
position={Position.Left}
tickFormat={memoryFormatter}
domain={getDomain(memoryTimeseries, memoryChartMetrics)}
ticks={6}
showGridLines
/>
<Settings
onPointerUpdate={pointerUpdate}
tooltip={tooltipProps}
theme={getTimelineChartTheme(isDarkMode)}
/>
</Chart>
</ChartContainer>
</ChartContainerWrapper>
<Chart ref={memoryChartRef} size={CHART_SIZE}>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={memoryChartMetrics[0]}
id="0"
series={usedMemoryMetricsTs}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={memoryChartMetrics[1]}
id="0"
series={freeMemoryMetricsTs}
stack={false}
/>
<Axis
id={'timestamp'}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={formatter}
/>
<Axis
id={'values'}
position={Position.Left}
tickFormat={memoryFormatter}
domain={getDomain(memoryTimeseries, memoryChartMetrics)}
ticks={6}
showGridLines
/>
<Settings
onPointerUpdate={pointerUpdate}
tooltip={tooltipProps}
theme={getTimelineChartTheme(isDarkMode)}
/>
</Chart>
</EuiFlexItem>
<ChartContainerWrapper>
<EuiFlexItem>
<ChartHeader title={NETWORK_CHART_TITLE} metrics={networkChartMetrics} />
<ChartContainer>
<Chart ref={networkChartRef}>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={networkChartMetrics[0]}
id="0"
series={rxMetricsTs}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={networkChartMetrics[1]}
id="0"
series={txMetricsTs}
stack={false}
/>
<Axis
id={'timestamp'}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={formatter}
/>
<Axis
id={'values'}
position={Position.Left}
tickFormat={networkFormatter}
domain={getDomain(networkTimeseries, networkChartMetrics)}
ticks={6}
showGridLines
/>
<Settings
onPointerUpdate={pointerUpdate}
tooltip={tooltipProps}
theme={getTimelineChartTheme(isDarkMode)}
/>
</Chart>
</ChartContainer>
</ChartContainerWrapper>
</ChartsContainer>
<Chart ref={networkChartRef} size={CHART_SIZE}>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={networkChartMetrics[0]}
id="0"
series={rxMetricsTs}
stack={false}
/>
<MetricExplorerSeriesChart
type={MetricsExplorerChartType.line}
metric={networkChartMetrics[1]}
id="0"
series={txMetricsTs}
stack={false}
/>
<Axis
id={'timestamp'}
position={Position.Bottom}
showOverlappingTicks={true}
tickFormat={formatter}
/>
<Axis
id={'values'}
position={Position.Left}
tickFormat={networkFormatter}
domain={getDomain(networkTimeseries, networkChartMetrics)}
ticks={6}
showGridLines
/>
<Settings
onPointerUpdate={pointerUpdate}
tooltip={tooltipProps}
theme={getTimelineChartTheme(isDarkMode)}
/>
</Chart>
</EuiFlexItem>
</EuiFlexGrid>
</TabContent>
);
};
const ChartsContainer = euiStyled.div`
display: flex;
flex-direction: row;
flex-wrap: wrap;
`;
const ChartContainerWrapper = euiStyled.div`
width: 50%
`;
const TimepickerWrapper = euiStyled.div`
padding: ${(props) => props.theme.eui.paddingSizes.m};
width: 50%;
`;
const ChartContainer: React.FC = ({ children }) => (
<div
style={{
width: '100%',
height: 150,
}}
>
{children}
</div>
);
const LoadingPlaceholder = () => {
return (
<div
style={{
width: '100%',
height: '100%',
height: '200px',
padding: '16px',
display: 'flex',
alignItems: 'center',

View file

@ -15,7 +15,7 @@ interface Props {
export const TimeDropdown = (props: Props) => (
<EuiSelect
compressed
fullWidth={true}
options={[
{
text: i18n.translate('xpack.infra.nodeDetails.metrics.last15Minutes', {

View file

@ -102,7 +102,9 @@ const TabComponent = (props: TabProps) => {
};
const TableWrapper = euiStyled.div`
margin-bottom: 20px
&:not(:last-child) {
margin-bottom: 16px
}
`;
const LoadingPlaceholder = () => {

View file

@ -4,18 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { EuiText } from '@elastic/eui';
import { EuiToolTip } from '@elastic/eui';
import { EuiButtonIcon } from '@elastic/eui';
import { EuiFlexGroup } from '@elastic/eui';
import { EuiFlexItem } from '@elastic/eui';
import { EuiLink } from '@elastic/eui';
import { EuiBasicTable } from '@elastic/eui';
import {
EuiText,
EuiToolTip,
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiLink,
EuiBasicTable,
EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { first } from 'lodash';
import React, { useCallback, useMemo, useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { euiStyled } from '../../../../../../../../../observability/public';
interface Row {
name: string;
@ -51,15 +53,19 @@ export const Table = (props: Props) => {
render: (_name: string, item: Row) => {
return (
<span>
<EuiToolTip
content={i18n.translate('xpack.infra.nodeDetails.tabs.metadata.setFilterTooltip', {
defaultMessage: 'View event with filter',
})}
>
<EuiFlexGroup gutterSize={'xs'}>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize={'xs'} alignItems={'center'} responsive={false}>
<EuiFlexItem grow={false}>
<EuiToolTip
content={i18n.translate(
'xpack.infra.nodeDetails.tabs.metadata.setFilterTooltip',
{
defaultMessage: 'View event with filter',
}
)}
>
<EuiButtonIcon
color="text"
color="subdued"
size="s"
iconType="filter"
aria-label={i18n.translate(
'xpack.infra.nodeDetails.tabs.metadata.filterAriaLabel',
@ -69,13 +75,13 @@ export const Table = (props: Props) => {
)}
onClick={() => onClick(item)}
/>
</EuiFlexItem>
<EuiFlexItem>
{!Array.isArray(item.value) && item.value}
{Array.isArray(item.value) && <ArrayValue values={item.value} />}
</EuiFlexItem>
</EuiFlexGroup>
</EuiToolTip>
</EuiToolTip>
</EuiFlexItem>
<EuiFlexItem>
{!Array.isArray(item.value) && item.value}
{Array.isArray(item.value) && <ArrayValue values={item.value} />}
</EuiFlexItem>
</EuiFlexGroup>
</span>
);
},
@ -86,20 +92,21 @@ export const Table = (props: Props) => {
return (
<>
<TitleWrapper>
<EuiText>
<h3>{title}</h3>
</EuiText>
</TitleWrapper>
<TableWithoutHeader tableLayout="fixed" compressed columns={columns} items={rows} />
<EuiText>
<h4>{title}</h4>
</EuiText>
<EuiSpacer size={'s'} />
<TableWithoutHeader
tableLayout={'fixed'}
compressed
responsive={false}
columns={columns}
items={rows}
/>
</>
);
};
const TitleWrapper = euiStyled.div`
margin-bottom: 10px
`;
class TableWithoutHeader extends EuiBasicTable {
renderTableHead() {
return <></>;
@ -123,7 +130,7 @@ const ArrayValue = (props: MoreProps) => {
return (
<>
{!isExpanded && (
<EuiFlexGroup gutterSize="none">
<EuiFlexGroup gutterSize={'xs'} responsive={false} alignItems={'baseline'} wrap={true}>
<EuiFlexItem grow={false}>
{first(values)}
{' ... '}
@ -148,7 +155,7 @@ const ArrayValue = (props: MoreProps) => {
))}
<EuiLink onClick={collapse}>
{i18n.translate('xpack.infra.nodeDetails.tabs.metadata.seeLess', {
defaultMessage: 'See less',
defaultMessage: 'Show less',
})}
</EuiLink>
</div>

View file

@ -17,11 +17,9 @@ export interface TabProps {
export const OVERLAY_Y_START = 266;
export const OVERLAY_BOTTOM_MARGIN = 16;
export const OVERLAY_HEADER_SIZE = 96;
const contentHeightOffset = OVERLAY_Y_START + OVERLAY_BOTTOM_MARGIN + OVERLAY_HEADER_SIZE;
export const TabContent = euiStyled.div`
padding: ${(props) => props.theme.eui.paddingSizes.s};
height: calc(100vh - ${contentHeightOffset}px);
padding: ${(props) => props.theme.eui.paddingSizes.m};
flex: 1;
overflow-y: auto;
overflow-x: hidden;
`;