تخطَّ إلى المحتوى

الوضع الداكن

تدعم جميع مكوّنات lh-ui افتراضيًا الوضعين الفاتح والداكن. فهذه ليست سمة أُضيفت لاحقًا، بل فرضية تصميمية لنظام الرموز.

مفتاح الوضع الداكن هو محدِّد CSS لا JS:

styles/theme/common/var-dark.scss
[data-theme='dark'],
.dark {
--lh-bg-color: #2A2520;
--lh-text-primary: #E8E0D8;
// ... 118 تجاوزًا
}

وطريقتان للتشغيل:

<!-- الطريقة الأولى: سمة data (موصى بها، الدلالة أوضح) -->
<html data-theme="dark">
<!-- الطريقة الثانية: صنف (لتوافق الكود القديم / مكتبات تبديل الطرف الثالث) -->
<body class="dark">

كل ما على طبقة واجهة المستخدم (ConfigProvider في كل مكتبة أو كود العمل) فعله هو تبديل هذه السمة / الصنف، فتتبدّل ألوان جميع المكوّنات فورًا — فمتغيرات CSS تُقيَّم في وقت التشغيل دون أي تكلفة إعادة تصيير.

function toggleDark(isDark: boolean) {
document.documentElement.dataset.theme = isDark ? 'dark' : 'light'
}

الوضع الداكن طبقة تجاوز

Section titled “الوضع الداكن طبقة تجاوز”

لا يكتب ملف الوضع الداكن إلا 118 عنصرًا، لا مجموعة كاملة من 185. فيُتجاوز فقط الرموز التي تحتاج إلى الانقلاب، ويُفرَض الباقي عن القيم الفاتحة.

ومبدأ التصميم هو إعادة توجيه الرموز الدلالية، لا إعادة كتابة كل مكوّن:

// ✅ الأسلوب الجيد: في الوضع الداكن تشير إلى الرموز الدلالية الداكنة
[data-theme='dark'],
.dark {
--lh-menu-item-color: var(--lh-text-primary);
--lh-table-cell-color: var(--lh-text-primary);
}
// ❌ الأسلوب السيئ: كتابة لون ملموس ثابت في الوضع الداكن
[data-theme='dark'],
.dark {
--lh-menu-item-color: rgba(255, 255, 255, 0.85); // ينفصل عن text-primary، وتحتاج كل عملية ضبط لاحقة إلى تعديلين
}

فخ الخبز في وقت الترجمة

Section titled “فخ الخبز في وقت الترجمة”

هو الفخ الأكثر وقوعًا في الوضع الداكن، وهو سبب وجود البند السابع من verify:styles.

الرموز التي تأخذ في var.scss قيمًا بصيغة #{$lh-foo}:

var.scss
:root {
--lh-menu-item-color: #{$lh-menu-item-color}; // يُستبدل متغير SCSS في وقت الترجمة بقيمة فاتحة ملموسة
}

تُخبَز متغيرات SCSS في وقت الترجمة إلى قيم حرفية، فتعادل:

:root {
--lh-menu-item-color: rgba(0, 0, 0, 0.88); // لا ينقلب تلقائيًا في الوضع الداكن!
}

والنتيجة: في الوضع الداكن تبقى نصوص القوائم / الجداول / الخطوط الزمنية تأخذ قيمًا فاتحة، فلا تظهر (أسود فوق أسود). وقد وقع نقص كهذا فعلًا، وسجلَّت عملية تداركه في changeset الإصدار 0.4.0.

إعادة توجيه صريحة إلى الرموز الدلالية الداكنة داخل var-dark.scss:

[data-theme='dark'],
.dark {
--lh-menu-item-color: var(--lh-text-primary);
}

سلسلة fallback تُقيَّم في وقت التشغيل فهي آمنة

Section titled “سلسلة fallback تُقيَّم في وقت التشغيل فهي آمنة”

سلسلة fallback داخل SCSS المكوّن:

