Compare commits

...

5 Commits

Author SHA1 Message Date
SabarigirisanSivakumarREO
3dbafdebee updated e2e test case 2025-07-01 15:16:32 +00:00
SabarigirisanSivakumarREO
1fd3023b44 updated e2e test case 2025-07-01 15:13:57 +00:00
SabarigirisanSivakumarREO
743a88f111 rollback quote symbol changes 2025-07-01 12:55:51 +00:00
SabarigirisanSivakumarREO
2e3792dcee updated as per comments 2025-07-01 12:53:26 +00:00
SabarigirisanSivakumarREO
74c6dacd27 Fixed database option announcement issues on setup page. 2025-06-30 10:48:53 +00:00
4 changed files with 65 additions and 8 deletions

View File

@@ -94,7 +94,7 @@ describe("scenarios > setup", () => {
cy.findByText("MySQL").click();
cy.findByText("Need help connecting?").should("be.visible");
cy.findByLabelText("Remove database").click();
cy.findByPlaceholderText("Search for a database…").type("SQL");
cy.findByLabelText("Search for a database").type("SQL");
cy.findByText("SQLite").click();
cy.findByText("Need help connecting?");
@@ -344,7 +344,7 @@ describe("scenarios > setup", () => {
.click();
cy.findByTestId("database-form").within(() => {
cy.findByPlaceholderText("Search for a database…").type("lite").blur();
cy.findByLabelText("Search for a database").type("lite").blur();
cy.findByText("SQLite").click();
cy.findByLabelText("Display name").type(dbName);
cy.findByLabelText("Filename").type("./resources/sqlite-fixture.db", {

View File

@@ -0,0 +1,26 @@
interface HiddenAriaMessageProps {
message: string;
ariaLive?: "polite" | "assertive";
ariaAtomic?: boolean;
}
export const HiddenAriaMessage = ({
message,
ariaLive = "polite",
ariaAtomic = true,
}: HiddenAriaMessageProps) => (
<div
className="visually-hidden"
aria-live={ariaLive}
aria-atomic={ariaAtomic}
style={{
position: "absolute",
left: "-9999px",
width: "1px",
height: "1px",
overflow: "hidden",
}}
>
{message}
</div>
);

View File

@@ -34,16 +34,21 @@ export const EngineCardRoot = styled.button<EngineCardRootProps>`
justify-content: center;
height: 5.375rem;
padding: 1rem;
border: 1px solid var(--mb-color-bg-medium);
border: 2px solid var(--mb-color-background);
border-radius: 0.375rem;
background-color: var(--mb-color-bg-white);
cursor: pointer;
outline: ${(props) => props.isActive && `2px solid var(--mb-color-focus)`};
outline: ${(props) => props.isActive && `2px solid var(--mb-color-brand)`};
&:hover {
border-color: var(--mb-color-brand);
background-color: ${() => lighten("brand", 0.6)};
}
&:focus {
border: 2px solid var(--mb-color-background);
outline: 2px solid var(--mb-color-brand);
}
`;
export const EngineCardTitle = styled.div`

View File

@@ -1,11 +1,13 @@
import type { ChangeEvent, KeyboardEvent } from "react";
import { useCallback, useMemo, useState } from "react";
import { useDebounce } from "react-use";
import { jt, t } from "ttag";
import ExternalLink from "metabase/common/components/ExternalLink";
import Input from "metabase/common/components/Input";
import { HiddenAriaMessage } from "metabase/common/components/HiddenAriaMessage";
import { useDocsUrl } from "metabase/common/hooks";
import { useUniqueId } from "metabase/common/hooks/use-unique-id";
import { TextInput } from "metabase/ui/components/inputs/TextInput";
import type { EngineOption } from "../../types";
import { getEngineLogo } from "../../utils/engine";
@@ -101,6 +103,7 @@ const EngineSearch = ({
const [searchText, setSearchText] = useState("");
const [activeIndex, setActiveIndex] = useState<number>();
const [isExpanded, setIsExpanded] = useState(false);
const [dbOptionsAriaMessage, setDbOptionsAriaMessage] = useState("");
const isSearching = searchText.length > 0;
const isNavigating = activeIndex != null;
const hasMoreOptions = options.length > DEFAULT_OPTIONS_COUNT;
@@ -110,6 +113,24 @@ const EngineSearch = ({
[options, isExpanded, isSearching, searchText],
);
const debouncedAriaMessage = useMemo(() => {
if (!searchText && visibleOptions.length === 0) {
return "";
}
return visibleOptions.length
? t`${visibleOptions.length} ${visibleOptions.length === 1 ? t`result` : t`results`} found. Use arrow keys to navigate.`
: t`No results found.`;
}, [searchText, visibleOptions]);
useDebounce(
() => {
setDbOptionsAriaMessage(debouncedAriaMessage);
},
50,
[debouncedAriaMessage],
);
const optionCount = visibleOptions.length;
const activeOption = isNavigating ? visibleOptions[activeIndex] : undefined;
@@ -138,17 +159,21 @@ const EngineSearch = ({
return (
<EngineSearchRoot role="combobox">
<Input
<TextInput
label={t`Search for a database`}
value={searchText}
placeholder={t`Search for a database…`}
autoFocus
aria-autocomplete="list"
aria-controls={getListBoxId(rootId)}
aria-activedescendant={getListOptionId(rootId, activeOption)}
fullWidth
onChange={handleSearch}
onKeyDown={handleKeyDown}
/>
<HiddenAriaMessage
ariaLive="polite"
ariaAtomic={true}
message={dbOptionsAriaMessage}
/>
{visibleOptions.length ? (
<EngineList
rootId={rootId}
@@ -219,6 +244,7 @@ const EngineCard = ({
return (
<EngineCardRoot
role="option"
tabIndex={0}
id={getListOptionId(rootId, option)}
isActive={isActive}
onClick={handleClick}