Skip to content
API 风格:

علامات التبويب Tabs ​

تبديل المحتوى على المستوى نفسه. مطابقة صارمة لنمط tabs في WAI-ARIA APG: ترابط ثلاثة أدوار tablist/tab/tabpanel + roving tabindex + تنقّل بأسهم لوحة المفاتيح.

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

الاستخدام الأساسي
محتوى النثر برسم الحبر.
vue
<script setup lang="ts">
</script>

<template>
  <LhTabs>
    <LhTabPane name="prose" label="نثر">محتوى النثر برسم الحبر.</LhTabPane>
    <LhTabPane name="poem" label="شعر">محتوى أوزان الشعر.</LhTabPane>
    <LhTabPane name="calligraphy" label="خط">محتوى الخط ونقوشه.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {}
</script>

<template>
  <LhTabs>
    <LhTabPane name="prose" label="نثر">محتوى النثر برسم الحبر.</LhTabPane>
    <LhTabPane name="poem" label="شعر">محتوى أوزان الشعر.</LhTabPane>
    <LhTabPane name="calligraphy" label="خط">محتوى الخط ونقوشه.</LhTabPane>
  </LhTabs>
</template>

مظهر البطاقة والتعطيل ​

مظهر البطاقة والتعطيل
للحبر خمس درجات.
vue
<script setup lang="ts">
</script>

<template>
  <LhTabs type="card">
    <LhTabPane name="ink" label="الحبر">للحبر خمس درجات.</LhTabPane>
    <LhTabPane name="cinnabar" label="الزنجفر" disabled>الزنجفر غير متاح.</LhTabPane>
    <LhTabPane name="gold" label="الذهب">تلوين بالأصفر العشبي.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {}
</script>

<template>
  <LhTabs type="card">
    <LhTabPane name="ink" label="الحبر">للحبر خمس درجات.</LhTabPane>
    <LhTabPane name="cinnabar" label="الزنجفر" disabled>الزنجفر غير متاح.</LhTabPane>
    <LhTabPane name="gold" label="الذهب">تلوين بالأصفر العشبي.</LhTabPane>
  </LhTabs>
</template>

الموضع السفلي ​

الموضع السفلي
الجبل ضخم ممتد.
vue
<script setup lang="ts">
</script>

<template>
  <LhTabs tab-position="bottom">
    <LhTabPane name="mountain" label="الجبل">الجبل ضخم ممتد.</LhTabPane>
    <LhTabPane name="water" label="الماء">الماء حالمة صافية.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {}
</script>

<template>
  <LhTabs tab-position="bottom">
    <LhTabPane name="mountain" label="الجبل">الجبل ضخم ممتد.</LhTabPane>
    <LhTabPane name="water" label="الماء">الماء حالمة صافية.</LhTabPane>
  </LhTabs>
</template>

قابل للإغلاق وقابل للإضافة ​

قابل للإغلاق وقابل للإضافة
محتوى اللفيفة الأولى.
vue
<script setup lang="ts">
import { ref } from 'vue'
const panes = ref([
  { name: 's1', label: 'لفيفة 1', content: 'محتوى اللفيفة الأولى.', disabled: false },
  { name: 's2', label: 'لفيفة 2', content: 'محتوى اللفيفة الثانية.', disabled: false },
])
let index = 2

const removePane = (name) => {
  const target = panes.value.find((pane) => pane.name === name)
  if (target) panes.value.splice(panes.value.indexOf(target), 1)
}
const addPane = () => {
  index += 1
  panes.value.push({ name: `s${index}`, label: `لفيفة ${index}`, content: 'محتوى لفيفة جديدة.', disabled: false })
}
</script>

<template>
  <!-- قابل للإغلاق وقابل للإضافة -->
  <LhTabs closable addable tab-position="bottom" @tab-remove="removePane" @tab-add="addPane">
    <LhTabPane
      v-for="pane in panes"
      :key="pane.name"
      :name="pane.name"
      :label="pane.label"
      :disabled="pane.disabled"
    >{{ pane.content }}</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {
  data() {
    return {
      panes: [
        { name: 's1', label: 'لفيفة 1', content: 'محتوى اللفيفة الأولى.', disabled: false },
        { name: 's2', label: 'لفيفة 2', content: 'محتوى اللفيفة الثانية.', disabled: false },
      ],
      index: 2,
    }
  },
  methods: {
    removePane(name) {
      const target = this.panes.find((pane) => pane.name === name)
      if (target) this.panes.splice(this.panes.indexOf(target), 1)
    },
    addPane() {
      this.index += 1
      this.panes.push({ name: `s${this.index}`, label: `لفيفة ${this.index}`, content: 'محتوى لفيفة جديدة.', disabled: false })
    },
  },
}
</script>

