Skip to content

useDisclosure

Composable headless state buka/tutup + ARIA props — dasar dari Disclosure/SimpleDisclosure, diekspor langsung untuk UI custom penuh.

Bagian dari: vue-salayout · Family: Headless


Import

ts
import { useDisclosure } from '@bpmlib/vue-salayout';

Instalasi: lihat Installation & Setup di halaman utama.


Usage

vue
<script setup lang="ts">
import { useDisclosure } from '@bpmlib/vue-salayout';

const { isOpen, toggle, triggerProps, panelProps } = useDisclosure({ defaultOpen: false });
</script>

<template>
  <button v-bind="triggerProps" @click="toggle">{{ isOpen ? 'Tutup' : 'Buka' }}</button>
  <div v-bind="panelProps" v-show="isOpen">Isi panel — markup sepenuhnya milik kamu.</div>
</template>

Tidak ada CSS, tidak ada opini DOM, tidak ada ketergantungan ke Card sama sekali — cocok kalau kamu butuh membangun UI disclosure custom sepenuhnya, bukan sekadar styling ulang.


API Reference

useDisclosure

Mengelola state buka/tutup satu item disclosure, uncontrolled (state lokal) atau controlled (didelegasikan lewat controlledOpen/onToggle) — mekanisme yang sama dipakai Disclosure/SimpleDisclosure secara internal saat nested di dalam Accordion, atau saat dipakai dengan v-model.

Parameters

NameTypeDefaultDescription
optionsUseDisclosureOptions{}Konfigurasi awal + hook controlled mode Lihat selengkapnya
options

Structure:

ts
interface UseDisclosureOptions {
  defaultOpen?: boolean;
  controlledOpen?: ComputedRef<boolean>;
  onToggle?: () => void;
  onOpen?: () => void;
  onClose?: () => void;
  onToggleState?: (isOpen: boolean) => void;
}

Properties:

  • defaultOpen - Status awal untuk pemakaian uncontrolled. Default: false
  • controlledOpen - Kalau diisi, status open didelegasikan ke sini alih-alih dikelola lokal Lihat selengkapnya
  • onToggle - Dipanggil alih-alih mutasi state lokal saat controlledOpen diisi Lihat selengkapnya
  • onOpen / onClose - Fire di setiap transisi buka/tutup nyata (tidak pernah saat mount, meski defaultOpen: true) Lihat selengkapnya
  • onToggleState - Fire bersamaan dengan onOpen/onClose, dengan status baru Lihat selengkapnya
controlledOpen

Dipakai saat sesuatu di luar composable ini (parent Accordion, v-model component pembungkus) yang benar-benar memegang status open/close.

Signature:

ts
controlledOpen?: ComputedRef<boolean>

Contoh:

vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import { useDisclosure } from '@bpmlib/vue-salayout';

const externalOpen = ref(false);
const { isOpen, toggle } = useDisclosure({
  controlledOpen: computed(() => externalOpen.value),
  onToggle: () => (externalOpen.value = !externalOpen.value),
});
</script>

Use Case: Membangun component pembungkus sendiri yang perlu koordinasi banyak instance sekaligus (pola yang sama dipakai Accordion untuk Disclosure/SimpleDisclosure).

onToggle

Signature:

ts
onToggle?: () => void

Dipanggil oleh toggle()/open()/close() sebagai ganti mutasi lokal, hanya saat controlledOpen diisi. open()/close() tidak memanggilnya kalau status sudah sesuai target (no-op).

Use Case: Titik satu-satunya tempat status eksternal benar-benar diubah, dipisah dari logic baca status (controlledOpen).

onOpen / onClose

Signature:

ts
onOpen?: () => void
onClose?: () => void

Contoh:

ts
useDisclosure({
  onOpen: () => console.log('Terbuka'),
  onClose: () => console.log('Tertutup'),
});

Use Case: Efek samping yang hanya perlu tahu arah transisi (mis. fokus elemen tertentu saat terbuka), tanpa peduli status barunya secara eksplisit.

onToggleState

Signature:

ts
onToggleState?: (isOpen: boolean) => void

Contoh:

ts
useDisclosure({
  onToggleState: (isOpen) => console.log('Status sekarang:', isOpen),
});

Use Case: Analytics/tracking interaksi buka-tutup tanpa perlu membedakan onOpen/onClose secara terpisah.

Returns

Contains:

isOpen
ts
isOpen: ComputedRef<boolean>

Status open/close saat ini — dari state lokal atau controlledOpen, tergantung mode.

⚠️ Penting - Penggunaan .value:

  • Di <script>: Perlu .valueisOpen.value
  • Di <template>: Tidak perlu .value (auto-unwrap) → isOpen
toggle, open, close
ts
toggle: () => void
open: () => void
close: () => void

Mutasi state lokal langsung (uncontrolled), atau delegasi ke onToggle (controlled) — lihat controlledOpen.

Contoh:

ts
const { isOpen, toggle, open, close } = useDisclosure();

toggle(); // buka jika tertutup, tutup jika terbuka
open();   // paksa terbuka
close();  // paksa tertutup
triggerProps
ts
triggerProps: ComputedRef<{ 'aria-expanded': boolean; 'aria-controls': string }>

Di-spread langsung ke elemen trigger custom kamu (v-bind="triggerProps").

panelProps
ts
panelProps: ComputedRef<{ id: string }>

Di-spread langsung ke elemen panel custom kamu (v-bind="panelProps") — id-nya sama dengan yang dirujuk triggerProps's aria-controls.

Digunakan oleh: Disclosure, SimpleDisclosure

Kapan pakai langsung: Gunakan composable ini langsung kalau kamu butuh markup/CSS custom penuh yang tidak bisa dicapai lewat slot trigger/caret/list/children milik Disclosure/SimpleDisclosure. Kalau default styling kedua component itu sudah cukup, pakai component stylized-nya saja.


Examples

1. Uncontrolled Dasar

vue
<script setup lang="ts">
import { useDisclosure } from '@bpmlib/vue-salayout';
const { isOpen, toggle, triggerProps, panelProps } = useDisclosure();
</script>

<template>
  <button v-bind="triggerProps" @click="toggle">Toggle</button>
  <div v-bind="panelProps" v-show="isOpen">Konten.</div>
</template>

2. Programmatic open()/close() Tanpa Trigger

vue
<script setup lang="ts">
import { useDisclosure } from '@bpmlib/vue-salayout';
const { isOpen, open, close, panelProps } = useDisclosure();
</script>

<template>
  <button @click="open()">Buka</button>
  <button @click="close()">Tutup</button>
  <div v-bind="panelProps" v-show="isOpen">Konten.</div>
</template>

  • Disclosure — stylized, memakai composable ini secara internal
  • SimpleDisclosure — stylized, memakai composable ini secara internal