DisclosureGroup

Container that manages multiple Disclosure items with coordinated expanded states

Usage

<script setup lang="ts">
import { DisclosureGroup } from '@hareui/vue'
</script>

Scan this QR code with your camera app to preview the HeroUI native components.

Expo Go QR Code

Expo must be installed on your device.

<script setup lang="ts">import type { ExpandedValue } from '@hareui/vue'import { Icon } from '@iconify/vue'import { Button, Disclosure, DisclosureGroup, Separator } from '@hareui/vue'import { ref } from 'vue'const expandedKeys = ref<ExpandedValue[]>(['preview'])</script><template>  <div class="w-full max-w-md">    <div class="flex flex-col gap-4 bg-transparent p-4">      <DisclosureGroup v-model="expandedKeys">        <Disclosure aria-label="Preview HeroUI Native" value="preview" :ui="{ bodyInner: 'mx-2 flex flex-col items-center gap-2 p-4 text-center' }">          <template #trigger="{ indicator }">            <Button              :class="['w-full border-none', { 'bg-transparent': !expandedKeys.includes('preview') }]"              :variant="expandedKeys.includes('preview') ? 'secondary' : 'tertiary'"            >              <div class="flex w-full items-center justify-start gap-2">                <Icon height="16" icon="gravity-ui:qr-code" width="16" />                Preview HeroUI Native              </div>              <component :is="indicator" class="text-muted" />            </Button>          </template>          <p class="text-sm text-muted">            Scan this QR code with your camera app to preview the HeroUI native components.          </p>          <img            alt="Expo Go QR Code"            class="aspect-square w-full max-w-54 object-cover"            src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/images/qr-code-native.png"          >          <p class="text-sm text-muted">            Expo must be installed on your device.          </p>          <Button class="mt-4" variant="primary">            <Icon class="[&_path]:fill-accent-foreground" icon="logos:expo-icon" />            Preview on Expo Go          </Button>        </Disclosure>        <Separator class="my-2" />        <Disclosure value="download" :ui="{ bodyInner: 'mx-2 flex flex-col items-center gap-2 p-4 text-center' }">          <template #trigger="{ indicator }">            <Button              :class="['w-full border-none', { 'bg-transparent': !expandedKeys.includes('download') }]"              :variant="expandedKeys.includes('download') ? 'secondary' : 'tertiary'"            >              <div class="flex w-full items-center justify-start gap-2">                <Icon icon="tabler:brand-apple-filled" />                Download App              </div>              <component :is="indicator" class="text-muted" />            </Button>          </template>          <p class="text-sm text-muted">            Download the HeroUI native app to explore our mobile components directly on your device.          </p>          <img            alt="App Store QR Code"            class="aspect-square w-full max-w-54 object-cover"            src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/images/qr-code-native.png"          >          <p class="text-sm text-muted">            Available on iOS and Android devices.          </p>          <Button class="mt-4" variant="primary">            <Icon icon="tabler:brand-apple-filled" />            Download on App Store          </Button>        </Disclosure>      </DisclosureGroup>    </div>  </div></template>

Anatomy

<template>
  <DisclosureGroup v-model="expanded">
    <Disclosure value="item1" title="…">
      <!-- optional: <template #trigger="{ open, indicator }" /> -->
      …
    </Disclosure>
  </DisclosureGroup>
</template>