.lh-button {
color: var(--lh-foo, var(--lh-bar, #333));
}

يُقيَّم fallback الخاص بـ var() في وقت التشغيل: ما دام أي رمز في السلسلة لديه تجاوز داكن، تتبعه السلسلة كلها وتنقلب. دون الحاجة إلى إعادة التصريح.

جدول المقارنة:

الأسلوب وقت التقييم السلوك في الوضع الداكن
var(--lh-foo, fallback) وقت التشغيل ✅ ينقلب إذا كان رمز في السلسلة لديه تجاوز داكن
#{$lh-foo} (إقحام SCSS) وقت الترجمة ❌ يُخبَز بالقيمة الفاتحة، ويحتاج إلى إعادة توجيه صريحة في var-dark
دوال SCSS مثل mix($lh-a, $lh-b) وقت الترجمة ❌ مماثل لما سبق

تفتيح الوضع الداكن للمسبقات ذات اللون الرئيسي الداكن

Section titled “تفتيح الوضع الداكن للمسبقات ذات اللون الرئيسي الداكن”

من بين المسبقات الداخلية الخمس، ذات اللون الرئيسي الداكن (青花瓷 / 朱砂 / 水墨) يغوص لونها الرئيسي في لون خلفية الصفحة في الوضع الداكن. ويتولى buildPresetDarkVars المعالجة تلقائيًا:

قاعدة الحكم: إذا كانت نسبة تباين --lh-primary-color مقابل خلفية الصفحة الداكنة #1A1A2E (DARK_PAGE_BG) أقل من 3 (DARK_PRIMARY_CONTRAST_THRESHOLD) يُحكَم بأنه لون رئيسي داكن، ثم:

[data-theme='dark'],
.dark {
--lh-primary-color: color-mix(in srgb, <قيمة حرفية> 55%, #fff); /* تفتيح 55% */
--lh-primary-color-hover: color-mix(in srgb, var(--lh-primary-color) 70%, #fff);
--lh-primary-color-active: color-mix(in srgb, var(--lh-primary-color) 85%, #000);
--lh-color-on-primary: #101410; /* بعد التفتيح يصبح تباين النص الأبيض غير كافٍ، فيُستبدل بالنص الأسود */
--lh-primary-color-bg: color-mix(in srgb, var(--lh-primary-color) 25%, transparent);
--lh-selected-color: color-mix(in srgb, var(--lh-primary-color) 40%, #fff);
}

لماذا يُعوَّض اللون الرئيسي المُفتَّح بقيمة حرفية لا var(): لأن color-mix(in srgb, var(--lh-primary-color) 55%, #fff) يُنشئ دورة CSS ذاتية الإشارة (تشير قيمة --lh-primary-color إلى نفسها). ولذلك تُعوَّض هذه القيمة بالقيمة الحرفية، بينما تستخدم البقية var() وتتبع اللون الرئيسي الحالي.

أما المسبقات ذات اللون الرئيسي الفاتح (松花绿 / 藤黄) فلا تحتاج إلى تفتيح، لكنها تحصل مع ذلك على إعادة تعريف داكنة لـ --lh-primary-color-bg و --lh-selected-color.

دلالة ترتيب حقن المسبقة

Section titled “دلالة ترتيب حقن المسبقة”

النص الذي يُولِّده buildPresetStyleText يضع كتلة :root { ... } أولًا ثم كتلة [data-theme='dark'], .dark { ... }. وعند تساوي الخصوصية يغلب الأخير، لذلك لا تتسرّب القيمة الفاتحة لـ --lh-selected-color المُعلَن عنها في :root للمسبقات ذات اللون الرئيسي الفاتح إلى الوضع الداكن.

وهذا أيضًا السبب الجذري لقاعدة «يكتب <style> فقط لا style مضمَّن» — فخصوصيةstyle المضمَّن 1,0,0,0 تطغى على كتلة متغيرات الوضع الداكن الكاملة في var-dark.scss، فيفشل الوضع الداكن مباشرةً (لمزيد من التفاصيل انظر النظرة العامة على السمة).

主色与衍生语义

令牌明色暗色SCSS 源备注
--lh-primary-color #3D649E$lh-primary
--lh-primary-color-hover #5078AB$lh-primary-hover
--lh-primary-color-active #2B4C7C$lh-primary-active
--lh-primary-color-bg color-mix(in srgb, var(--lh-primary-color) 25%, transparent)$lh-primary-light
--lh-primary-color-border #2A3A4A$lh-primary-lighter
--lh-color-on-primary #fff$lh-on-primary

状态

令牌明色暗色SCSS 源备注
--lh-hover-bg-color rgba(255, 255, 255, 0.08)$lh-hover-bg
--lh-selected-color color-mix(in srgb, var(--lh-primary-color) 40%, #fff)—

功能色

令牌明色暗色SCSS 源备注
--lh-success-color #6FA36E$lh-success
--lh-success-color-hover #82B581$lh-success-hover
--lh-success-color-active #5B8C5A$lh-success-active
--lh-success-color-bg #1A2A1A$lh-success-light
--lh-warning-color #D4B76F$lh-warning
--lh-warning-color-hover #E0C680$lh-warning-hover
--lh-warning-color-active #C4A35A$lh-warning-active
--lh-warning-color-bg #2A251A$lh-warning-light
--lh-danger-color #C45050$lh-danger
--lh-danger-color-hover #D46060$lh-danger-hover
--lh-danger-color-active #B23A3A$lh-danger-active
--lh-danger-color-bg #2A1A1A$lh-danger-light
--lh-info-color #8F8F8F$lh-info
--lh-info-color-hover #A0A0A0$lh-info-hover
--lh-info-color-active #7A7A7A$lh-info-active
--lh-info-color-bg #1A1A1A$lh-info-light

国风装饰色

令牌明色暗色SCSS 源备注
--lh-gold-color #D4A843$lh-gold
--lh-gold-color-hover #E8C35C$lh-gold-hover
--lh-gold-color-active #B8860B$lh-gold-active
--lh-gold-color-bg #2A241A$lh-gold-light
--lh-gold-color-border #3A2E1A$lh-gold-lighter
--lh-vermilion-color #E85D4A$lh-vermilion
--lh-vermilion-color-hover #FF7B6B$lh-vermilion-hover
--lh-vermilion-color-active #C43A31$lh-vermilion-active
--lh-vermilion-color-bg #2A1A18$lh-vermilion-light
--lh-jade-color #7AAE7A$lh-jade
--lh-jade-color-hover #9CC89C$lh-jade-hover
--lh-jade-color-active #5B8C5A$lh-jade-active
--lh-jade-color-bg #1A2A1A$lh-jade-light
--lh-decoration-color rgba(212, 168, 67, 0.08)$lh-decoration-color

文本

令牌明色暗色SCSS 源备注
--lh-text-primary #E8E0D8$lh-text-primary
--lh-text-regular #C8C0B8$lh-text-regular
--lh-text-secondary #A09890$lh-text-secondary
--lh-text-placeholder #7A7270$lh-text-placeholder
--lh-text-disabled #5A5250$lh-text-disabled

边框

令牌明色暗色SCSS 源备注
--lh-border-color-base #3A3530$lh-border-color-base
--lh-border-color-light #302B28$lh-border-color-light
--lh-border-color-lighter #2A2520$lh-border-color-lighter
--lh-border-color-extra-light #242018$lh-border-color-extra-light

圆角

令牌明色暗色SCSS 源备注
--lh-border-radius-base 沿用明色$lh-border-radius-base
--lh-border-radius-small 沿用明色$lh-border-radius-small
--lh-border-radius-round 沿用明色$lh-border-radius-round
--lh-border-radius-circle 沿用明色$lh-border-radius-circle

背景

令牌明色暗色SCSS 源备注
--lh-bg-color #2A2520$lh-bg-color
--lh-bg-color-page #1E1A16$lh-bg-color-page
--lh-bg-color-disabled #242018$lh-bg-color-disabled
--lh-bg-color-overlay rgba(10, 8, 6, 0.7)$lh-bg-color-overlay

阴影

令牌明色暗色SCSS 源备注
--lh-box-shadow-base 0 2px 12px 0 rgba(0, 0, 0, 0.5)$lh-box-shadow-base
--lh-box-shadow-light 0 2px 4px 0 rgba(0, 0, 0, 0.4)$lh-box-shadow-light
--lh-box-shadow-lighter 0 0 4px 0 rgba(0, 0, 0, 0.3)$lh-box-shadow-lighter

字体

令牌明色暗色SCSS 源备注
--lh-font-family 沿用明色$lh-font-family
--lh-font-size-extra-large 沿用明色$lh-font-size-extra-large
--lh-font-size-large 沿用明色$lh-font-size-large
--lh-font-size-medium 沿用明色$lh-font-size-medium
--lh-font-size-base 沿用明色$lh-font-size-base
--lh-font-size-small 沿用明色$lh-font-size-small
--lh-font-size-extra-small 沿用明色$lh-font-size-extra-small
--lh-font-weight-primary 沿用明色$lh-font-weight-primary
--lh-font-weight-bold 沿用明色$lh-font-weight-bold
--lh-font-line-height-primary 沿用明色$lh-font-line-height-primary

组件级 · control

令牌明色暗色SCSS 源备注
--lh-control-height-mini 沿用明色$lh-control-height-mini
--lh-control-height-small 沿用明色$lh-control-height-small
--lh-control-height-medium 沿用明色$lh-control-height-medium
--lh-control-height-large 沿用明色$lh-control-height-large
--lh-control-height-x-large 沿用明色$lh-control-height-x-large

间距

令牌明色暗色SCSS 源备注
--lh-spacing-xs 沿用明色$lh-spacing-xs
--lh-spacing-sm 沿用明色$lh-spacing-sm
--lh-spacing-md 沿用明色$lh-spacing-md
--lh-spacing-base 沿用明色$lh-spacing-base
--lh-spacing-lg 沿用明色$lh-spacing-lg
--lh-spacing-xl 沿用明色$lh-spacing-xl
--lh-spacing-xxl 沿用明色$lh-spacing-xxl

层级

令牌明色暗色SCSS 源备注
--lh-z-index-normal 沿用明色$lh-z-index-normal
--lh-z-index-dropdown 沿用明色$lh-z-index-dropdown
--lh-z-index-sticky 沿用明色$lh-z-index-sticky
--lh-z-index-fixed 沿用明色$lh-z-index-fixed
--lh-z-index-modal-backdrop 沿用明色$lh-z-index-modal-backdrop
--lh-z-index-modal 沿用明色$lh-z-index-modal
--lh-z-index-popover 沿用明色$lh-z-index-popover
--lh-z-index-tooltip 沿用明色$lh-z-index-tooltip

过渡

令牌明色暗色SCSS 源备注
--lh-transition-duration-fast 沿用明色$lh-transition-duration-fast
--lh-transition-duration-base 沿用明色$lh-transition-duration-base
--lh-transition-duration-slow 沿用明色$lh-transition-duration-slow
--lh-transition-function-ease-in-out 沿用明色$lh-transition-function-ease-in-out

禁用态

令牌明色暗色SCSS 源备注
--lh-disabled-bg-color #242018$lh-disabled-bg-color
--lh-disabled-text-color #5A5250$lh-disabled-text-color
--lh-disabled-border-color #302B28$lh-disabled-border-color
--lh-disabled-opacity 0.5$lh-disabled-opacity

组件级 · popover

令牌明色暗色SCSS 源备注
--lh-popover-bg-color #2A2520$lh-popover-bg-color
--lh-popover-border-color #3A3530$lh-popover-border-color
--lh-popover-border-radius 沿用明色$lh-popover-border-radius
--lh-popover-padding 沿用明色$lh-popover-padding
--lh-popover-title-color #E8E0D8$lh-popover-title-color
--lh-popover-content-color #C8C0B8$lh-popover-content-color
--lh-popover-arrow-size 沿用明色$lh-popover-arrow-size

组件级 · popconfirm

令牌明色暗色SCSS 源备注
--lh-popconfirm-padding 沿用明色$lh-popconfirm-padding
--lh-popconfirm-icon-size 沿用明色$lh-popconfirm-icon-size

组件级 · drawer

令牌明色暗色SCSS 源备注
--lh-drawer-bg-color #2A2520$lh-drawer-bg-color
--lh-drawer-border-color #3A3530$lh-drawer-border-color
--lh-drawer-header-padding 沿用明色$lh-drawer-header-padding
--lh-drawer-body-padding 沿用明色$lh-drawer-body-padding
--lh-drawer-footer-padding 沿用明色$lh-drawer-footer-padding
--lh-drawer-title-color #E8E0D8$lh-drawer-title-color
--lh-drawer-close-size 沿用明色$lh-drawer-close-size

组件级 · dropdown

令牌明色暗色SCSS 源备注
--lh-dropdown-bg-color #2A2520$lh-dropdown-bg-color
--lh-dropdown-border-color #3A3530$lh-dropdown-border-color
--lh-dropdown-border-radius 沿用明色$lh-dropdown-border-radius
--lh-dropdown-padding 沿用明色$lh-dropdown-padding
--lh-dropdown-item-height 沿用明色$lh-dropdown-item-height
--lh-dropdown-item-padding 沿用明色$lh-dropdown-item-padding
--lh-dropdown-item-color #C8C0B8$lh-dropdown-item-color
--lh-dropdown-item-hover-bg-color var(--lh-hover-bg-color)$lh-dropdown-item-hover-bg-color
--lh-dropdown-divider-color #302B28$lh-dropdown-divider-color

组件级 · message

令牌明色暗色SCSS 源备注
--lh-message-bg #2A2520$lh-message-bg-color
--lh-message-border #3A3530$lh-message-border-color
--lh-message-color #C8C0B8$lh-message-content-color
--lh-message-shadow 沿用明色$lh-message-shadow

组件级 · notification

令牌明色暗色SCSS 源备注
--lh-notification-bg #2A2520$lh-notification-bg-color
--lh-notification-border #3A3530$lh-notification-border-color
--lh-notification-title-color #E8E0D8$lh-notification-title-color
--lh-notification-content-color #C8C0B8$lh-notification-content-color
--lh-notification-width 沿用明色$lh-notification-width
--lh-notification-gap 沿用明色$lh-notification-gap
--lh-notification-shadow 沿用明色$lh-notification-shadow

组件级 · loading

令牌明色暗色SCSS 源备注
--lh-loading-bg rgba(10, 8, 6, 62%)$lh-loading-bg-color
--lh-loading-text-color #C8C0B8$lh-loading-text-color

组件级 · timeline

令牌明色暗色SCSS 源备注
--lh-timeline-line #302B28$lh-timeline-line
--lh-timeline-dot var(--lh-info-color)$lh-timeline-dot
--lh-timeline-timestamp var(--lh-text-secondary)$lh-timeline-timestamp

组件级 · collapse

令牌明色暗色SCSS 源备注
--lh-collapse-border #302B28$lh-collapse-border

组件级 · rate

令牌明色暗色SCSS 源备注
--lh-rate-active var(--lh-warning-color)$lh-rate-active

组件级 · segmented

令牌明色暗色SCSS 源备注
--lh-segmented-bg #242018$lh-segmented-bg

组件级 · calendar

令牌明色暗色SCSS 源备注
--lh-calendar-border var(--lh-border-color-lighter)$lh-calendar-border

组件级 · affix

令牌明色暗色SCSS 源备注
--lh-affix-z-index 沿用明色$lh-affix-z-index

组件级 · backtop

令牌明色暗色SCSS 源备注
--lh-backtop-z-index 沿用明色$lh-backtop-z-index

组件级 · menu

令牌明色暗色SCSS 源备注
--lh-menu-bg #242018$lh-menu-bg
--lh-menu-padding 沿用明色$lh-menu-padding
--lh-menu-border #302B28$lh-menu-border
--lh-menu-height 沿用明色$lh-menu-height
--lh-menu-collapse-width 沿用明色$lh-menu-collapse-width
--lh-menu-item-height 沿用明色$lh-menu-item-height
--lh-menu-item-padding 沿用明色$lh-menu-item-padding
--lh-menu-item-color var(--lh-text-primary)$lh-menu-item-color
--lh-menu-item-hover-bg #302B28$lh-menu-item-hover-bg
--lh-menu-item-active-color var(--lh-selected-color)$lh-menu-item-active-color
--lh-menu-item-active-bg var(--lh-primary-color-bg)$lh-menu-item-active-bg
--lh-menu-arrow-color var(--lh-text-secondary)$lh-menu-arrow-color
--lh-menu-z-index 沿用明色$lh-menu-z-index

组件级 · table

令牌明色暗色SCSS 源备注
--lh-table-bg #242018$lh-table-bg
--lh-table-color var(--lh-text-regular)$lh-table-color
--lh-table-header-bg #2A2420$lh-table-header-bg
--lh-table-header-color var(--lh-text-primary)$lh-table-header-color
--lh-table-border #302B28$lh-table-border
--lh-table-row-hover-bg #2A2420$lh-table-row-hover-bg
--lh-table-stripe-bg color-mix(in srgb, var(--lh-bg-color-page) 60%, transparent)$lh-table-stripe-bg
--lh-table-cell-padding 沿用明色$lh-table-cell-padding

组件级 · layout

令牌明色暗色SCSS 源备注
--lh-layout-header-height 沿用明色$lh-layout-header-height
--lh-layout-header-bg #242018$lh-layout-header-bg
--lh-layout-aside-width 沿用明色$lh-layout-aside-width
--lh-layout-aside-bg #242018$lh-layout-aside-bg
--lh-layout-main-bg #1C1815$lh-layout-main-bg
--lh-layout-border #302B28$lh-layout-border

组件级 · row

令牌明色暗色SCSS 源备注
--lh-row-gutter 沿用明色$lh-row-gutter

组件级 · tree

令牌明色暗色SCSS 源备注
--lh-tree-color #D8D0C8$lh-tree-color
--lh-tree-padding 沿用明色$lh-tree-padding
--lh-tree-node-height 沿用明色$lh-tree-node-height
--lh-tree-node-hover-bg #2A2420$lh-tree-node-hover-bg
--lh-tree-node-selected-color var(--lh-selected-color)$lh-tree-node-selected-color
--lh-tree-node-selected-bg var(--lh-primary-color-bg)$lh-tree-node-selected-bg
--lh-tree-arrow-color var(--lh-text-secondary)$lh-tree-arrow-color

组件级 · transfer

令牌明色暗色SCSS 源备注
--lh-transfer-panel-width 沿用明色$lh-transfer-panel-width
--lh-transfer-panel-height 沿用明色$lh-transfer-panel-height
--lh-transfer-bg #242018$lh-transfer-bg
--lh-transfer-border #302B28$lh-transfer-border

组件级 · upload

令牌明色暗色SCSS 源备注
--lh-upload-bg #242018$lh-upload-bg
--lh-upload-border var(--lh-border-color-base)$lh-upload-border
--lh-upload-trigger-padding 沿用明色$lh-upload-trigger-padding

组件级 · anchor

令牌明色暗色SCSS 源备注
--lh-anchor-color var(--lh-text-regular)$lh-anchor-color

组件级 · image

令牌明色暗色SCSS 源备注
--lh-image-viewer-mask rgba(0, 0, 0, 80%)—

无障碍焦点环

令牌明色暗色SCSS 源备注
--lh-focus-color #7FA6D9$lh-primary
--lh-focus-ring-width 沿用明色—
--lh-focus-ring-offset 沿用明色—

كيفية التحقق من اكتمال الوضع الداكن

Section titled “كيفية التحقق من اكتمال الوضع الداكن”

ثلاث وسائل من الأضعف إلى الأقوى:

  1. البند السابع من pnpm verify:styles (إمكانية الوصول الداكنة): فحص ساكن، يجد الرموز «المخبوزة فاتحة دون تجاوز في var-dark». وهذه بوابة CI.
  2. pnpm verify:theme (AA 4.5:1): يقرأ مخرجات es/ ويحسب نسب تباين المسبقات في الوضعين الفاتح والداكن. يتطلب تشغيل pnpm build أولًا. لا يُشغَّل في CI، بل يحرسه المستخدم يدويًا.
  3. الفحص البصري: تبديل الوضع الداكن في موقع docs / ساحات تجربة كل مكتبة ومراجعة كل مكوّن.

قائمة مراجعة ذاتية عند إضافة رمز جديد:

  • هل يحتاج هذا الرمز إلى الانقلاب في الوضع الداكن؟
  • إن احتاج، هل أُضيف تجاوز في var-dark.scss؟
  • هل قيمته على الصيغة #{$lh-*} إقحام؟ (نعم → يجب إضافة تجاوز داكن)
  • هل يستهلكه المكوّن عبر سلسلة var(--lh-x, fallback)؟

تم في 0.4.0 تدارك نقص الوضع الداكن بشكل منهجي (مشكلة عدم ظهور نصوص القوائم / الجداول / الخطوط الزمنية، انظر changeset). أما البنود المعروفة المتبقية فتُعالج مع «مشروع رموز الارتفاع» لاحقًا.

Copyright © 2024-2026 FengMo WenXue