Skip to content

Commit ab81783

Browse files
kibanamachinerbrtj
andauthored
[9.1] [ML] Anomalies Table: Restore focus to row actions menu (elastic#230918) (elastic#231567)
# Backport This will backport the following commits from `main` to `9.1`: - [[ML] Anomalies Table: Restore focus to row actions menu (elastic#230918)](elastic#230918) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Robert Jaszczurek","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-08-13T08:01:15Z","message":"[ML] Anomalies Table: Restore focus to row actions menu (elastic#230918)\n\nResolves https://github.com/elastic/kibana/issues/195016\n\nAfter the fix:\n\n\nhttps://github.com/user-attachments/assets/4b48b43c-9784-4475-84cb-146105e25f2c","sha":"1a227c46ad55657198a9db08819b66ddc938a9c5","branchLabelMapping":{"^v9.2.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Project:Accessibility",":ml","release_note:skip","Team:ML","backport:version","v9.2.0","v9.1.1"],"title":"[ML] Anomalies Table: Restore focus to row actions menu","number":230918,"url":"https://github.com/elastic/kibana/pull/230918","mergeCommit":{"message":"[ML] Anomalies Table: Restore focus to row actions menu (elastic#230918)\n\nResolves https://github.com/elastic/kibana/issues/195016\n\nAfter the fix:\n\n\nhttps://github.com/user-attachments/assets/4b48b43c-9784-4475-84cb-146105e25f2c","sha":"1a227c46ad55657198a9db08819b66ddc938a9c5"}},"sourceBranch":"main","suggestedTargetBranches":["9.1"],"targetPullRequestStates":[{"branch":"main","label":"v9.2.0","branchLabelMappingKey":"^v9.2.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/230918","number":230918,"mergeCommit":{"message":"[ML] Anomalies Table: Restore focus to row actions menu (elastic#230918)\n\nResolves https://github.com/elastic/kibana/issues/195016\n\nAfter the fix:\n\n\nhttps://github.com/user-attachments/assets/4b48b43c-9784-4475-84cb-146105e25f2c","sha":"1a227c46ad55657198a9db08819b66ddc938a9c5"}},{"branch":"9.1","label":"v9.1.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Robert Jaszczurek <[email protected]>
1 parent b45028d commit ab81783

File tree

6 files changed

+40
-8
lines changed

6 files changed

+40
-8
lines changed

x-pack/platform/packages/private/ml/ui_actions/src/aiops/ui_actions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* 2.0.
66
*/
77

8+
import type { EuiFlyoutProps } from '@elastic/eui';
89
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
910
import { i18n } from '@kbn/i18n';
1011
import type { Trigger } from '@kbn/ui-actions-plugin/public';
@@ -18,6 +19,7 @@ export interface CategorizeFieldContext {
1819
to: number;
1920
field?: { name: string; value: string };
2021
};
22+
focusTrapProps?: EuiFlyoutProps['focusTrapProps'];
2123
}
2224

2325
export const ACTION_CATEGORIZE_FIELD = 'ACTION_CATEGORIZE_FIELD';

x-pack/platform/plugins/shared/aiops/public/components/log_categorization/categorize_field_actions.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,16 @@ export const createCategorizeFieldAction = (coreStart: CoreStart, plugins: Aiops
2323
return field.esTypes?.includes('text') === true;
2424
},
2525
execute: async (context: CategorizeFieldContext) => {
26-
const { field, dataView, originatingApp, additionalFilter } = context;
26+
const { field, dataView, originatingApp, additionalFilter, focusTrapProps } = context;
2727
const { showCategorizeFlyout } = await import('./show_flyout');
28-
showCategorizeFlyout(field, dataView, coreStart, plugins, originatingApp, additionalFilter);
28+
showCategorizeFlyout(
29+
field,
30+
dataView,
31+
coreStart,
32+
plugins,
33+
originatingApp,
34+
additionalFilter,
35+
focusTrapProps
36+
);
2937
},
3038
});

