التخطي إلى المحتوى

السمات ​

السمة (skin) هي مظهر واحد لواجهة المحرر: شريط الأدوات، وما فيه من أزرار ومجموعات، وقوائم الفقاعة، والقوائم المنسدلة، والنوافذ الحوارية، والإطار المحيط بالمحتوى، وواجهة تحديد الصورة. وتحددها الخاصية skin:

vue
<Tiptapify skin="pastel" />

يتكوّن السمة (skin) من شيئين: الرموز (tokens) أي الألوان والأحجام على شكل متغيرات CSS، والشكل أي المتغيرات البنيوية التي لا يستطيع الرمز التعبير عنها. السمتان المدمجتان هما default — المظهر الكلاسيكي، شريط أدوات بارز مع مجموعات أزرار بارزة — وpastel، المظهر الهادئ. السمات المخصصة مواطن من الدرجة الأولى: تُعالَج registerSkin() وكائنات السمات المضمّنة بالآلية نفسها تمامًا، والسمات المدمجة مجرد سمات مسجَّلة وليست حالات خاصة.

المصطلحات: السمة (skin) مقابل سمة Vuetify (theme) ​

  • skin — المصطلح الموجَّه للمستخدم لمظهر واحد من واجهة المحرر: الرموز + الشكل. الخاصية هي skin، والأنواع هي TiptapifySkin*، والسجل هو registerSkin()، وفئة الجذر هي tiptapify-skin-{name}.
  • theme — مخصص لسمات Vuetify الفاتحة/الداكنة. تُبقي مكوّنات Tiptapify خصائص theme الخاصة بها مغذّاة باسم سمة Vuetify الحالية؛ ولا يمسّها نظام السمات (skins) إطلاقًا.

وهما يتكاملان: تشير معظم ألوان الرموز المدمجة إلى متغيرات سمة Vuetify (rgb(var(--v-theme-surface)) وغيرها)، فتتبع السمات الوضعين الفاتح والداكن تلقائيًا. أما الخلايا الداكنة الثابتة في عمود classic — مقبض تغيير الحجم (rgba(0, 0, 0, .5/.8))، وإطار الصورة العادي، وظل الفقاعة، وظلال ارتفاع القوائم والنوافذ الحوارية — فهي مقصودة: يرسم المظهر الكلاسيكي واجهة داكنة محايدة في السمتين، ويثبّتها خط الأساس المقيس. ويمكن للسمة المخصصة أن تشير إلى متغيرات السمة بحرية — راجع جدول الرموز.

المفهوم ​

الرموز (Tokens) ​

الرمز خاصية CSS مخصصة باسم --tf-*. ومفتاح الكتالوج هو صيغة camelCase للاحقة CSS: toolbarBg ← --tf-toolbar-bg، وdialogTitleSize ← --tf-dialog-title-size. والقيم نصوص عادية — ألوان، واختصارات حدود كاملة، وظلال، وحشوات، وأنصاف أقطار.

كل قاعدة سمة في المكتبة موجودة مرة واحدة، وتقرأ رمزها مع قيمة احتياطية تساوي القيمة الكلاسيكية (الأساسية):

css
.tiptapify-toolbar-group {
  border-radius: var(--tf-group-radius, 4px);
}

تُصدر السمة المحلَّلة تعديلاتها فقط كمتغيرات؛ وتحمل القيم الاحتياطية في CSS القيمة الأساسية. وتظهر المتغيرات على جذر المحرر — ولأن القوائم والنوافذ الحوارية تنتقل خارجه (teleport)، فتظهر أيضًا على غلاف SkinScope لكل قائمة وعلى بطاقة النافذة نفسها، فتتبع الرموز كل سطح.

الشكل (Shape) ​

ستة أعلام تحدد مجموعات القواعد التي تُطبَّق؛ وتتولى الرموز تلوينها:

العلمالقيمما الذي يبدّله
toolbarraised · flatارتفاع VToolbar بدون خط رفيع داخلي مقابل شريط مسطح بلون خفيف
groupsbox · flatأقسام شريط الأدوات كصناديق VBtnGroup بارزة (بنية 0.3.2: أزرار متصلة، وتلوّن رموز المجموعة الصندوق) مقابل صفوف div عادية بنظام flex
buttonsvuetify · quietأزرار Vuetify الأصلية مقابل أزرار شفافة بحالة ضغط محايدة
bubblecard · flatمحتفَظ به للتوافق: قوائم الفقاعة صف واحد من أزرار الأيقونات تلوّنه الرموز في الشكلين (وتتبع أزرارها buttons)
dialogclassic · softفاصل تحت العنوان وزر إغلاق بارز مقابل بطاقة ناعمة وزر إغلاق نصي
menuvuetify · softالقوائم المنسدلة: قائمة Vuetify مقابل البطاقة الفاتحة ذات الحشوة

