minusculas
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 4s

This commit is contained in:
2026-04-22 08:27:59 +02:00
parent 65d78ca215
commit 5a5f593025
63 changed files with 610 additions and 748 deletions

View File

@@ -12,21 +12,10 @@ Collapsible accordion component for organizing content into expandable sections.
| :--- | :--- | :--- | :--- |
| `title` | `string \| VNode \| Signal` | Required | Accordion section title |
| `open` | `boolean \| Signal<boolean>` | `false` | Whether the accordion is expanded |
| `name` | `string` | `-` | Group name for radio-style accordions (only one open at a time) |
| `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) |
| `name` | `string` | `auto-generated` | Group name for radio-style accordions |
| `class` | `string` | `''` | Additional CSS classes |
| `children` | `VNode \| Array<VNode>` | Required | Content to display when expanded |
## Styling
Accordion supports all **daisyUI Collapse classes**:
| Category | Keywords | Description |
| :--- | :--- | :--- |
| Type | `collapse-arrow`, `collapse-plus`, `collapse-minus` | Expand indicator style |
| Color | `collapse-primary`, `collapse-secondary`, `collapse-accent` | Color variants |
| Background | `bg-base-100`, `bg-base-200` | Background colors |
> For further details, check the [daisyUI Collapse Documentation](https://daisyui.com/components/collapse) Full reference for CSS classes.
| `items` | `Array` | `-` | Array of accordion items (alternative API) |
## Live Examples
@@ -39,7 +28,9 @@ Accordion supports all **daisyUI Collapse classes**:
</div>
</div>
```javascript
```js
const { Accordion, Div, Mount } = window;
const BasicDemo = () => {
const open1 = $(false);
const open2 = $(false);
@@ -49,24 +40,18 @@ const BasicDemo = () => {
Accordion({
title: 'Section 1',
open: open1,
onclick: () => open1(!open1())
}, [
Div({ class: 'p-2' }, 'Content for section 1. This is a basic accordion section.')
]),
children: Div({ class: 'p-2' }, 'Content for section 1. This is a basic accordion section.')
}),
Accordion({
title: 'Section 2',
open: open2,
onclick: () => open2(!open2())
}, [
Div({ class: 'p-2' }, 'Content for section 2. You can put any content here.')
]),
children: Div({ class: 'p-2' }, 'Content for section 2. You can put any content here.')
}),
Accordion({
title: 'Section 3',
open: open3,
onclick: () => open3(!open3())
}, [
Div({ class: 'p-2' }, 'Content for section 3. Accordions are great for FAQs.')
])
children: Div({ class: 'p-2' }, 'Content for section 3. Accordions are great for FAQs.')
})
]);
};
Mount(BasicDemo, '#demo-basic');
@@ -81,40 +66,78 @@ Mount(BasicDemo, '#demo-basic');
</div>
</div>
```javascript
```js
const { Accordion, Div, Mount } = window;
const GroupDemo = () => {
const openSection = $('section1');
return Div({ class: 'flex flex-col gap-2' }, [
Accordion({
name: 'group',
title: 'Section 1',
name: 'group',
open: () => openSection() === 'section1',
onclick: () => openSection('section1')
}, [
Div({ class: 'p-2' }, 'Content for section 1. Only one section can be open at a time.')
]),
children: Div({ class: 'p-2' }, 'Content for section 1. Only one section can be open at a time.')
}),
Accordion({
name: 'group',
title: 'Section 2',
name: 'group',
open: () => openSection() === 'section2',
onclick: () => openSection('section2')
}, [
Div({ class: 'p-2' }, 'Content for section 2. Opening this will close section 1.')
]),
children: Div({ class: 'p-2' }, 'Content for section 2. Opening this will close section 1.')
}),
Accordion({
title: 'Section 3',
name: 'group',
title: 'Section 3',
open: () => openSection() === 'section3',
onclick: () => openSection('section3')
}, [
Div({ class: 'p-2' }, 'Content for section 3. This is useful for FAQ sections.')
])
children: Div({ class: 'p-2' }, 'Content for section 3. This is useful for FAQ sections.')
})
]);
};
Mount(GroupDemo, '#demo-group');
```
### Using 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-items" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Accordion, Div, Mount } = window;
const ItemsDemo = () => {
const openItems = $({
item1: true,
item2: false,
item3: false
});
return Accordion({
items: [
{
title: 'First Item',
open: () => openItems().item1,
children: Div({ class: 'p-2' }, 'This is the content of the first item.')
},
{
title: 'Second Item',
open: () => openItems().item2,
children: Div({ class: 'p-2' }, 'This is the content of the second item.')
},
{
title: 'Third Item',
open: () => openItems().item3,
children: Div({ class: 'p-2' }, 'This is the content of the third item.')
}
]
});
};
Mount(ItemsDemo, '#demo-items');
```
### FAQ Accordion
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
@@ -124,26 +147,25 @@ Mount(GroupDemo, '#demo-group');
</div>
</div>
```javascript
```js
const { Accordion, Div, Mount } = window;
const FaqDemo = () => {
const openFaq = $('faq1');
const faqs = [
{ id: 'faq1', question: 'What is this component?', answer: 'This is an accordion component built with DaisyUI and Tailwind CSS for creating collapsible content sections.' },
{ id: 'faq2', question: 'How do I use it?', answer: 'Simply import the Accordion component and pass title and children props. Use the open prop to control expansion.' },
{ id: 'faq3', question: 'Can I have multiple open?', answer: 'Yes! By default, accordions can be opened independently. Use the name prop to create groups where only one can be open.' },
{ id: 'faq4', question: 'Is it accessible?', answer: 'Yes, the accordion uses proper ARIA attributes and keyboard navigation support.' }
{ id: 'faq2', question: 'How do I use it?', answer: 'Simply import the Accordion component and pass title and children props.' },
{ id: 'faq3', question: 'Can I have multiple open?', answer: 'Yes! By default, accordions can be opened independently.' }
];
return Div({ class: 'flex flex-col gap-2' }, faqs.map(faq =>
Accordion({
title: faq.question,
name: 'faq-group',
title: faq.question,
open: () => openFaq() === faq.id,
onclick: () => openFaq(openFaq() === faq.id ? '' : faq.id)
}, [
Div({ class: 'p-2 text-sm' }, faq.answer)
])
children: Div({ class: 'p-2 text-sm' }, faq.answer)
})
));
};
Mount(FaqDemo, '#demo-faq');
@@ -158,7 +180,9 @@ Mount(FaqDemo, '#demo-faq');
</div>
</div>
```javascript
```js
const { Accordion, Div, Span, Mount } = window;
const RichDemo = () => {
const open1 = $(true);
const open2 = $(false);
@@ -167,9 +191,7 @@ const RichDemo = () => {
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['📊', 'Statistics']),
open: open1,
onclick: () => open1(!open1())
}, [
Div({ class: 'p-2' }, [
children: Div({ class: 'p-2' }, [
Div({ class: 'grid grid-cols-2 gap-4' }, [
Div({ class: 'stat bg-base-100 rounded-lg p-3' }, [
Div({ class: 'stat-title' }, 'Users'),
@@ -178,24 +200,14 @@ const RichDemo = () => {
Div({ class: 'stat bg-base-100 rounded-lg p-3' }, [
Div({ class: 'stat-title' }, 'Revenue'),
Div({ class: 'stat-value text-lg' }, '$45,678')
]),
Div({ class: 'stat bg-base-100 rounded-lg p-3' }, [
Div({ class: 'stat-title' }, 'Growth'),
Div({ class: 'stat-value text-lg text-success' }, '+23%')
]),
Div({ class: 'stat bg-base-100 rounded-lg p-3' }, [
Div({ class: 'stat-title' }, 'Active'),
Div({ class: 'stat-value text-lg' }, '89%')
])
])
])
]),
}),
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['👥', 'Team Members']),
open: open2,
onclick: () => open2(!open2())
}, [
Div({ class: 'p-2 space-y-2' }, [
children: Div({ class: 'p-2 space-y-2' }, [
Div({ class: 'flex items-center gap-3 p-2 hover:bg-base-100 rounded-lg' }, [
Div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-primary text-primary-content rounded-full w-10 h-10 flex items-center justify-center' }, 'JD')
@@ -204,18 +216,9 @@ const RichDemo = () => {
Div({ class: 'font-medium' }, 'John Doe'),
Div({ class: 'text-sm opacity-70' }, 'Developer')
])
]),
Div({ class: 'flex items-center gap-3 p-2 hover:bg-base-100 rounded-lg' }, [
Div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-secondary text-secondary-content rounded-full w-10 h-10 flex items-center justify-center' }, 'JS')
]),
Div({ class: 'flex-1' }, [
Div({ class: 'font-medium' }, 'Jane Smith'),
Div({ class: 'text-sm opacity-70' }, 'Designer')
])
])
])
])
})
]);
};
Mount(RichDemo, '#demo-rich');
@@ -230,7 +233,9 @@ Mount(RichDemo, '#demo-rich');
</div>
</div>
```javascript
```js
const { Accordion, Div, Span, Button, Input, Radio, Mount } = window;
const FormAccordion = () => {
const openStep = $('step1');
const formData = $({
@@ -255,18 +260,15 @@ const FormAccordion = () => {
};
const handleSubmit = () => {
Toast('Form submitted!', 'alert-success', 2000);
console.log(formData());
window.Toast('Form submitted!', 'alert-success', 2000);
};
return Div({ class: 'flex flex-col gap-2' }, [
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['1⃣', 'Personal Information']),
name: 'form-steps',
title: Span({ class: 'flex items-center gap-2' }, ['1⃣', 'Personal Information']),
open: () => openStep() === 'step1',
onclick: () => openStep('step1')
}, [
Div({ class: 'p-4 space-y-4' }, [
children: Div({ class: 'p-4 space-y-4' }, [
Input({
label: 'Full Name',
value: () => formData().name,
@@ -288,14 +290,12 @@ const FormAccordion = () => {
}, 'Next →')
])
])
]),
}),
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['2⃣', 'Address']),
name: 'form-steps',
title: Span({ class: 'flex items-center gap-2' }, ['2⃣', 'Address']),
open: () => openStep() === 'step2',
onclick: () => openStep('step2')
}, [
Div({ class: 'p-4 space-y-4' }, [
children: Div({ class: 'p-4 space-y-4' }, [
Input({
label: 'Address',
value: () => formData().address,
@@ -304,20 +304,15 @@ const FormAccordion = () => {
}),
Div({ class: 'flex justify-between mt-2' }, [
Button({ class: 'btn btn-ghost btn-sm', onclick: prevStep }, '← Back'),
Button({
class: 'btn btn-primary btn-sm',
onclick: nextStep
}, 'Next →')
Button({ class: 'btn btn-primary btn-sm', onclick: nextStep }, 'Next →')
])
])
]),
}),
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['3⃣', 'Payment']),
name: 'form-steps',
title: Span({ class: 'flex items-center gap-2' }, ['3⃣', 'Payment']),
open: () => openStep() === 'step3',
onclick: () => openStep('step3')
}, [
Div({ class: 'p-4 space-y-4' }, [
children: Div({ class: 'p-4 space-y-4' }, [
Div({ class: 'flex flex-col gap-2' }, [
Radio({
label: 'Credit Card',
@@ -343,7 +338,7 @@ const FormAccordion = () => {
Button({ class: 'btn btn-success btn-sm', onclick: handleSubmit }, 'Submit')
])
])
])
})
]);
};
Mount(FormAccordion, '#demo-form');
@@ -354,11 +349,13 @@ Mount(FormAccordion, '#demo-form');
<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-col gap-6"></div>
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Accordion, Div, Span, Mount } = window;
const VariantsDemo = () => {
const open1 = $(true);
const open2 = $(false);
@@ -366,34 +363,26 @@ const VariantsDemo = () => {
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-sm font-bold' }, 'Default Accordion'),
Div({ class: 'flex flex-col gap-2' }, [
Accordion({ title: 'Default style', open: open1, onclick: () => open1(!open1()) }, [
Div({ class: 'p-2' }, 'Default accordion with standard styling.')
])
]),
Accordion({
title: 'Default style',
open: open1,
children: Div({ class: 'p-2' }, 'Default accordion with standard styling.')
}),
Div({ class: 'text-sm font-bold mt-2' }, 'Custom Styling'),
Div({ class: 'flex flex-col gap-2' }, [
Accordion({
title: Span({ class: 'text-primary font-bold' }, 'Primary Title'),
open: open2,
onclick: () => open2(!open2()),
class: 'bg-primary/5 border-primary/20'
}, [
Div({ class: 'p-2' }, 'Accordion with custom styling and primary color.')
])
]),
Accordion({
title: Span({ class: 'text-primary font-bold' }, 'Primary Title'),
open: open2,
class: 'bg-primary/5 border-primary/20',
children: Div({ class: 'p-2' }, 'Accordion with custom styling and primary color.')
}),
Div({ class: 'text-sm font-bold mt-2' }, 'With Icons'),
Div({ class: 'flex flex-col gap-2' }, [
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['✨', 'Featured Content']),
open: open3,
onclick: () => open3(!open3())
}, [
Div({ class: 'p-2' }, 'Accordion with emoji icons in the title.')
])
])
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['✨', 'Featured Content']),
open: open3,
children: Div({ class: 'p-2' }, 'Accordion with emoji icons in the title.')
})
]);
};
Mount(VariantsDemo, '#demo-variants');