diff --git a/.storybook/main.js b/.storybook/main.js
index f4d46fb062f7be4054f52bd4b9a3ca3fec0efb79..2211f3f0f8745ae6448c3143f0f2d89077fae009 100644
--- a/.storybook/main.js
+++ b/.storybook/main.js
@@ -21,6 +21,7 @@ module.exports = {
     resolve: {
       ...storybookConfig.resolve,
       alias: appConfig.resolve.alias,
+      extensions: appConfig.resolve.extensions,
     },
   }),
 };
diff --git a/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.jsx b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.jsx
deleted file mode 100644
index eec2dda0e4f883286298f16080a96e7d89f427d8..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.jsx
+++ /dev/null
@@ -1,217 +0,0 @@
-import React, { useCallback, useMemo, useState } from "react";
-import PropTypes from "prop-types";
-import { jt, t } from "ttag";
-import { getEngineLogo } from "metabase/lib/engine";
-import Settings from "metabase/lib/settings";
-import TextInput from "metabase/components/TextInput";
-import ExternalLink from "metabase/core/components/ExternalLink";
-import {
-  EngineCardIcon,
-  EngineCardImage,
-  EngineCardRoot,
-  EngineCardTitle,
-  EngineEmptyIcon,
-  EngineEmptyStateRoot,
-  EngineEmptyText,
-  EngineExpandButton,
-  EngineInfoIcon,
-  EngineInfoRoot,
-  EngineInfoTitle,
-  EngineListRoot,
-  EngineSearchRoot,
-} from "./EngineWidget.styled";
-
-const DEFAULT_OPTIONS_COUNT = 6;
-
-const EngineWidget = ({ field, options, isHosted }) => {
-  if (field.value) {
-    return <EngineInfo field={field} options={options} />;
-  } else {
-    return <EngineSearch field={field} options={options} isHosted={isHosted} />;
-  }
-};
-
-EngineWidget.propTypes = {
-  field: PropTypes.object.isRequired,
-  options: PropTypes.array.isRequired,
-  isHosted: PropTypes.bool,
-};
-
-const EngineInfo = ({ field, options }) => {
-  const option = options.find(option => option.value === field.value);
-
-  const handleClick = useCallback(() => {
-    field.onChange(undefined);
-  }, [field]);
-
-  return (
-    <EngineInfoRoot>
-      <EngineInfoTitle>{option ? option.name : field.value}</EngineInfoTitle>
-      <EngineInfoIcon
-        name="close"
-        size={18}
-        aria-label={t`Remove database`}
-        onClick={handleClick}
-      />
-    </EngineInfoRoot>
-  );
-};
-
-EngineInfo.propTypes = {
-  field: PropTypes.object.isRequired,
-  options: PropTypes.array.isRequired,
-};
-
-const EngineSearch = ({ field, options, isHosted }) => {
-  const [searchText, setSearchText] = useState("");
-  const [isExpanded, setIsExpanded] = useState(false);
-  const isSearching = searchText.length > 0;
-  const hasMoreOptions = options.length > DEFAULT_OPTIONS_COUNT;
-
-  const sortedOptions = useMemo(() => {
-    return getSortedOptions(options);
-  }, [options]);
-
-  const visibleOptions = useMemo(
-    () => getVisibleOptions(sortedOptions, isExpanded, isSearching, searchText),
-    [sortedOptions, isExpanded, isSearching, searchText],
-  );
-
-  return (
-    <EngineSearchRoot>
-      <TextInput
-        value={searchText}
-        placeholder={t`Search for a database…`}
-        onChange={setSearchText}
-      />
-      {visibleOptions.length ? (
-        <EngineList field={field} options={visibleOptions} />
-      ) : (
-        <EngineEmptyState isHosted={isHosted} />
-      )}
-      {!isSearching && hasMoreOptions && (
-        <EngineToggle
-          isExpanded={isExpanded}
-          onExpandedChange={setIsExpanded}
-        />
-      )}
-    </EngineSearchRoot>
-  );
-};
-
-EngineSearch.propTypes = {
-  field: PropTypes.object.isRequired,
-  options: PropTypes.array.isRequired,
-  isHosted: PropTypes.bool,
-};
-
-const EngineList = ({ field, options }) => {
-  return (
-    <EngineListRoot>
-      {options.map(option => (
-        <EngineCard key={option.value} field={field} option={option} />
-      ))}
-    </EngineListRoot>
-  );
-};
-
-EngineList.propTypes = {
-  field: PropTypes.object,
-  options: PropTypes.array,
-};
-
-const EngineCard = ({ field, option }) => {
-  const logo = getEngineLogo(option.value);
-
-  const handleClick = useCallback(() => {
-    field.onChange(option.value);
-  }, [field, option]);
-
-  return (
-    <EngineCardRoot key={option.value} onClick={handleClick}>
-      {logo ? (
-        <EngineCardImage src={logo} />
-      ) : (
-        <EngineCardIcon name="database" />
-      )}
-      <EngineCardTitle>{option.name}</EngineCardTitle>
-    </EngineCardRoot>
-  );
-};
-
-EngineCard.propTypes = {
-  field: PropTypes.object,
-  option: PropTypes.object,
-};
-
-const EngineEmptyState = ({ isHosted }) => {
-  return (
-    <EngineEmptyStateRoot>
-      <EngineEmptyIcon name="search" size={32} />
-      {isHosted ? (
-        <EngineEmptyText>{t`Didn’t find anything`}</EngineEmptyText>
-      ) : (
-        <EngineEmptyText>{jt`Don’t see your database? Check out our ${(
-          <ExternalLink href={Settings.docsUrl("developers-guide-drivers")}>
-            {t`Community Drivers`}
-          </ExternalLink>
-        )} page to see if it’s available for self-hosting.`}</EngineEmptyText>
-      )}
-    </EngineEmptyStateRoot>
-  );
-};
-
-EngineEmptyState.propTypes = {
-  isHosted: PropTypes.bool,
-};
-
-const EngineToggle = ({ isExpanded, onExpandedChange }) => {
-  const handleClick = useCallback(() => {
-    onExpandedChange(!isExpanded);
-  }, [isExpanded, onExpandedChange]);
-
-  return (
-    <EngineExpandButton
-      primary
-      iconRight={isExpanded ? "chevronup" : "chevrondown"}
-      onClick={handleClick}
-    >
-      {isExpanded ? t`Show less options` : t`Show more options`}
-    </EngineExpandButton>
-  );
-};
-
-EngineToggle.propTypes = {
-  isExpanded: PropTypes.bool,
-  onExpandedChange: PropTypes.func,
-};
-
-const getSortedOptions = options => {
-  return options.sort((a, b) => {
-    if (a.index >= 0 && b.index >= 0) {
-      return a.index - b.index;
-    } else if (a.index >= 0) {
-      return -1;
-    } else if (b.index >= 0) {
-      return 1;
-    } else {
-      return a.name.localeCompare(b.name);
-    }
-  });
-};
-
-const getVisibleOptions = (options, isExpanded, isSearching, searchText) => {
-  if (isSearching) {
-    return options.filter(e => includesIgnoreCase(e.name, searchText));
-  } else if (isExpanded) {
-    return options;
-  } else {
-    return options.slice(0, DEFAULT_OPTIONS_COUNT);
-  }
-};
-
-const includesIgnoreCase = (sourceText, searchText) => {
-  return sourceText.toLowerCase().includes(searchText.toLowerCase());
-};
-
-export default EngineWidget;
diff --git a/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.styled.jsx b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.styled.tsx
similarity index 65%
rename from frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.styled.jsx
rename to frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.styled.tsx
index 78af41a3191f201bc94506d95c0f5f13e04354eb..e01a2170e82c9c6eb8ccffdfcda73521583059ae 100644
--- a/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.styled.jsx
+++ b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.styled.tsx
@@ -1,15 +1,14 @@
 import styled from "styled-components";
 import { color, lighten } from "metabase/lib/colors";
 import { breakpointMinSmall } from "metabase/styled-components/theme";
