dropdown ok
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Dropdown
|
||||
|
||||
Dropdown component for creating menus, selectors, and action panels that appear when triggered. Supports both array-based items and custom content.
|
||||
Dropdown component for creating menus that appear when triggered. Uses DaisyUI's native details/summary pattern.
|
||||
|
||||
## Tag
|
||||
|
||||
@@ -12,11 +12,10 @@ Dropdown component for creating menus, selectors, and action panels that appear
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `label` | `string \| VNode \| Signal` | `-` | Button label or content |
|
||||
| `icon` | `string \| VNode \| Signal` | `-` | Icon displayed next to label |
|
||||
| `items` | `Array<MenuItem> \| Signal<Array>` | `-` | Array of menu items (alternative to children) |
|
||||
| `items` | `Array<MenuItem> \| Signal<Array>` | Required | Array of menu items |
|
||||
| `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) |
|
||||
| `children` | `VNode \| function` | `-` | Custom dropdown content (alternative to items) |
|
||||
|
||||
### MenuItem Structure (when using `items`)
|
||||
### MenuItem Structure
|
||||
|
||||
| Property | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
@@ -43,14 +42,16 @@ Dropdown supports all **daisyUI Dropdown classes**:
|
||||
Dropdown({
|
||||
label: "Menu",
|
||||
class: "dropdown-end dropdown-hover",
|
||||
items: menuItems
|
||||
items: [
|
||||
{ label: "Profile", onclick: () => console.log("Profile") },
|
||||
{ label: "Settings", onclick: () => console.log("Settings") }
|
||||
]
|
||||
});
|
||||
// Applies: right-aligned, opens on hover
|
||||
```
|
||||
|
||||
## Live Examples
|
||||
|
||||
### Basic Dropdown (Items Array)
|
||||
### Basic Dropdown
|
||||
|
||||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||||
<div class="card-body">
|
||||
@@ -73,7 +74,7 @@ const BasicDemo = () => {
|
||||
$mount(BasicDemo, '#demo-basic');
|
||||
```
|
||||
|
||||
### With Icons (Items Array)
|
||||
### With Icons
|
||||
|
||||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||||
<div class="card-body">
|
||||
@@ -98,7 +99,7 @@ const IconsDemo = () => {
|
||||
$mount(IconsDemo, '#demo-icons');
|
||||
```
|
||||
|
||||
### Action Dropdown (Items Array)
|
||||
### Action Dropdown
|
||||
|
||||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||||
<div class="card-body">
|
||||
@@ -126,7 +127,7 @@ const ActionsDemo = () => {
|
||||
$mount(ActionsDemo, '#demo-actions');
|
||||
```
|
||||
|
||||
### User Dropdown (Items Array)
|
||||
### User Dropdown
|
||||
|
||||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||||
<div class="card-body">
|
||||
@@ -167,7 +168,7 @@ $mount(UserDropdown, '#demo-user');
|
||||
```javascript
|
||||
const ReactiveDropdown = () => {
|
||||
const count = $(0);
|
||||
|
||||
$watch(()=>console.log(count()));
|
||||
const items = () => [
|
||||
{ label: `Count: ${count()}`, onclick: () => {} },
|
||||
{ label: 'Increment', onclick: () => count(count() + 1) },
|
||||
@@ -183,7 +184,7 @@ const ReactiveDropdown = () => {
|
||||
$mount(ReactiveDropdown, '#demo-reactive');
|
||||
```
|
||||
|
||||
### Notification Dropdown (Custom Children)
|
||||
### Notification Dropdown
|
||||
|
||||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||||
<div class="card-body">
|
||||
@@ -200,81 +201,34 @@ const NotificationsDropdown = () => {
|
||||
{ id: 3, title: 'Task completed', time: '2 hours ago', read: true }
|
||||
]);
|
||||
|
||||
const unreadCount = () => notifications().filter(n => !n.read).length;
|
||||
|
||||
const markAsRead = (id) => {
|
||||
notifications(notifications().map(n =>
|
||||
n.id === id ? { ...n, read: true } : n
|
||||
));
|
||||
};
|
||||
|
||||
const unreadCount = () => notifications().filter(n => !n.read).length;
|
||||
|
||||
return Dropdown({
|
||||
label: Span({ class: 'relative' }, [
|
||||
'🔔',
|
||||
() => unreadCount() > 0 ? Span({ class: 'badge badge-xs badge-error absolute -top-1 -right-2' }, unreadCount()) : null
|
||||
]),
|
||||
class: 'dropdown-end',
|
||||
children: () => Div({ class: 'w-80' }, [
|
||||
Div({ class: 'p-3 border-b border-base-300 font-bold' }, `Notifications (${unreadCount()} unread)`),
|
||||
Div({ class: 'max-h-64 overflow-y-auto' }, notifications().map(notif =>
|
||||
Div({
|
||||
class: `p-3 border-b border-base-300 cursor-pointer hover:bg-base-200 ${!notif.read ? 'bg-primary/5' : ''}`,
|
||||
onclick: () => markAsRead(notif.id)
|
||||
}, [
|
||||
Div({ class: 'font-medium' }, notif.title),
|
||||
Div({ class: 'text-xs opacity-60' }, notif.time),
|
||||
!notif.read && Span({ class: 'badge badge-xs badge-primary mt-1' }, 'New')
|
||||
])
|
||||
)),
|
||||
Div({ class: 'p-2 text-center' }, [
|
||||
Button({
|
||||
class: 'btn btn-xs btn-ghost w-full',
|
||||
onclick: () => notifications([])
|
||||
}, 'Clear all')
|
||||
])
|
||||
])
|
||||
items: () => notifications().map(notif => ({
|
||||
label: Div({ class: 'flex flex-col' }, [
|
||||
Span({ class: 'font-medium' }, notif.title),
|
||||
Span({ class: 'text-xs opacity-60' }, notif.time)
|
||||
]),
|
||||
class: notif.read ? '' : 'bg-primary/5',
|
||||
onclick: () => markAsRead(notif.id)
|
||||
}))
|
||||
});
|
||||
};
|
||||
|
||||
$mount(NotificationsDropdown, '#demo-notifications');
|
||||
```
|
||||
|
||||
### Custom Content Dropdown
|
||||
|
||||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||||
<div id="demo-custom" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
```javascript
|
||||
const CustomDropdown = () => {
|
||||
const selected = $('Option 1');
|
||||
|
||||
return Dropdown({
|
||||
label: () => selected(),
|
||||
children: () => Div({ class: 'p-4 min-w-48' }, [
|
||||
Div({ class: 'text-sm font-bold mb-2' }, 'Select an option'),
|
||||
Div({ class: 'flex flex-col gap-1' }, [
|
||||
Button({
|
||||
class: 'btn btn-ghost btn-sm justify-start',
|
||||
onclick: () => selected('Option 1')
|
||||
}, 'Option 1'),
|
||||
Button({
|
||||
class: 'btn btn-ghost btn-sm justify-start',
|
||||
onclick: () => selected('Option 2')
|
||||
}, 'Option 2'),
|
||||
Button({
|
||||
class: 'btn btn-ghost btn-sm justify-start',
|
||||
onclick: () => selected('Option 3')
|
||||
}, 'Option 3')
|
||||
])
|
||||
])
|
||||
});
|
||||
};
|
||||
$mount(CustomDropdown, '#demo-custom');
|
||||
```
|
||||
|
||||
### All Variants
|
||||
|
||||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||||
|
||||
Reference in New Issue
Block a user