component Accordion { outputs { change(payload: { value?: string | number | boolean | null; values?: Array; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null) open(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object }) close(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object }) } props { size: string = "default" color: string = "primary" variant: string = "default" class: string = "" id: string = "accordion" items: unknown[] = [] defaultOpen: unknown[] = [] multiple: boolean = false alwaysOpen: boolean = false disabled: boolean = false indicator: string = "plus" indicatorPosition: string = "start" showIndicator: boolean = true bordered: boolean = false separated: boolean = false flush: boolean = false contentItalic: boolean = false } state openValues = defaultOpen functions { shared function itemValue(item, index) { return item.value !== undefined && item.value !== "" ? String(item.value) : String(index) } shared function nestedValue(parent, parentIndex, item, index) { return itemValue(parent, parentIndex) + "." + itemValue(item, index) } shared function isOpen(value) { return openValues.includes(value) } shared function allowsMultiple() { return multiple || alwaysOpen } // Named rather than computed: an output is resolved as a property name, so // output[eventName] would not reach a parent binding. client function dispatchAccordionEvent(sourceEvent, eventName, value, item, payload) { payload = { component: "Accordion", value: value, item: item, open: isOpen(value), openValues: openValues } if (eventName === "open") { output.open(payload) } else if (eventName === "close") { output.close(payload) } else { output.change(payload) } } client function toggleItem(sourceEvent, value, item, wasOpen) { if (disabled || item.disabled) { return } wasOpen = isOpen(value) if (wasOpen) { openValues = openValues.filter((entry) => entry !== value) } else if (allowsMultiple()) { openValues = openValues.concat([value]) } else { openValues = [value] } dispatchAccordionEvent( sourceEvent, wasOpen ? "close" : "open", value, item ) dispatchAccordionEvent(sourceEvent, "change", value, item) } } view {
{#each items as item, index}

{#if item.content}

{item.content}

{/if} {#if item.children && item.children.length > 0}
{#each item.children as child, childIndex}

{child.content}

{/each}
{/if}
{/each}
} style { .wrn-next--accordion { --wrn-accordion-accent: var(--wrn-component-color); display: grid; width: 100%; color: var(--wrn-color-text); } .wrn-next__accordion-item { min-width: 0; } .wrn-next__accordion-heading { margin: 0; font: inherit; } .wrn-next__accordion-heading > button { display: flex; width: 100%; align-items: center; gap: 0.75rem; padding: 0.85rem 0; border: 0; background: transparent; color: var(--wrn-color-text); font: inherit; font-size: 0.88rem; font-weight: 700; text-align: left; cursor: pointer; } .wrn-next__accordion-heading > button > span:not(.wrn-next__accordion-indicator) { min-width: 0; flex: 1; } .wrn-next__accordion-heading > button:focus-visible { border-radius: var(--wrn-radius-sm); outline: 2px solid var(--wrn-accordion-accent); outline-offset: 2px; } .wrn-next__accordion-heading > button:disabled { cursor: not-allowed; opacity: 0.5; } .wrn-next__accordion-indicator { display: inline-flex; width: 1rem; height: 1rem; flex: 0 0 1rem; align-items: center; justify-content: center; color: var(--wrn-color-muted); font-size: 1rem; font-weight: 500; line-height: 1; transition: color var(--wrn-motion-fast) var(--wrn-ease-standard), transform var(--wrn-motion-fast) var(--wrn-ease-standard); } .wrn-next__accordion-indicator > span { display: inline-flex; align-items: center; justify-content: center; } .wrn-next__accordion-indicator > [class*="icon-["] { width: 0.95rem; height: 0.95rem; } .wrn-next__accordion-item[data-open="true"] > .wrn-next__accordion-heading .wrn-next__accordion-indicator { color: var(--wrn-accordion-accent); transform: rotate(45deg); } .wrn-next--accordion[data-indicator="chevron"] .wrn-next__accordion-item[data-open="true"] > .wrn-next__accordion-heading .wrn-next__accordion-indicator { transform: rotate(180deg); } .wrn-next__accordion-item[data-open="true"] > .wrn-next__accordion-heading > button { color: var(--wrn-accordion-accent); } .wrn-next__accordion-panel { display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows var(--wrn-motion-base) var(--wrn-ease-standard), opacity var(--wrn-motion-fast) var(--wrn-ease-standard); } .wrn-next__accordion-item[data-open="true"] > .wrn-next__accordion-panel { grid-template-rows: 1fr; opacity: 1; } .wrn-next__accordion-panel > div { overflow: hidden; } .wrn-next__accordion-content { padding: 0 0 1rem 1.75rem; color: var(--wrn-color-muted); font-size: 0.86rem; line-height: 1.65; } .wrn-next__accordion-content > p { color: inherit; } .wrn-next__accordion-content-italic > p::first-line { font-style: italic; } .wrn-next__accordion-nested { display: grid; margin-top: 0.5rem; } .wrn-next__accordion-nested .wrn-next__accordion-content { padding-left: 1.5rem; } .wrn-next--accordion-bordered { overflow: hidden; border: 1px solid var(--wrn-color-border); border-radius: var(--wrn-radius-md); background: var(--wrn-color-surface); } .wrn-next--accordion-bordered > .wrn-next__accordion-item + .wrn-next__accordion-item { border-top: 1px solid var(--wrn-color-border); } .wrn-next--accordion-bordered > .wrn-next__accordion-item > .wrn-next__accordion-heading > button { padding-inline: 1rem; } .wrn-next--accordion-bordered > .wrn-next__accordion-item > .wrn-next__accordion-panel .wrn-next__accordion-content { padding-inline: 1rem; } .wrn-next--accordion-separated { gap: 0.5rem; } .wrn-next--accordion-separated > .wrn-next__accordion-item { overflow: hidden; border: 1px solid transparent; border-radius: var(--wrn-radius-md); background: var(--wrn-color-surface-2); } .wrn-next--accordion-separated > .wrn-next__accordion-item[data-open="true"] { border-color: var(--wrn-color-border); } .wrn-next--accordion-separated > .wrn-next__accordion-item > .wrn-next__accordion-heading > button, .wrn-next--accordion-separated > .wrn-next__accordion-item > .wrn-next__accordion-panel .wrn-next__accordion-content { padding-inline: 1rem; } .wrn-next--accordion-flush { border-radius: 0; background: transparent; box-shadow: none; } @media (prefers-reduced-motion: reduce) { .wrn-next__accordion-panel, .wrn-next__accordion-indicator { transition: none; } } /* Shared component foundation. */ .wrn-component { --wrn-component-color: var(--wrn-color-primary); --wrn-component-scale: 1; margin: 0; color: var(--wrn-color-text); font-family: var(--wrn-font-sans, inherit); } .wrn-component--color-primary { --wrn-component-color: var(--wrn-color-primary); } .wrn-component--color-secondary { --wrn-component-color: var(--wrn-color-secondary); } .wrn-component--color-success { --wrn-component-color: var(--wrn-color-success); } .wrn-component--color-warning { --wrn-component-color: var(--wrn-color-warning); } .wrn-component--color-danger { --wrn-component-color: var(--wrn-color-danger); } .wrn-component--color-info { --wrn-component-color: var(--wrn-color-info); } .wrn-component--size-xs { --wrn-component-scale: 0.78; } .wrn-component--size-sm { --wrn-component-scale: 0.88; } .wrn-component--size-default, .wrn-component--size-md { --wrn-component-scale: 1; } .wrn-component--size-lg { --wrn-component-scale: 1.14; } .wrn-component--size-xl { --wrn-component-scale: 1.28; } .wrn-component:not(.wrn-btn) { font-size: calc(1em * var(--wrn-component-scale)); } .wrn-component :is(a, button, input, select, textarea):focus-visible { outline-color: var(--wrn-component-color); } .wrn-component p { margin: 0; color: var(--wrn-color-muted); line-height: 1.6; } } }