Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
12f6457
Update LogsOverviewHeader
iblancof Sep 5, 2025
a0a35dc
Add onToggle and forceState in ContentFrameworkSection
iblancof Sep 5, 2025
168185c
Update LogsOverviewStacktraceSection
iblancof Sep 5, 2025
5e3b81b
Manage separator in ContentFrameworkSection
iblancof Sep 5, 2025
6d0bf8f
Add spacer to the ContentFrameworkSection
iblancof Sep 5, 2025
396195f
Merge branch 'main' into 233743-discover-adapt-logs-flyout-to-use-the…
iblancof Sep 8, 2025
d1f281f
Merge branch 'main' into 233743-discover-adapt-logs-flyout-to-use-the…
iblancof Sep 9, 2025
b9b0a5d
Adapt highlights to new content framework
iblancof Sep 10, 2025
43d9af8
Update text truncate in NamePopoverContent
iblancof Sep 10, 2025
3f7c267
Extract data-test-subj as prop for TraceIdLink
iblancof Sep 10, 2025
4bfba42
Extract data-test-subj as prop for ServiceNameLink
iblancof Sep 10, 2025
7fe3acd
Add field type to NamePopoverContent
iblancof Sep 10, 2025
6fc6eca
Remove service name link from logs overview
iblancof Sep 10, 2025
4c665b9
Reorganize log overview
iblancof Sep 10, 2025
acf1f50
Update LogsOverviewDegradedFields to match ContentFramework UI
iblancof Sep 10, 2025
3879280
Update DiscoverFlyoutStreamField to match ContentFramework UI)
iblancof Sep 10, 2025
5ca23e9
Add function props to LogsOverviewHighlights
iblancof Sep 10, 2025
c94dba7
Add configuration for truncate value content
iblancof Sep 10, 2025
7b8ffb1
Remove unused imports
iblancof Sep 10, 2025
76ff72c
Fix beta badge alignment
iblancof Sep 10, 2025
ee9e8e5
Update table styles
iblancof Sep 10, 2025
c2fa690
Remove unused content
iblancof Sep 10, 2025
fc31cae
Merge branch 'main' into 233743-discover-adapt-logs-flyout-to-use-the…
iblancof Sep 15, 2025
3ca442b
Update streams links sizing
iblancof Sep 15, 2025
c575593
Update degraded fields text sizing
iblancof Sep 15, 2025
4017f8b
Merge branch 'main' into 233743-discover-adapt-logs-flyout-to-use-the…
iblancof Sep 15, 2025
6269920
Update logs overview tests
iblancof Sep 15, 2025
75fdea5
Refactor logs overview highlights
iblancof Sep 15, 2025
1f37e15
Unify constants
iblancof Sep 15, 2025
941a7f3
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Sep 15, 2025
49706b2
Clean translation keys
iblancof Sep 15, 2025
d7da6e6
Fix typing issues
iblancof Sep 15, 2025
97c007e
Merge branch '233743-discover-adapt-logs-flyout-to-use-the-new-conten…
iblancof Sep 15, 2025
02dd805
Create LazyContentFrameworkSection
iblancof Sep 16, 2025
a79c067
Fix ContentFrameworkSection imports
iblancof Sep 17, 2025
d1f518e
Refactor accordion state
iblancof Sep 17, 2025
0b96352
Improve flex html structure in NamePopoverContent
iblancof Sep 17, 2025
2ca38de
Make valueCellContent required
iblancof Sep 17, 2025
97b8324
Extract field label and description to a common place
iblancof Sep 17, 2025
6b82db3
Add missing export
iblancof Sep 17, 2025
5180847
Update translations
iblancof Sep 17, 2025
3c628de
Update NamePopoverContent tests
iblancof Sep 17, 2025
9c1cfc3
Update src/platform/plugins/shared/unified_doc_viewer/public/componen…
iblancof Sep 17, 2025
e0184db
[CI] Auto-commit changed files from 'node scripts/eslint_all_files --…
kibanamachine Sep 17, 2025
6267b28
Merge branch 'main' into 233743-discover-adapt-logs-flyout-to-use-the…
iblancof Sep 18, 2025
d08ecdd
Update test
iblancof Sep 18, 2025
fa45cfd
Inlcude highlights in header section
iblancof Sep 18, 2025
b1652d7
Fix type issues
iblancof Sep 18, 2025
4c4bf2a
Merge branch 'main' into 233743-discover-adapt-logs-flyout-to-use-the…
iblancof Sep 19, 2025
d3d7fc3
Refactor logs overview types and tests
iblancof Sep 19, 2025
e4c2c06
Update section reference in tests
iblancof Sep 19, 2025
3295964
Merge branch 'main' into 233743-discover-adapt-logs-flyout-to-use-the…
iblancof Sep 22, 2025
3ddd79d
Remove border bottom from last row
iblancof Sep 22, 2025
a0de7e4
Merge branch 'main' into 233743-discover-adapt-logs-flyout-to-use-the…
iblancof Sep 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@
*/

