up
This commit is contained in:
@@ -6,7 +6,7 @@ import { val, ui } from "../core/utils.js";
|
||||
* Tabs component
|
||||
*
|
||||
* daisyUI classes used:
|
||||
* - tabs, tabs-box, tabs-lifted, tabs-bordered
|
||||
* - tabs, tabs-box, tabs-lift, tabs-border
|
||||
* - tab, tab-content
|
||||
* - bg-base-100, border-base-300, p-6
|
||||
*/
|
||||
@@ -20,56 +20,43 @@ export const Tabs = (props) => {
|
||||
if (idx !== -1 && idx !== activeIndex()) activeIndex(idx);
|
||||
});
|
||||
|
||||
return Tag("div", { ...rest, class: "w-full" }, [
|
||||
// 1. Tab List: Aplanamos los botones para que sean hijos directos
|
||||
Tag("div", {
|
||||
role: "tablist",
|
||||
class: ui('tabs', className || 'tabs-box')
|
||||
}, () => {
|
||||
const list = itemsSignal();
|
||||
return list.map((it, idx) => {
|
||||
const isSelected = () => activeIndex() === idx;
|
||||
|
||||
const tab = Tag("button", {
|
||||
role: "tab",
|
||||
class: () => ui("tab", isSelected() ? "tab-active" : ""),
|
||||
onclick: (e) => {
|
||||
e.preventDefault();
|
||||
if (!val(it.disabled)) {
|
||||
if (it.onclick) it.onclick();
|
||||
activeIndex(idx);
|
||||
}
|
||||
// Contenedor principal con las clases de DaisyUI
|
||||
return Tag("div", { ...rest, class: ui('tabs', className) }, () => {
|
||||
const list = itemsSignal();
|
||||
const elements = [];
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const item = list[i];
|
||||
const isActive = () => activeIndex() === i;
|
||||
|
||||
// Botón (tab)
|
||||
const button = Tag("button", {
|
||||
class: () => ui("tab", isActive() ? "tab-active" : ""),
|
||||
onclick: (e) => {
|
||||
e.preventDefault();
|
||||
if (!val(item.disabled)) {
|
||||
if (item.onclick) item.onclick();
|
||||
activeIndex(i);
|
||||
}
|
||||
});
|
||||
|
||||
// Mantenemos el watch para el label por si es dinámico
|
||||
Watch(() => {
|
||||
const content = val(it.label);
|
||||
if (content instanceof Node) {
|
||||
tab.replaceChildren(content);
|
||||
} else {
|
||||
tab.textContent = String(content);
|
||||
}
|
||||
});
|
||||
|
||||
return tab;
|
||||
}
|
||||
});
|
||||
}),
|
||||
|
||||
// 2. Tab Content: Aquí el display:contents no molesta tanto,
|
||||
// pero lo aplanamos por consistencia
|
||||
Tag("div", { class: "tab-panels" }, () => {
|
||||
return itemsSignal().map((it, idx) => {
|
||||
const isVisible = () => activeIndex() === idx;
|
||||
|
||||
return Tag("div", {
|
||||
role: "tabpanel",
|
||||
class: "tab-content bg-base-100 border-base-300 p-6",
|
||||
style: () => isVisible() ? "display: block" : "display: none"
|
||||
}, [
|
||||
() => typeof it.content === "function" ? it.content() : it.content
|
||||
]);
|
||||
});
|
||||
})
|
||||
]);
|
||||
// Asignar etiqueta (puede ser texto o nodo)
|
||||
const label = val(item.label);
|
||||
if (label instanceof Node) {
|
||||
button.replaceChildren(label);
|
||||
} else {
|
||||
button.textContent = String(label);
|
||||
}
|
||||
elements.push(button);
|
||||
|
||||
// Contenido (tab-content) - debe ir inmediatamente después del botón
|
||||
const panel = Tag("div", {
|
||||
class: "tab-content bg-base-100 border-base-300 p-6",
|
||||
style: () => isActive() ? "display: block" : "display: none"
|
||||
}, () => val(item.content));
|
||||
elements.push(panel);
|
||||
}
|
||||
|
||||
return elements;
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user