Skip to main content

List

Die List-Komponente ermöglicht die Darstellung von Daten in Form von Listen mit verschiedenen Stilen und Funktionen.

Import

import { List, ListItem, ListItemText, ListItemIcon, ListItemAction } from '@smolitux/core';

Verwendung

Einfache Liste

<List>
<ListItem primary="Item 1" />
<ListItem primary="Item 2" />
<ListItem primary="Item 3" />
</List>

Liste mit primärem und sekundärem Text

<List>
<ListItem
primary="Inbox"
secondary="Alle eingehenden Nachrichten"
/>
<ListItem
primary="Gesendet"
secondary="Alle gesendeten Nachrichten"
/>
<ListItem
primary="Entwürfe"
secondary="Gespeicherte Entwürfe"
/>
</List>

Liste mit Icons

<List>
<ListItem
icon={<InboxIcon className="w-5 h-5" />}
primary="Inbox"
/>
<ListItem
icon={<SendIcon className="w-5 h-5" />}
primary="Gesendet"
/>
<ListItem
icon={<DraftIcon className="w-5 h-5" />}
primary="Entwürfe"
/>
</List>

Liste mit Aktionen

<List>
<ListItem
primary="Dokument 1"
action={
<Button size="sm" variant="text">Öffnen</Button>
}
/>
<ListItem
primary="Dokument 2"
action={
<Button size="sm" variant="text">Öffnen</Button>
}
/>
</List>

Liste mit Trennlinien

<List dividers>
<ListItem primary="Item 1" />
<ListItem primary="Item 2" />
<ListItem primary="Item 3" />
</List>

Horizontale Liste

<List horizontal>
<ListItem primary="Home" />
<ListItem primary="Produkte" />
<ListItem primary="Über uns" />
<ListItem primary="Kontakt" />
</List>

Geordnete Liste

<List variant="ordered">
<ListItem primary="Erster Schritt" />
<ListItem primary="Zweiter Schritt" />
<ListItem primary="Dritter Schritt" />
</List>

Ungeordnete Liste

<List variant="unordered">
<ListItem primary="Äpfel" />
<ListItem primary="Bananen" />
<ListItem primary="Orangen" />
</List>

Beschreibungsliste

<List variant="description">
<ListItem primary="Name" secondary="Max Mustermann" />
<ListItem primary="E-Mail" secondary="max@example.com" />
<ListItem primary="Telefon" secondary="+49 123 456789" />
</List>

Liste mit benutzerdefiniertem Marker

<List variant="unordered" marker="">
<ListItem primary="Erster Punkt" />
<ListItem primary="Zweiter Punkt" />
<ListItem primary="Dritter Punkt" />
</List>

Liste mit verschiedenen Größen

<>
<List size="sm" className="mb-4">
<ListItem primary="Kleine Liste" />
<ListItem primary="Mit kleiner Schrift" />
</List>

<List size="md" className="mb-4">
<ListItem primary="Mittlere Liste" />
<ListItem primary="Mit mittlerer Schrift" />
</List>

<List size="lg">
<ListItem primary="Große Liste" />
<ListItem primary="Mit großer Schrift" />
</List>
</>

Liste mit verschiedenen Dichten

<>
<List density="compact" className="mb-4">
<ListItem primary="Kompakte Liste" />
<ListItem primary="Mit weniger Abstand" />
</List>

<List density="default" className="mb-4">
<ListItem primary="Standard-Liste" />
<ListItem primary="Mit normalem Abstand" />
</List>

<List density="comfortable">
<ListItem primary="Komfortable Liste" />
<ListItem primary="Mit mehr Abstand" />
</List>
</>

Auswählbare Liste

function SelectableListExample() {
const [selectedItem, setSelectedItem] = useState('item1');

const handleSelectItem = (id) => {
setSelectedItem(id);
};

return (
<List
selectable
selectedItem={selectedItem}
onSelectItem={handleSelectItem}
>
<ListItem id="item1" primary="Auswählbares Item 1" />
<ListItem id="item2" primary="Auswählbares Item 2" />
<ListItem id="item3" primary="Auswählbares Item 3" />
</List>
);
}

Liste mit deaktivierten Items

<List>
<ListItem primary="Aktives Item" />
<ListItem primary="Deaktiviertes Item" disabled />
<ListItem primary="Aktives Item" />
</List>

Liste mit benutzerdefinierten Komponenten

