20260816220132
This commit is contained in:
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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user