Accessible Search

Committed-by: Rene Pfeuffer <rene.pfeuffer@cloudogu.com>
Co-authored-by: Laura Gorzitze <laura.gorzitze@cloudogu.com>
This commit is contained in:
Florian Scholdei
2023-08-29 15:22:57 +02:00
parent cd59873638
commit 9dc86ff11e
6 changed files with 91 additions and 57 deletions

View File

@@ -0,0 +1,2 @@
- type: fixed
description: Make search accessible

View File

@@ -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<HitProps> = ({ 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 (
<Hit>
<Hit.Content>
<Link to={`/group/${name}`}>
<Hit.Title>
<CardList.Card key={name}>
<CardList.Card.Row>
<CardList.Card.Title>
<Link ref={ref} to={`/group/${name}`}>
<TextHitField hit={hit} field="name" />
</Hit.Title>
</Link>
<p>
</Link>
</CardList.Card.Title>
</CardList.Card.Row>
{((description as ValueHitField).value || (description as HighlightedHitField).fragments) && (
<CardList.Card.Row className="is-size-7 has-text-secondary">
<TextHitField hit={hit} field="description" />
</p>
</Hit.Content>
<Hit.Right>
</CardList.Card.Row>
)}
<CardList.Card.Row className="is-size-7 has-text-secondary">
<DateFromNow date={date} />
</Hit.Right>
</Hit>
</CardList.Card.Row>
</CardList.Card>
);
};

View File

@@ -40,7 +40,7 @@ type Props = {
const hitComponents: { [name: string]: FC<HitProps> } = {
repository: RepositoryHit,
user: UserHit,
group: GroupHit
group: GroupHit,
};
const findComponent = (type: string) => {
@@ -73,13 +73,13 @@ const NoHits: FC = () => {
};
const Hits: FC<Props> = ({ type, hits }) => (
<div className="panel-block">
<>
{hits && hits.length > 0 ? (
hits.map((hit, c) => <HitComponent key={`${type}_${c}_${hit.score}`} hit={hit} type={type} />)
) : (
<NoHits />
)}
</div>
</>
);
export default Hits;

View File

@@ -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<HitProps> = ({ 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<HitProps> = ({ hit }) => {
}
return (
<Hit>
<Hit.Left>
<Link to={`/repo/${namespace}/${name}`}>
<RepositoryAvatar repository={repository} size={48} />
</Link>
</Hit.Left>
<Hit.Content>
<Link to={`/repo/${namespace}/${name}`}>
<Hit.Title>
{namespace}/{name}
</Hit.Title>
</Link>
<p>
<CardList.Card key={title}>
<CardList.Card.Row>
<CardList.Card.Title>
<StyledLink
ref={ref}
to={`/repo/${namespace}/${name}`}
className={classNames("is-flex", "is-justify-content-flex-start", "is-align-items-center")}
>
<RepositoryAvatar repository={repository} size={16} /> {title}
</StyledLink>
</CardList.Card.Title>
</CardList.Card.Row>
{((description as ValueHitField).value || (description as HighlightedHitField).fragments) && (
<CardList.Card.Row className="is-size-7 has-text-secondary">
<TextHitField hit={hit} field="description" />
</p>
</Hit.Content>
<Hit.Right>
</CardList.Card.Row>
)}
<CardList.Card.Row className="is-size-7 has-text-secondary">
<DateFromNow date={date} />
</Hit.Right>
</Hit>
</CardList.Card.Row>
</CardList.Card>
);
};

View File

@@ -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<Props> = ({ result, type, page, query }) => {
return (
<>
<div className="panel">
<Hits type={type} hits={hits} />
</div>
<CardListBox>
<KeyboardIterator>
<Hits type={type} hits={hits} />
</KeyboardIterator>
</CardListBox>
<LinkPaginator collection={result} page={page} filter={query} />
</>
);

View File

@@ -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<HitProps> = ({ 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 (
<Hit>
<Hit.Content>
<Link to={`/user/${name}`}>
<Hit.Title>
<CardList.Card key={name}>
<CardList.Card.Row>
<CardList.Card.Title>
<Link ref={ref} to={`/user/${name}`}>
<TextHitField hit={hit} field="name" />
</Hit.Title>
</Link>
<p>
<TextHitField hit={hit} field="displayName" /> &lt;
<TextHitField hit={hit} field="mail" />
&gt;
</p>
</Hit.Content>
<Hit.Right>
</Link>
</CardList.Card.Title>
</CardList.Card.Row>
<CardList.Card.Row className="is-size-7 has-text-secondary">
<TextHitField hit={hit} field="displayName" />
{mail && (
<>
{" "}
&lt;
<TextHitField hit={hit} field="mail" />
&gt;
</>
)}
</CardList.Card.Row>
<CardList.Card.Row className="is-size-7 has-text-secondary">
<DateFromNow date={date} />
</Hit.Right>
</Hit>
</CardList.Card.Row>
</CardList.Card>
);
};