Skip to content
API 风格:

درج Drawer ​

لوحة تنزلق من حافة الشاشة، تناسب العمليات المؤقتة الأقرب إلى الحافة مما هي عليه في Dialog (التفاصيل، التصفية، خطوات المعالج). مثل Dialog تستخدم role="dialog" + aria-modal="true"، ويبقى التركيز داخل اللوحة، ويمكن الإغلاق عبر Esc أو النقر على الطبقة المعتمة.

الاستخدام الأساسي ​

درج من الجهة اليمنى
vue
<template>
  <LhButton @click="basic = true">فتح الدرج</LhButton>
  <LhDrawer v-model="basic" title="تفاصيل الطلب">
    <p>يُوضع هنا المحتوى الرئيسي للدرج.</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">فتح الدرج</LhButton>
  <LhDrawer v-model="basic" title="تفاصيل الطلب">
    <p>يُوضع هنا المحتوى الرئيسي للدرج.</p>
  </LhDrawer>
</template>

أربع جهات ​

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>
  <!-- فتح درج من الجهة اليمنى -->
  <LhButton @click="openDir('right')">right</LhButton>
  <!-- فتح درج من الجهة اليسرى -->
  <LhButton @click="openDir('left')">left</LhButton>
  <!-- فتح درج من الأعلى -->
  <LhButton @click="openDir('top')">top</LhButton>
  <!-- فتح درج من الأسفل -->
  <LhButton @click="openDir('bottom')">bottom</LhButton>
  <!-- الانزلاق وفق الجهة المحددة -->
  <LhDrawer v-model="dirVisible" :title="`${direction} درج`" :direction="direction" :size="size">
    <p>الجهة الحالية: {{ 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>
  <!-- فتح درج من الجهة اليمنى -->
  <LhButton @click="openDir('right')">right</LhButton>
  <!-- فتح درج من الجهة اليسرى -->
  <LhButton @click="openDir('left')">left</LhButton>
  <!-- فتح درج من الأعلى -->
  <LhButton @click="openDir('top')">top</LhButton>
  <!-- فتح درج من الأسفل -->
  <LhButton @click="openDir('bottom')">bottom</LhButton>
  <!-- الانزلاق وفق الجهة المحددة -->
  <LhDrawer v-model="dirVisible" :title="`${direction} درج`" :direction="direction" :size="size">
    <p>الجهة الحالية: {{ direction }}</p>
  </LhDrawer>
</template>

حجم مخصص وقسم سفلي ​

size والفتحة footer
vue
<script setup lang="ts">
import { ref } from 'vue'

const sized = ref(false)
</script>

<template>
  <!-- فتح درج بعرض 480px -->
  <LhButton @click="sized = true">درج بعرض 480px</LhButton>
  <!-- درج بحجم ثابت، والقسم السفلي كمنطقة عمليات -->
  <LhDrawer v-model="sized" title="شروط التصفية" :size="480">
    <LhInput placeholder="تصفية بالاسم" />
    <LhInput placeholder="تصفية بالوسم" />
    <template #footer>
      <LhButton @click="sized = false">إلغاء</LhButton>
      <LhButton type="primary" @click="sized = false">تطبيق التصفية</LhButton>
    </template>
  </LhDrawer>
</template>
vue
<script>
export default {
  data() {
    return { sized: false }
  },
}
</script>

<template>
  <!-- فتح درج بعرض 480px -->
  <LhButton @click="sized = true">درج بعرض 480px</LhButton>
  <!-- درج بحجم ثابت، والقسم السفلي كمنطقة عمليات -->
  <LhDrawer v-model="sized" title="شروط التصفية" :size="480">
    <LhInput placeholder="تصفية بالاسم" />
    <LhInput placeholder="تصفية بالوسم" />
    <template #footer>
      <LhButton @click="sized = false">إلغاء</LhButton>
      <LhButton type="primary" @click="sized = false">تطبيق التصفية</LhButton>
    </template>
  </LhDrawer>
</template>

إذا مرّرت رقمًا إلى size فالوحدة هي px، وإذا مرّرت سلسلة نصية فهي تدعم النسبة المئوية (مثل '40%'). ويؤثر في الاتجاهين الأفقيين على العرض، وفي الاتجاهين الرأسيين على الارتفاع.

مفاتيح السلوك ​

mask-closable تمنع الإغلاق بالنقر على الطبقة المعتمة، وshow-close تخفي زر الإغلاق في الزاوية العلوية اليسرى، وclose-on-esc تعطّل الإغلاق عبر Esc، وlock-scroll تتحكم في قفل تمرير الصفحة عند الفتح، وteleport-target تحدد حاوية التركيب.

مفاتيح السلوك
vue
<script setup lang="ts">
import { ref } from 'vue'

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

<template>
  <!-- فتح درج «إغلاق بالزر فقط» -->
  <LhButton @click="adv1 = true">إغلاق بالزر فقط</LhButton>
  <!-- فتح درج «بدون قفل التمرير» -->
  <LhButton @click="adv2 = true">بدون قفل التمرير</LhButton>
  <!-- لا يؤدي النقر على الطبقة المعتمة ولا Esc إلى الإغلاق -->
  <LhDrawer
    v-model="adv1"
    title="إغلاق بالزر فقط"
    :mask-closable="false"
    :show-close="false"
    :close-on-esc="false"
  >
    <p>لا يؤدي النقر على الطبقة المعتمة ولا الضغط على Esc إلى الإغلاق، ولا يكون الإغلاق إلا عبر الزر.</p>
    <template #footer>
      <LhButton type="primary" @click="adv1 = false">إغلاق</LhButton>
    </template>
  </LhDrawer>
  <!-- عند الفتح تبقى الصفحة قابلة للتمرير -->
  <LhDrawer v-model="adv2" title="بدون قفل التمرير" :lock-scroll="false">
    <p>تبقى الصفحة قابلة للتمرير أثناء فتح الدرج.</p>
  </LhDrawer>
  <!-- التركيب في حاوية محددة -->
  <LhDrawer v-model="adv3" title="حاوية تركيب محددة" teleport-target="#drawer-host">
    <p>نُقلت اللوحة إلى الحاوية ذات المعرّف drawer-host.</p>
  </LhDrawer>
</template>
vue
<script>
export default {
  data() {
    return { adv1: false, adv2: false, adv3: false }
  },
}
</script>

<template>
  <!-- فتح درج «إغلاق بالزر فقط» -->
  <LhButton @click="adv1 = true">إغلاق بالزر فقط</LhButton>
  <!-- فتح درج «بدون قفل التمرير» -->
  <LhButton @click="adv2 = true">بدون قفل التمرير</LhButton>
  <!-- لا يؤدي النقر على الطبقة المعتمة ولا Esc إلى الإغلاق -->
  <LhDrawer
    v-model="adv1"
    title="إغلاق بالزر فقط"
    :mask-closable="false"
    :show-close="false"
    :close-on-esc="false"
  >
    <p>لا يؤدي النقر على الطبقة المعتمة ولا الضغط على Esc إلى الإغلاق، ولا يكون الإغلاق إلا عبر الزر.</p>
    <template #footer>
      <LhButton type="primary" @click="adv1 = false">إغلاق</LhButton>
    </template>
  </LhDrawer>
  <!-- عند الفتح تبقى الصفحة قابلة للتمرير -->
  <LhDrawer v-model="adv2" title="بدون قفل التمرير" :lock-scroll="false">
    <p>تبقى الصفحة قابلة للتمرير أثناء فتح الدرج.</p>
  </LhDrawer>
  <!-- التركيب في حاوية محددة -->
  <LhDrawer v-model="adv3" title="حاوية تركيب محددة" teleport-target="#drawer-host">
    <p>نُقلت اللوحة إلى الحاوية ذات المعرّف drawer-host.</p>
  </LhDrawer>
</template>

واجهة برمجة تطبيقات Drawer ​

الخصائص ​

الخاصيةالوصفالنوعالافتراضي
modelValueما إذا كان ظاهرًا (v-model)boolean—
titleالعنوان (يمكن أيضًا استخدام فتحة header)string—
directionالجهة"right" | "left" | "top" | "bottom"'right'
sizeالحجم: رقم يعني px، وتدعم السلسلة النسبة المئويةstring | number'30%'
maskClosableما إذا كان النقر على الطبقة المعتمة يُغلقbooleantrue
showCloseما إذا كان زر الإغلاق يُعرضbooleantrue
teleportTargetوجهة Teleport (محدِّد أو عنصر، الافتراضي body)string | HTMLElement'body'
lockScrollما إذا كان تمرير الصفحة مقفولًاbooleantrue
closeOnEscما إذا كان يستجيب للإغلاق عبر Escbooleantrue
themeVarsمتغيرات السمة على مستوى المكوّن، تتجاوز إعدادات ConfigProvider{ [x: string]: string; }—
bgPatternنمط الخلفية على مستوى المكوّن، يتجاوز إعدادات ConfigProviderstring—
sxخصائص التخطيط السريع sx (تُطبَّق على اللوحة)LhSxProps—

الأحداث ​

الحدثالوصفالمعاملات
update:model-valueتغيّر الظهور والإخفاء(value: boolean)
openيُطلق بعد الفتح—
closeيُطلق بعد الإغلاق—

الفتحات ​

الفتحةالوصف
defaultالمحتوى الرئيسي
headerترويسة مخصصة (تشمل منطقة العنوان)
footerمنطقة العمليات السفلية مخصصة

التوابع ​

التابعالوصف
openفتح برمجي
closeإغلاق برمجي

إمكانية الوصول ​

  • role="dialog" + aria-modal="true"؛ وعند وجود عنوان يُربط عبر aria-labelledby، وعند غيابه يُستخدم مفتاح اللغة drawer.title كقيمة احتياطية لـ aria-label
  • عند الفتح ينتقل التركيز إلى أول عنصر قابل للتركيز داخل اللوحة، ويدور Tab داخل اللوحة، وبعد الإغلاق يُعاد التركيز إلى المُشغِّل
  • الإغلاق عبر Esc (يمكن تعطيل هذا السلوك عبر close-on-esc)؛ الطبقة المعتمة زخرفية (aria-hidden)
  • زر الإغلاق هو <button> حقيقي، وقيمة aria-label من مفتاح اللغة drawer.close
  • تتدرّج حركة الانزلاق للداخل والخارج إلى تلاشٍ خالص عند prefers-reduced-motion

تعريفات الأنواع ​

بنى TypeScript التي يصدّرها هذا المكوّن خارجيًا (مستخرَجة تلقائيًا من packages/components/drawer/src/types.ts و@lh-ui/share/core/*؛ انقر كل عنصر لعرض التعريف كاملًا؛ وصف الخصائص في جدول الخصائص أعلاه):

LhDrawerProps
ts
/**
 * خاصيات مكوّن Drawer
 */
export interface LhDrawerProps {
  /** ما إذا كان ظاهرًا (v-model) */
  modelValue?: boolean
  /** العنوان */
  title?: string
  /** الجهة */
  direction?: LhDrawerDirection
  /** الحجم: رقم يعني px، وتدعم السلسلة النسبة المئوية */
  size?: string | number
  /** ما إذا كان النقر على الطبقة المعتمة يُغلق */
  maskClosable?: boolean
  /** ما إذا كان زر الإغلاق يُعرض */
  showClose?: boolean
  /** وجهة Teleport (محدِّد أو عنصر، الافتراضي body) */
  teleportTarget?: string | HTMLElement
  /** ما إذا كان تمرير الصفحة مقفولًا */
  lockScroll?: boolean
  /** ما إذا كان يستجيب للإغلاق عبر Esc */
  closeOnEsc?: boolean
  /** متغيرات السمة على مستوى المكوّن، تتجاوز إعدادات ConfigProvider */
  themeVars?: Record<string, string>
  /** نمط الخلفية على مستوى المكوّن، يتجاوز إعدادات ConfigProvider */
  bgPattern?: string
  /** خصائص التخطيط السريع sx (تُطبَّق على اللوحة) */
  sx?: LhSxProps
}
LhDrawerDirection (مأخوذ من @lh-ui/share/core/drawer (logic.ts))
ts
/**
 * منطق Drawer الدوالي البحت (بلا اعتماد على إطار عمل)
 */

/** جهة الدرج */
export type LhDrawerDirection = 'right' | 'left' | 'top' | 'bottom'

جمال التقاليد، أساس الكود