From f1a8dc19e8b6a62fe6249ad137e3c23fda2d7f63 Mon Sep 17 00:00:00 2001 From: gintil Date: Sat, 18 Jan 2025 15:24:42 -0500 Subject: [PATCH] Improve accessibility of comparisons tab content --- .../ArticlePlaceholderTable/index.tsx | 2 +- .../AddComparisonSelect.tsx | 76 +++--- .../ComparisonsTabSection/ComparisonTag.tsx | 19 +- .../ComparisonsTabSection/index.tsx | 257 +++++++++++------- .../client/src/mocks/data/userFeeds.ts | 1 + .../backend-api/client/src/mocks/handlers.ts | 2 +- 6 files changed, 214 insertions(+), 143 deletions(-) diff --git a/services/backend-api/client/src/features/feedConnections/components/ArticlePlaceholderTable/index.tsx b/services/backend-api/client/src/features/feedConnections/components/ArticlePlaceholderTable/index.tsx index 3facdfbbf..367001a7e 100644 --- a/services/backend-api/client/src/features/feedConnections/components/ArticlePlaceholderTable/index.tsx +++ b/services/backend-api/client/src/features/feedConnections/components/ArticlePlaceholderTable/index.tsx @@ -75,7 +75,7 @@ const PlaceholderRow = ({ - + {value.split("\n").map((line, idx) => ( // eslint-disable-next-line react/no-array-index-key diff --git a/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/AddComparisonSelect.tsx b/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/AddComparisonSelect.tsx index 07cc2692e..4fb9066db 100644 --- a/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/AddComparisonSelect.tsx +++ b/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/AddComparisonSelect.tsx @@ -1,5 +1,4 @@ -import { AddIcon } from "@chakra-ui/icons"; -import { Flex, IconButton, Select } from "@chakra-ui/react"; +import { Box, Button, Select, Stack, chakra } from "@chakra-ui/react"; import { useState } from "react"; interface Props { @@ -7,9 +6,16 @@ interface Props { isDisabled?: boolean; isLoading?: boolean; onChange: (value: string) => Promise; + formLabel: string; } -export const AddComparisonSelect = ({ properties, isDisabled, isLoading, onChange }: Props) => { +export const AddComparisonSelect = ({ + properties, + isDisabled, + isLoading, + onChange, + formLabel, +}: Props) => { const [value, setValue] = useState(""); const [isAdding, setIsAdding] = useState(false); @@ -21,35 +27,39 @@ export const AddComparisonSelect = ({ properties, isDisabled, isLoading, onChang }; return ( - - - } - isDisabled={isAdding || isDisabled || !value} - aria-label="Add comparison" - isLoading={isAdding || isLoading} - onClick={onClickAdd} - /> - + onClickAdd()}> + + {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */} + + + + ); }; diff --git a/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/ComparisonTag.tsx b/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/ComparisonTag.tsx index 8580cbcdc..cd10e897d 100644 --- a/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/ComparisonTag.tsx +++ b/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/ComparisonTag.tsx @@ -1,13 +1,14 @@ -import { Box, Spinner, Tag, TagCloseButton, TagLabel, TagRightIcon } from "@chakra-ui/react"; +import { Spinner, Tag, TagCloseButton, TagLabel, TagRightIcon } from "@chakra-ui/react"; import { useState } from "react"; interface Props { colorScheme: string; title: string; onDelete: () => Promise; + deleteButtonAriaLabel?: string; } -export const ComparisonTag = ({ colorScheme, title, onDelete }: Props) => { +export const ComparisonTag = ({ colorScheme, title, onDelete, deleteButtonAriaLabel }: Props) => { const [isDeleting, setIsDeleting] = useState(false); const onClickDelete = async () => { @@ -17,12 +18,12 @@ export const ComparisonTag = ({ colorScheme, title, onDelete }: Props) => { }; return ( - - - {title} - {isDeleting && } - {!isDeleting && onClickDelete()} />} - - + + {title} + {isDeleting && } + {!isDeleting && ( + onClickDelete()} /> + )} + ); }; diff --git a/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/index.tsx b/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/index.tsx index 515544fb0..d791e343e 100644 --- a/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/index.tsx +++ b/services/backend-api/client/src/features/feedConnections/components/ComparisonsTabSection/index.tsx @@ -4,6 +4,7 @@ import { AlertIcon, AlertTitle, Button, + Divider, Flex, Heading, HStack, @@ -177,7 +178,7 @@ export const ComparisonsTabSection = ({ const hasAlert = !!(fetchErrorAlert || parseErrorAlert || noArticlesAlert); return ( - + {error && ( @@ -191,112 +192,170 @@ export const ComparisonsTabSection = ({ )} - - - - Sample Article Properties - - } - isLoading={!!selectedArticleId && userFeedArticlesFetchStatus === "fetching"} - isDisabled={userFeedArticlesFetchStatus === "fetching"} - > - {t("features.feedConnections.components.articlePlaceholderTable.selectArticle")} - - } - feedId={feedId} - onArticleSelected={onSelectedArticle} - onClickRandomArticle={onClickRandomFeedArticle} - articleFormatOptions={articleFormatOptions} - /> - - {fetchErrorAlert || parseErrorAlert || noArticlesAlert} - {userFeedArticlesStatus === "loading" && ( - - - Loading article... + + + Comparisons + + + If you are either not receiving articles or getting duplicate articles, you can add + additional properties that can be used to determine if an article should or should not get + delivered. + + + + + + + {t( + "features.feedConnections.components.comparisonsTabSection.passingComparisonsTitle" + )} + + + {t( + "features.feedConnections.components.comparisonsTabSection.passingComparisonsDescription" + )} + - )} - {!hasAlert && userFeedArticles?.result.articles.length && ( - - + + Current passing comparisons + + {!passingComparisons?.length && ( + You currently have no passing comparisons created. + )} + {!!passingComparisons?.length && ( + + {passingComparisons.map((comparison) => ( + onRemovePassingComparison(comparison)} + deleteButtonAriaLabel={`Delete passing comparison ${comparison}`} + /> + ))} + + )} + + - )} - - - - - {t("features.feedConnections.components.comparisonsTabSection.passingComparisonsTitle")} - - - {t( - "features.feedConnections.components.comparisonsTabSection.passingComparisonsDescription" - )} - + {updateError && errorLocation === "passing" && ( + + )} - - {passingComparisons?.map((comparison) => ( - onRemovePassingComparison(comparison)} - /> - ))} - - - {updateError && errorLocation === "passing" && ( - - )} - - - - - {t( - "features.feedConnections.components.comparisonsTabSection.blockingComparisonsTitle" + + + + {t( + "features.feedConnections.components.comparisonsTabSection.blockingComparisonsTitle" + )} + + + {t( + "features.feedConnections.components.comparisonsTabSection.blockingComparisonsDescription" + )} + + + + + Current blocking comparisons + + {!blockingComparisons?.length && ( + + You currently have no blocking comparisons created. + )} - - - {t( - "features.feedConnections.components.comparisonsTabSection.blockingComparisonsDescription" + {!!blockingComparisons?.length && ( + + {blockingComparisons?.map((comparison) => ( + onRemoveBlockingComparison(comparison)} + deleteButtonAriaLabel={`Delete blocking comparison ${comparison}`} + /> + ))} + )} - + + + + {updateError && errorLocation === "blocking" && ( + + )} - - {blockingComparisons?.map((comparison) => ( - onRemoveBlockingComparison(comparison)} + + + + + Preview Sample Article Properties + + + Preview an article to see the properties that can be used for comparisons. + + + } + isLoading={!!selectedArticleId && userFeedArticlesFetchStatus === "fetching"} + isDisabled={userFeedArticlesFetchStatus === "fetching"} + size="sm" + > + Select article to preview + + } + feedId={feedId} + onArticleSelected={onSelectedArticle} + onClickRandomArticle={onClickRandomFeedArticle} + articleFormatOptions={articleFormatOptions} /> - ))} - - - {updateError && errorLocation === "blocking" && ( - - )} + + {fetchErrorAlert || parseErrorAlert || noArticlesAlert} + {userFeedArticlesStatus === "loading" && ( + + + Loading article... + + )} + {!hasAlert && userFeedArticles?.result.articles.length && ( + + + + )} + ); diff --git a/services/backend-api/client/src/mocks/data/userFeeds.ts b/services/backend-api/client/src/mocks/data/userFeeds.ts index 5e1d0a43a..08b0c3a0b 100644 --- a/services/backend-api/client/src/mocks/data/userFeeds.ts +++ b/services/backend-api/client/src/mocks/data/userFeeds.ts @@ -320,6 +320,7 @@ const mockUserFeeds: UserFeed[] = [ updatedAt: new Date().toISOString(), refreshRateOptions: [], healthStatus: UserFeedHealthStatus.Failed, + passingComparisons: ["title", "description"], connections: [], disabledCode: UserFeedDisabledCode.Manual, refreshRateSeconds: 60, diff --git a/services/backend-api/client/src/mocks/handlers.ts b/services/backend-api/client/src/mocks/handlers.ts index 01132c236..99c269d51 100644 --- a/services/backend-api/client/src/mocks/handlers.ts +++ b/services/backend-api/client/src/mocks/handlers.ts @@ -643,7 +643,7 @@ const handlers = [ return res( ctx.delay(500), - ctx.status(404), + ctx.status(200), ctx.json({ result: matchingUserFeed, })