@xihan-ui/styles 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -0
- package/README.md +1 -1
- package/component-tokens.d.ts +29 -0
- package/components.tokens.json +683 -27
- package/css/alert.css +2 -2
- package/css/approval.css +4 -4
- package/css/button.css +9 -5
- package/css/calendar-picker.css +3 -3
- package/css/calendar-range-picker.css +7 -7
- package/css/carousel.css +45 -13
- package/css/cartesian-chart.css +11 -11
- package/css/cascader.css +10 -10
- package/css/citation.css +2 -2
- package/css/code-view.css +6 -6
- package/css/color-picker.css +81 -0
- package/css/color-swatch-picker.css +9 -4
- package/css/combobox.css +12 -4
- package/css/command.css +1 -1
- package/css/date-field.css +39 -0
- package/css/date-picker.css +86 -9
- package/css/date-range-picker.css +47 -7
- package/css/diff-view.css +8 -8
- package/css/field-array.css +1 -1
- package/css/field.css +4 -0
- package/css/file-upload.css +1 -1
- package/css/float-button.css +140 -27
- package/css/form.css +14 -6
- package/css/graph-chart.css +2 -2
- package/css/highlight.css +1 -1
- package/css/image.css +1 -1
- package/css/mention.css +1 -1
- package/css/message-feed.css +1 -1
- package/css/notification.css +26 -20
- package/css/number-field.css +18 -18
- package/css/page-header.css +2 -2
- package/css/password-input.css +2 -2
- package/css/popconfirm.css +3 -3
- package/css/question-flow.css +8 -8
- package/css/radar-chart.css +6 -6
- package/css/rating.css +1 -1
- package/css/select.css +2 -2
- package/css/separator.css +2 -2
- package/css/side-nav.css +13 -13
- package/css/skeleton.css +5 -5
- package/css/slider.css +6 -6
- package/css/sortable.css +2 -2
- package/css/table.css +19 -2
- package/css/tags-input.css +1 -1
- package/css/time-picker.css +59 -2
- package/css/tool-call.css +7 -7
- package/css/tooltip.css +1 -1
- package/css/tree-select.css +2 -2
- package/css/tree.css +81 -11
- package/dist/css/accordion.css +269 -0
- package/dist/css/affix.css +47 -0
- package/dist/css/alert.css +247 -0
- package/dist/css/anchor.css +252 -0
- package/dist/css/approval.css +501 -0
- package/dist/css/avatar-group.css +99 -0
- package/dist/css/avatar.css +98 -0
- package/dist/css/back-top.css +161 -0
- package/dist/css/badge.css +205 -0
- package/dist/css/bar-code.css +62 -0
- package/dist/css/breadcrumb.css +230 -0
- package/dist/css/button-group.css +263 -0
- package/dist/css/button.css +219 -0
- package/dist/css/calendar-picker.css +467 -0
- package/dist/css/calendar-range-picker.css +554 -0
- package/dist/css/card.css +221 -0
- package/dist/css/carousel.css +710 -0
- package/dist/css/cartesian-chart.css +830 -0
- package/dist/css/cascader.css +961 -0
- package/dist/css/checkbox-group.css +358 -0
- package/dist/css/checkbox.css +257 -0
- package/dist/css/citation.css +470 -0
- package/dist/css/clipboard.css +315 -0
- package/dist/css/code-view.css +374 -0
- package/dist/css/collapsible.css +185 -0
- package/dist/css/color-field.css +176 -0
- package/dist/css/color-picker.css +595 -0
- package/dist/css/color-slider.css +281 -0
- package/dist/css/color-swatch-picker.css +250 -0
- package/dist/css/color-swatch.css +35 -0
- package/dist/css/combobox.css +574 -0
- package/dist/css/command.css +399 -0
- package/dist/css/context-menu.css +420 -0
- package/dist/css/date-field.css +317 -0
- package/dist/css/date-picker.css +868 -0
- package/dist/css/date-range-picker.css +886 -0
- package/dist/css/description.css +67 -0
- package/dist/css/descriptions.css +299 -0
- package/dist/css/dialog.css +455 -0
- package/dist/css/diff-view.css +513 -0
- package/dist/css/download-trigger.css +151 -0
- package/dist/css/drawer.css +552 -0
- package/dist/css/editable.css +295 -0
- package/dist/css/empty-state.css +163 -0
- package/dist/css/field-array.css +226 -0
- package/dist/css/field.css +166 -0
- package/dist/css/fieldset.css +102 -0
- package/dist/css/file-upload.css +429 -0
- package/dist/css/flex.css +441 -0
- package/dist/css/float-button.css +569 -0
- package/dist/css/floating-panel.css +429 -0
- package/dist/css/focus.css +46 -0
- package/dist/css/forced-colors.css +93 -0
- package/dist/css/form.css +393 -0
- package/dist/css/funnel-chart.css +106 -0
- package/dist/css/graph-chart.css +205 -0
- package/dist/css/grid-list.css +235 -0
- package/dist/css/grid.css +1201 -0
- package/dist/css/heatmap.css +552 -0
- package/dist/css/hierarchy-chart.css +298 -0
- package/dist/css/highlight.css +41 -0
- package/dist/css/hover-card.css +226 -0
- package/dist/css/icon.css +225 -0
- package/dist/css/image-cropper.css +373 -0
- package/dist/css/image-viewer.css +538 -0
- package/dist/css/image.css +98 -0
- package/dist/css/infinite-scroll.css +77 -0
- package/dist/css/input-group.css +275 -0
- package/dist/css/json-viewer.css +379 -0
- package/dist/css/kbd.css +72 -0
- package/dist/css/label.css +78 -0
- package/dist/css/layers.css +7 -0
- package/dist/css/layout.css +372 -0
- package/dist/css/liquid.css +106 -0
- package/dist/css/list.css +152 -0
- package/dist/css/listbox.css +390 -0
- package/dist/css/loading-bar.css +141 -0
- package/dist/css/log.css +306 -0
- package/dist/css/markdown-stream.css +149 -0
- package/dist/css/marquee.css +378 -0
- package/dist/css/masonry.css +70 -0
- package/dist/css/matrix-code.css +67 -0
- package/dist/css/mention.css +393 -0
- package/dist/css/menu.css +364 -0
- package/dist/css/menubar.css +456 -0
- package/dist/css/message-feed.css +318 -0
- package/dist/css/navigation-menu.css +513 -0
- package/dist/css/notification.css +782 -0
- package/dist/css/number-animation.css +44 -0
- package/dist/css/number-field.css +252 -0
- package/dist/css/overlay-arrow.css +56 -0
- package/dist/css/page-header.css +184 -0
- package/dist/css/pagination.css +450 -0
- package/dist/css/password-input.css +391 -0
- package/dist/css/pie-chart.css +247 -0
- package/dist/css/pin-input.css +199 -0
- package/dist/css/pointer.css +36 -0
- package/dist/css/popconfirm.css +320 -0
- package/dist/css/popover.css +279 -0
- package/dist/css/progress.css +501 -0
- package/dist/css/prompt-input.css +260 -0
- package/dist/css/question-flow.css +553 -0
- package/dist/css/radar-chart.css +233 -0
- package/dist/css/radio-group.css +598 -0
- package/dist/css/rating.css +294 -0
- package/dist/css/reasoning.css +343 -0
- package/dist/css/reset.css +117 -0
- package/dist/css/resizable.css +242 -0
- package/dist/css/sankey-chart.css +174 -0
- package/dist/css/scroll-area.css +240 -0
- package/dist/css/scrollbar.css +204 -0
- package/dist/css/select.css +612 -0
- package/dist/css/separator.css +122 -0
- package/dist/css/side-nav.css +476 -0
- package/dist/css/signature-pad.css +179 -0
- package/dist/css/skeleton.css +161 -0
- package/dist/css/slider.css +374 -0
- package/dist/css/sortable.css +228 -0
- package/dist/css/sparkline.css +164 -0
- package/dist/css/spinner.css +236 -0
- package/dist/css/splitter.css +159 -0
- package/dist/css/statistic.css +137 -0
- package/dist/css/steps.css +627 -0
- package/dist/css/switch.css +351 -0
- package/dist/css/table.css +1145 -0
- package/dist/css/tabs.css +944 -0
- package/dist/css/tag-group.css +247 -0
- package/dist/css/tag.css +310 -0
- package/dist/css/tags-input.css +322 -0
- package/dist/css/text-field.css +197 -0
- package/dist/css/time-field.css +277 -0
- package/dist/css/time-picker.css +707 -0
- package/dist/css/time-range-picker.css +746 -0
- package/dist/css/timeline.css +423 -0
- package/dist/css/timer.css +123 -0
- package/dist/css/timestamp.css +34 -0
- package/dist/css/toggle-group.css +424 -0
- package/dist/css/toggle.css +146 -0
- package/dist/css/tone.css +189 -0
- package/dist/css/tool-call.css +429 -0
- package/dist/css/toolbar.css +365 -0
- package/dist/css/tooltip.css +218 -0
- package/dist/css/tour.css +439 -0
- package/dist/css/transfer.css +638 -0
- package/dist/css/tree-select.css +878 -0
- package/dist/css/tree.css +733 -0
- package/dist/css/truncate.css +108 -0
- package/dist/css/typography.css +472 -0
- package/dist/css/undefined.css +58 -0
- package/dist/css/virtualizer.css +166 -0
- package/dist/css/visually-hidden.css +20 -0
- package/dist/css/watermark.css +82 -0
- package/dist/family/action-control.css +487 -0
- package/dist/family/chart.css +480 -0
- package/dist/family/check-mark.css +94 -0
- package/dist/family/choice-card.css +97 -0
- package/dist/family/collection-item.css +764 -0
- package/dist/family/field-chrome.css +287 -0
- package/dist/family/loading-ring.css +95 -0
- package/dist/family/material.css +72 -0
- package/dist/family/menu-choice.css +56 -0
- package/dist/family/motion.css +363 -0
- package/dist/family/swatch.css +59 -0
- package/dist/family/tag-list.css +59 -0
- package/family/action-control.css +3 -12
- package/index.css +7307 -6759
- package/index.unlayered.css +7309 -6761
- package/package.json +165 -164
|
@@ -0,0 +1,944 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021-Present XiHanFun and contributors.
|
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* 定义 tabs 样式。 */
|
|
7
|
+
|
|
8
|
+
/* line 档的页签归 Collection Item 导航当前(nav 语境):面、字色、字重、光标与按压时间线由家族配方按
|
|
9
|
+
家族角色(data-xh-collection-item / -size / -context)给,本皮肤只映射桥接槽;card / segment 档不归族,面与字仍写在本皮肤。
|
|
10
|
+
line 档的 2px 指示线由本皮肤画:标签带里放了 indicator 部件就由部件滑动,没放则选中标签自画一条静态线 */
|
|
11
|
+
@import '../family/collection-item.css';
|
|
12
|
+
|
|
13
|
+
@layer xihan.components {
|
|
14
|
+
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
15
|
+
.xh-scope-tabs {
|
|
16
|
+
--xh-tabs-skin: 1;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.xh-scope-tabs[data-part='root'] {
|
|
20
|
+
/* 尺寸档只换这三个私有槽,标签从 root 继承它们,换档不必给每个部件各写一条选择器 */
|
|
21
|
+
--xh-_tabs-trigger-h: var(--xh-control-h-md);
|
|
22
|
+
--xh-_tabs-trigger-px: var(--xh-control-px-md);
|
|
23
|
+
--xh-_tabs-trigger-font-size: var(--xh-control-font-md);
|
|
24
|
+
|
|
25
|
+
/* 缺省是 line 变体:透明标签带,选中项由文字与底部指示条表达。Web Components 升级前还没有
|
|
26
|
+
data-variant,这组几何基础值也必须画成相同结果,避免定义完成时闪换样式;line 档的面与字色由家族
|
|
27
|
+
按升级后写入的家族角色给,升级前那一帧只有几何没有面色(与 side-nav / menu 同)。
|
|
28
|
+
悬停与按下的面按承载面分档:line 档经家族走白底承载 hover 100 → pressed 200;card 坐在
|
|
29
|
+
画布上 hover 100 → pressed 200;segment 坐在淡底轨道里 hover 200 → pressed 300。card / segment 的
|
|
30
|
+
六支面槽只在各自形态块里赋值,line 档不消费它们 */
|
|
31
|
+
--xh-_tabs-list-gap: var(--xh-space-0);
|
|
32
|
+
--xh-_tabs-list-bg: transparent;
|
|
33
|
+
--xh-_tabs-list-p: var(--xh-space-0);
|
|
34
|
+
--xh-_tabs-list-radius: 0;
|
|
35
|
+
--xh-_tabs-list-border-width: 0;
|
|
36
|
+
--xh-_tabs-trigger-border-width: 0;
|
|
37
|
+
--xh-_tabs-trigger-border: transparent;
|
|
38
|
+
--xh-_tabs-trigger-radius: var(--xh-shape-control);
|
|
39
|
+
|
|
40
|
+
/* 语气落在选中态:指示条与选中标签的文字。
|
|
41
|
+
没写 data-tone 时 --xh-_tone 一族没被声明,两个槽都退回原来的取色 */
|
|
42
|
+
--xh-_tabs-accent: var(--xh-_tone, var(--xh-bg-brand));
|
|
43
|
+
--xh-_tabs-accent-text: var(--xh-_tone-fg, var(--xh-fg-brand-strong));
|
|
44
|
+
|
|
45
|
+
/* 翻页钮的盖底:标签带放不下时它浮在两端,挪到它底下的那截标签要被盖住。line / card 档的标签带是透明的,
|
|
46
|
+
盖底取 surface;坐在别的面上(画布、淡底面板)时由使用者槽换成所在的面。segment 档取轨道的淡底。
|
|
47
|
+
悬停与按下同样要盖得住:淡底阶梯取不透明档,line / card 在白底上 100 → 200,segment 在轨道上 200 → 300 */
|
|
48
|
+
--xh-_tabs-scroll-trigger-bg: var(--xh-bg-surface);
|
|
49
|
+
--xh-_tabs-scroll-trigger-bg-hover: var(--xh-bg-subtle-opaque);
|
|
50
|
+
--xh-_tabs-scroll-trigger-bg-pressed: var(--xh-bg-subtle-hover-opaque);
|
|
51
|
+
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
gap: var(--xh-tabs-gap, var(--xh-stack-gap-md));
|
|
55
|
+
/* 排在一行弹性 / 网格容器里时也让得开:不写这条,根的最小宽是整条标签带的自然宽,
|
|
56
|
+
外层再窄它也不缩,标签带永远"放得下"、翻页钮永远不露面,整行反倒被顶出去 */
|
|
57
|
+
min-inline-size: 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* 纵向:list 与 panel 并排 */
|
|
61
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical'] {
|
|
62
|
+
flex-direction: row;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* —— 尺寸 —— */
|
|
66
|
+
/* 缺省档写在上面的基础规则里 */
|
|
67
|
+
.xh-scope-tabs[data-part='root'][data-size='sm'] {
|
|
68
|
+
--xh-_tabs-trigger-h: var(--xh-control-h-sm);
|
|
69
|
+
--xh-_tabs-trigger-px: var(--xh-control-px-sm);
|
|
70
|
+
--xh-_tabs-trigger-font-size: var(--xh-control-font-sm);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.xh-scope-tabs[data-part='root'][data-size='lg'] {
|
|
74
|
+
--xh-_tabs-trigger-h: var(--xh-control-h-lg);
|
|
75
|
+
--xh-_tabs-trigger-px: var(--xh-control-px-lg);
|
|
76
|
+
--xh-_tabs-trigger-font-size: var(--xh-control-font-lg);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* —— 变体 —— */
|
|
80
|
+
/* 主变体的显式写法,与缺省视觉一致:透明标签带与底部基线,选中项由文字和滑动指示条强调。 */
|
|
81
|
+
.xh-scope-tabs[data-part='root'][data-variant='line'] {
|
|
82
|
+
--xh-_tabs-list-gap: var(--xh-space-0);
|
|
83
|
+
--xh-_tabs-list-bg: transparent;
|
|
84
|
+
--xh-_tabs-list-p: var(--xh-space-0);
|
|
85
|
+
--xh-_tabs-list-radius: 0;
|
|
86
|
+
--xh-_tabs-list-border-width: 0;
|
|
87
|
+
--xh-_tabs-trigger-border-width: 0;
|
|
88
|
+
--xh-_tabs-trigger-border: transparent;
|
|
89
|
+
--xh-_tabs-trigger-radius: var(--xh-shape-control);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* 卡片式:基线收掉,选中的那张标签自己成为一张有描边有底的卡片,顶边一条指示条。
|
|
93
|
+
标签坐在画布上,悬停 100 → 按下 200(白底承载) */
|
|
94
|
+
.xh-scope-tabs[data-part='root'][data-variant='card'] {
|
|
95
|
+
--xh-_tabs-list-gap: var(--xh-control-gap-md);
|
|
96
|
+
--xh-_tabs-list-bg: transparent;
|
|
97
|
+
--xh-_tabs-list-p: var(--xh-space-0);
|
|
98
|
+
--xh-_tabs-list-radius: 0;
|
|
99
|
+
--xh-_tabs-list-border-width: 0;
|
|
100
|
+
--xh-_tabs-trigger-border-width: var(--xh-stroke-thin);
|
|
101
|
+
--xh-_tabs-trigger-radius: var(--xh-shape-control);
|
|
102
|
+
--xh-_tabs-trigger-bg-hover: var(--xh-bg-subtle);
|
|
103
|
+
--xh-_tabs-trigger-bg-pressed: var(--xh-bg-subtle-hover);
|
|
104
|
+
--xh-_tabs-trigger-bg-active: var(--xh-_tone-subtle, var(--xh-bg-surface));
|
|
105
|
+
--xh-_tabs-trigger-bg-active-hover: var(--xh-_tone-subtle-hover, var(--xh-bg-surface));
|
|
106
|
+
--xh-_tabs-trigger-border-active: var(--xh-_tone-border, var(--xh-border-default));
|
|
107
|
+
--xh-_tabs-trigger-shadow-active: inset 0 var(--xh-stroke-thick) 0 0 var(--xh-_tabs-accent);
|
|
108
|
+
/* 选中文字不换品牌色:卡片面与顶边条已经表达选中 */
|
|
109
|
+
--xh-_tabs-accent-text: var(--xh-_tone-fg, var(--xh-fg-default));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* 分段式(有滑块开关):淡底轨道承载一块白色抬起的选中面,选中文字保持默认字色。
|
|
113
|
+
未选中标签坐在淡底轨道里,悬停 200 → 按下 300;选中面自己不再叠悬停 / 按下态。
|
|
114
|
+
选中面的三件(surface-raised 底、border-default 描边、raised 影)写在下面标签自己的规则里 */
|
|
115
|
+
.xh-scope-tabs[data-part='root'][data-variant='segment'] {
|
|
116
|
+
--xh-_tabs-list-gap: var(--xh-space-0_5);
|
|
117
|
+
--xh-_tabs-list-bg: var(--xh-bg-subtle);
|
|
118
|
+
--xh-_tabs-list-p: var(--xh-space-1);
|
|
119
|
+
--xh-_tabs-list-radius: var(--xh-shape-surface);
|
|
120
|
+
--xh-_tabs-list-border-width: 0;
|
|
121
|
+
--xh-_tabs-trigger-border-width: var(--xh-stroke-thin);
|
|
122
|
+
--xh-_tabs-trigger-border: transparent;
|
|
123
|
+
--xh-_tabs-trigger-radius: var(--xh-shape-control);
|
|
124
|
+
--xh-_tabs-trigger-bg-hover: var(--xh-bg-subtle-hover);
|
|
125
|
+
--xh-_tabs-trigger-bg-pressed: var(--xh-bg-subtle-active);
|
|
126
|
+
--xh-_tabs-trigger-bg-active: var(--xh-_tone-subtle, var(--xh-bg-surface-raised));
|
|
127
|
+
--xh-_tabs-trigger-bg-active-hover: var(--xh-_tone-subtle, var(--xh-bg-surface-raised));
|
|
128
|
+
--xh-_tabs-trigger-border-active: var(--xh-_tone-border, var(--xh-border-default));
|
|
129
|
+
--xh-_tabs-accent-text: var(--xh-_tone-fg, var(--xh-fg-default));
|
|
130
|
+
--xh-_tabs-scroll-trigger-bg: var(--xh-bg-subtle-opaque);
|
|
131
|
+
--xh-_tabs-scroll-trigger-bg-hover: var(--xh-bg-subtle-hover-opaque);
|
|
132
|
+
--xh-_tabs-scroll-trigger-bg-pressed: var(--xh-bg-subtle-active-opaque);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* 一行排不下不折行:标签整条沿主轴位移露出被裁掉的那截,两端的翻页钮与滚轮驱动,位移量由机器写在
|
|
136
|
+
--xh-_tabs-scroll 上(下面孩子那条规则读它)。只裁主轴(overflow-x: clip),交叉轴仍是 visible:
|
|
137
|
+
标签的焦点环画在盒内不受影响,粗指针下往块轴两侧外扩的命中区、segment 档抬起面的投影也都不被裁。
|
|
138
|
+
不做成滚动容器(overflow: hidden 会把两个轴一起裁,粗指针那圈外扩就没了;原生滚动条也不该露在标签带下) */
|
|
139
|
+
.xh-scope-tabs[data-part='list'] {
|
|
140
|
+
/* 位移量:放得下时 0,放不下时由机器写成内联样式盖过这条 */
|
|
141
|
+
--xh-_tabs-scroll: 0;
|
|
142
|
+
|
|
143
|
+
position: relative;
|
|
144
|
+
/* 关起标签带内的层序:segment 档的标签抬一层压在滑动的抬起面上、翻页钮再抬一层压在标签上,两个层号都不漏到外面去 */
|
|
145
|
+
isolation: isolate;
|
|
146
|
+
display: flex;
|
|
147
|
+
flex-wrap: nowrap;
|
|
148
|
+
overflow: clip visible;
|
|
149
|
+
align-items: center;
|
|
150
|
+
gap: var(--xh-tabs-list-gap, var(--xh-_tabs-list-gap));
|
|
151
|
+
padding: var(--xh-tabs-list-p, var(--xh-_tabs-list-p));
|
|
152
|
+
border-block-end: var(--xh-_tabs-list-border-width) solid var(--xh-tabs-list-border, var(--xh-border-default));
|
|
153
|
+
border-radius: var(--xh-tabs-list-radius, var(--xh-_tabs-list-radius));
|
|
154
|
+
background: var(--xh-tabs-list-bg, var(--xh-_tabs-list-bg));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* 竖排:主轴换成块向,裁块向、行向放开。竖排的标签带高随内容长,只有使用者限了高才会放不下 */
|
|
158
|
+
.xh-scope-tabs[data-part='list'][aria-orientation='vertical'] {
|
|
159
|
+
flex-direction: column;
|
|
160
|
+
align-items: stretch;
|
|
161
|
+
overflow: visible clip;
|
|
162
|
+
border-block-end: 0;
|
|
163
|
+
border-inline-end: var(--xh-_tabs-list-border-width) solid var(--xh-tabs-list-border, var(--xh-border-default));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* 排在标签带里的孩子——标签、分隔线、指示条——整体沿主轴位移;两端的翻页钮贴边不动,不在这条里。
|
|
167
|
+
位移量是机器逐帧补间写进来的(屏内的像素级推移走 continuous 档,与指示条同一档),这里不接过渡:
|
|
168
|
+
各部件各有自己的过渡清单(line 档的标签归家族),往每一份里都加一条 translate 会把家族与皮肤耦在一起 */
|
|
169
|
+
.xh-scope-tabs[data-part='list']
|
|
170
|
+
> :not(.xh-scope-tabs[data-part='prev-trigger'], .xh-scope-tabs[data-part='next-trigger']) {
|
|
171
|
+
translate: var(--xh-_tabs-scroll) 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.xh-scope-tabs[data-part='list'][aria-orientation='vertical']
|
|
175
|
+
> :not(.xh-scope-tabs[data-part='prev-trigger'], .xh-scope-tabs[data-part='next-trigger']) {
|
|
176
|
+
translate: 0 var(--xh-_tabs-scroll);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* segment 档的标签带是一块淡底面:--xh-bg-subtle 底 + 一圈透明占位边 + 无影(三选一)。
|
|
180
|
+
它同时是标签的淡底承载面,向内下发 hover 200 → pressed 300 的承载阶梯;
|
|
181
|
+
只写在标签带上不写在 root 上:内容面板里的按钮坐在画布上,不该跟着抬一档 */
|
|
182
|
+
.xh-scope-tabs[data-part='root'][data-variant='segment'] .xh-scope-tabs[data-part='list'] {
|
|
183
|
+
--xh-action-host-bg-hover: var(--xh-bg-subtle-hover);
|
|
184
|
+
--xh-action-host-bg-pressed: var(--xh-bg-subtle-active);
|
|
185
|
+
|
|
186
|
+
border: var(--xh-stroke-thin) solid var(--xh-tabs-list-border, transparent);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* 标签的几何三档共用;面、字色、字重与光标不在这里写:line 档由家族按投影的家族角色给,
|
|
190
|
+
card / segment 档写在下面带形态限定的规则里。本条 (0,2,0) 压过家族基础块 (0,1,0),写了面就会盖掉家族的换面 */
|
|
191
|
+
.xh-scope-tabs[data-part='trigger'] {
|
|
192
|
+
position: relative;
|
|
193
|
+
display: inline-flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
justify-content: center;
|
|
196
|
+
gap: var(--xh-tabs-trigger-gap, var(--xh-control-gap-md));
|
|
197
|
+
block-size: var(--xh-tabs-trigger-h, var(--xh-_tabs-trigger-h));
|
|
198
|
+
padding-inline: var(--xh-tabs-trigger-px, var(--xh-_tabs-trigger-px));
|
|
199
|
+
border: var(--xh-_tabs-trigger-border-width) solid var(--xh-tabs-trigger-border, var(--xh-_tabs-trigger-border));
|
|
200
|
+
border-radius: var(--xh-tabs-trigger-radius, var(--xh-_tabs-trigger-radius));
|
|
201
|
+
font-size: var(--xh-tabs-trigger-font-size, var(--xh-_tabs-trigger-font-size));
|
|
202
|
+
line-height: var(--xh-leading-none);
|
|
203
|
+
white-space: nowrap;
|
|
204
|
+
/* 家族基础块给条目写了 min-inline-size: 0(菜单条目要能收窄给文字省略号用);标签不省略号,
|
|
205
|
+
segment 档又按 flex: 1 1 0 等分带宽,下限归零后排不下的标签会被压到文字之下。
|
|
206
|
+
收回 auto:下限按文字算,排不下的那截由标签带位移露出 */
|
|
207
|
+
min-inline-size: auto;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* line 档(导航当前页):把公开槽映射到 Collection Item 的 nav 语境桥接槽。静息 muted / regular,
|
|
211
|
+
悬停 100 + default 字,按下 200 只换面;当前页透明面 + 品牌深字(随语气的 --xh-_tabs-accent-text)+
|
|
212
|
+
medium,叠悬停 100。2px 指示线不由家族按条目画:放了 indicator 部件是 list 上的滑动部件,
|
|
213
|
+
没放则由下面的静态线规则画在选中标签自己身上。高度由 block-size 定,块向内边距归零 */
|
|
214
|
+
.xh-scope-tabs[data-part='root'][data-variant='line'] .xh-scope-tabs[data-part='trigger'] {
|
|
215
|
+
--xh-collection-block-padding: var(--xh-space-0);
|
|
216
|
+
--xh-collection-bg-rest: var(--xh-tabs-trigger-bg, transparent);
|
|
217
|
+
--xh-collection-fg-rest: var(--xh-tabs-trigger-fg, var(--xh-fg-muted));
|
|
218
|
+
--xh-collection-font-weight-rest: var(--xh-tabs-trigger-font-weight, var(--xh-font-weight-regular));
|
|
219
|
+
--xh-collection-bg-hover: var(--xh-tabs-trigger-bg-hover, var(--xh-bg-subtle));
|
|
220
|
+
--xh-collection-fg-hover: var(--xh-tabs-trigger-fg-hover, var(--xh-fg-default));
|
|
221
|
+
--xh-collection-bg-pressed: var(--xh-tabs-trigger-bg-pressed, var(--xh-bg-subtle-hover));
|
|
222
|
+
--xh-collection-fg-pressed: var(--xh-tabs-trigger-fg-pressed, var(--xh-fg-default));
|
|
223
|
+
--xh-collection-bg-current: var(--xh-tabs-trigger-bg-active, transparent);
|
|
224
|
+
--xh-collection-bg-current-hover: var(--xh-tabs-trigger-bg-active-hover, var(--xh-bg-subtle));
|
|
225
|
+
--xh-collection-fg-current: var(--xh-tabs-trigger-fg-active, var(--xh-_tabs-accent-text));
|
|
226
|
+
--xh-collection-font-weight-current: var(--xh-tabs-trigger-font-weight-active, var(--xh-font-weight-medium));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* card / segment 档不归族:面、字色、字重、光标与过渡写在标签自己身上 */
|
|
230
|
+
.xh-scope-tabs[data-part='root']:is([data-variant='card'], [data-variant='segment'])
|
|
231
|
+
.xh-scope-tabs[data-part='trigger'] {
|
|
232
|
+
background: var(--xh-tabs-trigger-bg, transparent);
|
|
233
|
+
color: var(--xh-tabs-trigger-fg, var(--xh-fg-muted));
|
|
234
|
+
font-weight: var(--xh-tabs-trigger-font-weight, var(--xh-text-label-weight));
|
|
235
|
+
cursor: pointer;
|
|
236
|
+
/* 标签是铺开的一段(Tabs trigger 归行级),按下只换面不缩放:transition 里没有 scale */
|
|
237
|
+
transition:
|
|
238
|
+
color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
|
|
239
|
+
background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
|
|
240
|
+
box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* 横排标签的宽随文字走,不把标签带等分铺满一行:line 与 card 档是一排并列的页签,
|
|
244
|
+
每一枚只占自己的字宽加内衬,标签带右侧留白;放不下的那截由标签带位移露出 */
|
|
245
|
+
.xh-scope-tabs[data-part='root'][data-orientation='horizontal']
|
|
246
|
+
.xh-scope-tabs[data-part='trigger'] {
|
|
247
|
+
flex: 0 0 auto;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* 竖排标签的高就是控件高,不随标签带压缩:使用者限了高、标签带放不下时,靠位移露出被裁掉的那截(与横排同一套),
|
|
251
|
+
而不是把每一枚压扁到只剩一行字高 */
|
|
252
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical']
|
|
253
|
+
.xh-scope-tabs[data-part='trigger'] {
|
|
254
|
+
flex-shrink: 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/* segment 档是一条轨道里的格子(与 RadioGroup 的 segmented 形态同构):格子按可用宽度等分 */
|
|
258
|
+
.xh-scope-tabs[data-part='root'][data-orientation='horizontal'][data-variant='segment']
|
|
259
|
+
.xh-scope-tabs[data-part='trigger'] {
|
|
260
|
+
flex: 1 1 0;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* 禁用项带的是 aria-disabled 而非原生 disabled,:hover 照样命中;
|
|
264
|
+
不挡掉的话置灰的那一页悬停仍会换底,看着还能点。
|
|
265
|
+
悬停面按形态分档:card 100、segment 200(见各形态块上的私有槽);line 档由家族给 */
|
|
266
|
+
.xh-scope-tabs[data-part='root']:is([data-variant='card'], [data-variant='segment'])
|
|
267
|
+
.xh-scope-tabs[data-part='trigger']:not([data-disabled]):hover {
|
|
268
|
+
background: var(--xh-tabs-trigger-bg-hover, var(--xh-_tabs-trigger-bg-hover));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/* 按下去要有回应:card / segment 档的未选中标签换到按下面(card 200、segment 300),几何不动。
|
|
272
|
+
选中标签不叠按下面:card 的卡片面与 segment 的抬起面本身就是选中身份(有滑块开关无叠加态) */
|
|
273
|
+
.xh-scope-tabs[data-part='root']:is([data-variant='card'], [data-variant='segment'])
|
|
274
|
+
.xh-scope-tabs[data-part='trigger']:not([data-disabled]):not([data-state='active']):is(:active, [data-pressed]) {
|
|
275
|
+
background: var(--xh-tabs-trigger-bg-pressed, var(--xh-_tabs-trigger-bg-pressed));
|
|
276
|
+
transition-duration: var(--xh-motion-duration-press);
|
|
277
|
+
transition-timing-function: var(--xh-motion-ease-press);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* card / segment 档的选中标签:字色收回默认(--xh-_tabs-accent-text 在两档都落 fg-default),
|
|
281
|
+
由卡片面 / 抬起面表达当前;line 档的当前页由家族按 data-current 给 */
|
|
282
|
+
.xh-scope-tabs[data-part='root']:is([data-variant='card'], [data-variant='segment'])
|
|
283
|
+
.xh-scope-tabs[data-part='trigger'][data-state='active'] {
|
|
284
|
+
border-color: var(--xh-tabs-trigger-border-active, var(--xh-_tabs-trigger-border-active));
|
|
285
|
+
background: var(--xh-tabs-trigger-bg-active, var(--xh-_tabs-trigger-bg-active));
|
|
286
|
+
color: var(--xh-tabs-trigger-fg-active, var(--xh-_tabs-accent-text));
|
|
287
|
+
box-shadow: var(--xh-tabs-trigger-shadow-active, var(--xh-_tabs-trigger-shadow-active));
|
|
288
|
+
font-weight: var(--xh-tabs-trigger-font-weight-active, var(--xh-font-weight-medium));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/* segment 档的选中标签就是那块白色抬起的滑块面(有滑块开关):surface-raised 底 +
|
|
292
|
+
border-default 描边 + raised 影三件写在标签自己身上。标签带里放了 indicator 部件时,
|
|
293
|
+
这块面搬到部件上跟着滑(见下面的 indicator 规则),标签自己透空、只留字 */
|
|
294
|
+
.xh-scope-tabs[data-part='root'][data-variant='segment']
|
|
295
|
+
.xh-scope-tabs[data-part='trigger'][data-state='active'] {
|
|
296
|
+
border-color: var(--xh-tabs-trigger-border-active, var(--xh-_tone-border, var(--xh-border-default)));
|
|
297
|
+
background: var(--xh-tabs-trigger-bg-active, var(--xh-_tone-subtle, var(--xh-bg-surface-raised)));
|
|
298
|
+
box-shadow: var(--xh-tabs-trigger-shadow-active, var(--xh-elevation-raised));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* segment 档的标签压在抬起面之上:面是绝对定位的部件,写在标签之后也不许盖住字。
|
|
302
|
+
层号只在标签带的层叠上下文里比大小(list 上有 isolation: isolate) */
|
|
303
|
+
.xh-scope-tabs[data-part='root'][data-variant='segment'] .xh-scope-tabs[data-part='trigger'] {
|
|
304
|
+
z-index: 1;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.xh-scope-tabs[data-part='root'][data-variant='segment']
|
|
308
|
+
.xh-scope-tabs[data-part='list']:has(.xh-scope-tabs[data-part='indicator']:not([hidden]))
|
|
309
|
+
.xh-scope-tabs[data-part='trigger'][data-state='active'] {
|
|
310
|
+
border-color: transparent;
|
|
311
|
+
background: transparent;
|
|
312
|
+
box-shadow: none;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* 选中项被悬停:常态 :hover 那条带着禁用守卫,特指度高过上面那条选中档,
|
|
316
|
+
不单列一条的话指针一压到选中项上,形态档的选中底就被轻档吃掉 */
|
|
317
|
+
.xh-scope-tabs[data-part='root']:is([data-variant='card'], [data-variant='segment'])
|
|
318
|
+
.xh-scope-tabs[data-part='trigger']:not([data-disabled])[data-state='active']:hover {
|
|
319
|
+
background: var(--xh-tabs-trigger-bg-active-hover, var(--xh-_tabs-trigger-bg-active-hover));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/* line 档的禁用字色由家族按 aria-disabled 给 */
|
|
323
|
+
.xh-scope-tabs[data-part='root']:is([data-variant='card'], [data-variant='segment'])
|
|
324
|
+
.xh-scope-tabs[data-part='trigger'][data-disabled] {
|
|
325
|
+
color: var(--xh-fg-disabled);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.xh-scope-tabs[data-part='content'] {
|
|
329
|
+
padding-block: var(--xh-tabs-content-py, var(--xh-stack-gap-md));
|
|
330
|
+
color: var(--xh-tabs-content-fg, var(--xh-fg-default));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* —— 标签拖拽换位 —— */
|
|
334
|
+
/* 整张标签都是拖动源,光标换成抓手告诉人这张标签按得动。
|
|
335
|
+
这条不写 touch-action:整张标签关掉手势,标签带自己就滚不动了;
|
|
336
|
+
触屏那一路交给下面那块专属把手 */
|
|
337
|
+
.xh-scope-tabs[data-part='trigger'][data-draggable] {
|
|
338
|
+
cursor: grab;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/* 标签拖拽把手:标签里的一小块专属拖动区,按下即拖。触屏靠它起手,
|
|
342
|
+
代价只是这一小块地方不再跟着标签带滚。整张标签起手那一路原样保留,把手是叠加的第二个入口。
|
|
343
|
+
touch-action 不在这儿写:连接层按「拖不动就不写」把它写进了内联 style,
|
|
344
|
+
皮肤再写一遍会盖掉那份条件判断,让不可拖的标签也白白让出滚动 */
|
|
345
|
+
.xh-scope-tabs[data-part='tab-drag-trigger'] {
|
|
346
|
+
display: inline-flex;
|
|
347
|
+
flex: none;
|
|
348
|
+
align-items: center;
|
|
349
|
+
justify-content: center;
|
|
350
|
+
inline-size: var(--xh-tabs-drag-size, var(--xh-control-indicator-size));
|
|
351
|
+
block-size: var(--xh-tabs-drag-size, var(--xh-control-indicator-size));
|
|
352
|
+
border-radius: var(--xh-tabs-drag-radius, var(--xh-shape-control));
|
|
353
|
+
color: var(--xh-tabs-drag-fg, var(--xh-fg-subtle));
|
|
354
|
+
cursor: grab;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/* 抓手是两条与排列轴垂直的线:盒子取边框盒,两侧描边就是那两条线,宽高与线宽都走令牌。
|
|
358
|
+
标签带横排时标签左右排开,画的是两条竖线;竖排那一档在下面换成横线。
|
|
359
|
+
基础这一档同时兜住 root 上没写方向的情形。
|
|
360
|
+
:empty 守卫让作者塞进来的图标整个顶掉它,而不是两份叠在一起 */
|
|
361
|
+
.xh-scope-tabs[data-part='tab-drag-trigger']:empty::after {
|
|
362
|
+
content: '';
|
|
363
|
+
display: block;
|
|
364
|
+
inline-size: var(--xh-tabs-drag-grip-short, var(--xh-space-1));
|
|
365
|
+
block-size: var(--xh-tabs-drag-grip-long, var(--xh-space-2));
|
|
366
|
+
border-inline: var(--xh-stroke-thin) solid currentColor;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/* 竖排的标签上下排开,两条线跟着转九十度:长短对调,描边换到块向两侧,
|
|
370
|
+
行向那两条得显式清零,否则四边都留着描边,抓手成了一个方框 */
|
|
371
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical']
|
|
372
|
+
.xh-scope-tabs[data-part='tab-drag-trigger']:empty::after {
|
|
373
|
+
inline-size: var(--xh-tabs-drag-grip-long, var(--xh-space-2));
|
|
374
|
+
block-size: var(--xh-tabs-drag-grip-short, var(--xh-space-1));
|
|
375
|
+
border-inline: 0;
|
|
376
|
+
border-block: var(--xh-stroke-thin) solid currentColor;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.xh-scope-tabs[data-part='tab-drag-trigger']:not([data-disabled]):hover,
|
|
380
|
+
.xh-scope-tabs[data-part='tab-drag-trigger'][data-dragging] {
|
|
381
|
+
color: var(--xh-tabs-drag-fg-active, var(--xh-fg-default));
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.xh-scope-tabs[data-part='tab-drag-trigger'][data-dragging] {
|
|
385
|
+
cursor: grabbing;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/* 不可拖的标签照样带一个把手,这里保住它的位置、只把它压到禁用色。
|
|
389
|
+
收成 display: none 是不行的:把手占着标签内的头一格,藏掉之后同一条标签带里
|
|
390
|
+
能拖与不能拖的两张标签,文字起点会错开一格 */
|
|
391
|
+
.xh-scope-tabs[data-part='tab-drag-trigger'][data-disabled] {
|
|
392
|
+
color: var(--xh-tabs-drag-fg-disabled, var(--xh-fg-disabled));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/* 被拖的那张标签压暗,让人看得出正在搬的是它。这里只动 opacity、cursor 与 user-select,
|
|
396
|
+
一个 transform 都不写:标签原地不动,要落到哪儿全交给落点指示 */
|
|
397
|
+
.xh-scope-tabs[data-part='trigger'][data-dragging] {
|
|
398
|
+
opacity: var(--xh-tabs-dragging-opacity, var(--xh-state-dragging-opacity));
|
|
399
|
+
cursor: grabbing;
|
|
400
|
+
user-select: none;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/* 落点指示线:插到哪张标签的哪一侧,线就画在那张标签的那条边上。
|
|
404
|
+
定位上下文不必在这儿再给:标签的基础规则里已经是 position: relative。
|
|
405
|
+
线走 ::after:选中态那道指示画的是 box-shadow(card 档的顶边条、segment 档的浮起),
|
|
406
|
+
line 档放了部件时指示条在 list 上,没放时选中标签的静态线也占 ::after——它带 :not([data-drop]) 守卫,
|
|
407
|
+
拖动落到当前页上时让给落点线。标签自身不收 overflow,线不会被裁掉;仍整条画在盒内不压着边 */
|
|
408
|
+
.xh-scope-tabs[data-part='trigger']:is([data-drop='before'], [data-drop='after'])::after {
|
|
409
|
+
content: '';
|
|
410
|
+
position: absolute;
|
|
411
|
+
background: var(--xh-tabs-drop-fg, var(--xh-bg-brand));
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/* 线的方向跟着标签带的排法换:方向写在 root 的 data-orientation 上,从根往下选。
|
|
415
|
+
横排的标签左右排开,线是一条竖的,贯穿标签的块向、贴在行向的前后沿 */
|
|
416
|
+
.xh-scope-tabs[data-part='root'][data-orientation='horizontal']
|
|
417
|
+
.xh-scope-tabs[data-part='trigger']:is([data-drop='before'], [data-drop='after'])::after {
|
|
418
|
+
inset-block: 0;
|
|
419
|
+
inline-size: var(--xh-tabs-drop-line, var(--xh-stroke-thick));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/* 落在前沿还是后沿走逻辑属性:rtl 下 before 自己就换到右边去了。
|
|
423
|
+
换成 box-shadow 的偏移量则是物理的,写不出逻辑方向 */
|
|
424
|
+
.xh-scope-tabs[data-part='root'][data-orientation='horizontal']
|
|
425
|
+
.xh-scope-tabs[data-part='trigger'][data-drop='before']::after {
|
|
426
|
+
inset-inline-start: 0;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.xh-scope-tabs[data-part='root'][data-orientation='horizontal']
|
|
430
|
+
.xh-scope-tabs[data-part='trigger'][data-drop='after']::after {
|
|
431
|
+
inset-inline-end: 0;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/* 竖排的标签上下排开,线是一条横的,贯穿标签的行向、贴在块向的前后沿 */
|
|
435
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical']
|
|
436
|
+
.xh-scope-tabs[data-part='trigger']:is([data-drop='before'], [data-drop='after'])::after {
|
|
437
|
+
inset-inline: 0;
|
|
438
|
+
block-size: var(--xh-tabs-drop-line, var(--xh-stroke-thick));
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/* 块向同样走逻辑属性,跟着书写模式走 */
|
|
442
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical']
|
|
443
|
+
.xh-scope-tabs[data-part='trigger'][data-drop='before']::after {
|
|
444
|
+
inset-block-start: 0;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical']
|
|
448
|
+
.xh-scope-tabs[data-part='trigger'][data-drop='after']::after {
|
|
449
|
+
inset-block-end: 0;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/* 活动区域只说给读屏听,不占版面。声明与 shared/visually-hidden.ts 逐条同值。 */
|
|
453
|
+
.xh-scope-tabs[data-part='live-region'] {
|
|
454
|
+
position: absolute;
|
|
455
|
+
inline-size: 1px;
|
|
456
|
+
block-size: 1px;
|
|
457
|
+
padding: 0;
|
|
458
|
+
margin: -1px;
|
|
459
|
+
overflow: hidden;
|
|
460
|
+
clip-path: inset(50%);
|
|
461
|
+
white-space: nowrap;
|
|
462
|
+
border: 0;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/* 选中标签的四个几何量由机器量好写成私有槽 --xh-_tabs-indicator-x / -y / -w / -h(它量得到,样式表量不到);
|
|
466
|
+
line 档只取主轴那两支画一条线,这里管交叉轴的贴边与粗细,以及长什么样。它是可选部件——不渲染它时,
|
|
467
|
+
line 档由选中标签自画一条同规格的静态线(见下),card 档由卡片面表达,segment 档由标签自己的抬起面表达 */
|
|
468
|
+
.xh-scope-tabs[data-part='indicator'] {
|
|
469
|
+
/* 还没量到时的落点,量到即被机器写的私有槽盖过 */
|
|
470
|
+
--xh-_tabs-indicator-x: 0;
|
|
471
|
+
--xh-_tabs-indicator-y: 0;
|
|
472
|
+
--xh-_tabs-indicator-w: 0;
|
|
473
|
+
--xh-_tabs-indicator-h: 0;
|
|
474
|
+
--xh-_tabs-indicator-stretch: 0;
|
|
475
|
+
|
|
476
|
+
/* 摆在行首,落点交给 transform(只走合成),长度跟着标签宽走。标签带挪动时整条孩子
|
|
477
|
+
共用的 translate 叠在它之上,两者互不覆盖,过渡也只挂在 transform 上 */
|
|
478
|
+
position: absolute;
|
|
479
|
+
inset-block-end: 0;
|
|
480
|
+
inset-inline-start: 0;
|
|
481
|
+
inline-size: var(--xh-_tabs-indicator-w);
|
|
482
|
+
block-size: var(--xh-tabs-indicator-thickness, var(--xh-stroke-thick));
|
|
483
|
+
border-radius: var(--xh-tabs-indicator-radius, var(--xh-shape-pill));
|
|
484
|
+
background: var(--xh-tabs-indicator-color, var(--xh-_tabs-accent));
|
|
485
|
+
transform: translate(var(--xh-_tabs-indicator-x), 0);
|
|
486
|
+
transition:
|
|
487
|
+
transform var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
|
|
488
|
+
inline-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/* transform 只认物理方向:RTL 下行首在右边,起始缘量出的距离往左推 */
|
|
492
|
+
.xh-scope-tabs[data-part='indicator']:dir(rtl) {
|
|
493
|
+
transform: translate(calc(-1 * var(--xh-_tabs-indicator-x)), 0);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/* 卡片变体已经由卡片面表达状态,不再叠一条下划线。 */
|
|
497
|
+
.xh-scope-tabs[data-part='indicator'][data-variant='card'] {
|
|
498
|
+
display: none;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/* segment 档(有滑块开关):部件就是那块白色抬起的滑块面,四个几何量都取、整块跟着滑——
|
|
502
|
+
surface-raised 底 + border-default 描边 + raised 影三件与 RadioGroup segmented 形态的滑块同一套;
|
|
503
|
+
描边吃进盒里(border-box),面与标签仍是同一块矩形。标签压在它上面,点击一律交给标签。
|
|
504
|
+
用连续档而不是进场那条:滑块是被推过去的,起步就该有速度;四个几何量同时走,标签宽不等时才不会先变形再挪位 */
|
|
505
|
+
.xh-scope-tabs[data-part='indicator'][data-variant='segment'] {
|
|
506
|
+
inset-block-end: auto;
|
|
507
|
+
inset-inline-end: auto;
|
|
508
|
+
inset-inline-start: 0;
|
|
509
|
+
inset-block-start: 0;
|
|
510
|
+
inline-size: var(--xh-_tabs-indicator-w);
|
|
511
|
+
block-size: var(--xh-_tabs-indicator-h);
|
|
512
|
+
box-sizing: border-box;
|
|
513
|
+
border: var(--xh-stroke-thin) solid var(--xh-tabs-trigger-border-active, var(--xh-_tone-border, var(--xh-border-default)));
|
|
514
|
+
border-radius: var(--xh-tabs-trigger-radius, var(--xh-_tabs-trigger-radius));
|
|
515
|
+
background: var(--xh-tabs-trigger-bg-active, var(--xh-_tone-subtle, var(--xh-bg-surface-raised)));
|
|
516
|
+
box-shadow: var(--xh-tabs-trigger-shadow-active, var(--xh-elevation-raised));
|
|
517
|
+
pointer-events: none;
|
|
518
|
+
transform: translate(var(--xh-_tabs-indicator-x), var(--xh-_tabs-indicator-y));
|
|
519
|
+
transition:
|
|
520
|
+
transform var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
|
|
521
|
+
inline-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
|
|
522
|
+
block-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.xh-scope-tabs[data-part='indicator'][data-variant='segment']:dir(rtl) {
|
|
526
|
+
transform: translate(calc(-1 * var(--xh-_tabs-indicator-x)), var(--xh-_tabs-indicator-y));
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/* line 档没放 indicator 部件时,选中标签自画一条静态指示线(导航当前页):
|
|
530
|
+
横向缺省也要像纵向示例那样有一条选中线,作者不必为了这条线多放一个部件。
|
|
531
|
+
线画在选中标签的 ::after 上,以标签盒为定位参照(基础规则里已是 position: relative),
|
|
532
|
+
厚度 / 颜色 / 圆角与 indicator 部件读同一组槽与缺省——作者改一处,部件与静态线一起改。
|
|
533
|
+
不做动画:它随 data-current 在标签间跳,滑动只有部件做得到。
|
|
534
|
+
标签带里一旦放了 indicator 部件,这条线就收起、位置交给部件滑动,不重复画两条:
|
|
535
|
+
由标签带按 :has 探一次,把私有槽写成 none,线的 content 读它;标签自己不必再各带一段 :has。
|
|
536
|
+
::after 同时是换位落点线的载体:拖动中标签带着 data-drop 时让给落点线,松手即回来 */
|
|
537
|
+
.xh-scope-tabs[data-part='list']:has(.xh-scope-tabs[data-part='indicator']) {
|
|
538
|
+
--xh-_tabs-static-line: none;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.xh-scope-tabs[data-part='root'][data-variant='line']
|
|
542
|
+
.xh-scope-tabs[data-part='trigger'][data-current]:not([data-drop])::after {
|
|
543
|
+
content: var(--xh-_tabs-static-line, '');
|
|
544
|
+
position: absolute;
|
|
545
|
+
pointer-events: none;
|
|
546
|
+
border-radius: var(--xh-tabs-indicator-radius, var(--xh-shape-pill));
|
|
547
|
+
background: var(--xh-tabs-indicator-color, var(--xh-_tabs-accent));
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/* 横排:贴标签的块向末端(底边),横贯整枚标签 */
|
|
551
|
+
.xh-scope-tabs[data-part='root'][data-variant='line'][data-orientation='horizontal']
|
|
552
|
+
.xh-scope-tabs[data-part='trigger'][data-current]:not([data-drop])::after {
|
|
553
|
+
inset-block-end: 0;
|
|
554
|
+
inset-inline: 0;
|
|
555
|
+
block-size: var(--xh-tabs-indicator-thickness, var(--xh-stroke-thick));
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/* 竖排:贴标签的行向末端(与 indicator 部件同一侧,rtl 随逻辑属性镜像),纵贯整枚标签 */
|
|
559
|
+
.xh-scope-tabs[data-part='root'][data-variant='line'][data-orientation='vertical']
|
|
560
|
+
.xh-scope-tabs[data-part='trigger'][data-current]:not([data-drop])::after {
|
|
561
|
+
inset-inline-end: 0;
|
|
562
|
+
inset-block: 0;
|
|
563
|
+
inline-size: var(--xh-tabs-indicator-thickness, var(--xh-stroke-thick));
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/* 竖排 line 档:滑条从基线挪到结束缘那条轨道上,主轴换成块向,取 -y / -h 两支 */
|
|
567
|
+
.xh-scope-tabs[data-part='indicator'][data-orientation='vertical']:not([data-variant='segment']) {
|
|
568
|
+
inset-block-end: auto;
|
|
569
|
+
inset-inline-start: auto;
|
|
570
|
+
inset-inline-end: 0;
|
|
571
|
+
inset-block-start: 0;
|
|
572
|
+
block-size: var(--xh-_tabs-indicator-h);
|
|
573
|
+
inline-size: var(--xh-tabs-indicator-thickness, var(--xh-stroke-thick));
|
|
574
|
+
transform: translate(0, var(--xh-_tabs-indicator-y));
|
|
575
|
+
transition:
|
|
576
|
+
transform var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
|
|
577
|
+
block-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/* 首次落位与同一项的重量(窗口缩放、换上正式字体)直接到位,只有换项才滑:连接层在这一落点投影
|
|
581
|
+
data-instant。选择器带上排布与形态,压得过上面按它们单写的过渡 */
|
|
582
|
+
.xh-scope-tabs[data-part='indicator'][data-orientation][data-variant][data-instant] {
|
|
583
|
+
transition: none;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/* 液态档:两沿由弹簧逐帧推着走(连接层每一帧写好盒子),几何量不再补过渡(选择器带上排布与形态,压得过上面按它们单写的过渡);
|
|
587
|
+
被拉长时在另一个方向上压扁,表达体积守恒,拉长到目标的两倍时压到 --xh-motion-scale-squash */
|
|
588
|
+
:where([data-material='liquid']) .xh-scope-tabs[data-part='indicator'][data-orientation][data-variant] {
|
|
589
|
+
--xh-_tabs-indicator-squash: max(var(--xh-motion-scale-squash), calc(1 - var(--xh-_tabs-indicator-stretch) * (1 - var(--xh-motion-scale-squash))));
|
|
590
|
+
|
|
591
|
+
scale: 1 var(--xh-_tabs-indicator-squash);
|
|
592
|
+
transition: none;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
:where([data-material='liquid']) .xh-scope-tabs[data-part='indicator'][data-orientation='vertical'][data-variant] {
|
|
596
|
+
scale: var(--xh-_tabs-indicator-squash) 1;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/* 标签之间的细线:横排时是一条竖线,竖排时躺平 */
|
|
600
|
+
.xh-scope-tabs[data-part='separator'] {
|
|
601
|
+
flex: none;
|
|
602
|
+
align-self: center;
|
|
603
|
+
inline-size: var(--xh-tabs-separator-thickness, var(--xh-stroke-thin));
|
|
604
|
+
block-size: var(--xh-tabs-separator-size, var(--xh-space-4));
|
|
605
|
+
border-radius: var(--xh-tabs-separator-radius, var(--xh-shape-pill));
|
|
606
|
+
background: var(--xh-tabs-separator-color, var(--xh-border-default));
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
.xh-scope-tabs[data-part='separator'][data-orientation='vertical'] {
|
|
610
|
+
align-self: stretch;
|
|
611
|
+
inline-size: auto;
|
|
612
|
+
block-size: var(--xh-tabs-separator-thickness, var(--xh-stroke-thin));
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/* —— 两端翻页钮 —— */
|
|
616
|
+
/* 标签带放不下时浮在两端的单图标钮,接 Action Control icon 档 ghost 面(连接层投影 profile / variant / size):
|
|
617
|
+
盒取标签同高的正方形,四态面、0.97 按压与粗指针 44px 命中区由家族配方给。绝对定位贴在标签带两端、
|
|
618
|
+
不随标签位移;挪到它底下的那截标签由静息底盖住(透明 ghost 面盖不住字,静息 / 焦点 / 禁用三列换成盖底槽,
|
|
619
|
+
悬停与按下换成盖底档的不透明阶梯——line / card 在白底上 100 → 200,segment 在轨道上 200 → 300) */
|
|
620
|
+
.xh-scope-tabs[data-part='prev-trigger'],
|
|
621
|
+
.xh-scope-tabs[data-part='next-trigger'] {
|
|
622
|
+
--xh-action-visual-size: var(--xh-tabs-trigger-h, var(--xh-_tabs-trigger-h));
|
|
623
|
+
--xh-action-bg-rest: var(--xh-tabs-scroll-trigger-bg, var(--xh-_tabs-scroll-trigger-bg));
|
|
624
|
+
--xh-action-bg-hover: var(--xh-_tabs-scroll-trigger-bg-hover);
|
|
625
|
+
--xh-action-bg-pressed: var(--xh-_tabs-scroll-trigger-bg-pressed);
|
|
626
|
+
--xh-action-bg-focus-visible: var(--xh-tabs-scroll-trigger-bg, var(--xh-_tabs-scroll-trigger-bg));
|
|
627
|
+
--xh-action-bg-disabled: var(--xh-tabs-scroll-trigger-bg, var(--xh-_tabs-scroll-trigger-bg));
|
|
628
|
+
--xh-action-fg-rest: var(--xh-tabs-scroll-trigger-fg, var(--xh-fg-muted));
|
|
629
|
+
/* 作者塞进来的图标跟着 icon 档走,与皮肤画的兜底字形同一把尺 */
|
|
630
|
+
--xh-icon-size: var(--xh-tabs-scroll-icon-size, var(--xh-_action-profile-glyph-size));
|
|
631
|
+
|
|
632
|
+
position: absolute;
|
|
633
|
+
z-index: 2;
|
|
634
|
+
inset-block-start: 50%;
|
|
635
|
+
translate: 0 -50%;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/* 贴在标签带内衬盒的两端:segment 档的轨道留着一圈内衬,钮坐在内衬里、不压到轨道边上 */
|
|
639
|
+
.xh-scope-tabs[data-part='prev-trigger'] {
|
|
640
|
+
inset-inline-start: var(--xh-tabs-list-p, var(--xh-_tabs-list-p));
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.xh-scope-tabs[data-part='next-trigger'] {
|
|
644
|
+
inset-inline-end: var(--xh-tabs-list-p, var(--xh-_tabs-list-p));
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/* 竖排:两只钮躺平成横贯标签带的一条,各贴块向的首尾 */
|
|
648
|
+
.xh-scope-tabs[data-part='prev-trigger'][data-orientation='vertical'],
|
|
649
|
+
.xh-scope-tabs[data-part='next-trigger'][data-orientation='vertical'] {
|
|
650
|
+
inline-size: auto;
|
|
651
|
+
inset-inline: var(--xh-tabs-list-p, var(--xh-_tabs-list-p));
|
|
652
|
+
inset-block-start: auto;
|
|
653
|
+
translate: 0 0;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
.xh-scope-tabs[data-part='prev-trigger'][data-orientation='vertical'] {
|
|
657
|
+
inset-block-start: var(--xh-tabs-list-p, var(--xh-_tabs-list-p));
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
.xh-scope-tabs[data-part='next-trigger'][data-orientation='vertical'] {
|
|
661
|
+
inset-block-end: var(--xh-tabs-list-p, var(--xh-_tabs-list-p));
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/* 挪到头的那一侧是原生 disabled(不可聚焦),连接层同时给 data-disabled:到头即收起——
|
|
665
|
+
它浮在标签上,留着会盖住边上那枚完整露出的标签;配方 disabled 列给的面被 opacity 0 盖住,两者不冲突 */
|
|
666
|
+
.xh-scope-tabs[data-part='prev-trigger'][data-disabled],
|
|
667
|
+
.xh-scope-tabs[data-part='next-trigger'][data-disabled] {
|
|
668
|
+
opacity: 0;
|
|
669
|
+
pointer-events: none;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/* 没写内容就由皮肤画兜底字形:横排一左一右的 chevron,竖排一上一下;作者塞了自己的图形这几条即不命中 */
|
|
673
|
+
.xh-scope-tabs[data-part='prev-trigger']:empty::before,
|
|
674
|
+
.xh-scope-tabs[data-part='next-trigger']:empty::before {
|
|
675
|
+
content: '';
|
|
676
|
+
display: inline-block;
|
|
677
|
+
inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
678
|
+
block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
679
|
+
vertical-align: var(--xh-glyph-baseline-shift);
|
|
680
|
+
background-color: currentColor;
|
|
681
|
+
-webkit-mask: var(--xh-glyph-mark-chevron-left) center / contain no-repeat;
|
|
682
|
+
mask: var(--xh-glyph-mark-chevron-left) center / contain no-repeat;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.xh-scope-tabs[data-part='next-trigger']:empty::before {
|
|
686
|
+
-webkit-mask-image: var(--xh-glyph-mark-chevron-right);
|
|
687
|
+
mask-image: var(--xh-glyph-mark-chevron-right);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/* rtl 下标签序从右往左走,箭头跟着指向行进方向 */
|
|
691
|
+
[dir='rtl'] .xh-scope-tabs[data-part='prev-trigger']:empty::before {
|
|
692
|
+
-webkit-mask-image: var(--xh-glyph-mark-chevron-right);
|
|
693
|
+
mask-image: var(--xh-glyph-mark-chevron-right);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
[dir='rtl'] .xh-scope-tabs[data-part='next-trigger']:empty::before {
|
|
697
|
+
-webkit-mask-image: var(--xh-glyph-mark-chevron-left);
|
|
698
|
+
mask-image: var(--xh-glyph-mark-chevron-left);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
.xh-scope-tabs[data-part='prev-trigger'][data-orientation='vertical']:empty::before {
|
|
702
|
+
-webkit-mask-image: var(--xh-glyph-mark-chevron-up);
|
|
703
|
+
mask-image: var(--xh-glyph-mark-chevron-up);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
.xh-scope-tabs[data-part='next-trigger'][data-orientation='vertical']:empty::before {
|
|
707
|
+
-webkit-mask-image: var(--xh-glyph-mark-chevron-down);
|
|
708
|
+
mask-image: var(--xh-glyph-mark-chevron-down);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/* —— 「更多」钮 —— */
|
|
712
|
+
/* 放了「更多」钮:钮排在标签带之后、同一行(竖排是同一列的列尾)。它不能放进标签带——tablist 只收 tab,
|
|
713
|
+
所以是 root 的孩子;root 换成两轨网格,标签带占能伸缩的那一轨、钮占按内容的那一轨,面板等其余孩子横跨两轨排在
|
|
714
|
+
下面(竖排排在右侧)。钮收着(hidden)时那一轨是 0,标签带铺满;钮与标签带之间的间距挂在钮自己身上,
|
|
715
|
+
收着时一并让开。标签带的可用长度因此随钮的有无变:放不放得下由机器按让回钮那一截算,钮不会自己把自己留住 */
|
|
716
|
+
.xh-scope-tabs[data-part='root']:has(> .xh-scope-tabs[data-part='overflow-trigger']) {
|
|
717
|
+
display: grid;
|
|
718
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
719
|
+
column-gap: 0;
|
|
720
|
+
row-gap: var(--xh-tabs-gap, var(--xh-stack-gap-md));
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
.xh-scope-tabs[data-part='root']:has(> .xh-scope-tabs[data-part='overflow-trigger']) > * {
|
|
724
|
+
grid-column: 1 / -1;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
.xh-scope-tabs[data-part='root']:has(> .xh-scope-tabs[data-part='overflow-trigger'])
|
|
728
|
+
> .xh-scope-tabs[data-part='list'] {
|
|
729
|
+
grid-row: 1;
|
|
730
|
+
grid-column: 1;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
.xh-scope-tabs[data-part='root']:has(> .xh-scope-tabs[data-part='overflow-trigger'])
|
|
734
|
+
> .xh-scope-tabs[data-part='overflow-trigger'] {
|
|
735
|
+
grid-row: 1;
|
|
736
|
+
grid-column: 2;
|
|
737
|
+
align-self: center;
|
|
738
|
+
margin-inline-start: var(--xh-space-1);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/* 竖排:标签带与钮上下叠成左侧一列(钮在列尾),面板占右侧那一轨、跨两行 */
|
|
742
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical']:has(> .xh-scope-tabs[data-part='overflow-trigger']) {
|
|
743
|
+
grid-template-rows: minmax(0, 1fr) auto;
|
|
744
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
745
|
+
column-gap: var(--xh-tabs-gap, var(--xh-stack-gap-md));
|
|
746
|
+
row-gap: 0;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical']:has(> .xh-scope-tabs[data-part='overflow-trigger']) > * {
|
|
750
|
+
grid-row: 1 / -1;
|
|
751
|
+
grid-column: 2;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical']:has(> .xh-scope-tabs[data-part='overflow-trigger'])
|
|
755
|
+
> .xh-scope-tabs[data-part='list'] {
|
|
756
|
+
grid-row: 1;
|
|
757
|
+
grid-column: 1;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical']:has(> .xh-scope-tabs[data-part='overflow-trigger'])
|
|
761
|
+
> .xh-scope-tabs[data-part='overflow-trigger'] {
|
|
762
|
+
grid-row: 2;
|
|
763
|
+
grid-column: 1;
|
|
764
|
+
align-self: auto;
|
|
765
|
+
margin-inline-start: 0;
|
|
766
|
+
margin-block-start: var(--xh-space-1);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/* 钮本身:接 Action Control icon 档 ghost 面(连接层投影 profile / variant / size),盒取标签同高的正方形,
|
|
770
|
+
与两端翻页钮同一身份;四态面、0.97 按压、焦点环与粗指针 44px 命中区由家族配方给。它坐在 root 的面上
|
|
771
|
+
(不在标签带里),承载面阶梯走家族缺省的白底 100 → 200;字取次要色,与静息的标签、翻页钮同档 */
|
|
772
|
+
.xh-scope-tabs[data-part='overflow-trigger'] {
|
|
773
|
+
--xh-action-visual-size: var(--xh-tabs-trigger-h, var(--xh-_tabs-trigger-h));
|
|
774
|
+
--xh-action-fg-rest: var(--xh-fg-muted);
|
|
775
|
+
/* 作者塞进来的图标跟着 icon 档走,与皮肤画的兜底字形同一把尺 */
|
|
776
|
+
--xh-icon-size: var(--xh-_action-profile-glyph-size);
|
|
777
|
+
|
|
778
|
+
touch-action: manipulation;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/* 竖排:与竖排的翻页钮一样躺平成横贯标签带那一列的一条 */
|
|
782
|
+
.xh-scope-tabs[data-part='overflow-trigger'][data-orientation='vertical'] {
|
|
783
|
+
inline-size: auto;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/* 下拉开着:与悬停同档的中性面,不用品牌色、不另画环;列的是哪几个标签由下拉本身说明 */
|
|
787
|
+
.xh-scope-tabs[data-part='overflow-trigger'][data-state='open'] {
|
|
788
|
+
--xh-action-bg-rest: var(--xh-_action-variant-bg-hover);
|
|
789
|
+
--xh-action-bg-focus-visible: var(--xh-_action-variant-bg-hover);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/* 没写内容就由皮肤画兜底字形:横排三点(与工具条的「更多」同一枚)。作者塞了自己的图标这条即不命中 */
|
|
793
|
+
.xh-scope-tabs[data-part='overflow-trigger']:empty::before {
|
|
794
|
+
content: '';
|
|
795
|
+
display: inline-block;
|
|
796
|
+
inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
797
|
+
block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
798
|
+
background-color: currentColor;
|
|
799
|
+
-webkit-mask: var(--xh-glyph-mark-ellipsis) center / contain no-repeat;
|
|
800
|
+
mask: var(--xh-glyph-mark-ellipsis) center / contain no-repeat;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/* —— 关闭钮 —— */
|
|
804
|
+
/* 关闭钮与所属标签平级、紧跟其后(不嵌进 role=tab 的按钮里),画面上收进标签面的行尾:标签在行尾让出一格
|
|
805
|
+
(钮的边长 + 与行尾的留白 + 与文字的间距),钮以负的起始外边距退回这一格,结束外边距补回同样的留白,
|
|
806
|
+
下一枚标签的起点与没有关闭钮时一致。留白取标签与钮高度差的一半,钮在标签里上下左右都居中对齐。
|
|
807
|
+
面归 Action Control icon 档 ghost 面、xs 档(连接层投影):四态面、0.97 按压与粗指针命中区由家族配方给,
|
|
808
|
+
这里只管落位与字色。悬停落在钮上时标签自己回到静息面,只有钮亮起,按下去关的是哪一个一目了然 */
|
|
809
|
+
.xh-scope-tabs[data-part='root'] {
|
|
810
|
+
--xh-_tabs-close-size: var(--xh-control-action-size);
|
|
811
|
+
--xh-_tabs-close-inset: calc((var(--xh-tabs-trigger-h, var(--xh-_tabs-trigger-h)) - var(--xh-_tabs-close-size)) / 2);
|
|
812
|
+
/* 钮退回去的距离:横排退过自己、行尾留白与标签带间距;竖排退过半个标签高、半个钮高与标签带间距 */
|
|
813
|
+
--xh-_tabs-close-offset: calc(var(--xh-_tabs-close-size) + var(--xh-_tabs-close-inset) + var(--xh-tabs-list-gap, var(--xh-_tabs-list-gap)));
|
|
814
|
+
--xh-_tabs-close-offset-block: calc((var(--xh-tabs-trigger-h, var(--xh-_tabs-trigger-h)) + var(--xh-_tabs-close-size)) / 2 + var(--xh-tabs-list-gap, var(--xh-_tabs-list-gap)));
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
.xh-scope-tabs[data-part='trigger']:has(+ .xh-scope-tabs[data-part='close-trigger']:not([hidden])) {
|
|
818
|
+
padding-inline-end: calc(var(--xh-_tabs-close-size) + var(--xh-_tabs-close-inset) + var(--xh-space-1));
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
.xh-scope-tabs[data-part='close-trigger'] {
|
|
822
|
+
--xh-action-fg-rest: var(--xh-fg-muted);
|
|
823
|
+
/* 作者塞进来的图标跟着 xs 档走,与皮肤画的兜底字形同一把尺 */
|
|
824
|
+
--xh-icon-size: var(--xh-_action-profile-glyph-size);
|
|
825
|
+
|
|
826
|
+
flex: none;
|
|
827
|
+
/* segment 档的标签抬了一层压在滑动的抬起面上,钮排在标签之后、同一层即压在标签上 */
|
|
828
|
+
z-index: 1;
|
|
829
|
+
margin-inline-start: calc(-1 * var(--xh-_tabs-close-offset));
|
|
830
|
+
margin-inline-end: var(--xh-_tabs-close-inset);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
/* 竖排:标签上下排开,钮退回的是上一行——起始外边距改在块向,行向贴到行尾 */
|
|
834
|
+
.xh-scope-tabs[data-part='root'][data-orientation='vertical'] .xh-scope-tabs[data-part='close-trigger'] {
|
|
835
|
+
align-self: flex-end;
|
|
836
|
+
margin-block-start: calc(-1 * var(--xh-_tabs-close-offset-block));
|
|
837
|
+
margin-block-end: var(--xh-_tabs-close-inset);
|
|
838
|
+
margin-inline-start: 0;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/* 没写内容就由皮肤画一枚叉;作者塞了自己的图形这一条即不命中 */
|
|
842
|
+
.xh-scope-tabs[data-part='close-trigger']:empty::before {
|
|
843
|
+
content: '';
|
|
844
|
+
display: inline-block;
|
|
845
|
+
inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
846
|
+
block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
847
|
+
vertical-align: var(--xh-glyph-baseline-shift);
|
|
848
|
+
background-color: currentColor;
|
|
849
|
+
-webkit-mask: var(--xh-glyph-mark-close) center / contain no-repeat;
|
|
850
|
+
mask: var(--xh-glyph-mark-close) center / contain no-repeat;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
/* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
|
|
854
|
+
写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
|
|
855
|
+
.xh-scope-tabs[data-part='root'][hidden],
|
|
856
|
+
.xh-scope-tabs[data-part='list'][hidden],
|
|
857
|
+
.xh-scope-tabs[data-part='trigger'][hidden],
|
|
858
|
+
.xh-scope-tabs[data-part='close-trigger'][hidden],
|
|
859
|
+
.xh-scope-tabs[data-part='indicator'][hidden],
|
|
860
|
+
.xh-scope-tabs[data-part='separator'][hidden],
|
|
861
|
+
.xh-scope-tabs[data-part='prev-trigger'][hidden],
|
|
862
|
+
.xh-scope-tabs[data-part='next-trigger'][hidden],
|
|
863
|
+
.xh-scope-tabs[data-part='overflow-trigger'][hidden],
|
|
864
|
+
.xh-scope-tabs[data-part='tab-drag-trigger'][hidden] {
|
|
865
|
+
display: none;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/* 手指落点:命中区由伪元素向块轴两侧外扩,标签的盒与标签带的高度一点不动——
|
|
869
|
+
加高标签会把基线与滑条一起顶下去。
|
|
870
|
+
只扩块轴:标签在行内轴上首尾相接(segment 档只留半格缝),往两侧扩会与相邻标签的命中区叠上。
|
|
871
|
+
取 8px 是按最矮的 sm 档算的(28 + 8 × 2 = 44),md 与 lg 档更宽裕。
|
|
872
|
+
用 ::before:::after 已经被换位时的落点线占着 */
|
|
873
|
+
@media (pointer: coarse) {
|
|
874
|
+
.xh-scope-tabs[data-part='trigger']::before {
|
|
875
|
+
content: '';
|
|
876
|
+
position: absolute;
|
|
877
|
+
inset-block: -8px;
|
|
878
|
+
inset-inline: 0;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
@media (forced-colors: active) {
|
|
883
|
+
/* 滑条与分隔线画的都是一块纯底色,这一档里底色被统一换成 Canvas,两者整根消失。
|
|
884
|
+
滑条换成系统高亮色、分隔线换成前景色画回来 */
|
|
885
|
+
.xh-scope-tabs[data-part='indicator'] {
|
|
886
|
+
background: Highlight;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/* 没放部件时选中标签自画的那条静态线同样是一块纯底色,同一档换成系统高亮色 */
|
|
890
|
+
.xh-scope-tabs[data-part='root'][data-variant='line']
|
|
891
|
+
.xh-scope-tabs[data-part='trigger'][data-current]:not([data-drop])::after {
|
|
892
|
+
background: Highlight;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
.xh-scope-tabs[data-part='separator'] {
|
|
896
|
+
background: CanvasText;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/* 按下:常态靠底色深一档表出,这一档里底色被统一换掉;按住那一下用系统高亮反色画回来。
|
|
900
|
+
line 档的按下反色由家族的 forced-colors 段给 */
|
|
901
|
+
.xh-scope-tabs[data-part='root']:is([data-variant='card'], [data-variant='segment'])
|
|
902
|
+
.xh-scope-tabs[data-part='trigger']:not([data-disabled]):not([data-state='active']):is(:active, [data-pressed]) {
|
|
903
|
+
background: Highlight;
|
|
904
|
+
color: HighlightText;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
@media print {
|
|
909
|
+
/* 打印默认丢背景与投影:三档形态表达选中的三条通道(选中底、card 档的顶边条、
|
|
910
|
+
segment 档的浮起)在纸上一条都不剩,只有一条比别人深一点的字色。
|
|
911
|
+
改用下划线与字重表达同一件事,两者都不改盒子的高度 */
|
|
912
|
+
.xh-scope-tabs[data-part='trigger'][data-state='active'] {
|
|
913
|
+
font-weight: var(--xh-font-weight-semibold);
|
|
914
|
+
text-decoration: underline;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
/* 纸上翻不了页、关不了标签、也弹不出下拉,这几只钮不上纸 */
|
|
918
|
+
.xh-scope-tabs[data-part='prev-trigger'],
|
|
919
|
+
.xh-scope-tabs[data-part='next-trigger'],
|
|
920
|
+
.xh-scope-tabs[data-part='overflow-trigger'],
|
|
921
|
+
.xh-scope-tabs[data-part='close-trigger'] {
|
|
922
|
+
display: none;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
@media (forced-colors: active) {
|
|
927
|
+
/* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
|
|
928
|
+
字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
|
|
929
|
+
按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
|
|
930
|
+
禁用取 GrayText */
|
|
931
|
+
.xh-scope-tabs:is([data-part='prev-trigger'], [data-part='next-trigger'], [data-part='close-trigger'], [data-part='overflow-trigger']):empty::before {
|
|
932
|
+
forced-color-adjust: none;
|
|
933
|
+
background-color: ButtonText;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
.xh-scope-tabs:is([data-part='prev-trigger'], [data-part='next-trigger'], [data-part='close-trigger'], [data-part='overflow-trigger']):not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
|
|
937
|
+
background-color: HighlightText;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
.xh-scope-tabs:is([data-part='prev-trigger'], [data-part='next-trigger'], [data-part='close-trigger'], [data-part='overflow-trigger'])[data-disabled]:empty::before {
|
|
941
|
+
background-color: GrayText;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|