export * from './table';
export * from './section';
export * from './chart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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 { withSuspense } from '@kbn/shared-ux-utility';
import type { ContentFrameworkSectionProps } from './section/section';

const LazyContentFrameworkSection = React.lazy(() => import('./section'));
export const ContentFrameworkSection = withSuspense<ContentFrameworkSectionProps>(
LazyContentFrameworkSection,
<></>
);
Original file line number Diff line number Diff line change
Expand Up @@ -7,127 +7,8 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import React, { useState } from 'react';
import type { IconType } from '@elastic/eui';
import {
EuiAccordion,
EuiButtonEmpty,
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiHorizontalRule,
EuiIconTip,
EuiPanel,
EuiSpacer,
EuiTitle,
} from '@elastic/eui';
import { ContentFrameworkSection } from './section';

interface BaseAction {
icon: IconType;
ariaLabel: string;
dataTestSubj?: string;
label?: string;
}

type Action =
| (BaseAction & { onClick: () => void; href?: never })
| (BaseAction & { href: string; onClick?: never });

export interface ContentFrameworkSectionProps {
id: string;
title: string;
description?: string;
actions?: Action[];
children: React.ReactNode;
'data-test-subj'?: string;
initialIsOpen?: boolean;
}

export function ContentFrameworkSection({
id,
title,
description,
actions,
children,
'data-test-subj': accordionDataTestSubj,
initialIsOpen = true,
}: ContentFrameworkSectionProps) {
const [isAccordionExpanded, setIsAccordionExpanded] = useState(initialIsOpen);
const renderActions = () => (
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd" alignItems="center">
{actions?.map((action, idx) => {
const { icon, onClick, ariaLabel, label, dataTestSubj, href } = action;
const size = 'xs';
const buttonProps = onClick ? { onClick } : { href };
return (
<EuiFlexItem grow={false} key={idx}>
{label ? (
<EuiButtonEmpty
size={size}
iconType={icon}
aria-label={ariaLabel}
data-test-subj={dataTestSubj}
{...buttonProps}
>
{label}
</EuiButtonEmpty>
) : (
<EuiButtonIcon
size={size}
iconType={icon}
aria-label={ariaLabel}
data-test-subj={dataTestSubj}
{...buttonProps}
/>
)}
</EuiFlexItem>
);
})}
</EuiFlexGroup>
);

return (
<>
<EuiAccordion
data-test-subj={accordionDataTestSubj}
id={`sectionAccordion-${id}`}
initialIsOpen={isAccordionExpanded}
onToggle={setIsAccordionExpanded}
buttonContent={
<EuiFlexGroup alignItems="center" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiTitle size="xs">
<h3>{title}</h3>
</EuiTitle>
</EuiFlexItem>
{description && (
<EuiFlexItem grow={false}>
<EuiIconTip
content={description}
size="s"
color="subdued"
aria-label={description}
/>
</EuiFlexItem>
)}
</EuiFlexGroup>
}
extraAction={
actions?.length ? (
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem grow={false}>{renderActions()}</EuiFlexItem>
</EuiFlexGroup>
) : null
}
>
<>
<EuiSpacer size="s" />
<EuiPanel hasBorder={true} hasShadow={false} paddingSize="s">
{children}
</EuiPanel>
</>
</EuiAccordion>
{!isAccordionExpanded ? <EuiHorizontalRule margin="xs" /> : <EuiSpacer size="m" />}
</>
);
}
// Required for usage in React.lazy
// eslint-disable-next-line import/no-default-export
export default ContentFrameworkSection;
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import type { UnifiedDocViewerStorybookArgs } from '../../../../.storybook/preview';
import { ContentFrameworkSection, type ContentFrameworkSectionProps } from '.';
import APMSpanFixture from '../../../__fixtures__/span_apm_minimal.json';
import ContentFrameworkSection from '.';
import type { ContentFrameworkSectionProps } from './section';

type Args = UnifiedDocViewerStorybookArgs<ContentFrameworkSectionProps>;
const meta = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import type { ContentFrameworkSectionProps } from '.';
import { ContentFrameworkSection } from '.';
import userEvent from '@testing-library/user-event';
import { ContentFrameworkSection, type ContentFrameworkSectionProps } from './section';

const defaultProps: ContentFrameworkSectionProps = {
title: 'Test Section',
Expand All @@ -32,6 +32,7 @@ const defaultProps: ContentFrameworkSectionProps = {
],
children: <div>Section children</div>,
id: 'testSection',
'data-test-subj': 'testSection',
};

