Merge pull request #3001 from github/koesie10/validation-errors-focus

Add higlight on modeled method row when clicking in validation error
This commit is contained in:
Koen Vlaswinkel
2023-10-23 13:17:59 +02:00
committed by GitHub
2 changed files with 56 additions and 5 deletions

View File

@@ -1,4 +1,5 @@
import * as React from "react";
import { useCallback, useEffect, useState } from "react";
import { Meta, StoryFn } from "@storybook/react";
@@ -20,12 +21,33 @@ export default {
} as Meta<typeof MethodRowComponent>;
const Template: StoryFn<typeof MethodRowComponent> = (args) => {
const [modeledMethods, setModeledMethods] = useState<ModeledMethod[]>(
args.modeledMethods,
);
useEffect(() => {
setModeledMethods(args.modeledMethods);
}, [args.modeledMethods]);
const handleChange = useCallback(
(methodSignature: string, modeledMethods: ModeledMethod[]) => {
args.onChange(methodSignature, modeledMethods);
setModeledMethods(modeledMethods);
},
[args],
);
const gridTemplateColumns = args.viewState?.showMultipleModels
? MULTIPLE_MODELS_GRID_TEMPLATE_COLUMNS
: SINGLE_MODEL_GRID_TEMPLATE_COLUMNS;
return (
<DataGrid gridTemplateColumns={gridTemplateColumns}>
<MethodRowComponent {...args} />
<MethodRowComponent
{...args}
modeledMethods={modeledMethods}
onChange={handleChange}
/>
</DataGrid>
);
};

View File

@@ -5,12 +5,12 @@ import {
} from "@vscode/webview-ui-toolkit/react";
import * as React from "react";
import {
Fragment,
forwardRef,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { styled } from "styled-components";
import { vscode } from "../vscode-api";
@@ -108,6 +108,32 @@ const ModelableMethodRow = forwardRef<HTMLElement | undefined, MethodRowProps>(
onChange,
} = props;
const [focusedIndex, setFocusedIndex] = useState<number | null>(null);
useEffect(() => {
if (focusedIndex === null) {
return;
}
// If a row is focused, hide it when the user clicks anywhere. In this case, we do need to
// show the user where the method is anymore and they should have seen it.
const listener = () => {
setFocusedIndex(null);
};
// Use a timeout to ensure the click event is not triggered by the click that focused the row.
const timeoutId = setTimeout(
() => window.addEventListener("click", listener),
200,
);
return () => {
clearTimeout(timeoutId);
window.removeEventListener("click", listener);
};
}, [focusedIndex]);
const modeledMethods = useMemo(
() => modeledMethodsToDisplay(modeledMethodsProp, method, viewState),
[modeledMethodsProp, method, viewState],
@@ -212,7 +238,7 @@ const ModelableMethodRow = forwardRef<HTMLElement | undefined, MethodRowProps>(
{!props.modelingInProgress && (
<>
{modeledMethods.map((modeledMethod, index) => (
<Fragment key={index}>
<DataGridRow key={index} focused={focusedIndex === index}>
<DataGridCell>
<ModelTypeDropdown
method={method}
@@ -263,11 +289,14 @@ const ModelableMethodRow = forwardRef<HTMLElement | undefined, MethodRowProps>(
)}
</DataGridCell>
)}
</Fragment>
</DataGridRow>
))}
{validationErrors.map((error, index) => (
<DataGridCell gridColumn="span 5" key={index}>
<ModeledMethodAlert error={error} />
<ModeledMethodAlert
error={error}
setSelectedIndex={setFocusedIndex}
/>
</DataGridCell>
))}
</>