Do
Wenn es mehrere Filter einer Kategorie gibt, fasse sie in einem eigenen Button mit passender Bezeichnung zusammen.
Verwende <List />
, um eine Liste darzustellen.
import { typedList } from "@mittwald/flow-react-components/List"; import { type Domain, domains, } from "@/content/03-components/structure/list/examples/domainApi"; import Avatar from "@mittwald/flow-react-components/Avatar"; import Heading from "@mittwald/flow-react-components/Heading"; import Text from "@mittwald/flow-react-components/Text"; import ContextMenu from "@mittwald/flow-react-components/ContextMenu"; import { IconDomain, IconDownload, IconSubdomain, } from "@mittwald/flow-react-components/Icons"; import AlertBadge from "@mittwald/flow-react-components/AlertBadge"; import MenuItem from "@mittwald/flow-react-components/MenuItem"; import Button from "@mittwald/flow-react-components/Button"; import ActionGroup from "@mittwald/flow-react-components/ActionGroup"; export default () => { const DomainList = typedList<Domain>(); return ( <DomainList.List batchSize={5}> <DomainList.StaticData data={domains} /> <ActionGroup> <Button color="secondary" variant="soft" slot="secondary" > <IconDownload /> </Button> <Button color="accent">Anlegen</Button> </ActionGroup> <DomainList.Search /> <DomainList.Filter property="type" mode="some" name="Type" /> <DomainList.Sorting property="hostname" name="Domain A bis Z" direction="asc" /> <DomainList.Sorting property="hostname" name="Domain Z bis A" direction="desc" /> <DomainList.Sorting property="type" name="Type A bis Z" direction="asc" /> <DomainList.Sorting property="type" name="Type Z bis A" direction="desc" /> <DomainList.Table> <DomainList.TableHeader> <DomainList.TableColumn> Name </DomainList.TableColumn> <DomainList.TableColumn> Type </DomainList.TableColumn> <DomainList.TableColumn> TLD </DomainList.TableColumn> <DomainList.TableColumn> Hostname </DomainList.TableColumn> </DomainList.TableHeader> <DomainList.TableBody> <DomainList.TableRow> <DomainList.TableCell> {(domain) => domain.domain} </DomainList.TableCell> <DomainList.TableCell> {(domain) => domain.type} </DomainList.TableCell> <DomainList.TableCell> {(domain) => domain.tld} </DomainList.TableCell> <DomainList.TableCell> {(domain) => domain.hostname} </DomainList.TableCell> </DomainList.TableRow> </DomainList.TableBody> </DomainList.Table> <DomainList.Item> {(domain) => ( <DomainList.ItemView> <Avatar color={ domain.type === "Domain" ? "blue" : "teal" } > {domain.type === "Domain" ? ( <IconDomain /> ) : ( <IconSubdomain /> )} </Avatar> <Heading> {domain.hostname} {!domain.verified && ( <AlertBadge status="warning"> Unverifiziert </AlertBadge> )} </Heading> <Text>{domain.type}</Text> <ContextMenu> <MenuItem>Details anzeigen</MenuItem> <MenuItem>Löschen</MenuItem> </ContextMenu> </DomainList.ItemView> )} </DomainList.Item> </DomainList.List> ); }
Die List kann um eine Sortierung, einen Filter, ein SearchField oder eine Kombination dieser Elemente erweitert werden.
Nutze <List.Sorting />
innerhalb der List, um eine Sortiermethode anzulegen.
import { typedList } from "@mittwald/flow-react-components/List"; import { type Domain, domains, } from "@/content/03-components/structure/list/examples/domainApi"; import Avatar from "@mittwald/flow-react-components/Avatar"; import Heading from "@mittwald/flow-react-components/Heading"; import Text from "@mittwald/flow-react-components/Text"; import ContextMenu from "@mittwald/flow-react-components/ContextMenu"; import { IconDomain, IconSubdomain, } from "@mittwald/flow-react-components/Icons"; import AlertBadge from "@mittwald/flow-react-components/AlertBadge"; import MenuItem from "@mittwald/flow-react-components/MenuItem"; export default () => { const DomainList = typedList<Domain>(); return ( <DomainList.List batchSize={5}> <DomainList.StaticData data={domains} /> <DomainList.Sorting property="hostname" name="Domain A bis Z" direction="asc" /> <DomainList.Sorting property="hostname" name="Domain Z bis A" direction="desc" /> <DomainList.Sorting property="type" name="Type A bis Z" direction="asc" /> <DomainList.Sorting property="type" name="Type Z bis A" direction="desc" /> <DomainList.Item> {(domain) => ( <DomainList.ItemView> <Avatar color={ domain.type === "Domain" ? "blue" : "teal" } > {domain.type === "Domain" ? ( <IconDomain /> ) : ( <IconSubdomain /> )} </Avatar> <Heading> {domain.hostname} {!domain.verified && ( <AlertBadge status="warning"> Unverifiziert </AlertBadge> )} </Heading> <Text>{domain.type}</Text> <ContextMenu> <MenuItem>Details anzeigen</MenuItem> <MenuItem>Löschen</MenuItem> </ContextMenu> </DomainList.ItemView> )} </DomainList.Item> </DomainList.List> ); }
Über <List.Filter />
lassen sich Filtermöglichkeiten anlegen.
import { typedList } from "@mittwald/flow-react-components/List"; import { type Domain, domains, } from "@/content/03-components/structure/list/examples/domainApi"; import Avatar from "@mittwald/flow-react-components/Avatar"; import Heading from "@mittwald/flow-react-components/Heading"; import Text from "@mittwald/flow-react-components/Text"; import ContextMenu from "@mittwald/flow-react-components/ContextMenu"; import { IconDomain, IconSubdomain, } from "@mittwald/flow-react-components/Icons"; import AlertBadge from "@mittwald/flow-react-components/AlertBadge"; import MenuItem from "@mittwald/flow-react-components/MenuItem"; export default () => { const DomainList = typedList<Domain>(); return ( <DomainList.List batchSize={5}> <DomainList.StaticData data={domains} /> <DomainList.Filter property="type" mode="some" name="Type" /> <DomainList.Item> {(domain) => ( <DomainList.ItemView> <Avatar color={ domain.type === "Domain" ? "blue" : "teal" } > {domain.type === "Domain" ? ( <IconDomain /> ) : ( <IconSubdomain /> )} </Avatar> <Heading> {domain.hostname} {!domain.verified && ( <AlertBadge status="warning"> Unverifiziert </AlertBadge> )} </Heading> <Text>{domain.type}</Text> <ContextMenu> <MenuItem>Details anzeigen</MenuItem> <MenuItem>Löschen</MenuItem> </ContextMenu> </DomainList.ItemView> )} </DomainList.Item> </DomainList.List> ); }
Verwende <List.Search />
innerhalb der List, um ein
SearchField anzuzeigen.
import { typedList } from "@mittwald/flow-react-components/List"; import { type Domain, domains, } from "@/content/03-components/structure/list/examples/domainApi"; import Avatar from "@mittwald/flow-react-components/Avatar"; import Heading from "@mittwald/flow-react-components/Heading"; import Text from "@mittwald/flow-react-components/Text"; import ContextMenu from "@mittwald/flow-react-components/ContextMenu"; import { IconDomain, IconSubdomain, } from "@mittwald/flow-react-components/Icons"; import AlertBadge from "@mittwald/flow-react-components/AlertBadge"; import MenuItem from "@mittwald/flow-react-components/MenuItem"; export default () => { const DomainList = typedList<Domain>(); return ( <DomainList.List batchSize={5}> <DomainList.StaticData data={domains} /> <DomainList.Search /> <DomainList.Item> {(domain) => ( <DomainList.ItemView> <Avatar color={ domain.type === "Domain" ? "blue" : "teal" } > {domain.type === "Domain" ? ( <IconDomain /> ) : ( <IconSubdomain /> )} </Avatar> <Heading> {domain.hostname} {!domain.verified && ( <AlertBadge status="warning"> Unverifiziert </AlertBadge> )} </Heading> <Text>{domain.type}</Text> <ContextMenu> <MenuItem>Details anzeigen</MenuItem> <MenuItem>Löschen</MenuItem> </ContextMenu> </DomainList.ItemView> )} </DomainList.Item> </DomainList.List> ); }
Verwende <ActionGroup/>
innerhalb der List, um eine
ActionGroup anzuzeigen. Hier können
Aktionen definiert werden, die sich direkt auf die Liste beziehen."
import { typedList } from "@mittwald/flow-react-components/List"; import { type Domain, domains, } from "@/content/03-components/structure/list/examples/domainApi"; import Avatar from "@mittwald/flow-react-components/Avatar"; import Heading from "@mittwald/flow-react-components/Heading"; import Text from "@mittwald/flow-react-components/Text"; import ContextMenu from "@mittwald/flow-react-components/ContextMenu"; import { IconDomain, IconDownload, IconSubdomain, } from "@mittwald/flow-react-components/Icons"; import AlertBadge from "@mittwald/flow-react-components/AlertBadge"; import MenuItem from "@mittwald/flow-react-components/MenuItem"; import Button from "@mittwald/flow-react-components/Button"; import ActionGroup from "@mittwald/flow-react-components/ActionGroup"; export default () => { const DomainList = typedList<Domain>(); return ( <DomainList.List batchSize={5}> <DomainList.StaticData data={domains} /> <ActionGroup> <Button color="secondary" variant="soft" slot="secondary" > <IconDownload /> </Button> <Button color="accent">Anlegen</Button> </ActionGroup> <DomainList.Item> {(domain) => ( <DomainList.ItemView> <Avatar color={ domain.type === "Domain" ? "blue" : "teal" } > {domain.type === "Domain" ? ( <IconDomain /> ) : ( <IconSubdomain /> )} </Avatar> <Heading> {domain.hostname} {!domain.verified && ( <AlertBadge status="warning"> Unverifiziert </AlertBadge> )} </Heading> <Text>{domain.type}</Text> <ContextMenu> <MenuItem>Details anzeigen</MenuItem> <MenuItem>Löschen</MenuItem> </ContextMenu> </DomainList.ItemView> )} </DomainList.Item> </DomainList.List> ); }
Die List kann als Liste oder als Tabelle dargestellt werden. Nutze
<List.Item />
für die Darstellung als Liste und <List.Table />
, um sie als
Tabelle anzuzeigen
import { typedList } from "@mittwald/flow-react-components/List"; import { type Domain, domains, } from "@/content/03-components/structure/list/examples/domainApi"; import Avatar from "@mittwald/flow-react-components/Avatar"; import Heading from "@mittwald/flow-react-components/Heading"; import Text from "@mittwald/flow-react-components/Text"; import ContextMenu from "@mittwald/flow-react-components/ContextMenu"; import { IconDomain, IconSubdomain, } from "@mittwald/flow-react-components/Icons"; import AlertBadge from "@mittwald/flow-react-components/AlertBadge"; import MenuItem from "@mittwald/flow-react-components/MenuItem"; export default () => { const DomainList = typedList<Domain>(); return ( <DomainList.List batchSize={5} defaultViewMode="table"> <DomainList.StaticData data={domains} /> <DomainList.Table> <DomainList.TableHeader> <DomainList.TableColumn> Name </DomainList.TableColumn> <DomainList.TableColumn> Type </DomainList.TableColumn> <DomainList.TableColumn> TLD </DomainList.TableColumn> <DomainList.TableColumn> Hostname </DomainList.TableColumn> </DomainList.TableHeader> <DomainList.TableBody> <DomainList.TableRow> <DomainList.TableCell> {(domain) => domain.domain} </DomainList.TableCell> <DomainList.TableCell> {(domain) => domain.type} </DomainList.TableCell> <DomainList.TableCell> {(domain) => domain.tld} </DomainList.TableCell> <DomainList.TableCell> {(domain) => domain.hostname} </DomainList.TableCell> </DomainList.TableRow> </DomainList.TableBody> </DomainList.Table> <DomainList.Item> {(domain) => ( <DomainList.ItemView> <Avatar color={ domain.type === "Domain" ? "blue" : "teal" } > {domain.type === "Domain" ? ( <IconDomain /> ) : ( <IconSubdomain /> )} </Avatar> <Heading> {domain.hostname} {!domain.verified && ( <AlertBadge status="warning"> Unverifiziert </AlertBadge> )} </Heading> <Text>{domain.type}</Text> <ContextMenu> <MenuItem>Details anzeigen</MenuItem> <MenuItem>Löschen</MenuItem> </ContextMenu> </DomainList.ItemView> )} </DomainList.Item> </DomainList.List> ); }
Die Pagination wird standardmäßig bei jeder List aktiviert. Sie zeigt im
Standard 10 Einträge an und lädt über einen Klick auf "Mehr anzeigen" jeweils 10
Einträge nach. Diese Werte lassen sich über die batchSize
Property anpassen.
import { typedList } from "@mittwald/flow-react-components/List"; import { type Domain, domains, } from "@/content/03-components/structure/list/examples/domainApi"; import Avatar from "@mittwald/flow-react-components/Avatar"; import Heading from "@mittwald/flow-react-components/Heading"; import Text from "@mittwald/flow-react-components/Text"; import ContextMenu from "@mittwald/flow-react-components/ContextMenu"; import { IconDomain, IconSubdomain, } from "@mittwald/flow-react-components/Icons"; import AlertBadge from "@mittwald/flow-react-components/AlertBadge"; import MenuItem from "@mittwald/flow-react-components/MenuItem"; export default () => { const DomainList = typedList<Domain>(); return ( <DomainList.List batchSize={3}> <DomainList.StaticData data={domains} /> <DomainList.Item> {(domain) => ( <DomainList.ItemView> <Avatar color={ domain.type === "Domain" ? "blue" : "teal" } > {domain.type === "Domain" ? ( <IconDomain /> ) : ( <IconSubdomain /> )} </Avatar> <Heading> {domain.hostname} {!domain.verified && ( <AlertBadge status="warning"> Unverifiziert </AlertBadge> )} </Heading> <Text>{domain.type}</Text> <ContextMenu> <MenuItem>Details anzeigen</MenuItem> <MenuItem>Löschen</MenuItem> </ContextMenu> </DomainList.ItemView> )} </DomainList.Item> </DomainList.List> ); }
Die List bildet den strukturierten Rahmen der ListItems. ListItems stellen Elemente (z. B. Domains, E-Mail-Adressen, Projekte, ...) dar. Die List gruppiert diese Elemente und bietet Funktionen wie eine Sortierung, Filterung und Suche. Zusätzlich kann der User die Anzahl der angezeigten ListItems über einen „Mehr anzeigen“-Button steuern.
Verwende eine List, um ...
Wenn es mehrere Filter einer Kategorie gibt, fasse sie in einem eigenen Button mit passender Bezeichnung zusammen.
Hat ein Filter keine spezifische Kategorie, sollte er in einem allgemeinen Filter-Button platziert werden.
Standardmäßig werden 10 Einträge angezeigt. Verwende batchSize
, um die Anzahl
der Einträge anzupassen. Über den "Mehr anzeigen"-Button können bei Bedarf
weitere Einträge nachgeladen werden.
Beachte bei der Anpassung der Pagination, dass ...
Ist die Standardsortierung aktiv, steht auf dem Sortierungs-Button nur “Sortierung”. Wählt der User eine spezifische Sortierung aus, so wird diese hinten angehängt. Daher solltest du die Sortiermethode so benennen, dass direkt ersichtlich ist, wonach und in welcher Reihenfolge sie sortiert.
Benenne die Sortierung so, dass eindeutig ersichtlich ist, wonach und in welcher Reihenfolge sortiert wird.
Verzichte auf Formulierungen, die nicht eindeutig verstanden werden und keine klare Sortierreihenfolge kommunizieren.
Gesetzte Filter werden als Badges dargestellt. Diese müssen aus sich selbst heraus verständlich sein. Daher ist es ratsam, bei Begriffen, die mehrdeutig sein können, zusätzlichen Kontext zu liefern. Bei Filtern, die der User intuitiv einer bestimmten Kategorie zuordnen kann, ist dies nicht notwendig.
Intuitiv verständliche Filter benötigen keinen zusätzlichen Kontext. Erklärungsbedürftige Filter sollten mit weiterem Kontext versehen werden, um ihre Nutzung erleichtern.
Zusätzlicher Kontext ist bei intuitiven Filtern nicht notwendig.
Öffnet sich eine List im Modal, so sollte automatisch die Suche fokussiert sein,
um dem User eine direkte Eingabe zu ermöglichen. Setze daher auf der Suche die
Property autoFocus
, wenn sich die List in einem Modal öffnet.
Auf kleinen Bildschirmen (unter 551px) bricht der Header um, sodass die Suche unterhalb der Sortierung und des Filters dargestellt wird. Achte auf das Umbruchverhalten des ListItem's.
Häufig wird eine List als alleiniges Element einer Seite verwendet und besitzt
somit keine Heading. In diesen Fällen muss sie
mit einem aria-label
beschrieben werden. Ist die List mit einer eigenen
Heading versehen, so muss die Heading mit
aria-labelledby
der List zugeordnet werden.