Skip to content

Add React content type for field formatters#254843

Draft
kertal wants to merge 11 commits intoelastic:mainfrom
kertal:field-formats/react-content-type-clean
Draft

Add React content type for field formatters#254843
kertal wants to merge 11 commits intoelastic:mainfrom
kertal:field-formats/react-content-type-clean

Conversation

@kertal
Copy link
Member

@kertal kertal commented Feb 25, 2026

Note: it's not ready for review, experimental PR using cursor, accidentally wasn't opened as a draft, sorry 🙇

Summary

Introduce a third content type ('react') for field formatters that returns ReactNode instead of HTML strings.

Motivation

Field formatters historically returned HTML strings via 'html' content type, requiring consumers to use dangerouslySetInnerHTML. The new 'react' content type lets formatters return ReactNode directly, enabling safe rendering via {children}.

Commit-by-commit walkthrough

  1. Core infrastructure — Add ReactContextTypeConvert type, react_content_type.tsx with setup(), checkForMissingValueReact(), HTML entity decoding fallback, and convert()/getConverterFor() overloads for type-safe usage
  2. StringFormatreactConvert with getHighlightReact() (React-native highlight utility using null-byte markers instead of HTML concatenation) + comprehensive tests
  3. BooleanFormatreactConvert with missing value handling
  4. UrlFormat — Rename .ts.tsx, return native <a> and <img> elements
  5. ColorFormat — Return styled <span> elements + tests
  6. NumeralFormat, DateNanosFormat, StaticLookupFormatreactConvert with missing value handling; fix StaticLookup null coercion bug
  7. Aggregation format wrappers — Pass 'react' type through to underlying formatters (enables colored cells in Lens)
  8. Discover & Doc Viewer migration — Replace dangerouslySetInnerHTML with direct ReactNode rendering across data table, doc viewer table, logs overview, traces
  9. Remaining consumers — Lens, Maps, vis types, controls, data view field editor, workflows

Design decisions

  • HTML fallback: Formatters without reactConvert automatically delegate to their HTML output. Tag-free HTML strings get entity-decoded; strings with tags use dangerouslySetInnerHTML wrapped in a <span>. This ensures backward compatibility.
  • Overloads: convert('react') returns ReactNode; convert('html'|'text') returns string. TypeScript enforces correct usage at call sites.
  • Aggregation wrappers: AggsTermsFieldFormat forwards 'react' to the underlying formatter. AggsMultiTermsFieldFormat maps 'react''text' since join() requires strings.

Changes

  • 64 files changed, ~1160 insertions, ~340 deletions
  • New files: react_content_type.tsx, highlight_react.tsx + tests, formatted_field_value.tsx
  • Renamed: url.tsurl.tsx

Test plan

  • Type checks pass for field_formats, data, controls, lens, unified_doc_viewer
  • All 262 field_formats jest tests pass (including new react content type tests)
  • All 412 unified_doc_viewer jest tests pass
  • All 18 kbn-unified-data-table render cell tests pass
  • All 43 vis_types/table tests pass
  • Functional tests: management field formatters, visualize (Lens, precalculated histogram, range aggregations)
  • Manual verification of colored cells in Lens datatables
  • Manual verification of URL/image formatters in doc viewer
  • Manual verification of highlight rendering in Discover

Made with Cursor

kertal and others added 9 commits February 24, 2026 21:58
Introduce a third content type ('react') alongside 'html' and 'text'
that returns ReactNode instead of strings. This enables formatters to
produce native JSX, eliminating dangerouslySetInnerHTML in consumers.

Core changes:
- Add ReactContextTypeConvert, ReactContextTypeOptions types
- Add FieldFormatsContentType 'react' union member
- Create react_content_type.tsx with setup(), checkForMissingValueReact()
- Add convert()/getConverterFor() overloads for type-safe 'react' usage
- Add reactConvert property to FieldFormat base class
- HTML fallback: formatters without reactConvert delegate to HTML output,
  decoding entities for tag-free strings, using dangerouslySetInnerHTML
  for strings containing HTML tags
- Export new types and utilities from common/index.ts

Co-authored-by: Cursor <cursoragent@cursor.com>
Implement reactConvert for the String formatter that returns native
React elements instead of HTML strings:
- Missing value handling via checkForMissingValueReact
- Highlight support via new getHighlightReact() utility that produces
  <mark> elements instead of HTML string concatenation
