20260816220132

This commit is contained in:
oneao committed 2026-08-16 22:01:32 +08:00
1 parent b6f9a4c912
commit 72993ecdcd
179 files changed
+20050 -633

No files matched your search

@@ -0,0 +1,245 @@
/* Tree 组件样式:缩进、悬停/聚焦、选中、禁用、复选半选、拖拽指示线、过滤高亮、loading。
尺寸/间距/圆角/字号/阴影统一引用 --fms-* token,不写死数值。 */
.tree {
color: var(--fms-text);
font-size: var(--fms-font-size);
line-height: 1.5;
outline: none;
}
/* 单节点行:padding-left 为「固定左留白 + 层级缩进」;flex 布局承载 switcher/checkbox/title/grip */
.tree-node {
position: relative;
display: flex;
align-items: center;
min-height: var(--fms-tree-node-height);
padding-left: calc(var(--fms-tree-gutter-x) + var(--fms-tree-indent) * var(--level));
border-radius: var(--fms-control-radius);
cursor: default;
user-select: none;
transition:
background-color 0.15s ease,
color 0.15s ease,
border-color 0.15s ease,
box-shadow 0.15s ease;
}
.tree-node:hover:not(.is-disabled) {
background: var(--fms-secondary-hover);
cursor: pointer;
}
/* 键盘/鼠标聚焦:focus-visible 描边,避免鼠标点击也出现描边 */
.tree-node:focus-visible {
outline: 2px solid var(--fms-primary);
outline-offset: -2px;
}
/* 选中:主色淡底 + 主色加粗文字(不依赖单一颜色表达) */
.tree-node.is-selected {
background: color-mix(in srgb, var(--fms-primary) 6%, transparent);
}
.tree-node.is-selected .tree-node-content {
color: var(--fms-primary);
font-weight: 600;
}
.tree-node.is-disabled,
.tree-node.is-disabled .tree-node-content {
color: var(--fms-disabled-text);
cursor: not-allowed;
}
.tree-node.is-checkbox-disabled .tree-node-content {
opacity: 0.7;
}
/* 拖拽源:半透明提示 */
.tree-node.is-dragging {
opacity: 0.4;
}
/* ---------- 展开/收起图标 ---------- */
.tree-node-switcher {
display: inline-flex;
align-items: center;
justify-content: center;
flex: none;
width: var(--fms-tree-switcher-size);
height: var(--fms-tree-switcher-size);
margin-right: 2px;
color: var(--fms-text-secondary);
border-radius: 50%;
cursor: pointer;
transition:
background-color 0.15s ease,
color 0.15s ease;
}
.tree-node-switcher:hover:not(.is-placeholder) {
background: color-mix(in srgb, var(--fms-primary) 10%, transparent);
color: var(--fms-primary);
}
.tree-node-switcher.is-placeholder {
cursor: default;
}
.tree-switcher-icon {
width: var(--fms-tree-icon-size);
height: var(--fms-tree-icon-size);
transition: transform 0.2s cubic-bezier(0.2, 0.8, 0.4, 1);
}
.tree-switcher-icon.is-open {
transform: rotate(90deg);
}
.tree-spinner {
width: var(--fms-tree-icon-size);
height: var(--fms-tree-icon-size);
color: var(--fms-primary);
animation: tree-spin 0.8s linear infinite;
}
@keyframes tree-spin {
to {
transform: rotate(360deg);
}
}
/* ---------- 复选框 ---------- */
.tree-node-checkbox {
display: inline-flex;
align-items: center;
flex: none;
margin-right: 6px;
}
/* ---------- 标题 ---------- */
.tree-node-content {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
height: 100%;
padding: 0 var(--fms-tree-title-padding-x);
border-radius: var(--fms-control-radius);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tree-node.is-block .tree-node-content {
flex: 1 1 auto;
}
.tree-highlight {
background: color-mix(in srgb, var(--fms-primary) 22%, transparent);
color: var(--fms-primary);
font-weight: 600;
border-radius: 2px;
padding: 0 1px;
}
/* ---------- 拖拽手柄(在最左侧) ---------- */
.tree-node-grip {
display: inline-flex;
align-items: center;
flex: none;
width: var(--fms-tree-grip-size);
height: var(--fms-tree-grip-size);
margin-right: 4px;
color: var(--fms-text-secondary);
cursor: grab;
opacity: 0;
transition: opacity 0.15s;
}
.tree-node:hover .tree-node-grip {
opacity: 1;
}
.tree-node-grip:active {
cursor: grabbing;
}
/* ---------- 拖拽落点指示:圆点 + 连接线 ---------- */
.tree-node.drop-before::before,
.tree-node.drop-after::before {
content: '';
position: absolute;
left: calc(var(--fms-tree-gutter-x) + var(--fms-tree-indent) * var(--level));
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--fms-primary);
box-shadow: 0 0 0 2px var(--fms-card);
z-index: 1;
}
.tree-node.drop-before::before {
top: -4px;
}
.tree-node.drop-after::before {
bottom: -4px;
}
.tree-node.drop-before::after,
.tree-node.drop-after::after {
content: '';
position: absolute;
left: calc(var(--fms-tree-gutter-x) + var(--fms-tree-indent) * var(--level) + 8px);
right: 0;
height: var(--fms-tree-drop-line-size);
background: var(--fms-primary);
border-radius: var(--fms-tree-drop-line-size);
}
.tree-node.drop-before::after {
top: -1px;
}
.tree-node.drop-after::after {
bottom: -1px;
}
.tree-node.drop-inside {
background: color-mix(in srgb, var(--fms-primary) 12%, transparent);
outline: 2px solid color-mix(in srgb, var(--fms-primary) 55%, transparent);
outline-offset: -2px;
}
/* ---------- 展开/收起动画(grid-template-rows 高度过渡) ---------- */
.tree-node-children {
display: grid;
grid-template-columns: minmax(0, 1fr);
grid-template-rows: 1fr;
overflow: hidden;
}
.tree-collapse-enter-active,
.tree-collapse-leave-active {
transition:
grid-template-rows 0.22s cubic-bezier(0.2, 0.8, 0.4, 1),
opacity 0.18s ease;
}
.tree-collapse-enter-from,
.tree-collapse-leave-to {
grid-template-rows: 0fr;
opacity: 0;
}
.tree-node-children-inner {
overflow: hidden;
}
/* ---------- 空态 ---------- */
.tree-empty {
padding: 12px 8px;
color: var(--fms-text-secondary);
text-align: center;
}
.tree-disabled .tree-node {
cursor: not-allowed;
}
/* 尊重系统「减少动态效果」偏好 */
@media (prefers-reduced-motion: reduce) {
.tree-node,
.tree-switcher-icon,
.tree-node-grip,
.tree-spinner,
.tree-node-children {
transition: none;
animation: none;
}
.tree-collapse-enter-active,
.tree-collapse-leave-active {
transition: none;
}
}