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'

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 { 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"> renders title followed by the indicator.
  • With #trigger, the slotted element (e.g. Button) receives aria-expanded, aria-controls and the toggle handler, like HeroUI's <Button slot="trigger">.
  • Disclosure.Body's className maps to the bodyInner ui key.

ui keys: base, heading, trigger, indicator, content, body, bodyInner.

Examples

Render Function

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 { 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 keydata-slotDescription
basedisclosureBase container styles
headingdisclosure-headingHeading wrapper
triggerdisclosure-triggerTrigger button styles
indicatordisclosure-indicatorChevron indicator styles
contentdisclosure-contentContent 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-visible on trigger
  • Disabled: :disabled or [aria-disabled="true"] on trigger
  • Hidden: [aria-hidden="false"] on content for visibility

API Reference

Props

PropTypeDefaultDescription
asAsTag | Component"div"The element or component to render the root as.
titlestring-Text rendered by the default trigger. Ignored when #trigger is used.
valuestring | number-Identifies this disclosure inside a DisclosureGroup (HeroUI's id): the group's v-model holds these values. Defaults to a generated id.
openbooleanundefinedThe controlled expanded state of the disclosure. Use with v-model:open.
defaultOpenbooleanfalseThe expanded state of the disclosure when it is initially rendered. Use when you do not need to control its expanded state.
disabledbooleanfalseWhether the disclosure is disabled.
uiComponentSlots<{ slots: { base: string; heading: string; trigger: string[]; indicator: string[]; content: string[]; body: string; bodyInner: string; }; variants: {}; defaultVariants: {}; }>-Per-slot class overrides.

Slots

SlotPropsDescription
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.
defaultanyThe disclosure's panel content.

Emits

EventPayloadDescription
update:open[value: boolean]-

On this page

No Headings