-import Icon from "metabase/components/Icon";
-import IconButtonWrapper from "metabase/components/IconButtonWrapper";
 import Button from "metabase/core/components/Button";
+import Icon from "metabase/components/Icon";
 
 export const EngineSearchRoot = styled.div`
   display: block;
 `;
 
-export const EngineListRoot = styled.div`
+export const EngineListRoot = styled.ul`
   display: grid;
   grid-template-columns: 1fr;
   gap: 1.5rem;
@@ -20,13 +19,24 @@ export const EngineListRoot = styled.div`
   }
 `;
 
-export const EngineCardRoot = styled(IconButtonWrapper)`
+export interface EngineCardRootProps {
+  isActive: boolean;
+}
+
+export const EngineCardRoot = styled.li<EngineCardRootProps>`
+  display: flex;
   flex: 1 1 auto;
   flex-direction: column;
+  align-items: center;
+  justify-content: center;
   height: 5.375rem;
   padding: 1rem;
   border: 1px solid ${color("bg-medium")};
+  border-radius: 0.375rem;
   background-color: ${color("white")};
+  cursor: pointer;
+  outline: ${props =>
+    props.isActive ? `2px solid ${color("brand-light")}` : ""};
 
   &:hover {
     border-color: ${color("brand")};
@@ -73,26 +83,44 @@ export const EngineEmptyText = styled.div`
   text-align: center;
 `;
 
-export const EngineExpandButton = styled(Button)`
-  width: 100%;
-`;
-
-export const EngineInfoRoot = styled.div`
+export const EngineButtonRoot = styled.button`
   display: flex;
+  justify-content: space-between;
   align-items: center;
   color: ${color("white")};
+  width: 100%;
   padding: 0.75rem;
   border-radius: 0.5rem;
   border: 1px solid ${color("brand")};
   background-color: ${color("brand")};
+  transition: all 200ms linear;
+  transition-property: color, background-color;
+  cursor: pointer;
+
+  &:hover {
+    color: ${color("white")};
+    background-color: ${lighten("brand", 0.12)};
+  }
+
+  &:focus {
+    outline: 2px solid ${color("brand-light")};
+  }
+
+  &:focus:not(:focus-visible) {
+    outline: none;
+  }
 `;
 
-export const EngineInfoTitle = styled.div`
-  flex: 1 0 auto;
+export const EngineButtonTitle = styled.span`
+  flex: 0 1 auto;
   font-size: 1rem;
   font-weight: bold;
 `;
 
-export const EngineInfoIcon = styled(Icon)`
+export const EngineButtonIcon = styled(Icon)`
   cursor: pointer;
 `;
+
+export const EngineToggleRoot = styled(Button)`
+  width: 100%;
+`;
diff --git a/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.tsx b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6d55501ff1da002a62a96c5a4c5c77675408c6ee
--- /dev/null
+++ b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.tsx
@@ -0,0 +1,339 @@
+import React, { KeyboardEvent, useCallback, useMemo, useState } from "react";
+import { jt, t } from "ttag";
+import _ from "underscore";
+import { getEngineLogo } from "metabase/lib/engine";
+import Settings from "metabase/lib/settings";
+import TextInput from "metabase/components/TextInput";
+import ExternalLink from "metabase/core/components/ExternalLink";
+import {
+  EngineButtonIcon,
+  EngineButtonRoot,
+  EngineButtonTitle,
+  EngineCardIcon,
+  EngineCardImage,
+  EngineCardRoot,
+  EngineCardTitle,
+  EngineEmptyIcon,
+  EngineEmptyStateRoot,
+  EngineEmptyText,
+  EngineListRoot,
+  EngineSearchRoot,
+  EngineToggleRoot,
+} from "./EngineWidget.styled";
+import { EngineField, EngineOption } from "./types";
+
+const DEFAULT_OPTIONS_COUNT = 6;
+
+export interface EngineWidget {
+  field: EngineField;
+  options: EngineOption[];
+  isHosted?: boolean;
+}
+
+const EngineWidget = ({
+  field,
+  options,
+  isHosted,
+}: EngineWidget): JSX.Element => {
+  if (field.value) {
+    return <EngineButton field={field} options={options} />;
+  } else {
+    return <EngineSearch field={field} options={options} isHosted={isHosted} />;
+  }
+};
+
+interface EngineButtonProps {
+  field: EngineField;
+  options: EngineOption[];
+}
+
+const EngineButton = ({ field, options }: EngineButtonProps): JSX.Element => {
+  const option = options.find(option => option.value === field.value);
+
+  const handleClick = useCallback(() => {
+    field.onChange?.(undefined);
+  }, [field]);
+
+  return (
+    <EngineButtonRoot autoFocus onClick={handleClick}>
+      <EngineButtonTitle>
+        {option ? option.name : field.value}
+      </EngineButtonTitle>
+      <EngineButtonIcon
+        name="close"
+        size={18}
+        aria-label={t`Remove database`}
+      />
+    </EngineButtonRoot>
+  );
+};
+
+interface EngineSearchProps {
+  field: EngineField;
+  options: EngineOption[];
+  isHosted?: boolean;
+}
+
+const EngineSearch = ({
+  field,
+  options,
+  isHosted,
+}: EngineSearchProps): JSX.Element => {
+  const rootId = useMemo(() => _.uniqueId(), []);
+  const [searchText, setSearchText] = useState("");
+  const [activeIndex, setActiveIndex] = useState<number>();
+  const [isExpanded, setIsExpanded] = useState(false);
+  const isSearching = searchText.length > 0;
+  const isNavigating = activeIndex != null;
+  const hasMoreOptions = options.length > DEFAULT_OPTIONS_COUNT;
+
+  const sortedOptions = useMemo(() => {
+    return getSortedOptions(options);
+  }, [options]);
+
+  const visibleOptions = useMemo(
+    () => getVisibleOptions(sortedOptions, isExpanded, isSearching, searchText),
+    [sortedOptions, isExpanded, isSearching, searchText],
+  );
+
+  const optionCount = visibleOptions.length;
+  const activeOption = isNavigating ? visibleOptions[activeIndex] : undefined;
+
+  const handleSearch = useCallback((value: string) => {
+    setSearchText(value);
+    setActiveIndex(undefined);
+  }, []);
+
+  const handleKeyDown = useCallback(
+    (event: KeyboardEvent) => {
+      switch (event.key) {
+        case "Enter":
+          activeOption && field.onChange?.(activeOption.value);
+          event.preventDefault();
+          break;
+        case "ArrowUp":
+        case "ArrowDown":
+          setIsExpanded(true);
+          setActiveIndex(getActiveIndex(event.key, activeIndex, optionCount));
+          event.preventDefault();
+          break;
+      }
+    },
+    [field, activeIndex, activeOption, optionCount],
+  );
+
+  return (
+    <EngineSearchRoot role="combobox" aria-expanded="true">
+      <TextInput
+        value={searchText}
+        placeholder={t`Search for a database…`}
+        autoFocus
+        aria-autocomplete="list"
+        aria-controls={getListBoxId(rootId)}
+        aria-activedescendant={getListOptionId(rootId, activeOption)}
+        onChange={handleSearch}
+        onKeyDown={handleKeyDown}
+      />
+      {visibleOptions.length ? (
+        <EngineList
+          rootId={rootId}
+          options={visibleOptions}
+          activeIndex={activeIndex}
+          onOptionChange={field.onChange}
+        />
+      ) : (
+        <EngineEmptyState isHosted={isHosted} />
+      )}
+      {!isSearching && hasMoreOptions && (
+        <EngineToggle
+          isExpanded={isExpanded}
+          onExpandedChange={setIsExpanded}
+        />
+      )}
+    </EngineSearchRoot>
+  );
+};
+
+interface EngineListProps {
+  rootId: string;
+  options: EngineOption[];
+  activeIndex?: number;
+  onOptionChange?: (value: string) => void;
+}
+
+const EngineList = ({
+  rootId,
+  options,
+  activeIndex,
+  onOptionChange,
+}: EngineListProps): JSX.Element => {
+  return (
+    <EngineListRoot role="listbox" id={getListBoxId(rootId)}>
+      {options.map((option, optionIndex) => (
+        <EngineCard
+          key={option.value}
+          rootId={rootId}
+          option={option}
+          isActive={optionIndex === activeIndex}
+          onOptionChange={onOptionChange}
+        />
+      ))}
+    </EngineListRoot>
+  );
+};
+
+export interface EngineCardProps {
+  rootId: string;
+  option: EngineOption;
+  isActive: boolean;
+  onOptionChange?: (value: string) => void;
+}
+
+const EngineCard = ({
+  rootId,
+  option,
+  isActive,
+  onOptionChange,
+}: EngineCardProps): JSX.Element => {
+  const logo = getEngineLogo(option.value);
+
+  const handleClick = useCallback(() => {
+    onOptionChange?.(option.value);
+  }, [option, onOptionChange]);
+
+  return (
+    <EngineCardRoot
+      role="option"
+      id={getListOptionId(rootId, option)}
+      isActive={isActive}
+      onClick={handleClick}
+    >
+      {logo ? (
+        <EngineCardImage src={logo} />
+      ) : (
+        <EngineCardIcon name="database" />
+      )}
+      <EngineCardTitle>{option.name}</EngineCardTitle>
+    </EngineCardRoot>
+  );
+};
+
+interface EngineEmptyStateProps {
+  isHosted?: boolean;
+}
+
+const EngineEmptyState = ({ isHosted }: EngineEmptyStateProps): JSX.Element => {
+  return (
+    <EngineEmptyStateRoot>
+      <EngineEmptyIcon name="search" size={32} />
+      {isHosted ? (
+        <EngineEmptyText>{t`Didn’t find anything`}</EngineEmptyText>
+      ) : (
+        <EngineEmptyText>{jt`Don’t see your database? Check out our ${(
+          <ExternalLink
+            key="link"
+            href={Settings.docsUrl("developers-guide-drivers")}
+          >
+            {t`Community Drivers`}
+          </ExternalLink>
+        )} page to see if it’s available for self-hosting.`}</EngineEmptyText>
+      )}
+    </EngineEmptyStateRoot>
+  );
+};
+
+interface EngineToggleProps {
+  isExpanded: boolean;
+  onExpandedChange: (isExpanded: boolean) => void;
+}
+
+const EngineToggle = ({
+  isExpanded,
+  onExpandedChange,
+}: EngineToggleProps): JSX.Element => {
+  const handleClick = useCallback(() => {
+    onExpandedChange(!isExpanded);
+  }, [isExpanded, onExpandedChange]);
+
+  return (
+    <EngineToggleRoot
+      primary
+      iconRight={isExpanded ? "chevronup" : "chevrondown"}
+      onClick={handleClick}
+    >
+      {isExpanded ? t`Show fewer options` : t`Show more options`}
+    </EngineToggleRoot>
+  );
+};
+
+const getSortedOptions = (options: EngineOption[]): EngineOption[] => {
+  return options.sort((a, b) => {
+    if (a.index >= 0 && b.index >= 0) {
+      return a.index - b.index;
+    } else if (a.index >= 0) {
+      return -1;
+    } else if (b.index >= 0) {
+      return 1;
+    } else {
+      return a.name.localeCompare(b.name);
+    }
+  });
+};
+
+const getVisibleOptions = (
+  options: EngineOption[],
+  isExpanded: boolean,
+  isSearching: boolean,
+  searchText: string,
+): EngineOption[] => {
+  if (isSearching) {
+    return options.filter(e => includesIgnoreCase(e.name, searchText));
+  } else if (isExpanded) {
+    return options;
+  } else {
+    return options.slice(0, DEFAULT_OPTIONS_COUNT);
+  }
+};
+
+const includesIgnoreCase = (
+  sourceText: string,
+  searchText: string,
+): boolean => {
+  return sourceText.toLowerCase().includes(searchText.toLowerCase());
+};
+
+const getListBoxId = (rootId: string): string => {
+  return `${rootId}-listbox`;
+};
+
+const getListOptionId = (
+  rootId: string,
+  option?: EngineOption,
+): string | undefined => {
+  return option ? `${rootId}-option-${option.value}` : undefined;
+};
+
+const getActiveIndex = (
+  key: string,
+  activeIndex: number | undefined,
+  optionCount: number,
+): number | undefined => {
+  switch (key) {
+    case "ArrowDown":
+      if (activeIndex != null) {
+        return Math.min(activeIndex + 1, optionCount - 1);
+      } else {
+        return 0;
+      }
+    case "ArrowUp":
+      if (activeIndex != null) {
+        return Math.max(activeIndex - 1, 0);
+      } else {
+        return optionCount;
+      }
+    default:
+      return activeIndex;
+  }
+};
+
+export default EngineWidget;
diff --git a/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.unit.spec.js b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.unit.spec.tsx
similarity index 80%
rename from frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.unit.spec.js
rename to frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.unit.spec.tsx
index fe16e28de6423f11969ada0413d84c3887f15823..b20dfe4feb6c4d095a6023d62b8f3d699b3662a3 100644
--- a/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.unit.spec.js
+++ b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/EngineWidget.unit.spec.tsx
@@ -1,7 +1,8 @@
 import React from "react";
 import { render, screen } from "@testing-library/react";
-import userEvent from "@testing-library/user-event";
+import userEvent, { specialChars } from "@testing-library/user-event";
 import EngineWidget from "./EngineWidget";
+import { EngineField, EngineOption } from "./types";
 
 describe("EngineWidget", () => {
   it("should allow choosing a database", () => {
@@ -35,7 +36,7 @@ describe("EngineWidget", () => {
     expect(screen.getByText("H2")).toBeInTheDocument();
     expect(screen.getByText("Presto")).toBeInTheDocument();
 
-    userEvent.click(screen.getByText("Show less options"));
+    userEvent.click(screen.getByText("Show fewer options"));
     expect(screen.getByText("MySQL")).toBeInTheDocument();
     expect(screen.getByText("H2")).toBeInTheDocument();
     expect(screen.queryByText("Presto")).not.toBeInTheDocument();
@@ -74,14 +75,29 @@ describe("EngineWidget", () => {
 
     expect(screen.getByText(/Didn’t find anything/)).toBeInTheDocument();
   });
+
+  it("should allow selection via keyboard", () => {
+    const field = getField();
+    const options = getOptions();
+
+    render(<EngineWidget field={field} options={options} />);
+
+    const input = screen.getByRole("textbox");
+    userEvent.type(input, "sql");
+    userEvent.type(input, specialChars.arrowDown);
+    userEvent.type(input, specialChars.arrowDown);
+    userEvent.type(input, specialChars.enter);
+
+    expect(field.onChange).toHaveBeenCalledWith("postgres");
+  });
 });
 
-const getField = value => ({
+const getField = (value?: string): EngineField => ({
   value,
   onChange: jest.fn(),
 });
 
-const getOptions = () => [
+const getOptions = (): EngineOption[] => [
   {
     name: "MySQL",
     value: "mysql",
diff --git a/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/index.js b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/index.ts
similarity index 100%
rename from frontend/src/metabase/admin/databases/components/widgets/EngineWidget/index.js
rename to frontend/src/metabase/admin/databases/components/widgets/EngineWidget/index.ts
diff --git a/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/types.ts b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..11fc018baeec0466118868e08dc7376c7422df99
--- /dev/null
+++ b/frontend/src/metabase/admin/databases/components/widgets/EngineWidget/types.ts
@@ -0,0 +1,10 @@
+export interface EngineField {
+  value?: string;
+  onChange?: (value: string | undefined) => void;
+}
+
+export interface EngineOption {
+  name: string;
+  value: string;
+  index: number;
+}