describe('ContentFrameworkSection', () => {
Expand All @@ -40,13 +41,20 @@ describe('ContentFrameworkSection', () => {
expect(screen.getByText('Test Section')).toBeInTheDocument();
});

it('renders EuiBetaBadge when isTechPreview is true', () => {
const props = { ...defaultProps, isTechPreview: true };
render(<ContentFrameworkSection {...props} />);
expect(screen.getByTestId('ContentFrameworkSectionEuiBetaBadge')).toBeInTheDocument();
});

it('renders the description as EuiIconTip', () => {
render(<ContentFrameworkSection {...defaultProps} />);
expect(screen.getByText('Section description')).toBeInTheDocument();
});

it('renders actions as buttons', () => {
render(<ContentFrameworkSection {...defaultProps} />);

expect(screen.getByTestId('unifiedDocViewerSectionActionButton-expand')).toBeInTheDocument();
expect(
screen.getByTestId('unifiedDocViewerSectionActionButton-fullScreen')
Expand Down Expand Up @@ -84,4 +92,12 @@ describe('ContentFrameworkSection', () => {
screen.queryByTestId('unifiedDocViewerSectionActionButton-fullScreen')
).not.toBeInTheDocument();
});

it('calls onToggle when the accordion is toggled', async () => {
const onToggle = jest.fn();
render(<ContentFrameworkSection {...defaultProps} onToggle={onToggle} forceState="open" />);
const toggleBtn = screen.getByText('Test Section');
await userEvent.click(toggleBtn);
expect(onToggle).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* 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, { useEffect, useState } from 'react';
import type { EuiAccordionProps, IconType } from '@elastic/eui';
import {
EuiAccordion,
EuiBetaBadge,
EuiButtonEmpty,
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiHorizontalRule,
EuiIconTip,
EuiPanel,
EuiSpacer,
EuiTitle,
} from '@elastic/eui';

interface BaseAction {
icon: IconType;
ariaLabel: string;
dataTestSubj?: string;
label?: string;
}

type Action =
| (BaseAction & { onClick: () => void; href?: never })
| (BaseAction & { href: string; onClick?: never });

export interface ContentFrameworkSectionProps {
id: string;
title: string;
description?: string;
actions?: Action[];
children: React.ReactNode;
'data-test-subj'?: string;
onToggle?: (isOpen: boolean) => void;
forceState?: EuiAccordionProps['forceState'];
isTechPreview?: boolean;
hasBorder?: boolean;
hasPadding?: boolean;
}

export function ContentFrameworkSection({
id,
title,
description,
actions,
children,
onToggle,
forceState = 'open',
'data-test-subj': accordionDataTestSubj,
isTechPreview = false,
hasBorder = true,
hasPadding = true,
}: ContentFrameworkSectionProps) {
const [accordionState, setAccordionState] = useState<EuiAccordionProps['forceState']>(forceState);

const renderActions = () => (
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd" alignItems="center">
{actions?.map((action, idx) => {
const { icon, onClick, ariaLabel, label, dataTestSubj, href } = action;
const size = 'xs';
const buttonProps = onClick ? { onClick } : { href };
return (
<EuiFlexItem grow={false} key={idx}>
{label ? (
<EuiButtonEmpty
size={size}
iconType={icon}
aria-label={ariaLabel}
data-test-subj={dataTestSubj}
{...buttonProps}
>
{label}
</EuiButtonEmpty>
) : (
<EuiButtonIcon
size={size}
iconType={icon}
aria-label={ariaLabel}
data-test-subj={dataTestSubj}
{...buttonProps}
/>
)}
</EuiFlexItem>
);
})}
</EuiFlexGroup>
);

useEffect(() => {
setAccordionState(forceState);
}, [forceState]);

const handleToggle = (isOpen: boolean) => {
setAccordionState(isOpen ? 'open' : 'closed');
onToggle?.(isOpen);
};

return (
<>
<EuiAccordion
data-test-subj={accordionDataTestSubj}
id={`sectionAccordion-${id}`}
initialIsOpen={forceState === 'open'}
onToggle={handleToggle}
forceState={accordionState}
buttonContent={
<EuiFlexGroup alignItems="center" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiTitle size="xs">
<h3>{title}</h3>
</EuiTitle>
</EuiFlexItem>
{description ? (
<EuiFlexItem grow={false}>
{isTechPreview ? (
<EuiBetaBadge
size="s"
label={description}
alignment="middle"
color="hollow"
iconType="beaker"
title={title}
data-test-subj="ContentFrameworkSectionEuiBetaBadge"
/>
) : (
<EuiIconTip
content={description}
size="s"
color="subdued"
aria-label={description}
/>
)}
</EuiFlexItem>
) : null}
</EuiFlexGroup>
}
extraAction={
actions?.length && (
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem grow={false}>{renderActions()}</EuiFlexItem>
</EuiFlexGroup>
)
}
>
<>
<EuiSpacer size="s" />
<EuiPanel hasBorder={hasBorder} hasShadow={false} paddingSize={hasPadding ? 's' : 'none'}>
{children}
</EuiPanel>
</>
</EuiAccordion>
{accordionState === 'closed' ? <EuiHorizontalRule margin="xs" /> : <EuiSpacer size="m" />}
</>
);
}
Loading