<List>
<ListItem>
<ListItemIcon>
<UserIcon className="w-5 h-5" />
</ListItemIcon>
<ListItemText
primary="Benutzerprofil"
secondary="Persönliche Informationen verwalten"
/>
<ListItemAction>
<Button size="sm" variant="outlined">Bearbeiten</Button>
</ListItemAction>
</ListItem>
<ListItem>
<ListItemIcon>
<SettingsIcon className="w-5 h-5" />
</ListItemIcon>
<ListItemText
primary="Einstellungen"
secondary="Konto- und App-Einstellungen"
/>
<ListItemAction>
<Button size="sm" variant="outlined">Öffnen</Button>
</ListItemAction>
</ListItem>
</List>

Props

List Props

PropTypStandardBeschreibung
variant'default' | 'ordered' | 'unordered' | 'description' | 'custom''default'Variante der Liste
size'sm' | 'md' | 'lg''md'Größe der Liste
density'compact' | 'default' | 'comfortable''default'Dichte der Liste
align'start' | 'center' | 'end''start'Ausrichtung der Listenelemente
dividersbooleanfalseTrennlinien zwischen Listenelementen anzeigen
horizontalbooleanfalseHorizontale Liste
iconReactNode-Benutzerdefiniertes Icon für Listenelemente
marker'disc' | 'circle' | 'square' | 'none' | string-Benutzerdefiniertes Marker-Symbol für ungeordnete Listen
indentbooleantrueEinrückung der Liste
selectablebooleanfalseListenelemente können ausgewählt werden
selectedItemstring | number | nullnullAusgewähltes Listenelement (kontrollierter Modus)
onSelectItem(id: string | number) => void-Callback bei Auswahl eines Listenelements
classNamestring-Zusätzliche CSS-Klassen

ListItem Props

PropTypStandardBeschreibung
idstring | number-Eindeutige ID des Listenelements
primaryReactNode-Primärer Text
secondaryReactNode-Sekundärer Text
iconReactNode-Icon links vom Text
actionReactNode-Element rechts vom Text
selectedboolean-Ist das Element ausgewählt?
disabledbooleanfalseIst das Element deaktiviert?
onClick(event: React.MouseEvent<HTMLLIElement>) => void-Callback bei Klick auf das Listenelement
classNamestring-Zusätzliche CSS-Klassen

ListItemText Props

PropTypStandardBeschreibung
primaryReactNode-Primärer Text
secondaryReactNode-Sekundärer Text
classNamestring-Zusätzliche CSS-Klassen

ListItemIcon Props

PropTypStandardBeschreibung
childrenReactNode-Icon-Element
classNamestring-Zusätzliche CSS-Klassen

ListItemAction Props

PropTypStandardBeschreibung
childrenReactNode-Aktions-Element
classNamestring-Zusätzliche CSS-Klassen

Barrierefreiheit

Die List-Komponente ist für Barrierefreiheit optimiert:

  • Verwendet semantisch korrekte HTML-Elemente (ul, ol, li)
  • Unterstützt Tastaturnavigation für auswählbare Listen
  • Verwendet ARIA-Attribute für bessere Screenreader-Unterstützung
  • Deaktivierte Elemente werden mit aria-disabled gekennzeichnet
  • Ausgewählte Elemente werden mit aria-selected gekennzeichnet

Beispiele

function NavigationMenu() {
const [selectedItem, setSelectedItem] = useState('dashboard');

const handleSelectItem = (id) => {
setSelectedItem(id);
};

return (
<div className="w-64 bg-white border-r h-screen p-4">
<h2 className="text-lg font-bold mb-4">Admin Panel</h2>

<List
selectable
selectedItem={selectedItem}
onSelectItem={handleSelectItem}
>
<ListItem
id="dashboard"
icon={<DashboardIcon className="w-5 h-5" />}
primary="Dashboard"
/>
<ListItem
id="users"
icon={<UsersIcon className="w-5 h-5" />}
primary="Benutzer"
/>
<ListItem
id="products"
icon={<BoxIcon className="w-5 h-5" />}
primary="Produkte"
/>
<ListItem
id="orders"
icon={<ShoppingCartIcon className="w-5 h-5" />}
primary="Bestellungen"
secondary="12 neue Bestellungen"
/>
<ListItem
id="settings"
icon={<SettingsIcon className="w-5 h-5" />}
primary="Einstellungen"
/>
</List>
</div>
);
}

Kontaktliste

