@xihan-ui/styles 1.0.0 → 1.1.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 +192 -0
- package/README.md +1 -1
- package/css/resizable.css +113 -0
- package/css/sortable.css +103 -0
- package/css/table.css +293 -2
- package/css/tabs.css +140 -1
- package/css/tree.css +129 -0
- package/index.css +2 -0
- package/index.unlayered.css +778 -3
- package/package.json +4 -2
package/index.unlayered.css
CHANGED
|
@@ -5369,6 +5369,119 @@ input[data-scope='mention'][data-part='input'] {
|
|
|
5369
5369
|
visibility: visible;
|
|
5370
5370
|
}
|
|
5371
5371
|
|
|
5372
|
+
/* styles/resizable.css */
|
|
5373
|
+
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
5374
|
+
[data-scope='resizable'] {
|
|
5375
|
+
--xh-resizable-skin: 1;
|
|
5376
|
+
}
|
|
5377
|
+
|
|
5378
|
+
/* 分工:**尺寸与位移**由连接层每帧写进内联样式(inline-size / block-size / left / top)。
|
|
5379
|
+
这份皮肤一条都不碰那四个——内联优先级更高,写了不但是死声明,
|
|
5380
|
+
还会在拖动的每一帧跟连接层抢位置。皮肤只管定位上下文、把手落位与状态表现。 */
|
|
5381
|
+
|
|
5382
|
+
/* 定位上下文,八向可调靠它才成立:
|
|
5383
|
+
推西边与北边时容器的起点会动,那段位移写成 left / top。relative 的 left / top
|
|
5384
|
+
是视觉位移、元素仍占原位,因此对边钉得住。改成 static 会让这两个方向只变尺寸不移位。 */
|
|
5385
|
+
[data-scope='resizable'][data-part='root'] {
|
|
5386
|
+
position: relative;
|
|
5387
|
+
/* 把层序关在容器里:把手的 1 / 2 只跟彼此比,不跟外面的层号打架 */
|
|
5388
|
+
isolation: isolate;
|
|
5389
|
+
box-sizing: border-box;
|
|
5390
|
+
}
|
|
5391
|
+
|
|
5392
|
+
/* 调整期间关掉选中:把手一按就会把容器里的文字刷成选中态 */
|
|
5393
|
+
[data-scope='resizable'][data-part='root'][data-resizing] {
|
|
5394
|
+
user-select: none;
|
|
5395
|
+
}
|
|
5396
|
+
|
|
5397
|
+
[data-scope='resizable'][data-part='root'][hidden] {
|
|
5398
|
+
display: none;
|
|
5399
|
+
}
|
|
5400
|
+
|
|
5401
|
+
/* 把手压在边上,往外挪半个身位,两侧各留出一点可抓的余量——
|
|
5402
|
+
贴着边只有一两个像素能按到。落位按 data-edge 分派。 */
|
|
5403
|
+
[data-scope='resizable'][data-part='handle'] {
|
|
5404
|
+
position: absolute;
|
|
5405
|
+
z-index: 1;
|
|
5406
|
+
display: block;
|
|
5407
|
+
touch-action: none;
|
|
5408
|
+
}
|
|
5409
|
+
|
|
5410
|
+
[data-scope='resizable'][data-part='handle'][hidden] {
|
|
5411
|
+
display: none;
|
|
5412
|
+
}
|
|
5413
|
+
|
|
5414
|
+
/* 四条边:各占一整条,厚度是可抓的余量 */
|
|
5415
|
+
[data-scope='resizable'][data-part='handle'][data-edge='n'],
|
|
5416
|
+
[data-scope='resizable'][data-part='handle'][data-edge='s'] {
|
|
5417
|
+
inset-inline: var(--xh-resizable-grip, var(--xh-space-2));
|
|
5418
|
+
block-size: var(--xh-resizable-grip, var(--xh-space-2));
|
|
5419
|
+
}
|
|
5420
|
+
|
|
5421
|
+
[data-scope='resizable'][data-part='handle'][data-edge='e'],
|
|
5422
|
+
[data-scope='resizable'][data-part='handle'][data-edge='w'] {
|
|
5423
|
+
inset-block: var(--xh-resizable-grip, var(--xh-space-2));
|
|
5424
|
+
inline-size: var(--xh-resizable-grip, var(--xh-space-2));
|
|
5425
|
+
}
|
|
5426
|
+
|
|
5427
|
+
/* 落位用逻辑属性:e 说的是行尾侧,从右往左排版时它就该落在屏幕左边——
|
|
5428
|
+
机器那边也是把逻辑边翻成物理边再算几何的,两处同源 */
|
|
5429
|
+
[data-scope='resizable'][data-part='handle'][data-edge='n'] {
|
|
5430
|
+
inset-block-start: calc(var(--xh-resizable-grip, var(--xh-space-2)) / -2);
|
|
5431
|
+
}
|
|
5432
|
+
|
|
5433
|
+
[data-scope='resizable'][data-part='handle'][data-edge='s'] {
|
|
5434
|
+
inset-block-end: calc(var(--xh-resizable-grip, var(--xh-space-2)) / -2);
|
|
5435
|
+
}
|
|
5436
|
+
|
|
5437
|
+
[data-scope='resizable'][data-part='handle'][data-edge='e'] {
|
|
5438
|
+
inset-inline-end: calc(var(--xh-resizable-grip, var(--xh-space-2)) / -2);
|
|
5439
|
+
}
|
|
5440
|
+
|
|
5441
|
+
[data-scope='resizable'][data-part='handle'][data-edge='w'] {
|
|
5442
|
+
inset-inline-start: calc(var(--xh-resizable-grip, var(--xh-space-2)) / -2);
|
|
5443
|
+
}
|
|
5444
|
+
|
|
5445
|
+
/* 四个角:压在两条边的交点上,盖过相邻两条边(它们同时动两轴) */
|
|
5446
|
+
[data-scope='resizable'][data-part='handle'][data-edge='ne'],
|
|
5447
|
+
[data-scope='resizable'][data-part='handle'][data-edge='nw'],
|
|
5448
|
+
[data-scope='resizable'][data-part='handle'][data-edge='se'],
|
|
5449
|
+
[data-scope='resizable'][data-part='handle'][data-edge='sw'] {
|
|
5450
|
+
z-index: 2;
|
|
5451
|
+
inline-size: var(--xh-resizable-corner, var(--xh-space-3));
|
|
5452
|
+
block-size: var(--xh-resizable-corner, var(--xh-space-3));
|
|
5453
|
+
}
|
|
5454
|
+
|
|
5455
|
+
[data-scope='resizable'][data-part='handle'][data-edge='nw'] {
|
|
5456
|
+
inset-block-start: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
|
|
5457
|
+
inset-inline-start: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
|
|
5458
|
+
}
|
|
5459
|
+
|
|
5460
|
+
[data-scope='resizable'][data-part='handle'][data-edge='ne'] {
|
|
5461
|
+
inset-block-start: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
|
|
5462
|
+
inset-inline-end: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
|
|
5463
|
+
}
|
|
5464
|
+
|
|
5465
|
+
[data-scope='resizable'][data-part='handle'][data-edge='sw'] {
|
|
5466
|
+
inset-block-end: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
|
|
5467
|
+
inset-inline-start: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
|
|
5468
|
+
}
|
|
5469
|
+
|
|
5470
|
+
[data-scope='resizable'][data-part='handle'][data-edge='se'] {
|
|
5471
|
+
inset-block-end: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
|
|
5472
|
+
inset-inline-end: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
|
|
5473
|
+
}
|
|
5474
|
+
|
|
5475
|
+
[data-scope='resizable'][data-part='handle']:focus-visible {
|
|
5476
|
+
outline: var(--xh-ring-width) solid var(--xh-ring-focus);
|
|
5477
|
+
outline-offset: var(--xh-ring-offset);
|
|
5478
|
+
}
|
|
5479
|
+
|
|
5480
|
+
/* 没开放的边不显示把手:留着一个抓不动的区域只会让人反复去试 */
|
|
5481
|
+
[data-scope='resizable'][data-part='handle'][data-disabled] {
|
|
5482
|
+
display: none;
|
|
5483
|
+
}
|
|
5484
|
+
|
|
5372
5485
|
/* styles/result.css */
|
|
5373
5486
|
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
5374
5487
|
[data-scope='result'] {
|
|
@@ -19340,6 +19453,109 @@ input[data-scope='mention'][data-part='input'] {
|
|
|
19340
19453
|
/* hidden-input 是 type=hidden 的原生输入,浏览器本就不渲染它,
|
|
19341
19454
|
这里一条声明都不给:给了 display / 尺寸反而会把它拽回布局里,在拇指内部撑出一块空白。 */
|
|
19342
19455
|
|
|
19456
|
+
/* styles/sortable.css */
|
|
19457
|
+
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
19458
|
+
[data-scope='sortable'] {
|
|
19459
|
+
--xh-sortable-skin: 1;
|
|
19460
|
+
}
|
|
19461
|
+
|
|
19462
|
+
/* 分工:**每一项的位移**由连接层每帧写进内联 transform(让位与跟手都在那儿算)。
|
|
19463
|
+
这份皮肤一条都不碰 transform——内联优先级更高,写了不但是死声明,
|
|
19464
|
+
还会在拖动的每一帧跟连接层抢位置。皮肤只管排布方向、间距、光标与状态表现。 */
|
|
19465
|
+
|
|
19466
|
+
[data-scope='sortable'][data-part='root'] {
|
|
19467
|
+
display: flex;
|
|
19468
|
+
gap: var(--xh-sortable-gap, var(--xh-space-2));
|
|
19469
|
+
}
|
|
19470
|
+
|
|
19471
|
+
/* 拖动期间关掉选中:整项可拖时按下不 preventDefault,不关这条会一路刷蓝 */
|
|
19472
|
+
[data-scope='sortable'][data-part='root'][data-dragging] {
|
|
19473
|
+
user-select: none;
|
|
19474
|
+
}
|
|
19475
|
+
|
|
19476
|
+
[data-scope='sortable'][data-part='root'][data-orientation='vertical'] {
|
|
19477
|
+
flex-direction: column;
|
|
19478
|
+
}
|
|
19479
|
+
|
|
19480
|
+
[data-scope='sortable'][data-part='root'][data-orientation='horizontal'] {
|
|
19481
|
+
flex-direction: row;
|
|
19482
|
+
}
|
|
19483
|
+
|
|
19484
|
+
/* 换行网格:主轴横排、允许折行,落点按最近中心判,与单轴那两档是不同的判据 */
|
|
19485
|
+
[data-scope='sortable'][data-part='root'][data-orientation='both'] {
|
|
19486
|
+
flex-direction: row;
|
|
19487
|
+
flex-wrap: wrap;
|
|
19488
|
+
}
|
|
19489
|
+
|
|
19490
|
+
/* 项里面放什么、怎么排全是使用者的事:这里不给 display 也不给间距。
|
|
19491
|
+
给了会盖掉使用者自己的单元格布局——网格里的一格被压成 flex 行之后就不再撑满,
|
|
19492
|
+
看起来像是尺寸算错了。皮肤只管拖起来那一项的视觉反馈。 */
|
|
19493
|
+
|
|
19494
|
+
/* 让位期间关掉过渡,跟手的那一项才不会慢半拍粘在指针后面。
|
|
19495
|
+
其余项反过来要过渡:它们是被让开的,瞬移会看不出发生了什么。 */
|
|
19496
|
+
[data-scope='sortable'][data-part='root'][data-dragging] [data-part='item']:not([data-dragging]) {
|
|
19497
|
+
transition: transform var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
|
|
19498
|
+
}
|
|
19499
|
+
|
|
19500
|
+
[data-scope='sortable'][data-part='item'][data-dragging] {
|
|
19501
|
+
/* 拖起来的那一项浮在上面。层级由连接层写内联,这里只管观感 */
|
|
19502
|
+
box-shadow: var(--xh-sortable-item-shadow-dragging, var(--xh-elevation-raised));
|
|
19503
|
+
opacity: var(--xh-sortable-item-opacity-dragging, 0.9);
|
|
19504
|
+
}
|
|
19505
|
+
|
|
19506
|
+
[data-scope='sortable'][data-part='item-handle'] {
|
|
19507
|
+
display: inline-flex;
|
|
19508
|
+
align-items: center;
|
|
19509
|
+
justify-content: center;
|
|
19510
|
+
flex: none;
|
|
19511
|
+
inline-size: var(--xh-sortable-handle-size, var(--xh-control-action-size));
|
|
19512
|
+
block-size: var(--xh-sortable-handle-size, var(--xh-control-action-size));
|
|
19513
|
+
padding: 0;
|
|
19514
|
+
border: 0;
|
|
19515
|
+
border-radius: var(--xh-sortable-handle-radius, var(--xh-shape-control));
|
|
19516
|
+
background: transparent;
|
|
19517
|
+
color: var(--xh-sortable-handle-fg, var(--xh-fg-muted));
|
|
19518
|
+
cursor: grab;
|
|
19519
|
+
}
|
|
19520
|
+
|
|
19521
|
+
[data-scope='sortable'][data-part='item-handle']:hover {
|
|
19522
|
+
background: var(--xh-sortable-handle-bg-hover, var(--xh-bg-subtle-hover));
|
|
19523
|
+
color: var(--xh-sortable-handle-fg-hover, var(--xh-fg-default));
|
|
19524
|
+
}
|
|
19525
|
+
|
|
19526
|
+
[data-scope='sortable'][data-part='item-handle'][data-dragging] {
|
|
19527
|
+
cursor: grabbing;
|
|
19528
|
+
}
|
|
19529
|
+
|
|
19530
|
+
[data-scope='sortable'][data-part='item-handle']:focus-visible {
|
|
19531
|
+
outline: var(--xh-ring-width) solid var(--xh-ring-focus);
|
|
19532
|
+
outline-offset: var(--xh-ring-offset);
|
|
19533
|
+
}
|
|
19534
|
+
|
|
19535
|
+
[data-scope='sortable'][data-part='item-handle'][aria-disabled='true'] {
|
|
19536
|
+
cursor: not-allowed;
|
|
19537
|
+
color: var(--xh-sortable-handle-fg-disabled, var(--xh-fg-disabled));
|
|
19538
|
+
}
|
|
19539
|
+
|
|
19540
|
+
/* 活动区域只说给读屏听,不占版面。声明与 shared/visually-hidden.ts 逐条同值。 */
|
|
19541
|
+
[data-scope='sortable'][data-part='live-region'] {
|
|
19542
|
+
position: absolute;
|
|
19543
|
+
inline-size: 1px;
|
|
19544
|
+
block-size: 1px;
|
|
19545
|
+
padding: 0;
|
|
19546
|
+
margin: -1px;
|
|
19547
|
+
overflow: hidden;
|
|
19548
|
+
clip-path: inset(50%);
|
|
19549
|
+
white-space: nowrap;
|
|
19550
|
+
border: 0;
|
|
19551
|
+
}
|
|
19552
|
+
/* 给了 display 的角色节点必须补这条:display 声明会盖掉 UA 的 [hidden]{display:none},
|
|
19553
|
+
不补的话作者给节点加 hidden 后它照样显示 */
|
|
19554
|
+
[data-scope='sortable'][data-part='root'][hidden],
|
|
19555
|
+
[data-scope='sortable'][data-part='item-handle'][hidden] {
|
|
19556
|
+
display: none;
|
|
19557
|
+
}
|
|
19558
|
+
|
|
19343
19559
|
/* styles/splitter.css */
|
|
19344
19560
|
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
19345
19561
|
[data-scope='splitter'] {
|
|
@@ -20114,8 +20330,11 @@ input[data-scope='mention'][data-part='input'] {
|
|
|
20114
20330
|
}
|
|
20115
20331
|
|
|
20116
20332
|
/* —— 三个可叠加的外观开关 —— */
|
|
20117
|
-
/*
|
|
20118
|
-
|
|
20333
|
+
/* 斑马纹:表体偶数行换一层浅底。它是最底下那一档,悬停、选中、落点都要盖得过它,
|
|
20334
|
+
所以祖先链与 :nth-of-type 都收进 :where()——特指度落到与基础底同档(0-2-0),
|
|
20335
|
+
只靠排在基础底之后压过它一条。照字面写祖先链是 0-8-0,比悬停与选中都高,
|
|
20336
|
+
斑马表里偶数行会既不响应悬停也显不出选中 */
|
|
20337
|
+
:where([data-scope='table'][data-part='root'][data-striped] [data-scope='table'][data-part='body']) > [data-scope='table'][data-part='row']:where(:nth-of-type(even)) {
|
|
20119
20338
|
background: var(--xh-table-row-bg-striped, var(--xh-bg-subtle));
|
|
20120
20339
|
}
|
|
20121
20340
|
|
|
@@ -20260,6 +20479,294 @@ input[data-scope='mention'][data-part='input'] {
|
|
|
20260
20479
|
display: none;
|
|
20261
20480
|
}
|
|
20262
20481
|
|
|
20482
|
+
/* 列宽把手贴在表头格的行尾侧。它压在相邻两列的接缝上,因此往外挪半个身位,
|
|
20483
|
+
两边各留出一点可抓的余量——贴着边只有一两个像素能按到。 */
|
|
20484
|
+
[data-scope='table'][data-part='column-resize-trigger'] {
|
|
20485
|
+
display: inline-flex;
|
|
20486
|
+
flex: none;
|
|
20487
|
+
align-self: stretch;
|
|
20488
|
+
inline-size: var(--xh-table-resize-width, var(--xh-space-2));
|
|
20489
|
+
/* 推到行尾侧。把手在标记里是表头格的最后一个孩子,auto 外边距把它顶到那一头,
|
|
20490
|
+
不必给每个表头格加定位上下文——那条会落到所有既有表格上 */
|
|
20491
|
+
margin-inline-start: auto;
|
|
20492
|
+
align-items: center;
|
|
20493
|
+
justify-content: center;
|
|
20494
|
+
cursor: col-resize;
|
|
20495
|
+
touch-action: none;
|
|
20496
|
+
}
|
|
20497
|
+
|
|
20498
|
+
[data-scope='table'][data-part='column-resize-trigger'][hidden] {
|
|
20499
|
+
display: none;
|
|
20500
|
+
}
|
|
20501
|
+
|
|
20502
|
+
/* 接缝上那条线。平时借表头的分隔色,按住与聚焦时换成品牌色好认 */
|
|
20503
|
+
[data-scope='table'][data-part='column-resize-trigger']::after {
|
|
20504
|
+
content: '';
|
|
20505
|
+
display: block;
|
|
20506
|
+
inline-size: var(--xh-table-resize-line, var(--xh-stroke-thin));
|
|
20507
|
+
block-size: var(--xh-table-resize-line-length, 60%);
|
|
20508
|
+
border-radius: var(--xh-table-resize-radius, var(--xh-shape-pill));
|
|
20509
|
+
background: var(--xh-table-resize-fg, var(--xh-border-default));
|
|
20510
|
+
}
|
|
20511
|
+
|
|
20512
|
+
[data-scope='table'][data-part='column-resize-trigger']:hover::after,
|
|
20513
|
+
[data-scope='table'][data-part='column-resize-trigger'][data-resizing]::after {
|
|
20514
|
+
background: var(--xh-table-resize-fg-active, var(--xh-border-control-focus));
|
|
20515
|
+
block-size: 100%;
|
|
20516
|
+
}
|
|
20517
|
+
|
|
20518
|
+
[data-scope='table'][data-part='column-resize-trigger']:focus-visible {
|
|
20519
|
+
outline: var(--xh-ring-width) solid var(--xh-ring-focus);
|
|
20520
|
+
outline-offset: var(--xh-ring-offset);
|
|
20521
|
+
}
|
|
20522
|
+
|
|
20523
|
+
/* 不可改宽的列不显示把手:留着一条抓不动的线只会让人反复去试 */
|
|
20524
|
+
[data-scope='table'][data-part='column-resize-trigger'][data-disabled] {
|
|
20525
|
+
display: none;
|
|
20526
|
+
}
|
|
20527
|
+
|
|
20528
|
+
/* 列拖拽把手贴在表头格的行首侧,位置由源码顺序定,不写 auto 外边距:
|
|
20529
|
+
同一个表头格里的改宽把手已经用 margin-inline-start: auto 把自己顶到行尾侧,
|
|
20530
|
+
再添一条 auto,剩余空白会在两条外边距之间平分,两个把手谁都到不了自己那一头。
|
|
20531
|
+
待在行首侧还有一层好处:它的位置与这一列有多宽、格里有没有排序把手都无关 */
|
|
20532
|
+
[data-scope='table'][data-part='column-drag-trigger'] {
|
|
20533
|
+
display: inline-flex;
|
|
20534
|
+
flex: none;
|
|
20535
|
+
align-items: center;
|
|
20536
|
+
justify-content: center;
|
|
20537
|
+
inline-size: var(--xh-table-drag-size, var(--xh-control-indicator-size));
|
|
20538
|
+
block-size: var(--xh-table-drag-size, var(--xh-control-indicator-size));
|
|
20539
|
+
border-radius: var(--xh-table-trigger-radius, var(--xh-shape-control));
|
|
20540
|
+
color: var(--xh-table-drag-fg, var(--xh-fg-subtle));
|
|
20541
|
+
cursor: grab;
|
|
20542
|
+
/* 关掉这一轴的默认手势:不关的话触屏上手指一划就被系统当成滚动收走 */
|
|
20543
|
+
touch-action: none;
|
|
20544
|
+
}
|
|
20545
|
+
|
|
20546
|
+
[data-scope='table'][data-part='column-drag-trigger'][hidden] {
|
|
20547
|
+
display: none;
|
|
20548
|
+
}
|
|
20549
|
+
|
|
20550
|
+
/* 抓手是两条竖线:盒子取边框盒,两侧描边就是那两条线,宽高与线宽都走令牌。
|
|
20551
|
+
:empty 守卫让作者塞进来的图标整个顶掉它,而不是两份叠在一起 */
|
|
20552
|
+
[data-scope='table'][data-part='column-drag-trigger']:empty::after {
|
|
20553
|
+
content: '';
|
|
20554
|
+
display: block;
|
|
20555
|
+
inline-size: var(--xh-table-drag-grip-w, var(--xh-space-1));
|
|
20556
|
+
block-size: var(--xh-table-drag-grip-h, var(--xh-space-2));
|
|
20557
|
+
border-inline: var(--xh-stroke-thin) solid currentColor;
|
|
20558
|
+
}
|
|
20559
|
+
|
|
20560
|
+
[data-scope='table'][data-part='column-drag-trigger']:not([data-disabled]):hover,
|
|
20561
|
+
[data-scope='table'][data-part='column-drag-trigger'][data-dragging] {
|
|
20562
|
+
color: var(--xh-table-drag-fg-active, var(--xh-fg-default));
|
|
20563
|
+
}
|
|
20564
|
+
|
|
20565
|
+
[data-scope='table'][data-part='column-drag-trigger'][data-dragging] {
|
|
20566
|
+
cursor: grabbing;
|
|
20567
|
+
}
|
|
20568
|
+
|
|
20569
|
+
/* 不可拖的列照样带一个把手,这里保住它的位置、只把它压到禁用色。
|
|
20570
|
+
收成 display: none 是不行的:把手在行首侧,藏掉之后同一行里能拖与不能拖的两列,
|
|
20571
|
+
标题起点会错开一格 */
|
|
20572
|
+
[data-scope='table'][data-part='column-drag-trigger'][data-disabled] {
|
|
20573
|
+
color: var(--xh-table-drag-fg-disabled, var(--xh-fg-disabled));
|
|
20574
|
+
cursor: not-allowed;
|
|
20575
|
+
}
|
|
20576
|
+
|
|
20577
|
+
[data-scope='table'][data-part='column-drag-trigger']:focus-visible {
|
|
20578
|
+
outline: var(--xh-ring-width) solid var(--xh-ring-focus);
|
|
20579
|
+
outline-offset: var(--xh-ring-offset);
|
|
20580
|
+
}
|
|
20581
|
+
|
|
20582
|
+
/* 落点指示线:拖到哪一列的哪一侧,线就画在那一列的那条边上。列头与表体的格子一起画,
|
|
20583
|
+
线贯穿整张表才看得出这一列要落到哪儿。
|
|
20584
|
+
定位上下文由这条规则自己给:列头与格子平时都不定位,缺了它伪元素会一路上溯到表格根,
|
|
20585
|
+
线就飞到整张表的左上角去。
|
|
20586
|
+
冻结列排除在外:它靠 position: sticky 钉住,在这儿改成 relative 会把吸附顶掉;
|
|
20587
|
+
而冻结列既不可拖也不做落点,排除掉不会漏画任何一条线 */
|
|
20588
|
+
[data-scope='table'][data-part='column-header'][data-drop]:not([data-frozen]),
|
|
20589
|
+
[data-scope='table'][data-part='cell'][data-drop]:not([data-frozen]) {
|
|
20590
|
+
position: relative;
|
|
20591
|
+
}
|
|
20592
|
+
|
|
20593
|
+
/* 线整条画在盒内:列头与格子都收 overflow: hidden,压着边画会被裁掉半条 */
|
|
20594
|
+
[data-scope='table'][data-part='column-header'][data-drop]:not([data-frozen])::after,
|
|
20595
|
+
[data-scope='table'][data-part='cell'][data-drop]:not([data-frozen])::after {
|
|
20596
|
+
content: '';
|
|
20597
|
+
position: absolute;
|
|
20598
|
+
inset-block: 0;
|
|
20599
|
+
inline-size: var(--xh-table-drop-line, var(--xh-stroke-thick));
|
|
20600
|
+
background: var(--xh-table-drop-fg, var(--xh-border-control-focus));
|
|
20601
|
+
}
|
|
20602
|
+
|
|
20603
|
+
/* 落在哪一侧走逻辑属性:rtl 下 before 自己就换到右边去了。
|
|
20604
|
+
换成 box-shadow: inset 的话偏移量是物理的,书写方向一反 before 与 after 就调个个儿 */
|
|
20605
|
+
[data-scope='table'][data-part='column-header'][data-drop='before']:not([data-frozen])::after,
|
|
20606
|
+
[data-scope='table'][data-part='cell'][data-drop='before']:not([data-frozen])::after {
|
|
20607
|
+
inset-inline-start: 0;
|
|
20608
|
+
}
|
|
20609
|
+
|
|
20610
|
+
[data-scope='table'][data-part='column-header'][data-drop='after']:not([data-frozen])::after,
|
|
20611
|
+
[data-scope='table'][data-part='cell'][data-drop='after']:not([data-frozen])::after {
|
|
20612
|
+
inset-inline-end: 0;
|
|
20613
|
+
}
|
|
20614
|
+
|
|
20615
|
+
/* 被拖的那一列整列压暗,让人看得出正在搬的是它。这里只动 opacity 与 user-select,
|
|
20616
|
+
一个 transform 都不写:冻结列是 position: sticky,祖先一有 transform 就掉出吸附。
|
|
20617
|
+
位置的事全交给落点指示线,被拖的列自己原地不动 */
|
|
20618
|
+
[data-scope='table'][data-part='column-header'][data-dragging],
|
|
20619
|
+
[data-scope='table'][data-part='cell'][data-dragging] {
|
|
20620
|
+
opacity: var(--xh-table-dragging-opacity, var(--xh-state-dragging-opacity));
|
|
20621
|
+
user-select: none;
|
|
20622
|
+
}
|
|
20623
|
+
|
|
20624
|
+
/* —— 行拖拽排序 —— */
|
|
20625
|
+
/* 整行都是拖动源,光标换成抓手告诉人这一行按得动。
|
|
20626
|
+
这条不写 touch-action:整行关掉纵向手势,表格自己就滚不动了;
|
|
20627
|
+
触屏那一路交给下面那块专属把手 */
|
|
20628
|
+
[data-scope='table'][data-part='row'][data-row-draggable] {
|
|
20629
|
+
cursor: grab;
|
|
20630
|
+
}
|
|
20631
|
+
|
|
20632
|
+
/* 行拖拽把手:行里的一小块专属拖动区,按下即拖。触屏靠它起手,
|
|
20633
|
+
代价只是这一小块地方不再跟着表格滚。整行起手那一路原样保留,把手是叠加的第二个入口。
|
|
20634
|
+
touch-action 不在这儿写:连接层按「拖不动就不写」把它写进了内联 style,
|
|
20635
|
+
皮肤再写一遍会盖掉那份条件判断,让不可拖的行也白白让出滚动 */
|
|
20636
|
+
[data-scope='table'][data-part='row-drag-trigger'] {
|
|
20637
|
+
display: inline-flex;
|
|
20638
|
+
flex: none;
|
|
20639
|
+
/* 行是 align-items: stretch 的 flex 容器,不自己居中就会被拉成整行高 */
|
|
20640
|
+
align-self: center;
|
|
20641
|
+
align-items: center;
|
|
20642
|
+
justify-content: center;
|
|
20643
|
+
inline-size: var(--xh-table-row-drag-size, var(--xh-control-indicator-size));
|
|
20644
|
+
block-size: var(--xh-table-row-drag-size, var(--xh-control-indicator-size));
|
|
20645
|
+
border-radius: var(--xh-table-trigger-radius, var(--xh-shape-control));
|
|
20646
|
+
color: var(--xh-table-row-drag-fg, var(--xh-fg-subtle));
|
|
20647
|
+
cursor: grab;
|
|
20648
|
+
}
|
|
20649
|
+
|
|
20650
|
+
[data-scope='table'][data-part='row-drag-trigger'][hidden] {
|
|
20651
|
+
display: none;
|
|
20652
|
+
}
|
|
20653
|
+
|
|
20654
|
+
/* 抓手是两条横线:盒子取边框盒,块向两侧的描边就是那两条线,宽高与线宽都走令牌。
|
|
20655
|
+
线的走向与能拖的方向垂直——行沿块向上下排,画横线;列沿行向左右排,那边画的是竖线。
|
|
20656
|
+
两处都用逻辑属性,书写模式一换,线跟着排列轴自己转过去。
|
|
20657
|
+
:empty 守卫让作者塞进来的图标整个顶掉它,而不是两份叠在一起 */
|
|
20658
|
+
[data-scope='table'][data-part='row-drag-trigger']:empty::after {
|
|
20659
|
+
content: '';
|
|
20660
|
+
display: block;
|
|
20661
|
+
inline-size: var(--xh-table-row-drag-grip-long, var(--xh-space-2));
|
|
20662
|
+
block-size: var(--xh-table-row-drag-grip-short, var(--xh-space-1));
|
|
20663
|
+
border-block: var(--xh-stroke-thin) solid currentColor;
|
|
20664
|
+
}
|
|
20665
|
+
|
|
20666
|
+
[data-scope='table'][data-part='row-drag-trigger']:not([data-disabled]):hover,
|
|
20667
|
+
[data-scope='table'][data-part='row-drag-trigger'][data-dragging] {
|
|
20668
|
+
color: var(--xh-table-row-drag-fg-active, var(--xh-fg-default));
|
|
20669
|
+
}
|
|
20670
|
+
|
|
20671
|
+
[data-scope='table'][data-part='row-drag-trigger'][data-dragging] {
|
|
20672
|
+
cursor: grabbing;
|
|
20673
|
+
}
|
|
20674
|
+
|
|
20675
|
+
/* 不可拖的行照样带一个把手,这里保住它的位置、只把它压到禁用色。
|
|
20676
|
+
收成 display: none 是不行的:把手占着行首那一格,藏掉之后同一张表里能拖与不能拖的两行,
|
|
20677
|
+
首列内容的起点会错开一格 */
|
|
20678
|
+
[data-scope='table'][data-part='row-drag-trigger'][data-disabled] {
|
|
20679
|
+
color: var(--xh-table-row-drag-fg-disabled, var(--xh-fg-disabled));
|
|
20680
|
+
cursor: not-allowed;
|
|
20681
|
+
}
|
|
20682
|
+
|
|
20683
|
+
[data-scope='table'][data-part='row-drag-trigger']:focus-visible {
|
|
20684
|
+
outline: var(--xh-ring-width) solid var(--xh-ring-focus);
|
|
20685
|
+
outline-offset: var(--xh-ring-offset);
|
|
20686
|
+
}
|
|
20687
|
+
|
|
20688
|
+
/* 被拖的行整行压暗,与被拖的列同一档透明度。这里只动 opacity、cursor 与 user-select,
|
|
20689
|
+
一个 transform 都不写:斑马纹按 nth-of-type 算、行间线按兄弟选择器算,两者认的都是 DOM 位置,
|
|
20690
|
+
跟手让位会让它们在拖动全程与行错开。位置的事全交给落点指示线 */
|
|
20691
|
+
[data-scope='table'][data-part='row'][data-dragging] {
|
|
20692
|
+
opacity: var(--xh-table-dragging-opacity, var(--xh-state-dragging-opacity));
|
|
20693
|
+
cursor: grabbing;
|
|
20694
|
+
user-select: none;
|
|
20695
|
+
}
|
|
20696
|
+
|
|
20697
|
+
/* 详情行与它的数据行是同一块,一起压暗 */
|
|
20698
|
+
[data-scope='table'][data-part='expanded-row'][data-dragging] {
|
|
20699
|
+
opacity: var(--xh-table-dragging-opacity, var(--xh-state-dragging-opacity));
|
|
20700
|
+
}
|
|
20701
|
+
|
|
20702
|
+
/* 落点指示:插到两行之间画一条横线,落进一行里面画一整圈。两档都靠伪元素画,
|
|
20703
|
+
定位上下文只给带 data-drop 的那一行:缺了它伪元素会一路上溯到表格根,指示飞到整张表的左上角;
|
|
20704
|
+
写到所有行上则是给每一行都多担一份,而落点同一时刻只有一个 */
|
|
20705
|
+
[data-scope='table'][data-part='row'][data-drop] {
|
|
20706
|
+
position: relative;
|
|
20707
|
+
}
|
|
20708
|
+
|
|
20709
|
+
/* 线贯穿整行宽度,并且要压在单元格之上:行是 flex 容器,横向吸附的格子带着层号,
|
|
20710
|
+
伪元素不抬到它上面就会被盖住。
|
|
20711
|
+
选择器逐值列出前后两档,不写成裸 [data-drop]:换父那一档用的是同一个 ::after,
|
|
20712
|
+
裸写会让它先摊上一条线高的横条,再由下面那块整个改写 */
|
|
20713
|
+
[data-scope='table'][data-part='row']:is([data-drop='before'], [data-drop='after'])::after {
|
|
20714
|
+
content: '';
|
|
20715
|
+
position: absolute;
|
|
20716
|
+
z-index: calc(var(--xh-table-sticky-column-layer, 1) + 1);
|
|
20717
|
+
inset-inline: 0;
|
|
20718
|
+
block-size: var(--xh-table-drop-line, var(--xh-stroke-thick));
|
|
20719
|
+
background: var(--xh-table-drop-fg, var(--xh-border-control-focus));
|
|
20720
|
+
}
|
|
20721
|
+
|
|
20722
|
+
/* 线整条画在行内,不压着边。压着边画的话,首行那条上沿线会被表格根的圆角与滚动裁掉半条 */
|
|
20723
|
+
[data-scope='table'][data-part='row'][data-drop='before']::after {
|
|
20724
|
+
inset-block-start: 0;
|
|
20725
|
+
}
|
|
20726
|
+
|
|
20727
|
+
[data-scope='table'][data-part='row'][data-drop='after']::after {
|
|
20728
|
+
inset-block-end: 0;
|
|
20729
|
+
}
|
|
20730
|
+
|
|
20731
|
+
/* 落进这一行里面(这一行成为新的父):整行淡底,与上下沿那条横线一眼分得开。
|
|
20732
|
+
底色打在行上而不是伪元素上,横向吸附的格子取的是 background: inherit,跟着一起换色,
|
|
20733
|
+
横向滚过去时冻结列不会留下一块没上色的补丁。
|
|
20734
|
+
祖先写到 root 与 body 两层,是为把特指度抬到 0-8-0:拖动时指针必然停在落点这一行上、
|
|
20735
|
+
悬停恒真,而悬停那条是 0-6-0、选中那条是 0-3-0,少写一层祖先这块淡底就会被那两档盖掉。
|
|
20736
|
+
禁用的行不接换父落点,:not([data-disabled]) 不会漏画任何一处高亮 */
|
|
20737
|
+
[data-scope='table'][data-part='root'] [data-scope='table'][data-part='body'] > [data-scope='table'][data-part='row'][data-drop='inside']:not([data-disabled]) {
|
|
20738
|
+
background: var(--xh-table-drop-inside-bg, var(--xh-bg-brand-subtle));
|
|
20739
|
+
}
|
|
20740
|
+
|
|
20741
|
+
/* 换父那一档的描边:与底色分两层画,因为它得压在横向吸附的格子之上——
|
|
20742
|
+
格子带着层号,画在行自己的背景层上会被首尾的冻结列盖掉半圈。
|
|
20743
|
+
零偏移的内投影四边同时着色、不涉及方向,书写模式一换也不用调;
|
|
20744
|
+
整圈画在行内不压着边,与上下沿那条横线同一口径。
|
|
20745
|
+
行上不写 transform:冻结列是 position: sticky,祖先一有 transform 就掉出吸附 */
|
|
20746
|
+
[data-scope='table'][data-part='row'][data-drop='inside']::after {
|
|
20747
|
+
content: '';
|
|
20748
|
+
position: absolute;
|
|
20749
|
+
z-index: calc(var(--xh-table-sticky-column-layer, 1) + 1);
|
|
20750
|
+
inset: 0;
|
|
20751
|
+
box-shadow: inset 0 0 0 var(--xh-table-drop-line, var(--xh-stroke-thick))
|
|
20752
|
+
var(--xh-table-drop-fg, var(--xh-border-control-focus));
|
|
20753
|
+
/* 这一层盖满整行,让它不接指针,落点判定照旧落到行与格子上 */
|
|
20754
|
+
pointer-events: none;
|
|
20755
|
+
}
|
|
20756
|
+
|
|
20757
|
+
/* 活动区域只说给读屏听,不占版面。声明与 shared/visually-hidden.ts 逐条同值。 */
|
|
20758
|
+
[data-scope='table'][data-part='live-region'] {
|
|
20759
|
+
position: absolute;
|
|
20760
|
+
inline-size: 1px;
|
|
20761
|
+
block-size: 1px;
|
|
20762
|
+
padding: 0;
|
|
20763
|
+
margin: -1px;
|
|
20764
|
+
overflow: hidden;
|
|
20765
|
+
clip-path: inset(50%);
|
|
20766
|
+
white-space: nowrap;
|
|
20767
|
+
border: 0;
|
|
20768
|
+
}
|
|
20769
|
+
|
|
20263
20770
|
/* 排序方向用箭头字形表出来:aria-sort 只报给读屏,视觉侧也得有对应的东西 */
|
|
20264
20771
|
[data-scope='table'][data-part='sort-trigger']::after {
|
|
20265
20772
|
color: var(--xh-table-sort-fg, var(--xh-fg-subtle));
|
|
@@ -20559,11 +21066,150 @@ input[data-scope='mention'][data-part='input'] {
|
|
|
20559
21066
|
outline-offset: var(--xh-ring-offset);
|
|
20560
21067
|
}
|
|
20561
21068
|
|
|
21069
|
+
/* —— 标签拖拽换位 —— */
|
|
21070
|
+
/* 整张标签都是拖动源,光标换成抓手告诉人这张标签按得动。
|
|
21071
|
+
这条不写 touch-action:整张标签关掉手势,标签带自己就滚不动了;
|
|
21072
|
+
触屏那一路交给下面那块专属把手 */
|
|
21073
|
+
[data-scope='tabs'][data-part='trigger'][data-draggable] {
|
|
21074
|
+
cursor: grab;
|
|
21075
|
+
}
|
|
21076
|
+
|
|
21077
|
+
/* 标签拖拽把手:标签里的一小块专属拖动区,按下即拖。触屏靠它起手,
|
|
21078
|
+
代价只是这一小块地方不再跟着标签带滚。整张标签起手那一路原样保留,把手是叠加的第二个入口。
|
|
21079
|
+
touch-action 不在这儿写:连接层按「拖不动就不写」把它写进了内联 style,
|
|
21080
|
+
皮肤再写一遍会盖掉那份条件判断,让不可拖的标签也白白让出滚动 */
|
|
21081
|
+
[data-scope='tabs'][data-part='tab-drag-trigger'] {
|
|
21082
|
+
display: inline-flex;
|
|
21083
|
+
flex: none;
|
|
21084
|
+
align-items: center;
|
|
21085
|
+
justify-content: center;
|
|
21086
|
+
inline-size: var(--xh-tabs-drag-size, var(--xh-control-indicator-size));
|
|
21087
|
+
block-size: var(--xh-tabs-drag-size, var(--xh-control-indicator-size));
|
|
21088
|
+
border-radius: var(--xh-tabs-drag-radius, var(--xh-shape-control));
|
|
21089
|
+
color: var(--xh-tabs-drag-fg, var(--xh-fg-subtle));
|
|
21090
|
+
cursor: grab;
|
|
21091
|
+
}
|
|
21092
|
+
|
|
21093
|
+
/* 抓手是两条与排列轴垂直的线:盒子取边框盒,两侧描边就是那两条线,宽高与线宽都走令牌。
|
|
21094
|
+
标签带横排时标签左右排开,画的是两条竖线;竖排那一档在下面换成横线。
|
|
21095
|
+
基础这一档同时兜住 root 上没写方向的情形。
|
|
21096
|
+
:empty 守卫让作者塞进来的图标整个顶掉它,而不是两份叠在一起 */
|
|
21097
|
+
[data-scope='tabs'][data-part='tab-drag-trigger']:empty::after {
|
|
21098
|
+
content: '';
|
|
21099
|
+
display: block;
|
|
21100
|
+
inline-size: var(--xh-tabs-drag-grip-short, var(--xh-space-1));
|
|
21101
|
+
block-size: var(--xh-tabs-drag-grip-long, var(--xh-space-2));
|
|
21102
|
+
border-inline: var(--xh-stroke-thin) solid currentColor;
|
|
21103
|
+
}
|
|
21104
|
+
|
|
21105
|
+
/* 竖排的标签上下排开,两条线跟着转九十度:长短对调,描边换到块向两侧,
|
|
21106
|
+
行向那两条得显式清零,否则四边都留着描边,抓手成了一个方框 */
|
|
21107
|
+
[data-scope='tabs'][data-part='root'][data-orientation='vertical']
|
|
21108
|
+
[data-scope='tabs'][data-part='tab-drag-trigger']:empty::after {
|
|
21109
|
+
inline-size: var(--xh-tabs-drag-grip-long, var(--xh-space-2));
|
|
21110
|
+
block-size: var(--xh-tabs-drag-grip-short, var(--xh-space-1));
|
|
21111
|
+
border-inline: 0;
|
|
21112
|
+
border-block: var(--xh-stroke-thin) solid currentColor;
|
|
21113
|
+
}
|
|
21114
|
+
|
|
21115
|
+
[data-scope='tabs'][data-part='tab-drag-trigger']:not([data-disabled]):hover,
|
|
21116
|
+
[data-scope='tabs'][data-part='tab-drag-trigger'][data-dragging] {
|
|
21117
|
+
color: var(--xh-tabs-drag-fg-active, var(--xh-fg-default));
|
|
21118
|
+
}
|
|
21119
|
+
|
|
21120
|
+
[data-scope='tabs'][data-part='tab-drag-trigger'][data-dragging] {
|
|
21121
|
+
cursor: grabbing;
|
|
21122
|
+
}
|
|
21123
|
+
|
|
21124
|
+
/* 不可拖的标签照样带一个把手,这里保住它的位置、只把它压到禁用色。
|
|
21125
|
+
收成 display: none 是不行的:把手占着标签内的头一格,藏掉之后同一条标签带里
|
|
21126
|
+
能拖与不能拖的两张标签,文字起点会错开一格 */
|
|
21127
|
+
[data-scope='tabs'][data-part='tab-drag-trigger'][data-disabled] {
|
|
21128
|
+
color: var(--xh-tabs-drag-fg-disabled, var(--xh-fg-disabled));
|
|
21129
|
+
cursor: not-allowed;
|
|
21130
|
+
}
|
|
21131
|
+
|
|
21132
|
+
[data-scope='tabs'][data-part='tab-drag-trigger']:focus-visible {
|
|
21133
|
+
outline: var(--xh-ring-width) solid var(--xh-ring-focus);
|
|
21134
|
+
outline-offset: var(--xh-ring-offset);
|
|
21135
|
+
}
|
|
21136
|
+
|
|
21137
|
+
/* 被拖的那张标签压暗,让人看得出正在搬的是它。这里只动 opacity、cursor 与 user-select,
|
|
21138
|
+
一个 transform 都不写:标签原地不动,要落到哪儿全交给落点指示 */
|
|
21139
|
+
[data-scope='tabs'][data-part='trigger'][data-dragging] {
|
|
21140
|
+
opacity: var(--xh-tabs-dragging-opacity, var(--xh-state-dragging-opacity));
|
|
21141
|
+
cursor: grabbing;
|
|
21142
|
+
user-select: none;
|
|
21143
|
+
}
|
|
21144
|
+
|
|
21145
|
+
/* 落点指示线:插到哪张标签的哪一侧,线就画在那张标签的那条边上。
|
|
21146
|
+
定位上下文不必在这儿再给:标签的基础规则里已经是 position: relative。
|
|
21147
|
+
线走 ::after:选中态那道指示画的是 box-shadow(card 档的顶边条、segment 档的浮起),
|
|
21148
|
+
line 档只换文字色,标签上两个伪元素都空着,落点线不与谁抢。
|
|
21149
|
+
标签自身不收 overflow,线不会被裁掉;仍整条画在盒内不压着边 */
|
|
21150
|
+
[data-scope='tabs'][data-part='trigger']:is([data-drop='before'], [data-drop='after'])::after {
|
|
21151
|
+
content: '';
|
|
21152
|
+
position: absolute;
|
|
21153
|
+
background: var(--xh-tabs-drop-fg, var(--xh-border-control-focus));
|
|
21154
|
+
}
|
|
21155
|
+
|
|
21156
|
+
/* 线的方向跟着标签带的排法换:方向写在 root 的 data-orientation 上,从根往下选。
|
|
21157
|
+
横排的标签左右排开,线是一条竖的,贯穿标签的块向、贴在行向的前后沿 */
|
|
21158
|
+
[data-scope='tabs'][data-part='root'][data-orientation='horizontal']
|
|
21159
|
+
[data-scope='tabs'][data-part='trigger']:is([data-drop='before'], [data-drop='after'])::after {
|
|
21160
|
+
inset-block: 0;
|
|
21161
|
+
inline-size: var(--xh-tabs-drop-line, var(--xh-stroke-thick));
|
|
21162
|
+
}
|
|
21163
|
+
|
|
21164
|
+
/* 落在前沿还是后沿走逻辑属性:rtl 下 before 自己就换到右边去了。
|
|
21165
|
+
换成 box-shadow 的偏移量则是物理的,写不出逻辑方向 */
|
|
21166
|
+
[data-scope='tabs'][data-part='root'][data-orientation='horizontal']
|
|
21167
|
+
[data-scope='tabs'][data-part='trigger'][data-drop='before']::after {
|
|
21168
|
+
inset-inline-start: 0;
|
|
21169
|
+
}
|
|
21170
|
+
|
|
21171
|
+
[data-scope='tabs'][data-part='root'][data-orientation='horizontal']
|
|
21172
|
+
[data-scope='tabs'][data-part='trigger'][data-drop='after']::after {
|
|
21173
|
+
inset-inline-end: 0;
|
|
21174
|
+
}
|
|
21175
|
+
|
|
21176
|
+
/* 竖排的标签上下排开,线是一条横的,贯穿标签的行向、贴在块向的前后沿 */
|
|
21177
|
+
[data-scope='tabs'][data-part='root'][data-orientation='vertical']
|
|
21178
|
+
[data-scope='tabs'][data-part='trigger']:is([data-drop='before'], [data-drop='after'])::after {
|
|
21179
|
+
inset-inline: 0;
|
|
21180
|
+
block-size: var(--xh-tabs-drop-line, var(--xh-stroke-thick));
|
|
21181
|
+
}
|
|
21182
|
+
|
|
21183
|
+
/* 块向同样走逻辑属性,跟着书写模式走 */
|
|
21184
|
+
[data-scope='tabs'][data-part='root'][data-orientation='vertical']
|
|
21185
|
+
[data-scope='tabs'][data-part='trigger'][data-drop='before']::after {
|
|
21186
|
+
inset-block-start: 0;
|
|
21187
|
+
}
|
|
21188
|
+
|
|
21189
|
+
[data-scope='tabs'][data-part='root'][data-orientation='vertical']
|
|
21190
|
+
[data-scope='tabs'][data-part='trigger'][data-drop='after']::after {
|
|
21191
|
+
inset-block-end: 0;
|
|
21192
|
+
}
|
|
21193
|
+
|
|
21194
|
+
/* 活动区域只说给读屏听,不占版面。声明与 shared/visually-hidden.ts 逐条同值。 */
|
|
21195
|
+
[data-scope='tabs'][data-part='live-region'] {
|
|
21196
|
+
position: absolute;
|
|
21197
|
+
inline-size: 1px;
|
|
21198
|
+
block-size: 1px;
|
|
21199
|
+
padding: 0;
|
|
21200
|
+
margin: -1px;
|
|
21201
|
+
overflow: hidden;
|
|
21202
|
+
clip-path: inset(50%);
|
|
21203
|
+
white-space: nowrap;
|
|
21204
|
+
border: 0;
|
|
21205
|
+
}
|
|
21206
|
+
|
|
20562
21207
|
/* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
|
|
20563
21208
|
写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
|
|
20564
21209
|
[data-scope='tabs'][data-part='root'][hidden],
|
|
20565
21210
|
[data-scope='tabs'][data-part='list'][hidden],
|
|
20566
|
-
[data-scope='tabs'][data-part='trigger'][hidden]
|
|
21211
|
+
[data-scope='tabs'][data-part='trigger'][hidden],
|
|
21212
|
+
[data-scope='tabs'][data-part='tab-drag-trigger'][hidden] {
|
|
20567
21213
|
display: none;
|
|
20568
21214
|
}
|
|
20569
21215
|
|
|
@@ -24240,6 +24886,135 @@ input[data-scope='mention'][data-part='input'] {
|
|
|
24240
24886
|
mask: var(--xh-glyph-mark-check) center / contain no-repeat;
|
|
24241
24887
|
}
|
|
24242
24888
|
|
|
24889
|
+
/* —— 节点拖拽搬家 —— */
|
|
24890
|
+
/* 整行都是拖动源,光标换成抓手告诉人这一行按得动。
|
|
24891
|
+
这条不写 touch-action:整行关掉纵向手势,树容器自己就滚不动了;
|
|
24892
|
+
触屏那一路交给下面那块专属把手 */
|
|
24893
|
+
[data-scope='tree'][data-part='item'][data-draggable],
|
|
24894
|
+
[data-scope='tree'][data-part='branch-control'][data-draggable] {
|
|
24895
|
+
cursor: grab;
|
|
24896
|
+
}
|
|
24897
|
+
|
|
24898
|
+
/* 节点拖拽把手:行里的一小块专属拖动区,按下即拖。触屏靠它起手,
|
|
24899
|
+
代价只是这一小块地方不再跟着树滚。整行起手那一路原样保留,把手是叠加的第二个入口。
|
|
24900
|
+
touch-action 不在这儿写:连接层按「拖不动就不写」把它写进了内联 style,
|
|
24901
|
+
皮肤再写一遍会盖掉那份条件判断,让不可拖的节点也白白让出滚动 */
|
|
24902
|
+
[data-scope='tree'][data-part='node-drag-trigger'] {
|
|
24903
|
+
display: inline-flex;
|
|
24904
|
+
flex: none;
|
|
24905
|
+
align-items: center;
|
|
24906
|
+
justify-content: center;
|
|
24907
|
+
inline-size: var(--xh-tree-drag-size, var(--xh-control-indicator-size));
|
|
24908
|
+
block-size: var(--xh-tree-drag-size, var(--xh-control-indicator-size));
|
|
24909
|
+
border-radius: var(--xh-tree-drag-radius, var(--xh-shape-control));
|
|
24910
|
+
color: var(--xh-tree-drag-fg, var(--xh-fg-subtle));
|
|
24911
|
+
cursor: grab;
|
|
24912
|
+
}
|
|
24913
|
+
|
|
24914
|
+
[data-scope='tree'][data-part='node-drag-trigger'][hidden] {
|
|
24915
|
+
display: none;
|
|
24916
|
+
}
|
|
24917
|
+
|
|
24918
|
+
/* 抓手是两条横线:盒子取边框盒,块向两侧的描边就是那两条线,宽高与线宽都走令牌。
|
|
24919
|
+
线的走向与能拖的方向垂直——节点沿块向上下排,画的就是横线。
|
|
24920
|
+
用逻辑属性写,书写模式一换,线跟着排列轴自己转过去。
|
|
24921
|
+
:empty 守卫让作者塞进来的图标整个顶掉它,而不是两份叠在一起 */
|
|
24922
|
+
[data-scope='tree'][data-part='node-drag-trigger']:empty::after {
|
|
24923
|
+
content: '';
|
|
24924
|
+
display: block;
|
|
24925
|
+
inline-size: var(--xh-tree-drag-grip-long, var(--xh-space-2));
|
|
24926
|
+
block-size: var(--xh-tree-drag-grip-short, var(--xh-space-1));
|
|
24927
|
+
border-block: var(--xh-stroke-thin) solid currentColor;
|
|
24928
|
+
}
|
|
24929
|
+
|
|
24930
|
+
[data-scope='tree'][data-part='node-drag-trigger']:not([data-disabled]):hover,
|
|
24931
|
+
[data-scope='tree'][data-part='node-drag-trigger'][data-dragging] {
|
|
24932
|
+
color: var(--xh-tree-drag-fg-active, var(--xh-fg-default));
|
|
24933
|
+
}
|
|
24934
|
+
|
|
24935
|
+
[data-scope='tree'][data-part='node-drag-trigger'][data-dragging] {
|
|
24936
|
+
cursor: grabbing;
|
|
24937
|
+
}
|
|
24938
|
+
|
|
24939
|
+
/* 不可拖的节点照样带一个把手,这里保住它的位置、只把它压到禁用色。
|
|
24940
|
+
收成 display: none 是不行的:把手占着行首那一格,藏掉之后同一层里能拖与不能拖的两个节点,
|
|
24941
|
+
文字起点会错开一格,层级关系跟着读歪 */
|
|
24942
|
+
[data-scope='tree'][data-part='node-drag-trigger'][data-disabled] {
|
|
24943
|
+
color: var(--xh-tree-drag-fg-disabled, var(--xh-fg-disabled));
|
|
24944
|
+
cursor: not-allowed;
|
|
24945
|
+
}
|
|
24946
|
+
|
|
24947
|
+
[data-scope='tree'][data-part='node-drag-trigger']:focus-visible {
|
|
24948
|
+
outline: var(--xh-ring-width) solid var(--xh-ring-focus);
|
|
24949
|
+
outline-offset: var(--xh-ring-offset);
|
|
24950
|
+
}
|
|
24951
|
+
|
|
24952
|
+
/* 被拖的那一行压暗,让人看得出正在搬的是它。这里只动 opacity、cursor 与 user-select,
|
|
24953
|
+
一个 transform 都不写:行原地不动,要落到哪儿全交给落点指示 */
|
|
24954
|
+
[data-scope='tree'][data-part='item'][data-dragging],
|
|
24955
|
+
[data-scope='tree'][data-part='branch-control'][data-dragging] {
|
|
24956
|
+
opacity: var(--xh-tree-dragging-opacity, var(--xh-state-dragging-opacity));
|
|
24957
|
+
cursor: grabbing;
|
|
24958
|
+
user-select: none;
|
|
24959
|
+
}
|
|
24960
|
+
|
|
24961
|
+
/* 落点指示线:插到哪一行的哪一侧,横线就画在那一行的那条边上。
|
|
24962
|
+
定位上下文只给要画线的那一行:行平时都不定位,缺了它伪元素会一路上溯到最近的定位祖先,
|
|
24963
|
+
线就画到树外面去;写到所有行上则是给每一行都多担一份,而落点同一时刻只有一个。
|
|
24964
|
+
整块高亮那一档不在此列:它不靠伪元素,用不着这层上下文 */
|
|
24965
|
+
[data-scope='tree'][data-part='item']:is([data-drop='before'], [data-drop='after']),
|
|
24966
|
+
[data-scope='tree'][data-part='branch-control']:is([data-drop='before'], [data-drop='after']) {
|
|
24967
|
+
position: relative;
|
|
24968
|
+
}
|
|
24969
|
+
|
|
24970
|
+
/* 线贯穿整行宽度。行自身不收 overflow,线不会被行裁掉;
|
|
24971
|
+
但仍整条画在行内不压着边——压着边画的话,首行那条上沿线会被树容器的圆角与滚动裁掉半条 */
|
|
24972
|
+
[data-scope='tree'][data-part='item']:is([data-drop='before'], [data-drop='after'])::after,
|
|
24973
|
+
[data-scope='tree'][data-part='branch-control']:is([data-drop='before'], [data-drop='after'])::after {
|
|
24974
|
+
content: '';
|
|
24975
|
+
position: absolute;
|
|
24976
|
+
inset-inline: 0;
|
|
24977
|
+
block-size: var(--xh-tree-drop-line, var(--xh-stroke-thick));
|
|
24978
|
+
background: var(--xh-tree-drop-fg, var(--xh-border-control-focus));
|
|
24979
|
+
}
|
|
24980
|
+
|
|
24981
|
+
/* 落在上沿还是下沿走逻辑属性,块向跟着书写模式走。
|
|
24982
|
+
换成 box-shadow 的偏移量则是物理的,写不出逻辑方向 */
|
|
24983
|
+
[data-scope='tree'][data-part='item'][data-drop='before']::after,
|
|
24984
|
+
[data-scope='tree'][data-part='branch-control'][data-drop='before']::after {
|
|
24985
|
+
inset-block-start: 0;
|
|
24986
|
+
}
|
|
24987
|
+
|
|
24988
|
+
[data-scope='tree'][data-part='item'][data-drop='after']::after,
|
|
24989
|
+
[data-scope='tree'][data-part='branch-control'][data-drop='after']::after {
|
|
24990
|
+
inset-block-end: 0;
|
|
24991
|
+
}
|
|
24992
|
+
|
|
24993
|
+
/* 放进这个节点里面:整行淡底加一圈内描边,与上下沿那条横线一眼分得开。
|
|
24994
|
+
描边走零偏移的内投影,四边同时着色、不涉及方向,也跟着行的圆角走。
|
|
24995
|
+
选择器里那条 :not([data-disabled]) 是把特指度补到与悬停那条齐平,再靠排在它之后压过它:
|
|
24996
|
+
指针本来就停在落点这一行上,少了这一段,落点底色会被悬停那档灰盖掉。
|
|
24997
|
+
禁用的节点从来不做落点,这一段因此不会漏画任何一处高亮 */
|
|
24998
|
+
[data-scope='tree'][data-part='item'][data-drop='inside']:not([data-disabled]),
|
|
24999
|
+
[data-scope='tree'][data-part='branch-control'][data-drop='inside']:not([data-disabled]) {
|
|
25000
|
+
background: var(--xh-tree-drop-inside-bg, var(--xh-bg-brand-subtle));
|
|
25001
|
+
box-shadow: inset 0 0 0 var(--xh-tree-drop-line, var(--xh-stroke-thick))
|
|
25002
|
+
var(--xh-tree-drop-fg, var(--xh-border-control-focus));
|
|
25003
|
+
}
|
|
25004
|
+
|
|
25005
|
+
/* 活动区域只说给读屏听,不占版面。声明与 shared/visually-hidden.ts 逐条同值。 */
|
|
25006
|
+
[data-scope='tree'][data-part='live-region'] {
|
|
25007
|
+
position: absolute;
|
|
25008
|
+
inline-size: 1px;
|
|
25009
|
+
block-size: 1px;
|
|
25010
|
+
padding: 0;
|
|
25011
|
+
margin: -1px;
|
|
25012
|
+
overflow: hidden;
|
|
25013
|
+
clip-path: inset(50%);
|
|
25014
|
+
white-space: nowrap;
|
|
25015
|
+
border: 0;
|
|
25016
|
+
}
|
|
25017
|
+
|
|
24243
25018
|
/* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
|
|
24244
25019
|
写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
|
|
24245
25020
|
[data-scope='tree'][data-part='branch-checkbox'][hidden] {
|