Updateing Docs
This commit is contained in:
489
docs/components_old/dropdown.md
Normal file
489
docs/components_old/dropdown.md
Normal file
@@ -0,0 +1,489 @@
|
||||
# Dropdown
|
||||
|
||||
Dropdown component for creating menus, selectors, and action panels that appear when triggered. Supports both array-based items and custom content.
|
||||
|
||||
## Tag
|
||||
|
||||
`Dropdown`
|
||||
|
||||
## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| :----------- | :-------------------------------------- | :---------- | :----------------------------------------------- |
|
||||
| `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) |
|
||||
| `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) |
|
||||
| `children` | `VNode \| function` | `-` | Custom dropdown content (alternative to items) |
|
||||
|
||||
### MenuItem Structure (when using `items`)
|
||||
|
||||
| Property | Type | Description |
|
||||
| :---------- | :--------------------------- | :----------------------------------------------- |
|
||||
| `label` | `string \| VNode` | Menu item text |
|
||||
| `icon` | `string \| VNode` | Optional icon for the menu item |
|
||||
| `onclick` | `function` | Click handler |
|
||||
| `class` | `string` | Additional CSS classes for the menu item |
|
||||
|
||||
## Live Examples
|
||||
|
||||
### Basic Dropdown (Items Array)
|
||||
|
||||
<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-basic" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
```javascript
|
||||
const BasicDemo = () => {
|
||||
return Dropdown({
|
||||
label: 'Options',
|
||||
items: [
|
||||
{ label: 'Profile', onclick: () => Toast('Profile clicked', 'alert-info', 2000) },
|
||||
{ label: 'Settings', onclick: () => Toast('Settings clicked', 'alert-info', 2000) },
|
||||
{ label: 'Logout', onclick: () => Toast('Logged out', 'alert-warning', 2000), class: 'text-error' }
|
||||
]
|
||||
});
|
||||
};
|
||||
$mount(BasicDemo, '#demo-basic');
|
||||
```
|
||||
|
||||
### With Icons (Items Array)
|
||||
|
||||
<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-icons" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
```javascript
|
||||
const IconsDemo = () => {
|
||||
return Dropdown({
|
||||
label: 'Menu',
|
||||
icon: '☰',
|
||||
items: [
|
||||
{ icon: '👤', label: 'Profile', onclick: () => Toast('Profile', 'alert-info', 2000) },
|
||||
{ icon: '⭐', label: 'Favorites', onclick: () => Toast('Favorites', 'alert-info', 2000) },
|
||||
{ icon: '📁', label: 'Documents', onclick: () => Toast('Documents', 'alert-info', 2000) },
|
||||
{ icon: '⚙️', label: 'Settings', onclick: () => Toast('Settings', 'alert-info', 2000) }
|
||||
]
|
||||
});
|
||||
};
|
||||
$mount(IconsDemo, '#demo-icons');
|
||||
```
|
||||
|
||||
### Action Dropdown (Items Array)
|
||||
|
||||
<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-actions" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
```javascript
|
||||
const ActionsDemo = () => {
|
||||
const handleAction = (action) => {
|
||||
Toast(`${action} action`, 'alert-info', 2000);
|
||||
};
|
||||
|
||||
return Dropdown({
|
||||
label: 'Actions',
|
||||
class: 'dropdown-end',
|
||||
items: [
|
||||
{ icon: '✏️', label: 'Edit', onclick: () => handleAction('Edit') },
|
||||
{ icon: '📋', label: 'Copy', onclick: () => handleAction('Copy') },
|
||||
{ icon: '🗑️', label: 'Delete', onclick: () => handleAction('Delete'), class: 'text-error' }
|
||||
]
|
||||
});
|
||||
};
|
||||
$mount(ActionsDemo, '#demo-actions');
|
||||
```
|
||||
|
||||
### User Dropdown (Items Array)
|
||||
|
||||
<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-user" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
```javascript
|
||||
const UserDropdown = () => {
|
||||
return Dropdown({
|
||||
label: Span({ class: 'flex items-center gap-2' }, [
|
||||
Div({ class: 'avatar placeholder' }, [
|
||||
Div({ class: 'bg-primary text-primary-content rounded-full w-8 h-8 flex items-center justify-center text-sm' }, 'JD')
|
||||
]),
|
||||
'John Doe'
|
||||
]),
|
||||
class: 'dropdown-end',
|
||||
items: [
|
||||
{ label: 'Profile', onclick: () => Toast('Profile', 'alert-info', 2000) },
|
||||
{ label: 'Settings', onclick: () => Toast('Settings', 'alert-info', 2000) },
|
||||
{ label: 'Sign Out', onclick: () => Toast('Signed out', 'alert-warning', 2000), class: 'text-error' }
|
||||
]
|
||||
});
|
||||
};
|
||||
$mount(UserDropdown, '#demo-user');
|
||||
```
|
||||
|
||||
### Reactive Items
|
||||
|
||||
<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-reactive" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
```javascript
|
||||
const ReactiveDropdown = () => {
|
||||
const count = $(0);
|
||||
|
||||
const items = () => [
|
||||
{ label: `Count: ${count()}`, onclick: () => {} },
|
||||
{ label: 'Increment', onclick: () => count(count() + 1) },
|
||||
{ label: 'Decrement', onclick: () => count(count() - 1) },
|
||||
{ label: 'Reset', onclick: () => count(0) }
|
||||
];
|
||||
|
||||
return Dropdown({
|
||||
label: () => `Counter (${count()})`,
|
||||
items: items
|
||||
});
|
||||
};
|
||||
$mount(ReactiveDropdown, '#demo-reactive');
|
||||
```
|
||||
|
||||
### Notification Dropdown (Custom Children)
|
||||
|
||||
<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-notifications" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
```javascript
|
||||
const NotificationsDropdown = () => {
|
||||
const notifications = $([
|
||||
{ id: 1, title: 'New message', time: '5 min ago', read: false },
|
||||
{ id: 2, title: 'Update available', time: '1 hour ago', read: false },
|
||||
{ id: 3, title: 'Task completed', time: '2 hours ago', read: true }
|
||||
]);
|
||||
|
||||
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')
|
||||
])
|
||||
])
|
||||
});
|
||||
};
|
||||
$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">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||||
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300 flex flex-wrap gap-4 justify-center"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
```javascript
|
||||
const VariantsDemo = () => {
|
||||
const commonItems = [
|
||||
{ label: 'Item 1', onclick: () => Toast('Item 1', 'alert-info', 2000) },
|
||||
{ label: 'Item 2', onclick: () => Toast('Item 2', 'alert-info', 2000) },
|
||||
{ label: 'Item 3', onclick: () => Toast('Item 3', 'alert-info', 2000) }
|
||||
];
|
||||
|
||||
return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [
|
||||
Dropdown({ label: 'Default', items: commonItems }),
|
||||
Dropdown({ label: 'With Icon', icon: '☰', items: commonItems }),
|
||||
Dropdown({ label: 'End Position', class: 'dropdown-end', items: commonItems })
|
||||
]);
|
||||
};
|
||||
$mount(VariantsDemo, '#demo-variants');
|
||||
```
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const initDropdownExamples = () => {
|
||||
|
||||
// 1. Basic Dropdown (Items Array)
|
||||
const basicTarget = document.querySelector('#demo-basic');
|
||||
if (basicTarget && !basicTarget.hasChildNodes()) {
|
||||
const BasicDemo = () => {
|
||||
return Dropdown({
|
||||
label: 'Options',
|
||||
items: [
|
||||
{ label: 'Profile', onclick: () => Toast('Profile clicked', 'alert-info', 2000) },
|
||||
{ label: 'Settings', onclick: () => Toast('Settings clicked', 'alert-info', 2000) },
|
||||
{ label: 'Logout', onclick: () => Toast('Logged out', 'alert-warning', 2000), class: 'text-error' }
|
||||
]
|
||||
});
|
||||
};
|
||||
$mount(BasicDemo, basicTarget);
|
||||
}
|
||||
|
||||
// 2. With Icons (Items Array)
|
||||
const iconsTarget = document.querySelector('#demo-icons');
|
||||
if (iconsTarget && !iconsTarget.hasChildNodes()) {
|
||||
const IconsDemo = () => {
|
||||
return Dropdown({
|
||||
label: 'Menu',
|
||||
icon: '☰',
|
||||
items: [
|
||||
{ icon: '👤', label: 'Profile', onclick: () => Toast('Profile', 'alert-info', 2000) },
|
||||
{ icon: '⭐', label: 'Favorites', onclick: () => Toast('Favorites', 'alert-info', 2000) },
|
||||
{ icon: '📁', label: 'Documents', onclick: () => Toast('Documents', 'alert-info', 2000) },
|
||||
{ icon: '⚙️', label: 'Settings', onclick: () => Toast('Settings', 'alert-info', 2000) }
|
||||
]
|
||||
});
|
||||
};
|
||||
$mount(IconsDemo, iconsTarget);
|
||||
}
|
||||
|
||||
// 3. Action Dropdown (Items Array)
|
||||
const actionsTarget = document.querySelector('#demo-actions');
|
||||
if (actionsTarget && !actionsTarget.hasChildNodes()) {
|
||||
const ActionsDemo = () => {
|
||||
const handleAction = (action) => {
|
||||
Toast(`${action} action`, 'alert-info', 2000);
|
||||
};
|
||||
|
||||
return Dropdown({
|
||||
label: 'Actions',
|
||||
class: 'dropdown-end',
|
||||
items: [
|
||||
{ icon: '✏️', label: 'Edit', onclick: () => handleAction('Edit') },
|
||||
{ icon: '📋', label: 'Copy', onclick: () => handleAction('Copy') },
|
||||
{ icon: '🗑️', label: 'Delete', onclick: () => handleAction('Delete'), class: 'text-error' }
|
||||
]
|
||||
});
|
||||
};
|
||||
$mount(ActionsDemo, actionsTarget);
|
||||
}
|
||||
|
||||
// 4. User Dropdown (Items Array)
|
||||
const userTarget = document.querySelector('#demo-user');
|
||||
if (userTarget && !userTarget.hasChildNodes()) {
|
||||
const UserDropdown = () => {
|
||||
return Dropdown({
|
||||
label: Span({ class: 'flex items-center gap-2' }, [
|
||||
Div({ class: 'avatar placeholder' }, [
|
||||
Div({ class: 'bg-primary text-primary-content rounded-full w-8 h-8 flex items-center justify-center text-sm' }, 'JD')
|
||||
]),
|
||||
'John Doe'
|
||||
]),
|
||||
class: 'dropdown-end',
|
||||
items: [
|
||||
{ label: 'Profile', onclick: () => Toast('Profile', 'alert-info', 2000) },
|
||||
{ label: 'Settings', onclick: () => Toast('Settings', 'alert-info', 2000) },
|
||||
{ label: 'Sign Out', onclick: () => Toast('Signed out', 'alert-warning', 2000), class: 'text-error' }
|
||||
]
|
||||
});
|
||||
};
|
||||
$mount(UserDropdown, userTarget);
|
||||
}
|
||||
|
||||
// 5. Reactive Items
|
||||
const reactiveTarget = document.querySelector('#demo-reactive');
|
||||
if (reactiveTarget && !reactiveTarget.hasChildNodes()) {
|
||||
const ReactiveDropdown = () => {
|
||||
const count = $(0);
|
||||
|
||||
const items = () => [
|
||||
{ label: `Count: ${count()}`, onclick: () => {} },
|
||||
{ label: 'Increment', onclick: () => count(count() + 1) },
|
||||
{ label: 'Decrement', onclick: () => count(count() - 1) },
|
||||
{ label: 'Reset', onclick: () => count(0) }
|
||||
];
|
||||
|
||||
return Dropdown({
|
||||
label: () => `Counter (${count()})`,
|
||||
items: items
|
||||
});
|
||||
};
|
||||
$mount(ReactiveDropdown, reactiveTarget);
|
||||
}
|
||||
|
||||
// 6. Notification Dropdown (Custom Children)
|
||||
const notifTarget = document.querySelector('#demo-notifications');
|
||||
if (notifTarget && !notifTarget.hasChildNodes()) {
|
||||
const NotificationsDropdown = () => {
|
||||
const notifications = $([
|
||||
{ id: 1, title: 'New message', time: '5 min ago', read: false },
|
||||
{ id: 2, title: 'Update available', time: '1 hour ago', read: false },
|
||||
{ id: 3, title: 'Task completed', time: '2 hours ago', read: true }
|
||||
]);
|
||||
|
||||
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')
|
||||
])
|
||||
])
|
||||
});
|
||||
};
|
||||
$mount(NotificationsDropdown, notifTarget);
|
||||
}
|
||||
|
||||
// 7. Custom Content Dropdown
|
||||
const customTarget = document.querySelector('#demo-custom');
|
||||
if (customTarget && !customTarget.hasChildNodes()) {
|
||||
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, customTarget);
|
||||
}
|
||||
|
||||
// 8. All Variants
|
||||
const variantsTarget = document.querySelector('#demo-variants');
|
||||
if (variantsTarget && !variantsTarget.hasChildNodes()) {
|
||||
const VariantsDemo = () => {
|
||||
const commonItems = [
|
||||
{ label: 'Item 1', onclick: () => Toast('Item 1', 'alert-info', 2000) },
|
||||
{ label: 'Item 2', onclick: () => Toast('Item 2', 'alert-info', 2000) },
|
||||
{ label: 'Item 3', onclick: () => Toast('Item 3', 'alert-info', 2000) }
|
||||
];
|
||||
|
||||
return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [
|
||||
Dropdown({ label: 'Default', items: commonItems }),
|
||||
Dropdown({ label: 'With Icon', icon: '☰', items: commonItems }),
|
||||
Dropdown({ label: 'End Position', class: 'dropdown-end', items: commonItems })
|
||||
]);
|
||||
};
|
||||
$mount(VariantsDemo, variantsTarget);
|
||||
}
|
||||
};
|
||||
|
||||
initDropdownExamples();
|
||||
|
||||
if (window.$docsify) {
|
||||
window.$docsify.plugins = [].concat(window.$docsify.plugins || [], (hook) => {
|
||||
hook.doneEach(initDropdownExamples);
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
Reference in New Issue
Block a user