يُرمَّز الشكل المحلَّل على جذر المحرر كست فئات .tiptapify-shape-{flag}-{value}، ويُكشف كـ shape: ComputedRef<ResolvedShape> في useTiptapifyConfig() لمكوّنات شريط الأدوات المخصصة.

الوراثة (Extends) ​

تُحلَّل السمة فوق القاعدة الكلاسيكية، ثم سلسلة extends الخاصة بها بادئةً من الجذر، ثم أعضاؤها هي:

classic (base tokens + classic shape) → extends chain → own colors/metrics/flags

تُحلَّل الحلقات المفقودة إلى السلسلة المتراكمة (مع تحذير في وضع التطوير)؛ وتُحلَّل الحلقة الدائرية إلى classic (مع تحذير في وضع التطوير). تُشار السمة المسجّلة بالاسم؛ ويمكن لكائن سمة مضمّن أن يرث extends من اسم مسجّل ولا يدخل السجل العام أبدًا — فلا تتسرب السمات المخصصة بين المحررات. وتُتجاهل مفاتيح الرموز غير المعروفة مع تحذير في وضع التطوير.

عروض حية للأشكال الثلاثة في صفحة أمثلة السمات.

كتالوج الرموز ​

الجداول أدناه هي عقد الإصدار v1: مفاتيح الكتالوج (TiptapifySkinColors / TiptapifySkinMetrics) هي الأسماء التي يمكنك ضبطها. وخلايا classic هي القيم الاحتياطية في CSS — القيمة التي ترسمها القواعد الأساسية عندما لا تعدّل أي سمة الرمز.

شريط الأدوات / الشريط ​

الرمزمتغير CSSclassicpastel
toolbarBg--tf-toolbar-bgrgb(var(--v-theme-surface))rgba(var(--v-theme-on-surface), 0.03)
toolbarBorderBottom--tf-toolbar-border-bottomnone1px solid rgba(var(--v-border-color), var(--v-border-opacity))
toolbarFg--tf-toolbar-fginheritrgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity))

العناصر / المجموعات / الفواصل ​

الرمزمتغير CSSclassicpastel
itemsPadding--tf-items-padding12px 16px6px 8px
itemsGap--tf-items-gapnormal ¹6px
itemsRowGap--tf-items-row-gap5px4px
groupGap--tf-group-gap0px2px
groupHeight--tf-group-height32pxauto
groupBg--tf-group-bgrgb(var(--v-theme-surface))transparent
groupRadius--tf-group-radius4px0px
groupShadow--tf-group-shadowVuetify elevation 2 ²none
dividerWidth--tf-divider-width0px (spacer: margin 0 4px)1px
dividerHeight--tf-divider-height0px20px
dividerColor--tf-divider-colortransparentrgba(var(--v-border-color), var(--v-border-opacity))

¹ الخلية الكلاسيكية المقيسة هي normal — قيمة flex الأصلية في Vuetify، وهي ما تحمله القيمة الاحتياطية في CSS. والقيمة الأساسية في الكتالوج 0px هي الطول الصريح المكافئ لتعديلات السمات.

² الخلايا التي تقرأ «Vuetify elevation n» وصفية: فسلسلة الظل الثلاثي الدقيقة هي القيمة المقيسة في ملف خط الأساس المثبَّت (src/skins/__fixtures__/skin-baseline.json) وهي القيمة الاحتياطية في CSS. وبالنسبة إلى groupShadow هي elevation 2 (0 3px 1px -2px …, 0 2px 2px 0 …, 0 1px 5px 0 …) — ففي groups: 'box' يكون القسم VBtnGroup (elevation="4")، وتلوّن قاعدة الرمز الصندوق بهذا الظل الثلاثي فوق ارتفاع المجموعة نفسها: فالصندوق يملك الارتفاع، ولا تحمل الأزرار الفرعية المتصلة أيًا منه.

الأزرار ​

تُستهلك هذه الرموز فقط في buttons: 'quiet' — راجع قابلية الوصول.

