How to control accordions to open only one at a time

39 Views Asked by At

I have multiple accordions. I want to control the open state on the <details> tag to make sure only one accordion is open at a time. How can I achieve this?

Currently with the code below, the openState updates properly, but multiple accordions can be open at the same time (opened accordions does not close when other accordions are opened)

Parent component

<script lang="ts" setup>
const openState = ref(Array.from({ length: props.submenu.length }, () => false))

const toggleState = (index: number, newState: boolean) => {
  if (newState)
    openState.value = openState.value.map((_, i) => i === index)
  else
    openState.value[index] = newState
}
</script>

<template>
  <div>
    <template
      v-for="(menu, index) in submenu"
      :key="index"
    >
      <Accordion
        :is-open="openState[index]"
        :name="menu.title"
        @toggle-open-state="(newState) => { toggleState(index, newState) }"
      >
        <template #default>
          content
        </template>
      </Accordion>
    </template>
  </div>
</template>

Accordion component

<script setup lang="ts">
export interface Props {
  isOpen?: boolean
}

const props = defineProps<Props>()

const emits = defineEmits<{
  (e: 'toggle-open-state', isOpen: boolean): void
}>()

const detailsEl = ref()

const isOpen = computed({
  get() {
    return props.isOpen
  },
  set(value) {
    emits('toggle-open-state', value)
    detailsEl.value.open = value
  },
})

const toggleState = () => {
  isOpen.value = !isOpen.value
}
</script>

<template>
  <details
    ref="detailsEl"
    @click="toggleState"
  >
    <summary>
      <p v-html="name"/>
    </summary>
  </details>
</template>

0

There are 0 best solutions below