# List List component with custom item rendering, headers, and reactive data binding. ## Tag `List` ## Props | Prop | Type | Default | Description | | :----------- | :-------------------------------------- | :--------------- | :----------------------------------------------- | | `items` | `Array \| Signal` | `[]` | Data array to display | | `header` | `string \| VNode \| Signal` | `-` | Optional header content | | `render` | `function(item, index)` | `-` | Custom render function for each item | | `keyFn` | `function(item, index)` | `(item, idx) => idx` | Unique key function for items | | `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) | ## Live Examples ### Basic List

Live Demo

```javascript const BasicDemo = () => { const items = ['Apple', 'Banana', 'Orange', 'Grape', 'Mango']; return List({ items: items, render: (item) => Div({ class: 'p-3 hover:bg-base-200 transition-colors' }, [ Span({ class: 'font-medium' }, item) ]) }); }; $mount(BasicDemo, '#demo-basic'); ``` ### With Header

Live Demo

```javascript const HeaderDemo = () => { const users = [ { name: 'John Doe', email: 'john@example.com', status: 'active' }, { name: 'Jane Smith', email: 'jane@example.com', status: 'inactive' }, { name: 'Bob Johnson', email: 'bob@example.com', status: 'active' } ]; return List({ items: users, header: Div({ class: 'p-3 bg-primary/10 font-bold border-b border-base-300' }, 'Active Users'), render: (user) => Div({ class: 'p-3 border-b border-base-300 hover:bg-base-200' }, [ Div({ class: 'font-medium' }, user.name), Div({ class: 'text-sm opacity-70' }, user.email), Span({ class: `badge badge-sm ${user.status === 'active' ? 'badge-success' : 'badge-ghost'} mt-1` }, user.status) ]) }); }; $mount(HeaderDemo, '#demo-header'); ``` ### With Icons

Live Demo

```javascript const IconsDemo = () => { const settings = [ { icon: '🔊', label: 'Sound', description: 'Adjust volume and notifications' }, { icon: '🌙', label: 'Display', description: 'Brightness and dark mode' }, { icon: '🔒', label: 'Privacy', description: 'Security settings' }, { icon: '🌐', label: 'Network', description: 'WiFi and connections' } ]; return List({ items: settings, render: (item) => Div({ class: 'flex gap-3 p-3 hover:bg-base-200 transition-colors cursor-pointer' }, [ Div({ class: 'text-2xl' }, item.icon), Div({ class: 'flex-1' }, [ Div({ class: 'font-medium' }, item.label), Div({ class: 'text-sm opacity-60' }, item.description) ]), Span({ class: 'opacity-40' }, '→') ]) }); }; $mount(IconsDemo, '#demo-icons'); ``` ### With Badges

Live Demo

```javascript const BadgesDemo = () => { const notifications = [ { id: 1, message: 'New comment on your post', time: '5 min ago', unread: true }, { id: 2, message: 'Your order has been shipped', time: '1 hour ago', unread: true }, { id: 3, message: 'Welcome to the platform!', time: '2 days ago', unread: false }, { id: 4, message: 'Weekly digest available', time: '3 days ago', unread: false } ]; return List({ items: notifications, render: (item) => Div({ class: `flex justify-between items-center p-3 border-b border-base-300 hover:bg-base-200 ${item.unread ? 'bg-primary/5' : ''}` }, [ Div({ class: 'flex-1' }, [ Div({ class: 'font-medium' }, item.message), Div({ class: 'text-xs opacity-50' }, item.time) ]), item.unread ? Span({ class: 'badge badge-primary badge-sm' }, 'New') : null ]) }); }; $mount(BadgesDemo, '#demo-badges'); ``` ### Interactive List

Live Demo

```javascript const InteractiveDemo = () => { const selected = $(null); const items = [ { id: 1, name: 'Project Alpha', status: 'In Progress' }, { id: 2, name: 'Project Beta', status: 'Planning' }, { id: 3, name: 'Project Gamma', status: 'Completed' }, { id: 4, name: 'Project Delta', status: 'Review' } ]; const statusColors = { 'In Progress': 'badge-warning', 'Planning': 'badge-info', 'Completed': 'badge-success', 'Review': 'badge-accent' }; return Div({ class: 'flex flex-col gap-4' }, [ List({ items: items, render: (item) => Div({ class: `p-3 cursor-pointer transition-all hover:bg-base-200 ${selected() === item.id ? 'bg-primary/10 border-l-4 border-primary' : 'border-l-4 border-transparent'}`, onclick: () => selected(item.id) }, [ Div({ class: 'flex justify-between items-center' }, [ Div({ class: 'font-medium' }, item.name), Span({ class: `badge ${statusColors[item.status]}` }, item.status) ]) ]) }), () => selected() ? Div({ class: 'alert alert-info' }, `Selected: ${items.find(i => i.id === selected()).name}`) : Div({ class: 'alert alert-soft' }, 'Select a project to see details') ]); }; $mount(InteractiveDemo, '#demo-interactive'); ``` ### Reactive List