الرمزمتغير CSSقيمة quiet (في classic: Vuetify الأصلية)
buttonFg--tf-button-fgrgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity))
buttonHoverBg--tf-button-hover-bgrgba(var(--v-theme-on-surface), 0.07)
buttonHoverFg--tf-button-hover-fgrgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity))
buttonActiveBg--tf-button-active-bgrgba(var(--v-theme-on-surface), 0.1)
buttonActiveHoverBg--tf-button-active-hover-bgrgba(var(--v-theme-on-surface), 0.14)
buttonRadius--tf-button-radius6px

قوائم الفقاعة (التحديد، السطر الفارغ، الصورة) ​

الرمزمتغير CSSclassicpastel
bubbleBg--tf-bubble-bgrgb(var(--v-theme-surface))نفسه
bubbleBorder--tf-bubble-bordernone1px solid rgba(var(--v-border-color), var(--v-border-opacity))
bubbleShadow--tf-bubble-shadow0 4px 14px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.08)0 6px 20px rgba(0, 0, 0, 0.12)
bubbleRadius--tf-bubble-radius6px10px
bubblePadding--tf-bubble-padding4pxنفسه
bubbleGap--tf-bubble-gap2pxنفسه
الرمزمتغير CSSclassicpastel
menuListPadding--tf-menu-list-padding8px 0px4px
menuRadius--tf-menu-radius4px8px
menuBorder--tf-menu-bordernone1px solid rgba(var(--v-border-color), var(--v-border-opacity))
menuShadow--tf-menu-shadowVuetify elevation 8 ²0 4px 16px rgba(0, 0, 0, 0.08)
menuItemRadius--tf-menu-item-radius0px6px
menuItemPadding--tf-menu-item-paddingVuetify ³4px 8px
menuItemMinHeight--tf-menu-item-min-heightVuetify ³34px
menuItemActiveBg--tf-menu-item-active-bgVuetify ³rgba(var(--v-theme-on-surface), 0.06)

³ صندوق القائمة (نصف القطر والظل وحشوة القائمة) في القائمة الكلاسيكية قاعدة سمة اليوم — فغلاف الرموز SkinScope يقع بين قاعدة Vuetify الفرعية الخاصة والقائمة، لذا تستعيد المكتبة هذه البكسلات كقواعد سمة تقرأ الرموز أعلاه. أما بكسلات العنصر فتبقى أصلية من Vuetify (إذ يقيس ملف خط الأساس القيم الافتراضية لـ Vuetify هناك): فرموز العناصر الأربعة غير فعّالة ما دام menu: 'vuetify'.

النوافذ الحوارية ​

الرمزمتغير CSSclassicpastel
dialogShadow--tf-dialog-shadowVCard elevation ²0 20px 48px rgba(0, 0, 0, 0.16), 0 2px 6px rgba(0, 0, 0, 0.06)
dialogRadius--tf-dialog-radius4px (VCard)12px
dialogHeaderPadding--tf-dialog-header-padding8px 16px16px 12px 12px 20px
dialogContentPadding--tf-dialog-content-padding16px 24px 24px4px 20px
dialogActionsPadding--tf-dialog-actions-padding8px16px 20px 20px
dialogTitleSize--tf-dialog-title-size1.25rem1.125rem
dialogTitleWeight--tf-dialog-title-weight400600
dialogFieldRadius--tf-dialog-field-radiusfield default (4px)8px (outlined)
dialogActionBtnMinHeight--tf-dialog-action-btn-min-heightVuetify (auto)38px
dialogActionBtnRadius--tf-dialog-action-btn-radiusVuetify (4px)8px
dialogGridGap--tf-dialog-grid-gap24px16px

الإطار (غلاف حدود المحرر) ​

الرمزمتغير CSSclassicpastel
frameBorder--tf-frame-border1px solid rgba(var(--v-border-color), var(--v-border-opacity)), بدون الحافة العلويةإطار كامل
frameBg--tf-frame-bgtransparentrgb(var(--v-theme-surface))
frameShadow--tf-frame-shadownone0 1px 2px rgba(0, 0, 0, 0.05)

في شكل شريط الأدوات المسطح يرسم الإطار أيضًا فرقًا لكل جانب (حافة علوية، وحافة سفلية بشفافية حد 1.6×). وذلك الفرق ينتمي إلى الشكل لا إلى رمز: فلا يمكن الوصول إليه عبر الرموز.

