daisyui
daisyui copied to clipboard
Nested collapse elements & collapse menu
It is not possible to nest collapse elements.
<div tabindex="0" class="collapse">
<div class="collapse-title text-xl font-medium">Focus me to see content</div>
<div class="collapse-content">
<div tabindex="1" class="collapse">
<div class="collapse-title text-xl font-medium">Focus me to see content</div>
<div class="collapse-content">
<p>tabindex="0" attribute is necessary to make the div focusable</p>
</div>
</div>
</div>
</div>
Also I am trying to create a collapsing (side) menu (for an admin dashboard). I have seen a discussing that is marked as resolved here. The "solution" does not seem to work:
<ul class="menu">
<li><a href="#">Menu Item</a></li>
<li><a href="#">Menu Item</a></li>
<li tabindex="0" class="collapse">
<span class="collapse-title">Sub Menu Title</span>
<ul class="collapse-content">
<li><a href="#">Sub menu</a></li>
<li><a href="#">Sub menu</a></li>
<li><a href="#">Sub menu</a></li>
</ul>
</li>
<li><a href="#">Menu Item</a></li>
</ul>
Perhaps the menu can be created as a separate issue.
I got it to work when you use the checkbox method for the Collapse Component.
Here is Tailwind Playground Example
Hope this helps.
Running into this same issue ☹️
Not only will the nested collapse's collapse-open
& collapse-closed
classes not work, it also messes up the smooth transition on the parent's collapse.
As @rhscjohn-dev it works with checkbox method.
It's not possible with the focus method, because on a HTML page we can only focus one element at a time. When a collapse
is focused, its content will be visible, as soon as we focus on another element (including the child collapse
) the focus is lost and the parent will get closed.
@nenorrell I will be improving the selectors so it will work with the class names as well.
Let me know if you have any questions.
If anyone is looking for an interim workaround, I resolved this issue by doing the following:
(This example is a React component but the concept should apply outside of React as well)
import React, { PropsWithChildren, ReactNode, useState } from "react";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronDown } from "@fortawesome/free-solid-svg-icons";
interface ICollapse {
defaultExpand ?:boolean
headerContent :string | ReactNode
headerClasses ?:string[]
leftIcon ?:IconDefinition
}
export const Collapse = (props :PropsWithChildren<ICollapse>) => {
const [isExpanded, setIsExpanded] = useState<boolean>(props.defaultExpand || false);
return (
<div className="w-100">
<div className={`collapse-title cursor-pointer flex items-center justify-center
${props.headerClasses?.join(" ") || ""}`
}
onClick={()=> setIsExpanded(!isExpanded) }>
{
props.leftIcon ? <FontAwesomeIcon icon={props.leftIcon} className="mr-2" /> : null
}
<div className="w-full">{props.headerContent}</div>
<p className={`items-end transition ease-in-out ${isExpanded ? "" : "-rotate-90"}`}>
<FontAwesomeIcon icon={faChevronDown}/>
</p>
</div>
<div
className={`ease-linear duration-[1000ms] transition-[height] overflow-hidden
${isExpanded ? "h-fit" : "h-0"}
`}
>
{props.children}
</div>
</div>
);
It can then be consumed (in React) as:
export const SomeComponent = () => {
return (
<div className="row-auto">
<div className="mx-5 mt-5 bg-base-100 rounded-md text-base-content">
<Collapse
defaultExpand={true}
headerContent="This is the parent collapse"
headerClasses={['text-xl', 'font-medium', 'bg-primary', 'text-primary-content']}
leftIcon={faLayerGroup}
>
<Collapse
leftIcon={faSignsPost}
headerContent={
<div className="text-lg flex items-center">
<div className={`mx-2 p-1 px-2 w-20 text-center rounded-md inline-block`}>
This is the child collapse with extra HTML structure
</div>
<div className="rounded-md inline-block bg-base-300 text-base-content p-1 px-2 w-100">Some Title</div>
</div>
}
defaultExpand={defaultExpand}
>
</Collapse>
</Collapse>
</div>
</div>
);
};
This should give you the expected functionality