Live Demo

```javascript const ReactiveDemo = () => { const todos = $([ { id: 1, text: 'Complete documentation', done: false }, { id: 2, text: 'Review pull requests', done: false }, { id: 3, text: 'Deploy to production', done: false } ]); const newTodo = $(''); const addTodo = () => { if (newTodo().trim()) { const newId = Math.max(...todos().map(t => t.id), 0) + 1; todos([...todos(), { id: newId, text: newTodo(), done: false }]); newTodo(''); } }; const toggleTodo = (id) => { todos(todos().map(t => t.id === id ? { ...t, done: !t.done } : t )); }; const deleteTodo = (id) => { todos(todos().filter(t => t.id !== id)); }; const pendingCount = () => todos().filter(t => !t.done).length; return Div({ class: 'flex flex-col gap-4' }, [ Div({ class: 'flex gap-2' }, [ Input({ placeholder: 'Add new task...', value: newTodo, class: 'flex-1', oninput: (e) => newTodo(e.target.value), onkeypress: (e) => e.key === 'Enter' && addTodo() }), Button({ class: 'btn btn-primary', onclick: addTodo }, 'Add') ]), List({ items: todos, render: (todo) => Div({ class: `flex items-center gap-3 p-2 border-b border-base-300 hover:bg-base-200 ${todo.done ? 'opacity-60' : ''}` }, [ Checkbox({ value: todo.done, onclick: () => toggleTodo(todo.id) }), Span({ class: `flex-1 ${todo.done ? 'line-through' : ''}`, onclick: () => toggleTodo(todo.id) }, todo.text), Button({ class: 'btn btn-ghost btn-xs btn-circle', onclick: () => deleteTodo(todo.id) }, '✕') ]) }), Div({ class: 'text-sm opacity-70 mt-2' }, () => `${pendingCount()} tasks remaining`) ]); }; $mount(ReactiveDemo, '#demo-reactive'); ``` ### Avatar List

Live Demo

```javascript const AvatarDemo = () => { const contacts = [ { name: 'Alice Johnson', role: 'Developer', avatar: 'A', online: true }, { name: 'Bob Smith', role: 'Designer', avatar: 'B', online: false }, { name: 'Charlie Brown', role: 'Manager', avatar: 'C', online: true }, { name: 'Diana Prince', role: 'QA Engineer', avatar: 'D', online: false } ]; return List({ items: contacts, render: (contact) => Div({ class: 'flex gap-3 p-3 hover:bg-base-200 transition-colors' }, [ Div({ class: `avatar ${contact.online ? 'online' : 'offline'}`, style: 'width: 48px' }, [ Div({ class: 'rounded-full bg-primary text-primary-content flex items-center justify-center w-12 h-12 font-bold' }, contact.avatar) ]), Div({ class: 'flex-1' }, [ Div({ class: 'font-medium' }, contact.name), Div({ class: 'text-sm opacity-60' }, contact.role) ]), Div({ class: `badge badge-sm ${contact.online ? 'badge-success' : 'badge-ghost'}` }, contact.online ? 'Online' : 'Offline') ]) }); }; $mount(AvatarDemo, '#demo-avatar'); ``` ### All Variants

Live Demo

```javascript const VariantsDemo = () => { const items = ['Item 1', 'Item 2', 'Item 3']; return Div({ class: 'flex flex-col gap-6' }, [ Div({ class: 'text-sm font-bold' }, 'Default List'), List({ items: items, render: (item) => Div({ class: 'p-2' }, item) }), Div({ class: 'text-sm font-bold mt-2' }, 'With Shadow'), List({ items: items, render: (item) => Div({ class: 'p-2' }, item), class: 'shadow-lg' }), Div({ class: 'text-sm font-bold mt-2' }, 'Rounded Corners'), List({ items: items, render: (item) => Div({ class: 'p-2' }, item), class: 'rounded-box overflow-hidden' }) ]); }; $mount(VariantsDemo, '#demo-variants'); ```