الصور ومقابض تغيير الحجم ​

الرمزمتغير CSSclassicpastel
imageRadius--tf-image-radius0.125rem4px
imageBg--tf-image-bgtransparentrgba(var(--v-theme-on-surface), 0.04)
imageOutline--tf-image-outline1px solid rgba(0, 0, 0, 0.25) (محددة)2px solid rgb(var(--v-theme-primary))
imageOutlineHover--tf-image-outline-hovertransparentrgba(var(--v-theme-primary), 0.35)
handleBg--tf-handle-bgrgba(0, 0, 0, 0.5)rgb(var(--v-theme-primary))
handleBgHover--tf-handle-bg-hoverrgba(0, 0, 0, 0.8) (عند التمرير)rgb(var(--v-theme-primary))
handleBorder--tf-handle-bordernone2px solid rgb(var(--v-theme-surface))
handleShadow--tf-handle-shadownone0 0 0 1px rgba(0, 0, 0, 0.15)
handleRadius--tf-handle-radius2px50%

يتبع شريط أدوات الصورة العلم buttons: ففي الشكل الهادئ يحصل على السطح الهادئ — وتقرأ مسافاته 2px/4px المتغيرين --tf-bubble-gap / --tf-bubble-padding مع القيم الاحتياطية لقائمة الصورة؛ وليس هناك رمز مخصص لشريط أدوات الصورة.

غير موجودة في الكتالوج (منطقة المخرج الاحتياطي) ​

بعض الأبعاد المذكورة في نظرة التصميم العامة ليس لها رمز في كتالوج v1: ارتفاع شريط الأدوات، وعرض الإطار، ونصف قطر الإطار، وعرض الزر، وحشوة الزر، وعرض النافذة الحوارية. وجداول الكتالوج أعلاه هي العقد؛ ولهذه البكسلات افتح المخرج الاحتياطي ونسّق الفئات الثابتة مباشرة.

قابلية الوصول ​

العقد، مذكور مرة واحدة وتلتزم به كل مجموعة أعلاه:

يلوّن الرمز سطحًا فقط عندما يفعّل الشكل ذلك السطح؛ أما عناصر Vuetify الأصلية فتُنسَّق عبر ألوان سمة Vuetify.

لكل مجموعة:

  • شريط الأدوات والإطار وواجهة الصورة/المقابض — فعّالة في كل شكل؛ تلوّنها الرموز، وخلايا classic هي المظهر الأصلي الذي تعود إليه الرموز.
  • صندوق المجموعات (groupBg وgroupRadius وgroupHeight وgroupShadow) — في groups: 'box' يكون القسم VBtnGroup (بنية 0.3.2: تتصل الأزرار ويحمل الصندوق الارتفاع)؛ وتلوّنه قواعد الصندوق برموز المجموعة، ويحافظ --tf-group-height على عقد 32px باستخدام !important (فقاعدة الكثافة في Vuetify تنازعه، كما في 0.3.2). وفي groups: 'flat' تكون الأقسام صفوف div عادية (شفافة وبلا ظل ونصف القطر 0 هو أساس الشكل).
  • الخطوط الرفيعة للفواصل (dividerWidth/Height/Color) — الخط الرفيع المرئي ميزة خاصة بـ groups: 'flat'؛ وفي الشكل الصندوقي يكون الفاصل مباعدًا بحجم صفري (margin: 0 4px من القاعدة الأساسية).
  • حشوة العناصر/المسافات — الصف المدمج 6px 8px مرتبط بالشريط المسطح (toolbar: 'flat')، ومسافات المجموعات بالأقسام المسطحة (groups: 'flat')؛ ويحتفظ الشريط البارز بالقياسات الكلاسيكية.
  • الأزرار (buttonFg وbuttonHover* وbuttonActive* وbuttonRadius) — غير فعّالة في buttons: 'vuetify': فأزرار Vuetify الأصلية ترسم حالاتها بنفسها. نسّقها بألوان سمة Vuetify (primary وsurface وغيرهما) — فالأشكال الكلاسيكية ترثها عن قصد.
  • قياسات عناصر القائمة (menuItemRadius/Padding/MinHeight/ActiveBg) — غير فعّالة في menu: 'vuetify'؛ فـ Vuetify تملك بكسلات تلك العناصر. أما صندوق قائمة القائمة (نصف القطر/الظل/الحشوة) فتلوّنه السمة في الشكلين (راجع ملاحظة القائمة).
  • واجهة النافذة الحوارية الناعمة (dialogActionBtn* وdialogFieldRadius والحشوات الناعمة والفاصل المفقود) — تُرسم في dialog: 'soft'؛ وفي dialog: 'classic' تكون النافذة VCard بالحشوات الكلاسيكية.
  • واجهة الفقاعة — قوائم التحديد والسطر الفارغ والصورة صف واحد من أزرار الأيقونات في الشكلين، تلوّنها رموز الفقاعة؛ ولم يعد bubble يغيّر بنيتها.

