perf: 优化节点下拉框UI

This commit is contained in:
2026-03-01 16:13:50 +08:00
parent f872db6c59
commit beeb62c4fc
3 changed files with 59 additions and 44 deletions

View File

@@ -179,7 +179,7 @@
{/snippet}
<div {...rest} class="tf-select {rest['class']}">
<FloatingTrigger bind:this={triggerObject} onShow={() => isOpen = true} onHide={() => { isOpen = false; hoveredItem = null; }}>
<FloatingTrigger bind:this={triggerObject} onShow={() => isOpen = true} onHide={() => { isOpen = false; hoveredItem = null; }} syncWidth={true}>
<button class="tf-select-input nopan nodrag {isOpen ? 'active' : ''}" {...rest}>
<div class="tf-select-input-value">
{#each activeItemsState as item, index (`${index}_${item.value}`)}
@@ -303,11 +303,10 @@
flex-direction: column;
background: #fff;
margin-top: 5px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
width: max-content;
min-width: 100%;
border: 1px solid #e5e7eb;
border-radius: 6px;
padding: 4px;
width: 100%;
z-index: 99999;
box-sizing: border-box;
max-height: 220px;
@@ -318,20 +317,20 @@
.tf-select-default-item {
display: flex;
align-items: center;
padding: 5px 10px;
padding: 6px 12px;
border: none;
background: #fff;
border-radius: 5px;
border-radius: 4px;
cursor: pointer;
line-height: 100%;
line-height: 1.5;
gap: 2px;
width: 100%;
text-align: left;
font-size: 13px;
color: #333;
color: #111827;
&:hover {
background: #f0f0f0;
background: #f5f5f7;
}
}
@@ -347,11 +346,11 @@
background: #fff;
margin-top: 5px;
border: 1px solid #e5e7eb;
border-radius: 10px; /* slightly smaller radius */
width: 280px; /* Reduced width to be more compact */
border-radius: 10px;
/* Removed fixed width to allow syncWidth to control it */
z-index: 99999;
box-sizing: border-box;
max-height: 400px; /* slightly less tall */
max-height: 400px;
overflow: hidden;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
}
@@ -360,13 +359,13 @@
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 12px; /* tighter padding */
padding: 10px 12px;
border-bottom: 1px solid #f3f4f6;
background: #fff;
}
.tf-select-model-header-title {
font-size: 13px; /* smaller title */
font-size: 13px;
font-weight: 600;
color: #111827;
}
@@ -381,13 +380,13 @@
.tf-select-model-list {
display: flex;
flex-direction: column;
padding: 8px; /* tighter padding */
padding: 8px;
overflow-y: auto;
gap: 4px; /* tighter gap between items */
gap: 4px;
}
.tf-select-model-group-title {
font-size: 12px; /* smaller group title */
font-size: 12px;
font-weight: 500;
color: #6b7280;
margin-top: 6px;
@@ -399,7 +398,7 @@
}
.tf-select-model-group-icon {
width: 14px; /* smaller icon */
width: 14px;
height: 14px;
display: flex;
align-items: center;
@@ -420,7 +419,7 @@
.tf-select-model-item {
display: flex;
align-items: flex-start;
padding: 6px 8px; /* tighter item padding */
padding: 6px 8px;
border: none;
background: transparent;
border-radius: 6px;
@@ -440,7 +439,7 @@
.tf-select-model-icon {
flex-shrink: 0;
width: 32px; /* smaller item icon */
width: 32px;
height: 32px;
border-radius: 6px;
overflow: hidden;
@@ -452,7 +451,7 @@
}
.tf-select-model-icon :global(svg), .tf-select-model-icon img {
width: 70%; /* icon inside box */
width: 70%;
height: 70%;
object-fit: contain;
}
@@ -466,13 +465,13 @@
.tf-select-model-info {
display: flex;
flex-direction: column;
gap: 2px; /* tighter info gap */
gap: 2px;
flex-grow: 1;
overflow: hidden;
}
.tf-select-model-title {
font-size: 13px; /* smaller font */
font-size: 13px;
font-weight: 500;
color: #111827;
white-space: nowrap;
@@ -489,19 +488,19 @@
.tf-select-model-tag {
background: #f3f4f6;
color: #6b7280;
font-size: 10px; /* smaller tag */
font-size: 10px;
padding: 1px 6px;
border-radius: 4px;
}
.tf-select-model-desc {
font-size: 11px; /* smaller desc */
font-size: 11px;
color: #6b7280;
line-height: 1.3;
margin-top: 2px;
display: -webkit-box;
-webkit-line-clamp: 2; /* limit lines */
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
@@ -513,11 +512,10 @@
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
border: 1px solid #e5e7eb;
overflow: hidden;
min-width: 220px;
/* width expands naturally since createFloating sets minWidth, not width */
width: max-content;
max-width: 600px;
box-sizing: border-box;
max-height: 480px;
transition: width 0.2s ease;
z-index: 99999;
}
@@ -528,22 +526,27 @@
overflow-y: auto;
&.tf-select-primary-list {
width: 220px;
width: 100%; /* Default fills the wrapper, which is minWidth-constrained by the input */
flex-shrink: 0;
background: #f9fafb;
}
/* When a secondary list is open, we fix the primary list to 100% of the input's width (done via absolute positioning or just keeping it wide enough) */
.tf-select-wrapper:has(.tf-select-secondary-list) &.tf-select-primary-list {
/* Let it take the width of the input minus borders/paddings if needed, but minWidth handles it mostly */
width: auto;
min-width: 180px;
}
&.tf-select-secondary-list {
flex-grow: 1;
min-width: 200px;
min-width: 220px;
background: #fff;
padding: 12px;
border-left: 1px solid #f3f4f6;
animation: slideIn 0.2s ease-out;
box-sizing: border-box;
}
}
@keyframes slideIn {
} @keyframes slideIn {
from { opacity: 0; transform: translateX(-10px); }
to { opacity: 1; transform: translateX(0); }
}