Do
Wenn es mehrere Filter einer Kategorie gibt, fasse sie in einem eigenen Button mit passender Bezeichnung zusammen.
Die List bildet den strukturierten Rahmen für sogenannte ListItems. Alternativ können in der List Elemente in einer Table dargestellt werden, wenn eine tabellarische Ansicht mit Spalten sinnvoll ist.
Ein ListItem ist ein Eintrag in der List und repräsentiert ein spezifisches Element einer übergeordneten Kategorie (z. B. Domains, E-Mail-Adressen, Projekte …). Dabei werden nur die Informationen angezeigt, die notwendig sind, um das jeweilige Element zu verstehen.
Die List fasst alle ListItems bzw. Tabelleneinträge zusammen und stellt Funktionen wie Sortierung, Filterung und Suche bereit. Zusätzlich kann der User über einen „Mehr anzeigen“-Button steuern, wie viele ListItems gleichzeitig angezeigt werden.
Achte bei der Verwendung einer List darauf, dass...
Verwende eine List, um ...
Die List unterstützt drei verschiedene Ansichten: Liste, Raster und Tabelle.
In der Listen- und Rasteransicht werden unterschiedliche Varianten des ListItems dargestellt. In der Tabellenansicht verwendet die List die Table-Component. Sind mehrere Ansichten verfügbar, können User über den Ansichts-Button zwischen ihnen wechseln.
Der Sortierungs-Button wird stets links neben dem Filter-Button angezeigt. Die Standardsortierung sollte dem häufigsten Anwendungsfall entsprechen (z. B. „Neueste zuerst“ bei einer Änderungshistorie). Die aktive Sortierung wird im Sortierungs-Button angezeigt (siehe Abschnitt Writing guidelines).
Ein Klick auf den Filter-Button öffnet ein ContextMenu, in dem Filter aktiviert oder deaktiviert werden können.
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 maximal 10 ListItems angezeigt. Mit der Option batchSize
kann die Anzahl der anfänglichen ListItems angepasst werden. Über den "Mehr
anzeigen"-Button können bei Bedarf
weitere ListItems nachgeladen werden.
Beachte bei der Anpassung der Pagination, dass ...
ListItems sind die zentralen Bestandteile der List. Sie repräsentieren jeweils ein spezifisches Element und können entweder in einer Listen- oder Rasteransicht dargestellt werden.
In der Listenansicht besteht ein ListItem typischerweise aus:
In der Rasteransicht ist die Darstellung kompakter und stärker visuell ausgerichtet. Der Avatar wird hier größer und in eckiger Form angezeigt. Die grundlegenden Funktionen sind vergleichbar mit denen der Listenansicht, allerdings entfällt in diesem Modus der Top Content sowie die Accordion-Funktion.
Wird eine List mit einer Tabellenansicht verwendet, sind die Guidelines der Table zu beachten.
Die IllustratedMessage wird in zwei Anwendungsfällen verwendet:
Ist die Standardsortierung aktiv, zeigt der Sortierungs-Button lediglich “Sortierung” an. Wählt der User eine spezifische Sortierung aus, wird der Button-Text entsprechend angepasst. Die Sortiermethode sollte so benannt werden, dass sofort ersichtlich ist, nach welchem Kriterium und in welcher Reihenfolge sortiert wird.
Benenne die Sortierung so, dass eindeutig ersichtlich ist, wonach und in welcher Reihenfolge sortiert wird.
Verzichte auf Sortierformulierungen, die nicht eindeutig verständlich sind oder keine klare Reihenfolge vermitteln.
Aktive Filter werden als Badges dargestellt. Diese sollten selbsterklärend sein. Bei mehrdeutigen Begriffen empfiehlt es sich, zusätzlichen Kontext anzugeben.
Intuitiv verständliche Filter benötigen keinen zusätzlichen Kontext. Erklärungsbedürftige Filter sollten hingegen mit weiterem Text versehen werden, um ihre Nutzung zu erleichtern.
Bei intuitiven Filtern sollte auf zusätzlichen Text verzichtet werden. Meist genügt da ein einzelnes beschreibendes Wort.
Wenn sich eine List im Modal öffnet, sollte das Suchfeld automatisch fokussiert
sein, um dem User eine direkte Eingabe zu ermöglichen. Setze dafür auf das
Suchfeld die Property autoFocus.
Auf kleinen Bildschirmgrößen passt sich der Header der List an. Ansicht und Sortierung werden in einem Icon-Button zusammengefasst, auch die Filter werden unter einem Icon-Button versteckt. Auf besonders kleinen Bildschirmen wandern diese Elemente zusammen mit der Suche eine Zeile nach unten.
Der Inhalt der ListItems bricht in der Regel bei kleineren Bildschirmgrößen um. Der Top Content (siehe Content Slots im Overview) kann mithilfe von ColumnLayouts auf kleinen Bildschirmen ausgeblendet werden. Dabei dürfen jedoch nur Informationen ausgeblendet werden, die der User nicht benötigt, um das ListItem zu verstehen.
Wird eine List als einziger Hauptinhalt auf einer Seite verwendet, ist keine
zusätzliche Heading erforderlich. In diesem
Fall muss die List über ein aria-label beschrieben werden.
Hat die List hingegen eine eigene Heading, muss diese mit aria-labelledby der
List zugeordnet werden.
Mit typedList<T> lässt sich eine List für einen bestimmten Datentyp erzeugen.
Im Tab Develop stehen verschiedene Anleitungen zum technischen Aufbau bereit.
import { ActionGroup, AlertBadge, Avatar, Button, ContextMenu, Heading, IconDomain, IconSubdomain, MenuItem, Text, typedList, } from "@mittwald/flow-react-components"; import { type Domain, domains, } from "@/content/04-components/structure/list/examples/domainApi"; export default () => { const DomainList = typedList<Domain>(); return ( <DomainList.List batchSize={4} aria-label="Domains" defaultViewMode="list" getItemId={(domain) => domain.id} > <DomainList.StaticData data={domains} /> <ActionGroup> <Button color="accent">Anlegen</Button> </ActionGroup> <DomainList.Search /> <DomainList.Filter property="type" mode="some" name="Typ" /> <DomainList.Sorting property="hostname" name="Alphabetisch" direction="asc" directionName="aufsteigend" defaultEnabled /> <DomainList.Sorting property="hostname" name="Alphabetisch" direction="desc" directionName="absteigend" /> <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 textValue={(domain) => domain.domain} showTiles > {(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 Liste unterstützt die Ansichten Liste, Raster und Tabelle. Wird mehr
als eine Ansicht verwendet, kann über ein Menü zwischen den Ansichten gewechselt
werden. Die Default-Ansicht wird über das Property defaultViewMode festgelegt.
Nutze <List.Item />, um die List in der Listenansicht darzustellen.
Für die Rasteransicht wird ebenfalls das <List.Item /> verwendet. Nutze
showTiles, um diese Ansicht zu aktivieren. Die Listenansicht kann deaktiviert
werden, indem showList auf false gesetzt wird.
Über das maxTileWidth-Property lässt sich die maximale Breite der Kacheln
steuern.
Nutze <List.Table />, um die List als
Table darzustellen.
| Name | Type | TLD | Hostname |
|---|---|---|---|
In einer List lassen sich ListItems mit unterschiedlichen Interaktions- und Aufbaumöglichkeiten einsetzen.
Ein ListItem bietet das Property href an, um das Element zu verlinken.
Das Accordion-Verhalten wird über die accordion-Property aktiviert. Dadurch
lässt sich ein ListItem per Klick ein- oder ausklappen. Der erweiterte Inhalt
wird in <Content slot="bottom" /> platziert.
Checkboxen in einem ListItem
werden automatisch am Anfang der Zeile angeordnet. Die Funktionalität der
Checkbox wird nicht von der List gesteuert und muss individuell implementiert
werden. Achte bei der Implementierung jedoch darauf, dass die gesamte Zeile zur
Auswahl des Elements genutzt werden kann. Nutze dafür onAction der List.
In einem ListItem kann zusätzlicher <Content/ > (Top und Bottom Content)
platziert werden. Die Position wird über das slot-Property gesteuert.
Dem ListItem können die
ColumnLayout Properties s,
m und l mitgegeben werden, um das Seitenverhältnis sowie das
Umbruchverhalten von Header und Content zu steuern.
Da für die ColumnLayout-Spalten auch null gesetzt werden kann, ist es möglich,
nicht zwingend benötigten Content in kleineren Ansichten auszublenden. In diesem
Fall werden auch die entsprechenden Content Slots nicht angezeigt.
Verwende eine ActionGroup innerhalb des <Content />, um
Buttons in der List zu platzieren.
Die List bietet Sortierung, Filter, Suche und Pagination an. Detaillierte Anleitungen zu den einzelnen Einstellmöglichkeiten stehen unter dem Develop-Tab der List zur Verfügung.
Nutze <List.Sorting /> innerhalb der List, um eine Sortiermethode anzulegen.
Über <List.Filter /> lassen sich Filtermöglichkeiten für die List anlegen.
Über priority kann eingestellt werden, ob Filter immer sichtbar sein sollen
(primary) oder nur in einem "Alle Filter" Modal angezeigt werden (secondary).
"Alle Filter" wird automatisch angezeigt, sobald es secondary Filter gibt.
Mit dem mode="dateRange" kannst du einen Filter definieren, der es ermöglicht,
einen Zeitraum auszuwählen. So lassen sich Einträge gezielt zwischen einem
Start- und Enddatum eingrenzen.
| Rechnung | Datum |
|---|---|
Verwende <List.Search /> innerhalb der List, um ein
SearchField anzuzeigen.
Standardmäßig wird die Suche automatisch gestartet. Soll die Suche nur beim
Drücken auf Enter ausgelöst werden, kann das Property autoSubmit auf false
gesetzt werden.
Die Pagination ist standardmäßig bei jeder List aktiviert, kann jedoch über
hidePagination deaktiviert werden. Über die batchSize-Property kann
festgelegt werden, wie viele Einträge gleichzeitig angezeigt werden sollen.
Während die Daten einer List initial geladen werden, zeigt die List eine
Loading View aus Skeleton-Platzhaltern an. Ohne weitere Angabe wird dafür
ein generisches Skeleton verwendet. Über das loadingView-Property eines
<List.Item /> (bzw. eines <TableCell /> in der Tabellenansicht) lässt sich
diese Ansicht anpassen.
Gestalte die Loading View so, dass sie dem tatsächlichen Inhalt in Aufbau und
Größe möglichst nahekommt, und verwende dafür
Skeleton und SkeletonText. So
wirkt der Übergang von der Lade- zur Inhaltsansicht ruhig und ohne
Layout-Sprung.
Mit emptyView kann eine benutzerdefinierte Ansicht angezeigt werden, wenn die
Liste keine Einträge enthält. So lässt sich beispielsweise eine Illustration mit
einem Hinweistext anzeigen, um die Nutzer zu informieren, dass keine Daten
vorhanden sind, und ihnen gegebenenfalls Tipps zu geben, wie sie Daten
hinzufügen können.
In der Regel sollte als Empty View eine IllustratedMessage verwendet werden, um eine konsistente Nutzererfahrung zu gewährleisten.
Für den Fall, dass eine Suche oder ein Filter kein Ergebnis liefert, kann über
emptySearchResultView eine eigene Ansicht angezeigt werden. Wird sie nicht
gesetzt, zeigt die List einen passenden, vordefinierten Hinweis an.
Loading View (mehrere Skeleton-Zeilen) und Empty View (in der Regel eine einzelne IllustratedMessage) unterscheiden sich in der Höhe. Beim initialen Laden einer leeren Liste entsteht dadurch ein sichtbarer Sprung, sobald von der Lade- zur Leeransicht gewechselt wird.
Ist die List in eine Seite eingebettet, die bereits einen eigenen Ladezustand
anzeigt, lässt sich dieser Sprung vermeiden, indem die List beim initialen Laden
keinen eigenen Ladezustand rendert. Wie sich das über das
disableInitialSuspenseBoundary-Property steuern lässt, ist im Develop-Tab
beschrieben.
Verwende <ActionGroup /> innerhalb der List, um eine
ActionGroup anzuzeigen. Hier
können eine oder mehrere Aktionen definiert werden, die sich direkt auf die
Liste beziehen.
Verwende eine <ListSummary />, um eine Zusammenfassung anzuzeigen,
beispielsweise die Gesamtsumme der Beträge. Über das position-Property wird
festgelegt, ob die Summary oberhalb oder unterhalb der List erscheint.
Die List Component erlaubt das Rendern und Verwalten von Daten in einer strukturierten Liste. Daten können entweder statisch oder asynchron, z. B. über eine API, geladen werden.
Für die Anzeige statischer Daten kann die Component <StaticData /> verwendet
werden:
dataArray: Ein Array mit den Daten, die direkt in der List gerendert werden.Mit <LoaderAsync> können Daten dynamisch aus einer API oder anderen
asynchronen Quellen nachgeladen werden:
Mit <LoaderHooks> können Daten dynamisch über React Hooks nachgeladen werden.
Der Einsatz von Suspense ist hierbei erforderlich.
manualPagination): Aktiviert das serverseitige Paging.manualSorting): Die Sortierung erfolgt auf dem Server.manualFiltering): Filter werden nicht client-seitig
angewendet, sondern an den Server weitergeleitet.Die <LoaderAsync>-Component benötigt eine Async Loader Function, die die
Daten anhand von Steuerungsoptionen lädt. Diese Funktion erhält ein
options-Objekt mit den folgenden Parametern:
options-Objekts| Property | Typ | Beschreibung |
|---|---|---|
filtering | { [key: string]: { mode: "all" | "some" | "one"; values: any[] } } | Enthält Filter für die Daten. Jedes Key-Value-Paar repräsentiert eine Filterbedingung für ein Datenfeld. |
searchString | string | Der eingegebene Suchbegriff. |
pagination | { offset: number; limit: number } | Enthält Offset (Startpunkt) und Limit (maximale Anzahl an Datensätzen). |
sorting | { [key: string]: "asc" | "desc" } | Gibt an, nach welchen Datenfeldern sortiert werden soll. |
Die Funktion muss ein Object mit folgender Struktur zurückgeben:
| Property | Typ | Beschreibung |
|---|---|---|
data | any[] | Array der geladenen Daten. |
itemTotalCount | number | Gesamtanzahl der Datensätze (nur bei Pagination erforderlich). |
Standardmäßig wird die nächste Seite über einen "Mehr anzeigen"-Button nachgeladen. Für sehr lange Listen, in denen ohne konkretes Suchziel gestöbert wird, kann stattdessen Infinite Scroll aktiviert werden: Die nächste Seite wird automatisch geladen, sobald das Ende der Liste in den sichtbaren Bereich scrollt.
manualPagination.Während die Daten initial geladen werden, zeigt die List eine Loading View aus
Skeleton-Platzhaltern an. Über loadingView an einem <List.Item /> – oder an
einem <TableCell /> in der Tabellenansicht – kann diese Ansicht angepasst
werden:
Wird kein loadingView gesetzt, verwendet die List ein generisches Skeleton.
emptyView: Wird angezeigt, wenn die Liste keine Einträge enthält.emptySearchResultView: Wird angezeigt, wenn eine Suche oder ein Filter kein
Ergebnis liefert.Ist das jeweilige Property nicht gesetzt, zeigt die List eine passende, vordefinierte Ansicht an.
Beim initialen Laden umschließt die List das Laden der Daten standardmäßig mit
einer eigenen Suspense-Boundary
und zeigt währenddessen ihre Loading View an. Über
disableInitialSuspenseBoundary an der Datenquelle (<List.StaticData />,
<List.LoaderAsync />, <List.LoaderHooks />) lässt sich dieses Verhalten
steuern:
| Wert | Verhalten |
|---|---|
false (Default) | Die List rendert beim initialen Laden ihre eigene Loading View (Skeleton). |
true | Die List rendert beim initialen Laden keine eigene Suspense-Boundary. Das Suspending wird an die nächste übergeordnete Suspense-Boundary weitergereicht; die List erscheint erst mit geladenen Daten. |
false, wenn die List den Hauptinhalt darstellt oder
keine übergeordnete Ladeanzeige existiert. Nutzer erhalten so unmittelbar ein
visuelles Feedback direkt in der Liste.true, wenn die List in eine Seite oder einen Bereich
eingebettet ist, die bzw. der bereits einen eigenen Ladezustand anzeigt. So
wird die List atomar dargestellt und der Layout-Shift zwischen Loading und
Empty View vermieden.In der Regel werden Filter für ein Property der List gesetzt:
Die Anzeige des Filter-Values kann angepasst werden, um z. B. Übersetzungen zu ermöglichen:
Es gibt die Möglichkeit, eigene Properties zu verwenden, die nicht in der List
vorkommen . Hierfür muss dem property ein "$" vorangestellt werden:
| Property | Typ | Beschreibung |
|---|---|---|
defaultSelected | string[] | Array der als default gesetzten Filter |
matcher | FilterMatcher<T, TProp, string> | Definiert eine eigene Filterlogik für die Listenelemente |
mode | "all" | "some" | "one" | Bestimmt, wie mehrere ausgewählte Filterwerte miteinander kombiniert werden |
name | string | Der Anzeigename des Filters |
property | string | Das für die Filterung verwendete Property |
values | string[] | Die Optionen für den Filter |
Die List unterstützt eine Sortierung nach Properties:
Es gibt außerdem die Möglichkeit, eine eigene Sortierung zu benutzen:
| Property | Typ | Beschreibung |
|---|---|---|
customSortingFn | SortingFn<T> | Möglichkeit eine eigene Sortierfunktion zu definieren |
defaultEnabled | boolean | "hidden" | Bestimmt, ob die Sortierung als default gesetzt wird, bei "hidden" ist die Sortier-Option nicht sichtbar, wird aber im Hintergrund angewendet |
direction | "asc" | "desc" | Auf- oder absteigende Sortierung |
name | string | Der Anzeigename der Sortier-Option |
directionName | string | Der Anzeigename der Sortierrichtung |
property | string | Das für die Sortierung verwendete Property |
| Property | Type | Default | Description |
|---|---|---|---|
batchSize | number | - | The number of items to be displayed on one page. |
infiniteScroll | boolean | false | Automatically loads the next batch of items when the user scrolls to the end of the list, instead of showing a "Show more" button. |
hidePagination | boolean | - | |
emptySearchResultView | ReactNode | - | |
emptyView | ReactNode | - | |
children | ReactNode | - | |
wrapWith | ReactElement<unknown, string | JSXElementConstructor<any>> | - | |
ref | Ref<HTMLSpanElement> | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see React Docs |
key | Key | - | |
disallowEmptySelection | boolean | - | Whether the collection allows empty selection. |
disabledKeys | Iterable<Key> | - | The currently disabled keys in the collection (controlled). |
selectionMode | SelectionMode | - | The type of selection that is allowed in the collection. |
selectedKeys | Iterable<Key> | "all" | - | The currently selected keys in the collection (controlled). |
defaultSelectedKeys | Iterable<Key> | "all" | - | The initial selected keys in the collection (uncontrolled). |
selectionBehavior | SelectionBehavior | - | |
accordion | boolean | - | |
settingStorageKey | string | - | |
loadingItemsCount | number | - | |
getItemId | GetItemId<never> | - | |
defaultViewMode | ListViewMode | - | |
settingsStorageDefaults | ListSettingsStorageDefaults | - |
| Property | Type | Default | Description |
|---|---|---|---|
onChange | OnListChanged<never, unknown> | - | |
onSelectionChange | ((keys: Selection) => void) | - | Handler that is called when the selection changes. |
onAction | ItemActionFn<never> | - |
| Property | Type | Default | Description |
|---|---|---|---|
aria-label | string | - | |
aria-labelledby | string | - |