From 9dc86ff11e9fac6859891ad098f351d8d0ef42ee Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Tue, 29 Aug 2023 15:22:57 +0200 Subject: [PATCH] Accessible Search Committed-by: Rene Pfeuffer Co-authored-by: Laura Gorzitze --- gradle/changelog/accessibility_search.yaml | 2 + scm-ui/ui-webapp/src/search/GroupHit.tsx | 34 +++++++----- scm-ui/ui-webapp/src/search/Hits.tsx | 6 +-- scm-ui/ui-webapp/src/search/RepositoryHit.tsx | 53 ++++++++++++------- scm-ui/ui-webapp/src/search/Results.tsx | 10 ++-- scm-ui/ui-webapp/src/search/UserHit.tsx | 43 +++++++++------ 6 files changed, 91 insertions(+), 57 deletions(-) create mode 100644 gradle/changelog/accessibility_search.yaml diff --git a/gradle/changelog/accessibility_search.yaml b/gradle/changelog/accessibility_search.yaml new file mode 100644 index 0000000000..a45a6f59c4 --- /dev/null +++ b/gradle/changelog/accessibility_search.yaml @@ -0,0 +1,2 @@ +- type: fixed + description: Make search accessible diff --git a/scm-ui/ui-webapp/src/search/GroupHit.tsx b/scm-ui/ui-webapp/src/search/GroupHit.tsx index 3dd2ee54be..5203891106 100644 --- a/scm-ui/ui-webapp/src/search/GroupHit.tsx +++ b/scm-ui/ui-webapp/src/search/GroupHit.tsx @@ -24,37 +24,43 @@ import React, { FC } from "react"; import { - Hit, HitProps, DateFromNow, TextHitField, useDateHitFieldValue, - useStringHitFieldValue + useStringHitFieldValue, } from "@scm-manager/ui-components"; import { Link } from "react-router-dom"; +import { CardList } from "@scm-manager/ui-layout"; +import { useKeyboardIteratorTarget } from "@scm-manager/ui-shortcuts"; +import { HighlightedHitField, ValueHitField } from "@scm-manager/ui-types"; const GroupHit: FC = ({ hit }) => { + const ref = useKeyboardIteratorTarget(); const name = useStringHitFieldValue(hit, "name"); const lastModified = useDateHitFieldValue(hit, "lastModified"); const creationDate = useDateHitFieldValue(hit, "creationDate"); const date = lastModified || creationDate; + const description = hit.fields["description"]; return ( - - - - + + + + - - -

+ + + + {((description as ValueHitField).value || (description as HighlightedHitField).fragments) && ( + -

-
- + + )} + - -
+ + ); }; diff --git a/scm-ui/ui-webapp/src/search/Hits.tsx b/scm-ui/ui-webapp/src/search/Hits.tsx index eff27eef23..25a1789839 100644 --- a/scm-ui/ui-webapp/src/search/Hits.tsx +++ b/scm-ui/ui-webapp/src/search/Hits.tsx @@ -40,7 +40,7 @@ type Props = { const hitComponents: { [name: string]: FC } = { repository: RepositoryHit, user: UserHit, - group: GroupHit + group: GroupHit, }; const findComponent = (type: string) => { @@ -73,13 +73,13 @@ const NoHits: FC = () => { }; const Hits: FC = ({ type, hits }) => ( -
+ <> {hits && hits.length > 0 ? ( hits.map((hit, c) => ) ) : ( )} -
+ ); export default Hits; diff --git a/scm-ui/ui-webapp/src/search/RepositoryHit.tsx b/scm-ui/ui-webapp/src/search/RepositoryHit.tsx index 936d4599dc..de25eff1c0 100644 --- a/scm-ui/ui-webapp/src/search/RepositoryHit.tsx +++ b/scm-ui/ui-webapp/src/search/RepositoryHit.tsx @@ -30,17 +30,29 @@ import { DateFromNow, RepositoryAvatar, TextHitField, - Hit, - HitProps + HitProps, } from "@scm-manager/ui-components"; +import { CardList } from "@scm-manager/ui-layout"; +import classNames from "classnames"; +import styled from "styled-components"; +import { HighlightedHitField, ValueHitField } from "@scm-manager/ui-types"; +import { useKeyboardIteratorTarget } from "@scm-manager/ui-shortcuts"; + +const StyledLink = styled(Link)` + gap: 0.5rem; +`; const RepositoryHit: FC = ({ hit }) => { + const ref = useKeyboardIteratorTarget(); + const namespace = useStringHitFieldValue(hit, "namespace"); const name = useStringHitFieldValue(hit, "name"); const type = useStringHitFieldValue(hit, "type"); const lastModified = useDateHitFieldValue(hit, "lastModified"); const creationDate = useDateHitFieldValue(hit, "creationDate"); const date = lastModified || creationDate; + const description = hit.fields["description"]; + const title = `${namespace}/${name}`; // the embedded repository is only a subset of the repository (RepositoryCoordinates), // so we should use the fields to get more information @@ -50,26 +62,27 @@ const RepositoryHit: FC = ({ hit }) => { } return ( - - - - - - - - - - {namespace}/{name} - - -

+ + + + + {title} + + + + {((description as ValueHitField).value || (description as HighlightedHitField).fragments) && ( + -

-
- + + )} + - -
+ + ); }; diff --git a/scm-ui/ui-webapp/src/search/Results.tsx b/scm-ui/ui-webapp/src/search/Results.tsx index 1827856e89..f0248df89e 100644 --- a/scm-ui/ui-webapp/src/search/Results.tsx +++ b/scm-ui/ui-webapp/src/search/Results.tsx @@ -27,6 +27,8 @@ import { QueryResult } from "@scm-manager/ui-types"; import Hits from "./Hits"; import { LinkPaginator } from "@scm-manager/ui-components"; import { Redirect, useLocation } from "react-router-dom"; +import { CardListBox } from "@scm-manager/ui-layout"; +import { KeyboardIterator } from "@scm-manager/ui-shortcuts"; type Props = { result: QueryResult; @@ -50,9 +52,11 @@ const Results: FC = ({ result, type, page, query }) => { return ( <> -
- -
+ + + + + ); diff --git a/scm-ui/ui-webapp/src/search/UserHit.tsx b/scm-ui/ui-webapp/src/search/UserHit.tsx index b3f131e46c..3db02557b2 100644 --- a/scm-ui/ui-webapp/src/search/UserHit.tsx +++ b/scm-ui/ui-webapp/src/search/UserHit.tsx @@ -29,34 +29,43 @@ import { useDateHitFieldValue, useStringHitFieldValue, TextHitField, - Hit, - HitProps + HitProps, } from "@scm-manager/ui-components"; +import { CardList } from "@scm-manager/ui-layout"; +import { useKeyboardIteratorTarget } from "@scm-manager/ui-shortcuts"; const UserHit: FC = ({ hit }) => { + const ref = useKeyboardIteratorTarget(); const name = useStringHitFieldValue(hit, "name"); + const mail = useStringHitFieldValue(hit, "mail"); const lastModified = useDateHitFieldValue(hit, "lastModified"); const creationDate = useDateHitFieldValue(hit, "creationDate"); const date = lastModified || creationDate; return ( - - - - + + + + - - -

- < - - > -

-
- + + + + + + {mail && ( + <> + {" "} + < + + > + + )} + + - -
+ + ); };