Disclosure
A disclosure is a collapsible section with a header containing a heading and a trigger button, and a panel that wraps the content.
Usage
import { Disclosure } from '@hareui/vue'<script setup lang="ts">import { Button, Disclosure } from '@hareui/vue'import { Icon } from '@iconify/vue'import { ref } from 'vue'const isExpanded = ref(true)</script><template> <div class="w-full max-w-md text-center"> <Disclosure v-model:open="isExpanded" :ui="{ bodyInner: 'shadow-panel flex flex-col items-center rounded-3xl bg-surface p-4 text-center' }" > <template #trigger="{ indicator }"> <Button variant="secondary"> <Icon icon="gravity-ui:qr-code" /> Preview HeroUI Native <component :is="indicator" /> </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 icon="tabler:brand-apple-filled" /> Download on App Store </Button> </Disclosure> </div></template>Anatomy
HeroUI's compound parts (Disclosure.Heading, Disclosure.Trigger, Disclosure.Indicator, Disclosure.Content, Disclosure.Body) become props and named slots:
<Disclosure title="…" v-model:open="open">
<!-- replaces the trigger; render the themed chevron with <component :is="indicator" /> -->
<template #trigger="{ open, indicator }" />
<!-- replaces the chevron inside the default trigger -->
<template #indicator="{ open }" />
<!-- default slot = Disclosure.Body's content -->
</Disclosure>- Without
#trigger, a<button data-slot="disclosure-trigger">renderstitlefollowed by the indicator. - With
#trigger, the slotted element (e.g.Button) receivesaria-expanded,aria-controlsand the toggle handler, like HeroUI's<Button slot="trigger">. Disclosure.Body'sclassNamemaps to thebodyInneruikey.
ui keys: base, heading, trigger, indicator, content, body, bodyInner.
Examples
Render Function
<script setup lang="ts">import { Button, Disclosure } from '@hareui/vue'import { Icon } from '@iconify/vue'import { defineComponent, h, ref } from 'vue'const isExpanded = ref(true)const CustomRoot = defineComponent((_, { attrs, slots }) => () => h('div', { ...attrs, 'data-custom': 'foo' }, slots.default?.()))</script><template> <div class="w-full max-w-md text-center"> <Disclosure :as="CustomRoot" v-model:open="isExpanded" :ui="{ bodyInner: 'shadow-panel flex flex-col items-center rounded-3xl bg-surface p-4 text-center' }" > <template #trigger="{ indicator }"> <Button variant="secondary"> <Icon icon="gravity-ui:qr-code" /> Preview HeroUI Native <component :is="indicator" /> </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 icon="tabler:brand-apple-filled" /> Download on App Store </Button> </Disclosure> </div></template>Customization
Tailwind CSS
<script setup lang="ts">import { Button, Disclosure } from '@hareui/vue'import { Icon } from '@iconify/vue'import { ref } from 'vue'const isExpanded = ref(false)</script><template> <div class="w-full max-w-sm"> <Disclosure v-model:open="isExpanded" :ui="{ bodyInner: 'mt-2 rounded-xl border border-border/70 bg-surface/50 p-4 text-sm leading-relaxed text-muted dark:bg-neutral-900/50' }" > <template #trigger="{ indicator }"> <Button class="w-full justify-between rounded-xl border border-border/70 bg-linear-to-b from-neutral-50/90 to-white px-4 py-3 font-medium text-foreground shadow-sm ring-1 ring-black/5 hover:bg-muted/30 dark:from-neutral-900/80 dark:to-neutral-900 dark:ring-white/10" variant="ghost" > <span class="flex items-center gap-2"> <Icon class="size-4 text-muted" icon="gravity-ui:shopping-bag" /> Shipping details </span> <component :is="indicator" class="text-muted" /> </Button> </template> Orders ship within 2 business days. Standard delivery takes 3–5 days; express is available at checkout. </Disclosure> </div></template>Global CSS
To customize the Disclosure component classes app-wide, override the disclosure theme with createHareUI:
app.use(createHareUI({
ui: {
disclosure: {
slots: {
base: 'relative',
trigger: 'cursor-pointer',
indicator: 'transition-transform duration-300',
content: 'overflow-hidden transition-all',
},
},
},
}))Styling Reference
Each rendered element carries the same data-slot string as HeroUI, so selectors translate 1:1.
ui key | data-slot | Description |
|---|---|---|
base | disclosure | Base container styles |
heading | disclosure-heading | Heading wrapper |
trigger | disclosure-trigger | Trigger button styles |
indicator | disclosure-indicator | Chevron indicator styles |
content | disclosure-content | Content container with animations |
Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- Expanded:
[data-expanded="true"]on indicator for rotation - Focus:
:focus-visibleon trigger - Disabled:
:disabledor[aria-disabled="true"]on trigger - Hidden:
[aria-hidden="false"]on content for visibility
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
as | AsTag | Component | "div" | The element or component to render the root as. |
title | string | - | Text rendered by the default trigger. Ignored when #trigger is used. |
value | string | number | - | Identifies this disclosure inside a DisclosureGroup (HeroUI's id): the group's
v-model holds these values. Defaults to a generated id. |
open | boolean | undefined | The controlled expanded state of the disclosure. Use with v-model:open. |
defaultOpen | boolean | false | The expanded state of the disclosure when it is initially rendered. Use when you do not need to control its expanded state. |
disabled | boolean | false | Whether the disclosure is disabled. |
ui | ComponentSlots<{ slots: { base: string; heading: string; trigger: string[]; indicator: string[]; content: string[]; body: string; bodyInner: string; }; variants: {}; defaultVariants: {}; }> | - | Per-slot class overrides. |
Slots
| Slot | Props | Description |
|---|---|---|
trigger | { open: boolean; indicator: Component; } | Replaces the whole trigger content (default: the title text followed by #indicator).
Compose it with your own interactive element (e.g. Button) for full control of the
trigger's look; the disclosure wires expand/collapse behavior onto that element. |
indicator | { open: boolean; } | Replaces the chevron indicator rendered inside the default trigger. |
default | any | The disclosure's panel content. |
Emits
| Event | Payload | Description |
|---|---|---|
update:open | [value: boolean] | - |




