page Collapsecomponent { seo { title = "Collapse component" description = "Theme-aware, responsive collapse component." } view {
W WRNexusJS
base component

Collapse

Theme-aware, responsive collapse component.

@wrnexus/ui 0.5.08 props1 slots3 events

Usage

Components are auto-discovered. Use the component directly in any .wrn view:

<Collapse
  size="default"
  color="primary"
  items="[]"
  multiple="false"
  mode="panel"
/>

Legacy mount name: data-component="Collapse".

Props and attributes

PropTypeRequirementDefault
sizestringOptional"default"
colorstringOptional"primary"
itemsstringOptional[]
multiplebooleanOptionalfalse
modestringOptional"panel"
initialOpenIndexesstringOptional[]
ariaLabelstringOptional"Collapsible content"
classstringOptional""

Slots

  • default

Events

  • toggle
  • open
  • close

Source contract

Installed source: components/Collapse.wrn

component Collapse {
  props {
    @event toggle = function
    @event open = function
    @event close = function
    size = "default"
    color = "primary"
    items = []
    multiple = false
    mode = "panel"
    initialOpenIndexes = []
    ariaLabel = "Collapsible content"
    class = ""
  }

  state openIndexes = initialOpenIndexes

  functions {
    function isOpen(index) {
      return openIndexes.includes(index)
    }

    function toggleItem(index, item, opening) {
      if (item.disabled) {
        return
      }
      opening = !isOpen(index)
      if (opening) {
        if (multiple) {
          openIndexes = openIndexes.concat(index)
        } else {
          openIndexes = [index]
        }
        $emit("open", { index: index, item: item })
      } else {
        openIndexes = openIndexes.filter((openIndex) => openIndex !== index)
        $emit("close", { index: index, item: item })
      }
      $emit("toggle", {
        index: index,
        item: item,
        open: opening,
        openIndexes: openIndexes
      })
    }
  }

  view {
        <section
      {...attrs}
      class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--collapse {class}"
      data-mode="{mode}"
      aria-label="{ariaLabel}"
    >
      {#each items as item, index}
        <article class="wire-next__collapse-item" data-open="{isOpen(index)}">
          {#if mode === "inline" && item.preview}
            <p class="wire-next__collapse-preview">{item.preview}</p>
          {/if}

          <button
            class="wire-next__collapse-trigger"
            type="button"
            aria-expanded="{isOpen(index) ? 'true' : 'false'}"
            aria-controls="{item.id || 'collapse-panel-' + index}"
            disabled="{item.disabled}"
            @click="toggleItem(index, item)"
          >
        <span>{isOpen(index) ? (item.closeLabel || "Read less") : item.label}</span>
        <span class="icon-[lucide--chevron-down] wire-next__collapse-chevron" aria-hidden="true">
        </span>
        </button>
        <div
            id="{item.id || 'collapse-panel-' + index}"
            class="wire-next__collapse-panel"
            data-open="{isOpen(index)}"
            aria-hidden="{isOpen(index) ? 'false' : 'true'}"
            inert="{!isOpen(index)}"
          >
        <div class="wire-next__collapse-content">
              {#if item.title}<h4>{item.title}</h4>{/if}
              {#if item.content}<p>{item.content}</p>{/if}
              {#if item.links && item.links.length}
                <nav aria-label="Related links">
                  {#each item.links as link}<a href="{link.href || '#'}">{link.label}</a>{/each}
                </nav>
              {/if}
            </div>
        </div>
        </article>
      {/each}
      <slot />
        </section>
    }
}
} }