- Falls back to textConvert for plain values

Add getHighlightReact() — a React-native equivalent of getHighlightHtml()
that uses null-byte markers for iterative replacement, then parses into
React nodes with <mark> elements. No HTML escaping needed since React
handles XSS natively.

Includes comprehensive tests for both getHighlightReact and
StringFormat.reactConvert covering highlights, missing values, and XSS.

Co-authored-by: Cursor <cursoragent@cursor.com>
Implement reactConvert for the Boolean formatter:
- Missing value handling via checkForMissingValueReact
- Delegates to textConvert for the actual true/false label

Co-authored-by: Cursor <cursoragent@cursor.com>
Rename url.ts → url.tsx to support JSX and implement reactConvert:
- Missing value handling via checkForMissingValueReact
- Returns native <a> and <img> elements instead of HTML strings
- Preserves link target, rel attributes, and image dimensions
- Falls back to textConvert for plain text output

Co-authored-by: Cursor <cursoragent@cursor.com>
Implement reactConvert for the Color formatter:
- Returns styled <span> elements with inline color/background-color
- Missing value handling via checkForMissingValueReact
- Falls back to plain text when no color rule matches

Add tests verifying rendered DOM structure and plain text fallback.

Co-authored-by: Cursor <cursoragent@cursor.com>
…kupFormat

NumeralFormat (Bytes, Percent, Currency, Number):
- Implement reactConvert with missing value handling
- Delegate to textConvert for formatted numeric output

DateNanosFormat:
- Implement reactConvert with missing value handling
- Delegate to textConvert for formatted date output

StaticLookupFormat:
- Fix textConvert to use explicit null-checks instead of || chain,
  preventing boolean false from being treated as "no match"
- Add null guard so null values return '' instead of the string 'null'

Co-authored-by: Cursor <cursoragent@cursor.com>
Update AggsTermsFieldFormat to forward 'react' type to the underlying
formatter instead of mapping it to 'text'. This allows styled React
output (e.g. colored spans from ColorFormat) to flow through aggregation
formatting in Lens datatables.

AggsMultiTermsFieldFormat continues mapping 'react' to 'text' since
join() requires string values.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace dangerouslySetInnerHTML with direct ReactNode rendering across
the Discover ecosystem:

kbn-discover-utils:
- Add formatFieldValueReact() returning ReactNode via 'react' type
- Add FormattedFieldValue component for React-safe rendering
- Update formatHit/getFormattedFields to support React output

kbn-unified-data-table:
- Switch cell rendering from format(..., 'html') + innerHTML to
  format(..., 'react') + direct children
- Remove dangerouslySetInnerHTML from source_document, cell values

unified_doc_viewer:
- Doc viewer table: use formattedAsReact instead of formattedAsHtml
- TableFieldValue: render children instead of dangerouslySetInnerHTML
- FormattedValue: accept ReactNode instead of HTML string
- Content breakdown, logs overview, traces: render React children
- Update all related tests to pass JSX instead of HTML strings

Co-authored-by: Cursor <cursoragent@cursor.com>
Switch from format(..., 'html') + dangerouslySetInnerHTML to
format(..., 'react') + direct ReactNode rendering across:

- Lens datatable cell rendering
- Maps tooltip property display
- Table vis cell (vis_types/table)
- Legacy metric expression format utility
- TSVB field formatter
- Data view field editor: format samples, preview, image modal
- Controls plugin: restrict DataControlFieldFormatter to string types
- Workflows management index form

Update optimizer bundle size limits to reflect the new react_content_type
module inclusion.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kertal kertal requested review from a team as code owners February 25, 2026 05:45
@botelastic botelastic bot added the Team:One Workflow Team label for One Workflow (Workflow automation) label Feb 25, 2026
@kertal kertal self-assigned this Feb 25, 2026
@kertal kertal removed the Team:One Workflow Team label for One Workflow (Workflow automation) label Feb 25, 2026
@kertal kertal changed the title Add React content type for field formatters — eliminate dangerouslySetInnerHTML Add React content type for field formatters Feb 25, 2026
@kertal kertal marked this pull request as draft February 25, 2026 05:50
@elasticmachine
Copy link
Contributor

