Skip to content

Commit 9bd021b

Browse files
authored
[UiSettings] Add technical preview badge configuration for advance settings (#225620)
## 📓 Summary From the o11y team, we wanted to have a technical preview badge available next to our new advanced settings. Historically, new settings in technical preview have been created added some custom text in the description, which is not much highlighted. To align with the design definition and make this available to every solution, a new `technicalPreview` option is available when configuring a setting now: ```ts type TechnicalPreviewSettings = | boolean | { /** Technical Preview custom message */ message?: string; /** Key to documentation links */ docLinksKey?: string; }; interface UISettingsParams { // ... /** A flag indicating that this setting is a technical preview. If true, the setting will display a tech preview badge after the title. */ technicalPreview?: TechnicalPreviewSettings; } ``` This has been applied to most of the detected settings in technical preview. <img width="3005" alt="Screenshot 2025-06-27 at 13 12 00" src="https://github.com/user-attachments/assets/5e8a4770-3926-4017-acb7-30cd05db6eab" />
1 parent 0723ee9 commit 9bd021b

File tree

19 files changed

+170
-92
lines changed

19 files changed

+170
-92
lines changed

src/core/packages/ui-settings/common/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export type {
1616
UserProvidedValues,
1717
UiSettingsScope,
1818
GetUiSettingsContext,
19+
TechnicalPreviewSettings,
1920
} from './src/ui_settings';
2021
export { type DarkModeValue, parseDarkModeValue } from './src/dark_mode';
2122
export {

src/core/packages/ui-settings/common/src/ui_settings.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ export interface DeprecationSettings {
4646
docLinksKey: string;
4747
}
4848

49+
/**
50+
* Type for the technical preview settings.
51+
* @public
52+
* */
53+
export type TechnicalPreviewSettings =
54+
| boolean
55+
| {
56+
/** Technical Preview message */
57+
message?: string;
58+
/** Key to documentation links */
59+
docLinksKey?: string;
60+
};
61+
4962
export interface GetUiSettingsContext {
5063
request?: KibanaRequest;
5164
}
@@ -86,6 +99,8 @@ export interface UiSettingsParams<T = unknown> {
8699
type?: UiSettingsType;
87100
/** optional deprecation information. Used to generate a deprecation warning. */
88101
deprecation?: DeprecationSettings;
102+
/** A flag indicating that this setting is a technical preview. If true, the setting will display a tech preview badge after the title. */
103+
technicalPreview?: TechnicalPreviewSettings;
89104
/**
90105
* index of the settings within its category (ascending order, smallest will be displayed first).
91106
* Used for ordering in the UI.

src/platform/packages/shared/kbn-management/settings/components/field_row/field_row.test.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,42 @@ describe('Field', () => {
329329
expect(getByText('Custom setting')).toBeInTheDocument();
330330
});
331331

332+
it('should render technical preview badge if it is technical preview', () => {
333+
const { getByText } = render(
334+
wrap(
335+
<FieldRow
336+
field={getFieldDefinition({
337+
id,
338+
setting: { ...setting, technicalPreview: true },
339+
params: { isCustom: true },
340+
})}
341+
onFieldChange={handleChange}
342+
isSavingEnabled={true}
343+
/>
344+
)
345+
);
346+
347+
expect(getByText('Technical preview')).toBeInTheDocument();
348+
});
349+
350+
it('should NOT render technical preview badge if the technicalPreview is false or unspecified', () => {
351+
const { queryByText } = render(
352+
wrap(
353+
<FieldRow
354+
field={getFieldDefinition({
355+
id,
356+
setting,
357+
params: { isCustom: true },
358+
})}
359+
onFieldChange={handleChange}
360+
isSavingEnabled={true}
361+
/>
362+
)
363+
);
364+
365+
expect(queryByText('Technical preview')).not.toBeInTheDocument();
366+
});
367+
332368
it('should render unsaved value if there are unsaved changes', () => {
333369
const { getByTestId, getByAltText } = render(
334370
wrap(

src/platform/packages/shared/kbn-management/settings/components/field_row/field_row.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type Definition<T extends SettingType = SettingType> = Pick<
5050
| 'name'
5151
| 'savedValue'
5252
| 'type'
53+
| 'technicalPreview'
5354
| 'unsavedFieldId'
5455
>;
5556

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
import React from 'react';
11+
12+
import { EuiBetaBadge, EuiBetaBadgeProps } from '@elastic/eui';
13+
import { i18n } from '@kbn/i18n';
14+
15+
import { FieldDefinition, SettingType } from '@kbn/management-settings-types';
16+
import { isBoolean } from 'lodash';
17+
18+
/**
19+
* Props for a {@link FieldTitle} component.
20+
*/
21+
export interface TechnicalPreviewBadgeProps<T extends SettingType> {
22+
/** The {@link FieldDefinition} corresponding the setting. */
23+
field: Pick<FieldDefinition<T>, 'technicalPreview'>;
24+
}
25+
26+
const defaultLabel = i18n.translate('management.settings.field.technicalPreviewLabel', {
27+
defaultMessage: 'Technical preview',
28+
});
29+
30+
const defaultTooltip = i18n.translate('management.settings.technicalPreviewDefaultTooltip', {
31+
defaultMessage:
32+
'This functionality is in technical preview. It may change or be removed in a future release.',
33+
});
34+
35+
const badgeBaseProps: Pick<EuiBetaBadgeProps, 'alignment' | 'label' | 'size'> = {
36+
alignment: 'middle',
37+
label: defaultLabel,
38+
size: 's',
39+
};
40+
41+
/**
42+
*
43+
*/
44+
export const FieldTitleTechnicalPreviewBadge = <T extends SettingType>({
45+
field,
46+
}: TechnicalPreviewBadgeProps<T>) => {
47+
if (!field.technicalPreview) {
48+
return null;
49+
}
50+
51+
if (isBoolean(field.technicalPreview)) {
52+
return <EuiBetaBadge {...badgeBaseProps} tooltipContent={defaultTooltip} />;
53+
}
54+
55+
if (!field.technicalPreview.docLinksKey) {
56+
return (
57+
<EuiBetaBadge
58+
{...badgeBaseProps}
59+
tooltipContent={field.technicalPreview.message || defaultTooltip}
60+
/>
61+
);
62+
}
63+
64+
return (
65+
<EuiBetaBadge
66+
{...badgeBaseProps}
67+
tooltipContent={field.technicalPreview.message || defaultTooltip}
68+
href={field.technicalPreview.docLinksKey}
69+
target="_blank"
70+
/>
71+
);
72+
};

src/platform/packages/shared/kbn-management/settings/components/field_row/title/title.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { FieldDefinition, UnsavedFieldChange, SettingType } from '@kbn/managemen
1717
import { useFieldStyles } from '../field_row.styles';
1818
import { FieldTitleCustomIcon } from './icon_custom';
1919
import { FieldTitleUnsavedIcon } from './icon_unsaved';
20+
import { FieldTitleTechnicalPreviewBadge } from './technical_preview_badge';
2021

2122
/**
2223
* Props for a {@link FieldTitle} component.
@@ -25,7 +26,7 @@ export interface TitleProps<T extends SettingType> {
2526
/** The {@link FieldDefinition} corresponding the setting. */
2627
field: Pick<
2728
FieldDefinition<T>,
28-
'displayName' | 'savedValue' | 'isCustom' | 'id' | 'type' | 'isOverridden'
29+
'displayName' | 'savedValue' | 'isCustom' | 'id' | 'type' | 'isOverridden' | 'technicalPreview'
2930
>;
3031
/** Emotion-based `css` for the root React element. */
3132
css?: Interpolation<Theme>;
@@ -50,16 +51,13 @@ export const FieldTitle = <T extends SettingType>({
5051
});
5152

5253
return (
53-
<EuiFlexGroup gutterSize="xs" alignItems="center">
54+
<EuiFlexGroup gutterSize="s" alignItems="center">
5455
<EuiFlexItem grow={false} css={cssFieldTitle}>
5556
<h3 {...props}>{field.displayName}</h3>
5657
</EuiFlexItem>
57-
<EuiFlexItem grow={false}>
58-
<FieldTitleCustomIcon {...{ field }} />
59-
</EuiFlexItem>
60-
<EuiFlexItem grow={false}>
61-
<FieldTitleUnsavedIcon {...{ field, unsavedChange }} />
62-
</EuiFlexItem>
58+
<FieldTitleTechnicalPreviewBadge {...{ field }} />
59+
<FieldTitleCustomIcon {...{ field }} />
60+
<FieldTitleUnsavedIcon {...{ field, unsavedChange }} />
6361
</EuiFlexGroup>
6462
);
6563
};

src/platform/packages/shared/kbn-management/settings/field_definition/get_definition.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export const getFieldDefinition = <T extends SettingType>(
103103
userValue: savedValue,
104104
value: defaultValue,
105105
solution,
106+
technicalPreview,
106107
} = setting;
107108

108109
const { isCustom, isOverridden } = params;
@@ -146,6 +147,7 @@ export const getFieldDefinition = <T extends SettingType>(
146147
type,
147148
unsavedFieldId: `${id}-unsaved`,
148149
solution,
150+
technicalPreview,
149151
};
150152

151153
// TODO: clintandrewhall - add validation (e.g. `select` contains non-empty `options`)

src/platform/packages/shared/kbn-management/settings/types/field_definition.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010
import { ReactElement } from 'react';
1111

1212
import { UiCounterMetricType } from '@kbn/analytics';
13-
import { DeprecationSettings, UiSettingsSolution } from '@kbn/core-ui-settings-common';
13+
import {
14+
DeprecationSettings,
15+
TechnicalPreviewSettings,
16+
UiSettingsSolution,
17+
} from '@kbn/core-ui-settings-common';
1418

1519
import { KnownTypeToValue, SettingType } from './setting_type';
1620

@@ -93,6 +97,11 @@ export interface FieldDefinition<
9397
* @see {@link UiSettingsSolution}
9498
*/
9599
solution?: UiSettingsSolution;
100+
/**
101+
* Technical preview information for the field
102+
* @see {@link TechnicalPreviewSettings}
103+
*/
104+
technicalPreview?: TechnicalPreviewSettings;
96105
}
97106

98107
/**

src/platform/plugins/shared/ai_assistant_management/selection/server/plugin.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,7 @@ export class AIAssistantManagementSelectionPlugin
5858
'aiAssistantManagementSelection.preferredAIAssistantTypeSettingDescription',
5959
{
6060
defaultMessage:
61-
'<em>[technical preview]</em> Whether to show the AI Assistant menu item in Observability and Search, everywhere, or nowhere.',
62-
values: {
63-
em: (chunks) => `<em>${chunks}</em>`,
64-
},
61+
'Whether to show the AI Assistant menu item in Observability and Search, everywhere, or nowhere.',
6562
}
6663
),
6764
schema: schema.oneOf(
@@ -90,6 +87,7 @@ export class AIAssistantManagementSelectionPlugin
9087
},
9188
requiresPageReload: true,
9289
solution: 'oblt',
90+
technicalPreview: true,
9391
},
9492
});
9593

src/platform/plugins/shared/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)