التعديل المساوي لقيمة الكتالوج الأساسية لا يُصدَر — ففي شكل غير كلاسيكي يرسم أساس الشكل نفسه عبر القيمة الاحتياطية في CSS، لذا فإن «استعادة» قيمة كلاسيكية (مثل إعادة buttonActiveBg إلى rgb(var(--v-theme-primary)) في buttons: 'quiet') لا تفعل شيئًا بصمت. ولفرض قيمة بمظهر كلاسيكي في شكل غير كلاسيكي، اضبط تعديلًا يختلف عن أساس الكتالوج — فقيمة حرفية مكافئة مثل rgba(var(--v-theme-primary), 1) تُرسم بالشكل نفسه وتنجو من التخطي.

لا تُوصَّل الرموز بالمسارات الأصلية عن قصد — وهذا ما يُبقي default مطابقًا للمظهر الكلاسيكي بكسلًا ببكسل بينما يمر كل شيء عبر الكتالوج.

وصفات ​

الوراثة من pastel ​

ورّث الشكل الهادئ وأعد تلوين بعض الأسطح. الأسماء المسجّلة تعمل على أي محرر:

ts
// main.ts — call once, before any editor mounts
import { registerSkin } from 'tiptapify'

registerSkin('mint', {
  extends: 'pastel',
  colors: {
    toolbarBg: 'rgba(0, 128, 0, 0.05)',   // mint tint over the pastel wash
    handleBg: 'rgb(0, 100, 0)',           // deep green handles
    handleBgHover: 'rgb(0, 128, 0)',
    imageOutline: '2px solid rgb(0, 100, 0)',
    imageOutlineHover: 'rgba(0, 100, 0, 0.35)',
  },
})
vue
<Tiptapify skin="mint" />

يأتي الشكل (flat/quiet/soft) من pastel؛ وتحتفظ الرموز التي لم تمسّها بقيم pastel — فيبقى طلاء الزر الهادئ محايدًا، ولا يتحرك إلا ما تعدّله. هذه هي السمة المعروضة حيًّا في صفحة الأمثلة.

الوراثة من default ​

احتفظ بالبنية الكلاسيكية وعدّل الألوان:

ts
registerSkin('paper', {
  extends: 'default',
  colors: { toolbarBg: 'rgb(var(--v-theme-background))' },
  metrics: { groupRadius: '8px', itemsPadding: '10px 14px' },
})

extends: 'default' هو الجذر الضمني، لذا يمكن حذف المفتاح: فـ { toolbar: 'flat', … } يبدأ من classic أيضًا.

تخصيص كامل ​

بدون extends وبدون تسجيل: مرّر الكائن إلى الخاصية skin واضبط أعلام الشكل والرموز بحرية. يضع name تسميتك الخاصة على فئة الجذر (انظر أدناه)؛ وبدونه تكون tiptapify-skin-inline.

vue
<script setup lang="ts">
import { defineSkin } from 'tiptapify'

const slate = defineSkin({
  name: 'slate',
  toolbar: 'flat',
  groups: 'flat',
  buttons: 'quiet',
  bubble: 'flat',
  dialog: 'soft',
  menu: 'soft',
  colors: { toolbarBg: 'rgb(30, 41, 59)', toolbarFg: 'rgb(226, 232, 240)' },
  metrics: { buttonRadius: '8px' },
})
</script>

<template>
  <Tiptapify :skin="slate" />
</template>

defineSkin دالة مساعدة تعيد ما تُمرَّر به لتعريف ثوابت مكتوبة الأنواع (ولا تدخل أي سجل). ويمكن ضبط أعلام الشكل فرادى — فكل علم تحذفه يبقى كلاسيكيًا.

المخرج الاحتياطي: فئة الجذر ​