Each Disclosure inside the group is identified by its value (HeroUI's id); the group's v-model holds the expanded values. Anything else can sit between the disclosures (e.g. a Separator).

ui keydata-slotElement
basedisclosure-grouproot element

Examples

Controlled

You can control which disclosures are expanded with external navigation controls using v-model and the useDisclosureGroupNavigation composable.

HeroUI Native

Scan this QR code with your camera app to preview the HeroUI native components.

Expo Go QR Code

Expo must be installed on your device.

<script setup lang="ts">import type { ExpandedValue } from '@hareui/vue'import { Icon } from '@iconify/vue'import { Button, Disclosure, DisclosureGroup, Separator, useDisclosureGroupNavigation } from '@hareui/vue'import { ref } from 'vue'const expandedKeys = ref<ExpandedValue[]>(['preview'])const itemIds = ['preview', 'download'] // Track our disclosure itemsconst { isNextDisabled, isPrevDisabled, onNext, onPrevious } = useDisclosureGroupNavigation({  expandedKeys,  itemIds,  onExpandedChange: (keys) => { expandedKeys.value = keys },})</script><template>  <div class="w-full max-w-md">    <div class="flex flex-col gap-4 rounded-3xl p-4">      <div class="mb-2 flex items-center justify-between">        <h3 class="text-lg font-semibold">          HeroUI Native        </h3>        <div class="flex gap-2">          <Button aria-label="Previous disclosure" :disabled="isPrevDisabled" size="sm" variant="secondary" @click="onPrevious">            <Icon class="size-4" icon="gravity-ui:chevron-up" />          </Button>          <Button aria-label="Next disclosure" :disabled="isNextDisabled" size="sm" variant="secondary" @click="onNext">            <Icon class="size-4" icon="gravity-ui:chevron-down" />          </Button>        </div>      </div>      <DisclosureGroup v-model="expandedKeys">        <Disclosure aria-label="Preview HeroUI Native" value="preview" :ui="{ bodyInner: 'mx-2 flex flex-col items-center gap-2 p-4 text-center' }">          <template #trigger="{ indicator }">            <Button              :class="['w-full border-none', { 'bg-transparent': !expandedKeys.includes('preview') }]"              :variant="expandedKeys.includes('preview') ? 'secondary' : 'tertiary'"            >              <div class="flex w-full items-center justify-start gap-2">                <Icon height="16" icon="gravity-ui:qr-code" width="16" />                Preview HeroUI Native              </div>              <component :is="indicator" class="text-muted" />            </Button>          </template>          <p class="text-sm text-muted">            Scan this QR code with your camera app to preview the HeroUI native components.          </p>          <img            alt="Expo Go QR Code"            class="aspect-square w-full max-w-54 object-cover"            src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/images/qr-code-native.png"          >          <p class="text-sm text-muted">            Expo must be installed on your device.          </p>          <Button class="mt-4" variant="primary">            <Icon class="[&_path]:fill-accent-foreground" icon="logos:expo-icon" />            Preview on Expo Go          </Button>        </Disclosure>        <Separator class="my-2" />        <Disclosure value="download" :ui="{ bodyInner: 'mx-2 flex flex-col items-center gap-2 p-4 text-center' }">          <template #trigger="{ indicator }">            <Button              :class="['w-full border-none', { 'bg-transparent': !expandedKeys.includes('download') }]"              :variant="expandedKeys.includes('download') ? 'secondary' : 'tertiary'"            >              <div class="flex w-full items-center justify-start gap-2">                <Icon icon="tabler:brand-apple-filled" />                Download HeroUI Native              </div>              <component :is="indicator" class="text-muted" />            </Button>          </template>          <p class="text-sm text-muted">            Scan this QR code with your camera app to preview the HeroUI native components.          </p>          <img            alt="App Store QR Code"            class="aspect-square w-full max-w-54 object-cover"            src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/images/qr-code-native.png"          >          <p class="text-sm text-muted">            Expo must be installed on your device.          </p>          <Button class="mt-4" variant="primary">            <Icon icon="tabler:brand-apple-filled" />            Download on App Store          </Button>        </Disclosure>      </DisclosureGroup>    </div>  </div></template>

Customization

Tailwind CSS

<script setup lang="ts">import { Button, Disclosure, DisclosureGroup, Separator } from '@hareui/vue'</script><template>  <DisclosureGroup class="w-full max-w-sm rounded-xl bg-default-soft p-2">    <Disclosure value="billing" :ui="{ bodyInner: 'text-sm text-muted' }">      <template #trigger="{ indicator }">        <Button class="w-full justify-between" variant="ghost">          Billing          <component :is="indicator" class="text-muted" />        </Button>      </template>      Invoices are issued on the first of each month.    </Disclosure>    <Separator class="my-1" />    <Disclosure value="support" :ui="{ bodyInner: 'text-sm text-muted' }">      <template #trigger="{ indicator }">        <Button class="w-full justify-between" variant="ghost">          Support          <component :is="indicator" class="text-muted" />        </Button>      </template>      Reach us at [email protected]. Typical response time is under one business day.    </Disclosure>  </DisclosureGroup></template>

Global Configuration

To customize the DisclosureGroup classes for the whole app, extend the disclosureGroup theme in createHareUI:

app.use(createHareUI({
  ui: {
    disclosureGroup: {
      slots: {
        base: 'w-full [contain:layout_style]',
      },
    },
  },
}))

Styling Reference

Slots

  • base → [data-slot="disclosure-group"] – base container styles with layout containment

Interactive States

The component supports both CSS pseudo-classes and data attributes for flexibility:

  • Disabled: [data-disabled="true"] on the group; every child Disclosure's trigger gets :disabled
  • Expanded Management: Automatically manages [data-expanded] states on child Disclosure items

API Reference

Props

PropTypeDefaultDescription
asAsTag | Component"div"The element or component to render the root as.
modelValueExpandedValue[]undefinedThe expanded disclosures' values. Use v-model to control them.
defaultValueExpandedValue[]-The disclosures expanded on first render (uncontrolled).
multiplebooleanfalseWhether multiple disclosures can be expanded at once (HeroUI's allowsMultipleExpanded).
disabledbooleanfalseWhether all disclosures in the group are disabled.
uiComponentSlots<{ slots: { base: string; }; variants: {}; defaultVariants: {}; }>-Per-slot class overrides.

Slots

SlotPropsDescription
default{ expanded: ExpandedValue[]; disabled: boolean; }The Disclosure items (and anything between them, e.g. Separator).

Emits

EventPayloadDescription
update:modelValue[value: ExpandedValue[]]-

useDisclosureGroupNavigation

OptionTypeDefaultDescription
expandedKeysMaybeRefOrGetter<ExpandedValue[]>-The current v-model value
itemIdsMaybeRefOrGetter<ExpandedValue[]>-Every disclosure's value, in display order
onExpandedChange(keys: ExpandedValue[]) => void-Called with the new expanded values
multipleMaybeRefOrGetter<boolean>falseKeep previously expanded disclosures open while navigating

Returns currentIndex, isPrevDisabled, isNextDisabled (computed refs) and onPrevious, onNext.

On this page

No Headings