x-pack/platform/plugins/shared/aiops/public/components/log_categorization/show_flyout.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { UI_SETTINGS } from '@kbn/data-plugin/public';
1919
import { DatePickerContextProvider, type DatePickerDependencies } from '@kbn/ml-date-picker';
2020
import { StorageContextProvider } from '@kbn/ml-local-storage';
2121
import type { CategorizationAdditionalFilter } from '@kbn/aiops-log-pattern-analysis/create_category_request';
22+
import type { EuiFlyoutProps } from '@elastic/eui';
2223
import type { AiopsPluginStartDeps } from '../../types';
2324
import { LogCategorizationFlyout } from './log_categorization_for_flyout';
2425
import { AiopsAppContext, type AiopsAppContextValue } from '../../hooks/use_aiops_app_context';
@@ -32,7 +33,8 @@ export async function showCategorizeFlyout(
3233
coreStart: CoreStart,
3334
plugins: AiopsPluginStartDeps,
3435
originatingApp: string,
35-
additionalFilter?: CategorizationAdditionalFilter
36+
additionalFilter?: CategorizationAdditionalFilter,
37+
focusTrapProps?: EuiFlyoutProps['focusTrapProps']
3638
): Promise<void> {
3739
const { overlays, application, i18n } = coreStart;
3840

@@ -91,6 +93,7 @@ export async function showCategorizeFlyout(
9193
closeButtonProps: { 'aria-label': 'aiopsCategorizeFlyout' },
9294
onClose: onFlyoutClose,
9395
size: 'l',
96+
focusTrapProps,
9497
}
9598
);
9699

x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/anomalies_table.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { AnomalyDetails } from './anomaly_details';
2626
import { mlTableService } from '../../services/table_service';
2727
import { getColumns } from './anomalies_table_columns';
2828
import { RuleEditorFlyout } from '../rule_editor';
29+
import type { FocusTrapProps } from '../../util/create_focus_trap_props';
2930

3031
interface AnomaliesTableProps {
3132
bounds?: TimeRangeBounds;
@@ -75,7 +76,7 @@ export const AnomaliesTable: FC<AnomaliesTableProps> = React.memo(
7576
}, [tableData]);
7677

7778
const [showRuleEditorFlyout, setShowRuleEditorFlyout] = useState<
78-
((anomaly: MlAnomaliesTableRecordExtended) => void) | null
79+
((anomaly: MlAnomaliesTableRecordExtended, focusTrapProps: FocusTrapProps) => void) | null
7980
>(null);
8081

