The accordion component is for displaying collapsible content.
Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet , consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
< p >< strong > Lorem ipsum dolor </ strong > < a href = " # " > sit amet </ a > , consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </ p >
< details data-component = " Accordion " class = " group/details flex flex-col border-t last-of-type:border-b " >
class = " group/summary flex cursor-pointer items-center justify-between py-24 marker:content-none focus:outline-none "
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
class = " relative size-28 shrink-0 rounded border-2 border-transparent text-gray-600 transition-all group-hover/summary:bg-sky-200 group-focus-visible/summary:border-sky-700 group-active/summary:bg-sky-300 dark:group-hover/summary:bg-gray-800 dark:group-focus-visible/summary:border-gray-600 dark:group-active/summary:bg-gray-700 "
class = " absolute inset-0 m-auto h-4 w-20 bg-[var(--sl-color-gray-1)] "
class = " absolute inset-0 m-auto h-4 w-20 rotate-90 bg-[var(--sl-color-gray-1)] transition-transform duration-500 group-open/details:rotate-[360deg] "
< strong > Lorem ipsum dolor </ strong > < a href = " # " > sit amet </ a > , consectetur
adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
Anatomy
This component is comprised of several elements that work together to create an accordion. The following are the elements that make up the Accordion component.
import Accordion from ' @/components/elements/accordion/Accordion.ts '
API Reference
Root
The root element of the Accordion component. This element wraps the summary and content elements.
Summary
The summary is the element that is always visible and is used to trigger the accordion to open and close. This component is based on the <summary>
element and can take in any additional HTML attributes. The following are the custom props that can be passed to the component.
Prop Type Default hideMarker Hide the expand/collapse marker for the summary element. This is useful when you want to use a custom marker than what is provided
boolean
false
Content
The content is the element that is hidden by default and is shown when the accordion is opened. By default, this component is based on the <div>
element but can be changed to any HTML element by adjusting the as
property.
Prop Type Default as The HTML tag to render. By default the component will render as a `div`.
TagType
div
Accessibility
The <Accordion>
component leverages the <details>
and <summary>
elements which are natively accessible. The following are some additional accessibility features that are built into the component:
The <summary>
element has both a hover and focus state that can be styled to indicate that it is interactive for both keyboard and mouse users.
Examples
Custom Summary & Content
You can customize the summary and content elements to fit the needs of your project. In this example, we have replaced the marker in the summary and provided an image as the content.
Lorem ipsum dolor sit amet Expand
Collapse
< Accordion . Summary hideMarker >
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
< div class = " btn-contained group-open/details:hidden group-focus-visible/summary:ring-4 " > Expand </ div >
< div class = " btn-contained hidden group-open/details:flex group-focus-visible/summary:ring-4 " > Collapse </ div >
< Accordion . Content as = " img " src = " https://plus.unsplash.com/premium_photo-1675629118284-c9eb039df8cd?q=80&w=2576&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D " alt = " a snow covered field with trees and mountains in the background " class = " w-full object-cover " />
data-component = " Accordion "
class = " group/details flex flex-col border-t last-of-type:border-b "
class = " group/summary flex cursor-pointer items-center justify-between py-24 marker:content-none focus:outline-none "
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
class = " btn-contained group-open/details:hidden group-focus-visible/summary:ring-4 "
class = " btn-contained hidden group-open/details:flex group-focus-visible/summary:ring-4 "
src = " https://plus.unsplash.com/premium_photo-1675629118284-c9eb039df8cd?q=80 & w=2576 & auto=format & fit=crop & ixlib=rb-4.0.3 & ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D "
alt = " a snow covered field with trees and mountains in the background "
class = " mb-24 w-full object-cover "
Accordion List
Accordions can be stacked to display a list of items that can be expanded and collapsed.
Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet , consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet , consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet , consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
< p >< strong > Lorem ipsum dolor </ strong > < a href = " # " > sit amet </ a > , consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </ p >
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
< p >< strong > Lorem ipsum dolor </ strong > < a href = " # " > sit amet </ a > , consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </ p >
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
< p >< strong > Lorem ipsum dolor </ strong > < a href = " # " > sit amet </ a > , consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </ p >
< details data-component = " Accordion " class = " group/details flex flex-col border-t last-of-type:border-b " >
class = " group/summary flex cursor-pointer items-center justify-between py-24 marker:content-none focus:outline-none "
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
class = " relative size-28 shrink-0 rounded border-2 border-transparent text-gray-600 transition-all group-hover/summary:bg-sky-200 group-focus-visible/summary:border-sky-700 group-active/summary:bg-sky-300 dark:group-hover/summary:bg-gray-800 dark:group-focus-visible/summary:border-gray-600 dark:group-active/summary:bg-gray-700 "
class = " absolute inset-0 m-auto h-4 w-20 bg-[var(--sl-color-gray-1)] "
class = " absolute inset-0 m-auto h-4 w-20 rotate-90 bg-[var(--sl-color-gray-1)] transition-transform duration-500 group-open/details:rotate-[360deg] "
< strong > Lorem ipsum dolor </ strong > < a href = " # " > sit amet </ a > , consectetur
adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
< details data-component = " Accordion " class = " group/details flex flex-col border-t last-of-type:border-b " >
class = " group/summary flex cursor-pointer items-center justify-between py-24 marker:content-none focus:outline-none "
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
class = " relative size-28 shrink-0 rounded border-2 border-transparent text-gray-600 transition-all group-hover/summary:bg-sky-200 group-focus-visible/summary:border-sky-700 group-active/summary:bg-sky-300 dark:group-hover/summary:bg-gray-800 dark:group-focus-visible/summary:border-gray-600 dark:group-active/summary:bg-gray-700 "
class = " absolute inset-0 m-auto h-4 w-20 bg-[var(--sl-color-gray-1)] "
class = " absolute inset-0 m-auto h-4 w-20 rotate-90 bg-[var(--sl-color-gray-1)] transition-transform duration-500 group-open/details:rotate-[360deg] "
< strong > Lorem ipsum dolor </ strong > < a href = " # " > sit amet </ a > , consectetur
adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
< details data-component = " Accordion " class = " group/details flex flex-col border-t last-of-type:border-b " >
class = " group/summary flex cursor-pointer items-center justify-between py-24 marker:content-none focus:outline-none "
< h2 class = " text-lg " > Lorem ipsum dolor sit amet </ h2 >
class = " relative size-28 shrink-0 rounded border-2 border-transparent text-gray-600 transition-all group-hover/summary:bg-sky-200 group-focus-visible/summary:border-sky-700 group-active/summary:bg-sky-300 dark:group-hover/summary:bg-gray-800 dark:group-focus-visible/summary:border-gray-600 dark:group-active/summary:bg-gray-700 "
class = " absolute inset-0 m-auto h-4 w-20 bg-[var(--sl-color-gray-1)] "
class = " absolute inset-0 m-auto h-4 w-20 rotate-90 bg-[var(--sl-color-gray-1)] transition-transform duration-500 group-open/details:rotate-[360deg] "
< strong > Lorem ipsum dolor </ strong > < a href = " # " > sit amet </ a > , consectetur
adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
Astro Component
It’s recommended that an element like this is made as a reusable component. In this case, we have put together the following Astro compound component to serve as a blueprint for how you could possibly set up an Accordion component, and what properties to consider.
import Root from ' ./Root.astro '
import Summary from ' ./Summary.astro '
import Content from ' ./Content.astro '
export default Object . assign ( { Root , Summary , Content } )
import type { HTMLAttributes } from ' astro/types '
interface Props extends HTMLAttributes < ' details ' > {}
const { class : className , ... attrs } = Astro . props
data-component = " Accordion "
' group/details flex flex-col border-t last-of-type:border-b ' ,
import type { HTMLAttributes } from ' astro/types '
interface Props extends HTMLAttributes < ' summary ' > {
Hide expand/collapse marker for the summary element
const { hideMarker = false , class : className , ... attrs } = Astro . props
' group/summary flex cursor-pointer items-center justify-between py-24 marker:content-none focus:outline-none ' ,
' relative size-28 shrink-0 rounded border-2 border-transparent text-gray-600 transition-all ' ,
' group-hover/summary:bg-sky-200 group-focus-visible/summary:border-sky-700 group-active/summary:bg-sky-300 ' ,
' dark:group-hover/summary:bg-gray-800 dark:group-focus-visible/summary:border-gray-600 dark:group-active/summary:bg-gray-700 ' ,
< span class = " absolute inset-0 m-auto h-4 w-20 bg-[var(--sl-color-gray-1)] " />
< span class = " absolute inset-0 m-auto h-4 w-20 rotate-90 bg-[var(--sl-color-gray-1)] transition-transform duration-500 group-open/details:rotate-[360deg] " />
import type { HTMLTag , Polymorphic } from ' astro/types '
type Props < Tag extends HTMLTag > = Polymorphic <{
The HTML tag to render for the component. By default the component will render as a `div`.
const { as : Tag , class : className , ... attrs } = Astro . props
const Element = Tag ? Tag : ' div '
< Element class:list = { [ ' mb-24 ' , className ] } {... attrs } >