Skip to content
API 风格:

Tiroir ​

Panneau latéral coulissant depuis le bord de l'écran, adapté aux interactions temporaires plus proches du bord qu'un Dialog (détails, filtres, étapes d'un assistant). Comme le Dialog, il repose sur role="dialog" + aria-modal="true", avec un piège de focus à l'intérieur du panneau ; Échap et le clic sur le masque ferment tous deux le tiroir.

Utilisation de base ​

Tiroir droit
vue
<template>
  <LhButton @click="basic = true">Ouvrir le tiroir</LhButton>
  <LhDrawer v-model="basic" title="Détail de la commande">
    <p>Le contenu principal du tiroir se place ici.</p>
  </LhDrawer>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const basic = ref(false)
</script>
vue
<script>
export default {
  data() {
    return { basic: false }
  },
}
</script>

<template>
  <LhButton @click="basic = true">Ouvrir le tiroir</LhButton>
  <LhDrawer v-model="basic" title="Détail de la commande">
    <p>Le contenu principal du tiroir se place ici.</p>
  </LhDrawer>
</template>

Quatre directions ​

right / left / top / bottom
vue
<script setup lang="ts">
import { ref } from 'vue'
const dirVisible = ref(false)
const direction = ref<'right' | 'left' | 'top' | 'bottom'>('right')
const size = ref('40%')
function openDir(d: 'right' | 'left' | 'top' | 'bottom') {
  direction.value = d
  dirVisible.value = true
}
</script>

<template>
  <!-- Ouvrir le tiroir droit -->
  <LhButton @click="openDir('right')">right</LhButton>
  <!-- Ouvrir le tiroir gauche -->
  <LhButton @click="openDir('left')">left</LhButton>
  <!-- Ouvrir le tiroir supérieur -->
  <LhButton @click="openDir('top')">top</LhButton>
  <!-- Ouvrir le tiroir inférieur -->
  <LhButton @click="openDir('bottom')">bottom</LhButton>
  <!-- Coulissement dans la direction spécifiée -->
  <LhDrawer v-model="dirVisible" :title="`Tiroir ${direction}`" :direction="direction" :size="size">
    <p>Direction actuelle : {{ direction }}</p>
  </LhDrawer>
</template>
vue
<script>
export default {
  data() {
    return { dirVisible: false, direction: 'right', size: '40%' }
  },
  methods: {
    openDir(d) {
      this.direction = d
      this.dirVisible = true
    },
  },
}
</script>

<template>
  <!-- Ouvrir le tiroir droit -->
  <LhButton @click="openDir('right')">right</LhButton>
  <!-- Ouvrir le tiroir gauche -->
  <LhButton @click="openDir('left')">left</LhButton>
  <!-- Ouvrir le tiroir supérieur -->
  <LhButton @click="openDir('top')">top</LhButton>
  <!-- Ouvrir le tiroir inférieur -->
  <LhButton @click="openDir('bottom')">bottom</LhButton>
  <!-- Coulissement dans la direction spécifiée -->
  <LhDrawer v-model="dirVisible" :title="`Tiroir ${direction}`" :direction="direction" :size="size">
    <p>Direction actuelle : {{ direction }}</p>
  </LhDrawer>
</template>

Taille personnalisée et pied de panneau ​

size et slot footer
vue
<script setup lang="ts">
import { ref } from 'vue'

const sized = ref(false)
</script>

<template>
  <!-- Ouvrir un tiroir de 480 px de large -->
  <LhButton @click="sized = true">Tiroir de 480 px de large</LhButton>
  <!-- Tiroir à taille fixée, le pied de panneau sert de zone d'actions -->
  <LhDrawer v-model="sized" title="Filtres" :size="480">
    <LhInput placeholder="Filtrer par nom" />
    <LhInput placeholder="Filtrer par étiquette" />
    <template #footer>
      <LhButton @click="sized = false">Annuler</LhButton>
      <LhButton type="primary" @click="sized = false">Appliquer les filtres</LhButton>
    </template>
  </LhDrawer>
</template>
vue
<script>
export default {
  data() {
    return { sized: false }
  },
}
</script>

<template>
  <!-- Ouvrir un tiroir de 480 px de large -->
  <LhButton @click="sized = true">Tiroir de 480 px de large</LhButton>
  <!-- Tiroir à taille fixée, le pied de panneau sert de zone d'actions -->
  <LhDrawer v-model="sized" title="Filtres" :size="480">
    <LhInput placeholder="Filtrer par nom" />
    <LhInput placeholder="Filtrer par étiquette" />
    <template #footer>
      <LhButton @click="sized = false">Annuler</LhButton>
      <LhButton type="primary" @click="sized = false">Appliquer les filtres</LhButton>
    </template>
  </LhDrawer>
</template>

size est en px lorsqu'un nombre est transmis, et accepte les pourcentages sous forme de chaîne (par exemple '40%'). Il s'applique à la largeur pour les directions gauche/droite, et à la hauteur pour haut/bas.

Comportements ​

mask-closable empêche la fermeture par clic sur le masque, show-close masque le bouton de fermeture en haut à droite, close-on-esc désactive la fermeture avec Échap, lock-scroll empêche le verrouillage du défilement de la page à l'ouverture, et teleport-target désigne le conteneur de montage.

Comportements
vue
<script setup lang="ts">
import { ref } from 'vue'

const adv1 = ref(false)
const adv2 = ref(false)
const adv3 = ref(false)
</script>

<template>
  <!-- Ouvrir le tiroir « Boutons uniquement » -->
  <LhButton @click="adv1 = true">Boutons uniquement</LhButton>
  <!-- Ouvrir le tiroir « Défilement non verrouillé » -->
  <LhButton @click="adv2 = true">Défilement non verrouillé</LhButton>
  <!-- Le clic sur le masque et Échap ne ferment pas -->
  <LhDrawer
    v-model="adv1"
    title="Boutons uniquement"
    :mask-closable="false"
    :show-close="false"
    :close-on-esc="false"
  >
    <p>Le clic sur le masque et Échap ne ferment pas le panneau, seule la fermeture par bouton est possible.</p>
    <template #footer>
      <LhButton type="primary" @click="adv1 = false">Fermer</LhButton>
    </template>
  </LhDrawer>
  <!-- La page reste défilable à l'ouverture -->
  <LhDrawer v-model="adv2" title="Défilement non verrouillé" :lock-scroll="false">
    <p>La page reste défilable lorsque le tiroir est ouvert.</p>
  </LhDrawer>
  <!-- Montage dans le conteneur désigné -->
  <LhDrawer v-model="adv3" title="Conteneur de montage désigné" teleport-target="#drawer-host">
    <p>Le panneau est téléporté dans le conteneur d'id drawer-host.</p>
  </LhDrawer>
</template>
vue
<script>
export default {
  data() {
    return { adv1: false, adv2: false, adv3: false }
  },
}
</script>

<template>
  <!-- Ouvrir le tiroir « Boutons uniquement » -->
  <LhButton @click="adv1 = true">Boutons uniquement</LhButton>
  <!-- Ouvrir le tiroir « Défilement non verrouillé » -->
  <LhButton @click="adv2 = true">Défilement non verrouillé</LhButton>
  <!-- Le clic sur le masque et Échap ne ferment pas -->
  <LhDrawer
    v-model="adv1"
    title="Boutons uniquement"
    :mask-closable="false"
    :show-close="false"
    :close-on-esc="false"
  >
    <p>Le clic sur le masque et Échap ne ferment pas le panneau, seule la fermeture par bouton est possible.</p>
    <template #footer>
      <LhButton type="primary" @click="adv1 = false">Fermer</LhButton>
    </template>
  </LhDrawer>
  <!-- La page reste défilable à l'ouverture -->
  <LhDrawer v-model="adv2" title="Défilement non verrouillé" :lock-scroll="false">
    <p>La page reste défilable lorsque le tiroir est ouvert.</p>
  </LhDrawer>
  <!-- Montage dans le conteneur désigné -->
  <LhDrawer v-model="adv3" title="Conteneur de montage désigné" teleport-target="#drawer-host">
    <p>Le panneau est téléporté dans le conteneur d'id drawer-host.</p>
  </LhDrawer>
</template>

Drawer API ​

Props ​

PropriétéDescriptionTypeValeur par défaut
modelValueAffichage (v-model)boolean—
titleTitre (le slot header convient également)string—
directionDirection"right" | "left" | "top" | "bottom"'right'
sizeTaille : nombre en px, la chaîne accepte les pourcentagesstring | number'30%'
maskClosableFermer lors d'un clic sur le masquebooleantrue
showCloseAfficher le bouton de fermeturebooleantrue
teleportTargetCible du Teleport (sélecteur ou élément, body par défaut)string | HTMLElement'body'
lockScrollVerrouiller le défilement de la pagebooleantrue
closeOnEscRépondre à Échap pour fermerbooleantrue
themeVarsVariables de thème au niveau du composant, surchargeant la configuration de ConfigProvider{ [x: string]: string; }—
bgPatternMotif d'arrière-plan au niveau du composant, surchargeant la configuration de ConfigProviderstring—
sxPropriétés de mise en page rapide sx (appliquées au panneau)LhSxProps—

Events ​

ÉvénementDescriptionParamètre
update:model-valueChangement de visibilité(value: boolean)
openDéclenché après l'ouverture—
closeDéclenché après la fermeture—

Slots ​

SlotDescription
defaultContenu principal
headerEn-tête personnalisé (incluant la zone de titre)
footerZone d'actions personnalisée en pied de panneau

Methods ​

MéthodeDescription
openOuverture programmatique
closeFermeture programmatique

Accessibilité ​

  • role="dialog" + aria-modal="true" ; avec un titre, l'association se fait via aria-labelledby, sans titre le pack de langue drawer.title sert de aria-label de repli
  • À l'ouverture, le focus se déplace sur le premier élément focusable du panneau, Tab boucle à l'intérieur du panneau, et le focus est rendu au déclencheur après fermeture
  • Fermeture par Échap (désactivable avec close-on-esc) ; le masque est décoratif (aria-hidden)
  • Le bouton de fermeture est un véritable <button>, son aria-label est issu du pack de langue drawer.close
  • L'animation de coulissement est réduite à un simple fondu lorsque prefers-reduced-motion est actif

Définitions de types ​

Les structures de types TypeScript exportées par ce composant sont présentées ci-dessous (extraction automatique à partir des sources packages/components/drawer/src/types.ts et @lh-ui/share/core/* ; cliquez sur chaque entrée pour afficher la définition complète ; la description des propriétés se trouve dans le tableau Props ci-dessus) :

LhDrawerProps
ts
/**
 * Props du composant Drawer
 */
export interface LhDrawerProps {
  /** Affichage (v-model) */
  modelValue?: boolean
  /** Titre */
  title?: string
  /** Direction */
  direction?: LhDrawerDirection
  /** Taille : nombre en px, la chaîne accepte les pourcentages */
  size?: string | number
  /** Fermer lors d'un clic sur le masque */
  maskClosable?: boolean
  /** Afficher le bouton de fermeture */
  showClose?: boolean
  /** Cible du Teleport (sélecteur ou élément, body par défaut) */
  teleportTarget?: string | HTMLElement
  /** Verrouiller le défilement de la page */
  lockScroll?: boolean
  /** Répondre à Échap pour fermer */
  closeOnEsc?: boolean
  /** Variables de thème au niveau du composant, surchargeant la configuration de ConfigProvider */
  themeVars?: Record<string, string>
  /** Motif d'arrière-plan au niveau du composant, surchargeant la configuration de ConfigProvider */
  bgPattern?: string
  /** Propriétés de mise en page rapide sx (appliquées au panneau) */
  sx?: LhSxProps
}
LhDrawerDirection (provient de @lh-ui/share/core/drawer (logic.ts))
ts
/**
 * Logique en fonctions pures du Drawer (sans dépendance de framework)
 */

/** Direction du tiroir */
export type LhDrawerDirection = 'right' | 'left' | 'top' | 'bottom'

La beauté de la tradition, la fondation du code