8182
const {

x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/links_menu.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ import { useMlApi, useMlKibana } from '../../contexts/kibana';
6363
import { useMlIndexUtils } from '../../util/index_service';
6464

6565
import { getQueryStringForInfluencers } from './get_query_string_for_influencers';
66+
import type { FocusTrapProps } from '../../util/create_focus_trap_props';
67+
import { createFocusTrapProps } from '../../util/create_focus_trap_props';
6668

6769
const LOG_RATE_ANALYSIS_MARGIN_FACTOR = 20;
6870
const LOG_RATE_ANALYSIS_BASELINE_FACTOR = 15;
@@ -74,7 +76,7 @@ interface LinksMenuProps {
7476
showViewSeriesLink: boolean;
7577
isAggregatedData: boolean;
7678
interval: 'day' | 'hour' | 'second';
77-
showRuleEditorFlyout: (anomaly: MlAnomaliesTableRecord) => void;
79+
showRuleEditorFlyout: (anomaly: MlAnomaliesTableRecord, focusTrapProps: FocusTrapProps) => void;
7880
onItemClick: () => void;
7981
sourceIndicesWithGeoFields: SourceIndicesWithGeoFields;
8082
selectedJob?: MlJob;
@@ -99,6 +101,12 @@ export const LinksMenuUI = (props: LinksMenuProps) => {
99101
const isCategorizationAnomalyRecord = isCategorizationAnomaly(props.anomaly);
100102

101103
const closePopover = props.onItemClick;
104+
const focusTrapProps = useMemo(() => {
105+
const triggerElement = document.getElementById(
106+
`mlAnomaliesListRowActionsButton-${props.anomaly.rowId}`
107+
);
108+
return createFocusTrapProps(triggerElement);
109+
}, [props.anomaly.rowId]);
102110

103111
const kibana = useMlKibana();
104112
const {
@@ -917,7 +925,7 @@ export const LinksMenuUI = (props: LinksMenuProps) => {
917925
icon="controlsHorizontal"
918926
onClick={() => {
919927
closePopover();
920-
props.showRuleEditorFlyout(anomaly);
928+
props.showRuleEditorFlyout(anomaly, focusTrapProps);
921929
}}
922930
data-test-subj="mlAnomaliesListRowActionConfigureRulesButton"
923931
>
@@ -969,6 +977,7 @@ export const LinksMenuUI = (props: LinksMenuProps) => {
969977
}
970978
: {}),
971979
},
980+
focusTrapProps,
972981
});
973982
}}
974983
data-test-subj="mlAnomaliesListRowActionPatternAnalysisButton"
@@ -1017,6 +1026,7 @@ export const LinksMenu: FC<Omit<LinksMenuProps, 'onItemClick'>> = (props) => {
10171026
values: { time: formatHumanReadableDateTimeSeconds(props.anomaly.time) },
10181027
})}
10191028
data-test-subj="mlAnomaliesListRowActionsButton"
1029+
id={`mlAnomaliesListRowActionsButton-${props.anomaly.rowId}`}
10201030
/>
10211031
);
10221032

x-pack/platform/plugins/shared/ml/public/application/components/rule_editor/rule_editor_flyout.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class RuleEditorFlyoutUI extends Component {
7676
isScopeEnabled: false,
7777
filterListIds: [],
7878
isFlyoutVisible: false,
79+
focusTrapProps: {},
7980
};
8081

8182
this.partitioningFieldNames = [];
@@ -101,7 +102,7 @@ class RuleEditorFlyoutUI extends Component {
101102
}
102103
}
103104

104-
showFlyout = (anomaly) => {
105+
showFlyout = (anomaly, focusTrapProps) => {
105106
let ruleIndex = -1;
106107
const job = this.props.selectedJob ?? this.mlJobService.getJob(anomaly.jobId);
107108
if (job === undefined) {
@@ -147,6 +148,7 @@ class RuleEditorFlyoutUI extends Component {
147148
isConditionsEnabled,
148149
isScopeEnabled: false,
149150
isFlyoutVisible: true,
151+
focusTrapProps,
150152
});
151153

152154
if (this.partitioningFieldNames.length > 0 && this.canGetFilters) {
@@ -499,6 +501,7 @@ class RuleEditorFlyoutUI extends Component {
499501
filterListIds,
500502
isConditionsEnabled,
501503
isScopeEnabled,
504+
focusTrapProps,
502505
} = this.state;
503506

504507
if (isFlyoutVisible === false) {
@@ -509,7 +512,11 @@ class RuleEditorFlyoutUI extends Component {
509512

510513
if (ruleIndex === -1) {
511514
flyout = (
512-
<EuiFlyout onClose={this.closeFlyout} aria-labelledby="flyoutTitle">
515+
<EuiFlyout
516+
onClose={this.closeFlyout}
517+
aria-labelledby="flyoutTitle"
518+
focusTrapProps={focusTrapProps}
519+
>
513520
<EuiFlyoutHeader hasBorder={true}>
514521
<EuiTitle size="m">
515522
<h1 id="flyoutTitle">
@@ -569,6 +576,7 @@ class RuleEditorFlyoutUI extends Component {
569576
data-test-subj="mlRuleEditorFlyout"
570577
onClose={this.closeFlyout}
571578
aria-labelledby="flyoutTitle"
579+
focusTrapProps={focusTrapProps}
572580
>
573581
<EuiFlyoutHeader hasBorder={true}>
574582
<EuiTitle size="m">

0 commit comments

Comments
 (0)