يحمل كل جذر محرر tiptapify-skin-{name} (وtiptapify-skin-inline للكائن المضمّن بلا اسم). لا تربط المكتبة أي قاعدة باسم سمة أبدًا — فالفئة لك:

css
/* Style the frame of one skin, dimensions the catalog does not cover */
.tiptapify-skin-mint .tiptapify-frame {
  max-width: 720px;
  margin-inline: auto;
}

المقابض الثابتة التي يمكنك الكتابة عليها:

الفئةأين
tiptapify-skin-{name}جذر المحرر
tiptapify-shape-{flag}-{value} ×6جذر المحرر — الشكل المحلَّل
tiptapify-toolbar · tiptapify-toolbar-items · tiptapify-toolbar-group · menu-dividerشريط الأدوات وأقسامه
tiptapify-quiet-buttonsجذرا شريط الأدوات والفقاعة في buttons: 'quiet'
tiptapify-bubble-row · tiptapify-bubble-dividerصف كل قائمة فقاعة والخط الرفيع بين مجموعاتها
tiptapify-bubble-menu · floating-menu · tiptapify-image-menuصفوف قوائم التحديد والسطر الفارغ والصورة
tiptapify-btn--activeزر مضغوط في قائمة فقاعة (تنسيق نشط، أو عوم الصورة)
tiptapify-menu · tiptapify-menu--softمحتوى تراكب القائمة المنسدلة، حامل قواعد القائمة الناعمة
tiptapify-skin-scopeعنصر div لنطاق الرموز داخل القوائم المنقولة (teleport)
tiptapify-dialog · tiptapify-dialog--softبطاقة النافذة الحوارية وحاملها الناعم
tiptapify-frameغلاف حدود المحرر

الدفاع عن سمة المستهلك. بُنيت طبقة السمات لتصمد أمام سمات الإدارة التي تضيف حشوات وتعيد طلاء عناصر Vuetify الداخلية: تُقيَّد القواعد بفئات الشكل/الحامل، وتستخدم فئات مضاعفة (.v-list.v-list و.v-btn.v-btn.v-btn) لرفع التخصيص، وتُبقي !important فقط حيث أثبتت حالة سمة الإدارة في الإيداع الأساسي أنه ضروري (مجموعة الدفاع في menu.css). وفيما يلي أعراف تُبقي تعديلاتك الخاصة تعمل في ساحة المعركة نفسها:

  • حصر شيفرة CSS الخاصة بك تحت .tiptapify-skin-{name} (أو فئة شكل) — وليس على عناصر Vuetify الداخلية مباشرة؛
  • فضّل الرموز (--tf-*) لأبعاد الكتالوج، والفئات لغيرها؛
  • طابِق المضاعفة عند تجاوز مكوّنات Vuetify (فـ .v-list-item المفردة تخسر أمام قواعد السمة).

العقد البصري (ملاحظة للمساهمين) ​

الأنماط المحسوبة للسمات المدمجة مثبَّتة بملف خط الأساس src/skins/__fixtures__/skin-baseline.json (13 قسمًا × فاتح/داكن): تكتمل طبقة CSS عندما تطابقه المصفوفة المقيسة. ملاحظات قراءة للملف:

  • لا يمكن فرض أبعاد hover/active من الصفحة، لذا يقرأ التسجيل نص تصريح أول قاعدة CSSOM مطابقة لكل محدد hover ويحلّه عبر عنصر فحص داخل جذر السمة (الحقل resolved) — فهو عقد القاعدة الفائزة، وليس لقطة حية لـ :hover.
  • يسجّل _meta.selectors.menu نص المحدد السابق لـ SkinScope. والملف مجمّد (قيم معيارية)، فالحقل قديم عن قصد؛ وتثبّت حزمة التسجيل المحدد الحالي.
  • يحمل الملف تغييراته المعتمدة في _meta.notes: فاستعادة بنية VBtnGroup بتاريخ 2026-10-18 في groups: 'box' أعادت قياس حقول الأزرار الفرعية الكلاسيكية groupBtn/buttonsActive (زوايا متصلة، والصندوق يملك الارتفاع). وحقول pastel لم تُمسّ — فالتغيير البصري المتعمد يحدّث فقط الخلايا الكلاسيكية المتأثرة، ويسجّل ملاحظة، ويُشحن مع سطر في CHANGELOG.

انظر أيضًا ​

صدر بموجب ترخيص MIT.