<template>
  <!-- قابل للإغلاق وقابل للإضافة -->
  <LhTabs closable addable tab-position="bottom" @tab-remove="removePane" @tab-add="addPane">
    <LhTabPane
      v-for="pane in panes"
      :key="pane.name"
      :name="pane.name"
      :label="pane.label"
      :disabled="pane.disabled"
    >{{ pane.content }}</LhTabPane>
  </LhTabs>
</template>

عند إغلاق العلامة النشطة يتبدّل المكوّن تلقائيًا إلى العلامة المجاورة المتاحة، ويُطلق tab-remove؛ ويتحمل المستخدم مسؤولية حذف العلامة المقابلة من مصدر البيانات.

استخدام مح controlled ​

استخدام مح controlled
محتوى رسم الحبر.

العلامة الحالية: mo

vue
<script setup lang="ts">
import { ref } from 'vue'
const active = ref('mo')
</script>

<template>
  <LhTabs v-model="active" type="card">
    <LhTabPane name="zh" label="النمط الصيني">محتوى النمط الصيني.</LhTabPane>
    <LhTabPane name="mo" label="رسم الحبر">محتوى رسم الحبر.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {
  data() {
    return { active: 'mo' }
  },
}
</script>

<template>
  <LhTabs v-model="active" type="card">
    <LhTabPane name="zh" label="النمط الصيني">محتوى النمط الصيني.</LhTabPane>
    <LhTabPane name="mo" label="رسم الحبر">محتوى رسم الحبر.</LhTabPane>
  </LhTabs>
</template>

Tabs API ​

LhTabs Props ​

اسم الخاصيةالوصفالنوعالافتراضي
modelValueاسم العلامة النشطة حاليًا (v-model)string—
typeالمظهر"line" | "card"'line'
closableالعلامات قابلة للإغلاقbooleanfalse
addableإظهار زر الإضافةbooleanfalse
tabPositionموضع العلامات"top" | "bottom"'top'
sxخصائص التخطيط السريع sxLhSxProps—

LhTabs Events ​

اسم الحدثالوصفوسائط الاستدعاء
update:modelValueتتغير العلامة النشطة (v-model)(name: string)
tab-changeتتغير العلامة النشطة(name: string)
tab-removeتُغلق علامة(name: string)
tab-addالنقر على زر الإضافة—

LhTabPane Props ​

اسم الخاصيةالوصفالنوعالافتراضي
nameالمُعرّف الفريد للعلامة (مفتاح ثابت، لا يُستحسن تعديله ديناميكيًا)string—
labelعنوان العلامةstring''
disabledتعطيلbooleanfalse

Slots ​

اسم الفتحةالوصفالمكوّن المعني
defaultلوحة العلامات (قائمة LhTabPane)LhTabs
defaultمحتوى اللوحةLhTabPane

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

مطابقة صارمة لنمط tabs في WAI-ARIA APG:

  • رأس العلامات role="tablist"، وكل علامة role="tab" (aria-selected + aria-controls)، واللوحة role="tabpanel" (aria-labelledby + tabindex="0")
  • roving tabindex: العلامة النشطة وحدها قابلة للوصول عبر Tab، أما البقية فعليها tabindex="-1"
  • أسهم لوحة المفاتيح تنقل بين العلامات المتاحة وتُفعّلها تلقائيًا (متخطية المعطّلة)، وHome/End تقفز إلى الطرفين
  • عند closable يُغلق المفتاح Delete العلامة الحالية؛ وأيقونة الإغلاق زخرفة aria-hidden، والإغلاق بلوحة المفاتيح يتم عبر Delete، تفاديًا لتداخل الأزرار
  • العلامة المعطّلة لا يمكن تركيزها أو تفعيلها، وعمليات مثل tab-remove لا تنفّذ على العناصر المعطّلة

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

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

LhTabsProps
ts
export interface LhTabsProps {
  /** اسم العلامة النشطة حاليًا (v-model) */
  modelValue?: string
  /** المظهر */
  type?: LhTabsType
  /** العلامات قابلة للإغلاق */
  closable?: boolean
  /** إظهار زر الإضافة */
  addable?: boolean
  /** موضع العلامات */
  tabPosition?: LhTabsPosition
  /** خصائص التخطيط السريع sx */
  sx?: LhSxProps
}
LhTabPaneProps
ts
export interface LhTabPaneProps {
  /** المُعرّف الفريد للعلامة (مفتاح ثابت، لا يُستحسن تعديله ديناميكيًا) */
  name: string
  /** عنوان العلامة */
  label?: string
  /** تعطيل */
  disabled?: boolean
}
LhTabsType (مأخوذ من @lh-ui/share/core/tabs)
ts
/**
 * مظهر علامات التبويب
 */
export type LhTabsType = 'line' | 'card'
LhTabsPosition (مأخوذ من @lh-ui/share/core/tabs)
ts
/**
 * موضع علامات التبويب
 */
export type LhTabsPosition = 'top' | 'bottom'

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