function ContactList() {
const contacts = [
{ id: 1, name: 'Max Mustermann', email: 'max@example.com', avatar: '/avatars/max.jpg', status: 'online' },
{ id: 2, name: 'Anna Schmidt', email: 'anna@example.com', avatar: '/avatars/anna.jpg', status: 'offline' },
{ id: 3, name: 'Tom Müller', email: 'tom@example.com', avatar: '/avatars/tom.jpg', status: 'busy' },
{ id: 4, name: 'Lisa Weber', email: 'lisa@example.com', avatar: '/avatars/lisa.jpg', status: 'away' }
];

const getStatusColor = (status) => {
switch (status) {
case 'online': return 'bg-green-500';
case 'offline': return 'bg-gray-400';
case 'busy': return 'bg-red-500';
case 'away': return 'bg-yellow-500';
default: return 'bg-gray-400';
}
};

return (
<div className="max-w-md mx-auto bg-white rounded-lg shadow-md overflow-hidden">
<div className="p-4 bg-primary-600 text-white">
<h2 className="text-lg font-bold">Kontakte</h2>
</div>

<List dividers>
{contacts.map(contact => (
<ListItem
key={contact.id}
id={contact.id}
icon={
<div className="relative">
<Avatar
src={contact.avatar}
alt={contact.name}
size="md"
/>
<span
className={`absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-white ${getStatusColor(contact.status)}`}
/>
</div>
}
primary={contact.name}
secondary={contact.email}
action={
<Button
size="sm"
variant="text"
icon={<MessageIcon className="w-4 h-4" />}
/>
}
/>
))}
</List>
</div>
);
}

Todo-Liste

function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: 'Design-Meeting vorbereiten', completed: false },
{ id: 2, text: 'Präsentation erstellen', completed: false },
{ id: 3, text: 'E-Mails beantworten', completed: true },
{ id: 4, text: 'Projekt-Dokumentation aktualisieren', completed: false }
]);

const handleToggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};

const handleDeleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};

return (
<div className="max-w-md mx-auto bg-white rounded-lg shadow-md overflow-hidden">
<div className="p-4 bg-primary-600 text-white">
<h2 className="text-lg font-bold">Aufgaben</h2>
</div>

<List dividers>
{todos.map(todo => (
<ListItem
key={todo.id}
icon={
<Checkbox
checked={todo.completed}
onChange={() => handleToggleTodo(todo.id)}
/>
}
primary={
<span className={todo.completed ? 'line-through text-gray-400' : ''}>
{todo.text}
</span>
}
action={
<Button
size="sm"
variant="text"
color="danger"
icon={<TrashIcon className="w-4 h-4" />}
onClick={() => handleDeleteTodo(todo.id)}
/>
}
/>
))}
</List>

<div className="p-4 border-t">
<input
type="text"
placeholder="Neue Aufgabe hinzufügen..."
className="w-full px-3 py-2 border rounded-md"
onKeyPress={(e) => {
if (e.key === 'Enter' && e.target.value.trim()) {
setTodos([
...todos,
{
id: Date.now(),
text: e.target.value.trim(),
completed: false
}
]);
e.target.value = '';
}
}}
/>
</div>
</div>
);
}

FAQ-Liste

function FAQList() {
const faqs = [
{
question: 'Was ist Smolitux UI?',
answer: 'Smolitux UI ist eine moderne React-Komponentenbibliothek für die einheitliche Gestaltung von Anwendungen im Smolitux Ökosystem.'
},
{
question: 'Wie installiere ich Smolitux UI?',
answer: 'Sie können Smolitux UI mit npm oder yarn installieren: npm install @smolitux/core oder yarn add @smolitux/core'
},
{
question: 'Ist Smolitux UI für Produktionsanwendungen geeignet?',
answer: 'Ja, Smolitux UI ist für den Einsatz in Produktionsanwendungen konzipiert und wird regelmäßig aktualisiert und getestet.'
},
{
question: 'Unterstützt Smolitux UI Barrierefreiheit?',
answer: 'Ja, Smolitux UI legt großen Wert auf Barrierefreiheit und folgt den WCAG-Richtlinien, um eine inklusive Benutzererfahrung zu gewährleisten.'
}
];

const [expandedItem, setExpandedItem] = useState(null);

const toggleItem = (index) => {
setExpandedItem(expandedItem === index ? null : index);
};

return (
<div className="max-w-2xl mx-auto">
<h2 className="text-2xl font-bold mb-6">Häufig gestellte Fragen</h2>

<List variant="custom" dividers>
{faqs.map((faq, index) => (
<ListItem
key={index}
onClick={() => toggleItem(index)}
className="cursor-pointer"
>
<div className="w-full">
<div className="flex justify-between items-center">
<h3 className="text-lg font-medium">{faq.question}</h3>
<div className="ml-4">
{expandedItem === index ? (
<MinusIcon className="w-5 h-5" />
) : (
<PlusIcon className="w-5 h-5" />
)}
</div>
</div>

{expandedItem === index && (
<div className="mt-2 text-gray-600">
{faq.answer}
</div>
)}
</div>
</ListItem>
))}
</List>
</div>
);
}