🤖 Jobs for this PR can be triggered through checkboxes. 🚧

ℹ️ To trigger the CI, please tick the checkbox below 👇

  • Click to trigger kibana-pull-request for this PR!
  • Click to trigger kibana-deploy-project-from-pr for this PR!
  • Click to trigger kibana-deploy-cloud-from-pr for this PR!
  • Click to trigger kibana-entity-store-performance-from-pr for this PR!
  • Click to trigger kibana-storybooks-from-pr for this PR!

@kertal kertal requested a review from Copilot February 25, 2026 18:01
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduce a new 'react' content type for field formatters so consumers can render formatted values as ReactNode (avoiding dangerouslySetInnerHTML), while keeping fallback behavior for legacy HTML-formatters.

Changes:

  • Add core 'react' content type plumbing (convert/getConverterFor overloads, react content type setup + fallback wrapper).
  • Update multiple UI consumers (Lens, Maps, unified doc viewer, unified data table, data view field editor) to render React nodes directly.
  • Add React-native highlight utilities (getHighlightReact) and extend formatters (String/Url/Color/etc.) with reactConvert.

Reviewed changes

Copilot reviewed 64 out of 64 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
x-pack/platform/plugins/shared/maps/public/classes/tooltips/es_tooltip_property.tsx Switch tooltip formatting to convert(..., 'react') to avoid HTML injection.
x-pack/platform/plugins/shared/lens/public/visualizations/datatable/components/cell_value.tsx Render formatted cell content as ReactNode instead of dangerouslySetInnerHTML.
src/platform/plugins/shared/workflows_management/public/features/run_workflow/ui/workflow_execute_index_form.tsx Use formatHitReact and render formatted values directly.
src/platform/plugins/shared/vis_types/timeseries/public/application/components/lib/create_field_formatter.ts Default to 'text' when no context type is provided.
src/platform/plugins/shared/unified_doc_viewer/public/components/observability/traces/components/highlight_field/index.tsx Update highlight field to accept/render ReactNode formatted values.
src/platform/plugins/shared/unified_doc_viewer/public/components/observability/traces/components/highlight_field/highlight_field.test.tsx Update tests to pass React nodes instead of HTML strings.
src/platform/plugins/shared/unified_doc_viewer/public/components/observability/traces/components/about/field_configurations.tsx Adjust formatter signatures to accept React formatted values.
src/platform/plugins/shared/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx Render table cell values as React children.
src/platform/plugins/shared/unified_doc_viewer/public/components/doc_viewer_table/table_cell.tsx Feed formattedAsReact into table UI.
src/platform/plugins/shared/unified_doc_viewer/public/components/doc_viewer_table/field_row.ts Add lazy formattedAsReact using formatFieldValueReact.
src/platform/plugins/shared/unified_doc_viewer/public/components/doc_viewer_logs_overview/sub_components/content_breakdown/content_breakdown.tsx Remove HTML injection path; render fallback content as text children.
src/platform/plugins/shared/unified_doc_viewer/public/components/doc_viewer_logs_overview/sub_components/content_breakdown/content_breakdown.test.tsx Update EuiCodeBlock mock to assert children rendering.
src/platform/plugins/shared/unified_doc_viewer/public/components/doc_viewer_logs_overview/sub_components/badges/event_type.tsx Render event type value directly (no dangerouslySetInnerHTML).
src/platform/plugins/shared/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_highlights.tsx Adjust formatter signatures for React formatted values.
src/platform/plugins/shared/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview.test.tsx Update EuiCodeBlock mock to React children.
src/platform/plugins/shared/unified_doc_viewer/public/components/content_framework/table/table.test.tsx Mock getFormattedFieldsReact for table tests.
src/platform/plugins/shared/unified_doc_viewer/public/components/content_framework/table/index.tsx Use getFormattedFieldsReact and accept React formatted values.
src/platform/plugins/shared/unified_doc_viewer/public/components/content_framework/table/components/formatted_value.tsx Render formatted values as React children.
src/platform/plugins/shared/unified_doc_viewer/public/components/content_framework/table/components/formatted_value.test.tsx Update tests for ReactNode rendering.
src/platform/plugins/shared/field_formats/common/utils/index.ts Export getHighlightReact from shared utils.
src/platform/plugins/shared/field_formats/common/utils/highlight/index.ts Export new React highlight helper.
src/platform/plugins/shared/field_formats/common/utils/highlight/highlight_react.tsx Implement React-based highlight rendering with <mark>.
src/platform/plugins/shared/field_formats/common/utils/highlight/highlight_react.test.tsx Add tests for React highlight logic.
src/platform/plugins/shared/field_formats/common/types.ts Add 'react' to content types + React converter types/options.
src/platform/plugins/shared/field_formats/common/index.ts Export react content type symbols and React option/convert types.
src/platform/plugins/shared/field_formats/common/field_format.ts Add reactConvert, react content type setup, and type-safe overloads.
src/platform/plugins/shared/field_formats/common/converters/url.tsx Add reactConvert returning native <a>, <img>, <audio>.
src/platform/plugins/shared/field_formats/common/converters/string.ts Add reactConvert and React highlighting for strings.
src/platform/plugins/shared/field_formats/common/converters/string.test.ts Add react content type tests for StringFormat.
src/platform/plugins/shared/field_formats/common/converters/static_lookup.ts Fix null/empty handling when mapping lookup entries.
src/platform/plugins/shared/field_formats/common/converters/numeral.ts Add reactConvert + missing value handling.
src/platform/plugins/shared/field_formats/common/converters/date_nanos_shared.ts Add reactConvert + missing value handling.
src/platform/plugins/shared/field_formats/common/converters/color.tsx Add reactConvert producing styled <span>.
src/platform/plugins/shared/field_formats/common/converters/color.test.ts Add react content type tests for ColorFormat.
src/platform/plugins/shared/field_formats/common/converters/boolean.ts Add reactConvert + missing value handling.
src/platform/plugins/shared/field_formats/common/content_types/react_content_type.tsx Add react content type setup + HTML fallback wrapper.
src/platform/plugins/shared/field_formats/common/content_types/index.ts Export react content type setup and helpers.
src/platform/plugins/shared/data_view_field_editor/public/components/preview/types.ts Change preview formatted value type to ReactNode.
src/platform/plugins/shared/data_view_field_editor/public/components/preview/preview_controller.tsx Use 'react' converters for preview formatting.
src/platform/plugins/shared/data_view_field_editor/public/components/preview/image_preview_modal.tsx Render image preview content as React nodes.
src/platform/plugins/shared/data_view_field_editor/public/components/preview/field_list/field_list_item.tsx Render formatted values directly; update image detection.
src/platform/plugins/shared/data_view_field_editor/public/components/preview/field_list/field_list.tsx Use 'react' formatting for preview list.
src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/types.ts Change sample output type to ReactNode.
src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/samples/samples.tsx Render sample output as ReactNode directly.
src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/url/url.tsx Switch URL sample converter type to 'react'.
src/platform/plugins/shared/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx Update sample converter signature to return ReactNode.
src/platform/plugins/shared/data/common/search/aggs/utils/get_aggs_formats.ts Forward 'react' through aggs field format wrapper(s).
src/platform/plugins/shared/controls/public/controls/data_controls/types.ts Narrow allowed formatter types for controls (string-based).
src/platform/plugins/shared/chart_expressions/expression_legacy_metric/public/utils/format.ts Constrain format type to `'html'
src/platform/plugins/private/vis_types/table/public/components/table_vis_cell.tsx Render formatted values as React children for table vis cells.
src/platform/plugins/private/vis_types/table/public/components/table_vis_cell.test.tsx Update expected convert call to 'react'.
src/platform/plugins/private/vis_types/table/public/components/snapshots/table_vis_cell.test.tsx.snap Update snapshot after removing HTML injection.
src/platform/packages/shared/kbn-unified-data-table/src/utils/get_render_cell_value.tsx Use formatFieldValueReact and render react children.
src/platform/packages/shared/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx Update inline snapshots for React children rendering.
src/platform/packages/shared/kbn-unified-data-table/src/components/source_document.tsx Use formatHitReact and React rendering for source doc values.
src/platform/packages/shared/kbn-unified-data-table/src/components/compare_documents/hooks/use_comparison_cell_value.tsx Use formatFieldValueReact to avoid HTML injection.
src/platform/packages/shared/kbn-discover-utils/src/utils/get_formatted_fields.ts Add getFormattedFieldsReact.
src/platform/packages/shared/kbn-discover-utils/src/utils/format_value.ts Add formatFieldValueReact.
src/platform/packages/shared/kbn-discover-utils/src/utils/format_hit.ts Add formatHitReact + caching.
src/platform/packages/shared/kbn-discover-utils/src/types.ts Add FormattedHitReact type.
src/platform/packages/shared/kbn-discover-utils/src/index.ts Export FormattedFieldValue.
src/platform/packages/shared/kbn-discover-utils/src/components/formatted_field_value.tsx Add FormattedFieldValue React component wrapper.
src/platform/packages/shared/kbn-discover-utils/index.ts Re-export new React-formatting utilities + component.
packages/kbn-optimizer/limits.yml Update optimizer limits to reflect bundle size changes.

Comment on lines 237 to 239
static from(convertFn: FieldFormatConvertFunction): FieldFormatInstanceType {
return createCustomFieldFormat(convertFn);
return createCustomFieldFormat(convertFn as TextContextTypeConvert);
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FieldFormat.from still accepts FieldFormatConvertFunction (now includes html/react) but forces the implementation into TextContextTypeConvert via a cast. This is type-unsafe and can break callers that pass an html-only converter (or any non-text signature). Consider either (a) narrowing the from parameter type to TextContextTypeConvert explicitly, or (b) updating createCustomFieldFormat (and from) to properly support the full FieldFormatConvertFunction union, including react.

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +65
export function getFormattedFieldsReact<T extends Record<string, ReactNode>>(
doc: DataTableRecord,
fields: Array<keyof T>,
{ dataView, fieldFormats }: { dataView: DataView; fieldFormats: FieldFormatsStart }
): T {
const formatField = <K extends keyof T>(field: K) => {
const fieldStr = field as string;
return doc.flattened[fieldStr] !== undefined && doc.flattened[fieldStr] !== null
? (formatFieldValueReact(
doc.flattened[fieldStr],
doc.raw,
fieldFormats,
dataView,
dataView.fields.getByName(fieldStr)
) as T[K])
: undefined;
};

return fields.reduce<{ [key in keyof T]?: ReactNode }>((acc, field) => {
acc[field] = formatField(field);
return acc;
}, {}) as T;
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function can return undefined for missing fields (: undefined in formatField), but the generic constraint/return type is T extends Record<string, ReactNode> and ): T, which implies values are always present. This mismatch is currently hidden by casts and can leak undefined into places expecting a ReactNode. Suggest changing the signature to reflect optionality (e.g., T extends Record<string, ReactNode | undefined> and/or returning Partial<T>), and removing the final as T cast if possible.

Copilot uses AI. Check for mistakes.
Comment on lines 45 to +47
const messageCodeBlockProps = formattedValue
? { language: 'json', children: formattedValue }
: {
language: 'txt',
dangerouslySetInnerHTML: { __html: escapeAndPreserveHighlightTags(value ?? '') },
};
: { language: 'txt', children: value ?? '' };
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes the previous escapeAndPreserveHighlightTags(...) path. If value can contain highlight markup (e.g., <mark> tags or other formatting inserted upstream) and formattedValue is absent, this will now render the markup as literal text instead of preserving highlight behavior. If the UI still relies on highlight preservation here, consider adding a React equivalent to the old behavior (e.g., parsing known highlight markers into <mark> React nodes), or ensuring formattedValue is always provided when highlight markup is present.

Copilot uses AI. Check for mistakes.
Comment on lines +66 to 67
const doesContainImage = React.isValidElement(formattedValue) && formattedValue.type === 'img';

Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This image detection only works when the formatted output is a top-level <img />. With the new 'react' fallback, image-like HTML may be wrapped (e.g., <span dangerouslySetInnerHTML=...>), or an image may be nested under other elements (e.g., <a><img/></a>), causing doesContainImage to be false and breaking the image-preview path. Consider broadening detection to (1) inspect dangerouslySetInnerHTML.__html when the node is a wrapper element, and/or (2) recursively search children for an img element.

Suggested change
const doesContainImage = React.isValidElement(formattedValue) && formattedValue.type === 'img';
const containsImageNode = (node: unknown): boolean => {
if (!React.isValidElement(node)) {
return false;
}
if (node.type === 'img') {
return true;
}
const props: any = (node as any).props;
if (
props &&
props.dangerouslySetInnerHTML &&
typeof props.dangerouslySetInnerHTML.__html === 'string' &&
props.dangerouslySetInnerHTML.__html.includes('<img')
) {
return true;
}
if (props && props.children) {
return React.Children.toArray(props.children).some(containsImageNode);
}
return false;
};
const doesContainImage = containsImageNode(formattedValue);

Copilot uses AI. Check for mistakes.

interface Props {
imgHTML: string;
imgHTML: React.ReactNode;
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prop is now a ReactNode, but it is still named imgHTML, which implies a string of HTML. Renaming it to something like imgContent/imgNode would better reflect the new contract and avoid confusion at call sites.

Copilot uses AI. Check for mistakes.
Comment on lines +172 to +175
convert = (val: string, type?: FieldFormatsContentType) =>
this.convertTerms(val, type) as any;
getConverterFor = (type?: FieldFormatsContentType) => (val: string) =>
this.convertTerms(val, type) as any;
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new 'react' behavior forces convert/getConverterFor to use as any, which removes type safety for all callers of these aggs formats. Instead of casting, consider updating the relevant field-format wrapper or interface types so that 'react' is reflected in the return type (e.g., overloads similar to FieldFormat.convert), or splitting string-only vs React-capable code paths with explicit typing.

Copilot uses AI. Check for mistakes.
Comment on lines +45 to +56
const decodeHTMLEntities = (html: string): string => {
if (!HTML_ENTITY_RE.test(html)) {
return html;
}
return html
.replaceAll('&amp;', '&')
.replaceAll('&lt;', '<')
.replaceAll('&gt;', '>')
.replaceAll('&quot;', '"')
.replaceAll('&#39;', "'")
.replaceAll('&#x27;', "'");
};
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTML_ENTITY_RE matches any numeric or named entity, but decodeHTMLEntities only decodes a small hard-coded subset. This can lead to inconsistent output between legacy HTML rendering and the new React fallback for tag-free strings containing other entities (e.g., &#x2F;, &#8217;, &nbsp;). Consider using a more complete decoding approach for tag-free strings (e.g., a DOM-based decode in the browser, or a small well-audited entity decoder utility) so the React fallback matches existing HTML behavior more reliably.

Copilot uses AI. Check for mistakes.
Comment on lines +169 to +186
for (const key of Object.keys(flattened)) {
const field = dataView.fields.getByName(key);
const displayKey = field?.displayName;
const pairs = highlights[key] ? renderedPairs : otherPairs;

if (displayKey) {
const multiParent = field.getSubtypeMulti?.()?.multi.parent;
const isHighlighted = Boolean(highlights[key]);
const isParentHighlighted = Boolean(multiParent && highlights[multiParent]);

if ((isHighlighted && !isParentHighlighted) || shouldShowFieldHandler(key)) {
pairs.push([displayKey, undefined, key]);
}
} else {
pairs.push([key, undefined, key]);
}
}

Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within formatHitReact, the code looks up field metadata twice (dataView.fields.getByName(key) in the first loop, then dataView.getFieldByName(key) again when formatting). If these accessors differ in cost, this adds unnecessary overhead when rendering many rows. Consider carrying the resolved field through (e.g., store it alongside the pair) so the second loop can reuse it instead of performing another lookup.

Copilot uses AI. Check for mistakes.
Comment on lines +197 to +206
for (const pair of renderedPairs) {
const key = pair[2]!;
pair[1] = formatFieldValueReact(
flattened[key],
hit.raw,
fieldFormats,
dataView,
dataView.getFieldByName(key)
);
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within formatHitReact, the code looks up field metadata twice (dataView.fields.getByName(key) in the first loop, then dataView.getFieldByName(key) again when formatting). If these accessors differ in cost, this adds unnecessary overhead when rendering many rows. Consider carrying the resolved field through (e.g., store it alongside the pair) so the second loop can reuse it instead of performing another lookup.

Copilot uses AI. Check for mistakes.
@kertal
Copy link
Member Author

kertal commented Feb 25, 2026

/ci

@elasticmachine
Copy link
Contributor

elasticmachine commented Feb 25, 2026

💔 Build Failed

Failed CI Steps

Metrics [docs]

‼️ ERROR: no builds found for mergeBase sha [d6ae96d]

History

cc @kertal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants