feat(ui): Enhance mention models dropdown with improved styling and scrollbar
This commit is contained in:
parent
0fdb2ed0ef
commit
94e0559dd3
@ -459,6 +459,7 @@
|
|||||||
"embedding_model": "Embedding Model",
|
"embedding_model": "Embedding Model",
|
||||||
"embedding_model_tooltip": "Add in Settings->Model Provider->Manage",
|
"embedding_model_tooltip": "Add in Settings->Model Provider->Manage",
|
||||||
"free": "Free",
|
"free": "Free",
|
||||||
|
"no_matches": "No models available",
|
||||||
"parameter_name": "Parameter Name",
|
"parameter_name": "Parameter Name",
|
||||||
"parameter_type": {
|
"parameter_type": {
|
||||||
"boolean": "Boolean",
|
"boolean": "Boolean",
|
||||||
|
|||||||
@ -479,7 +479,8 @@
|
|||||||
},
|
},
|
||||||
"vision": "画像",
|
"vision": "画像",
|
||||||
"websearch": "ウェブ検索",
|
"websearch": "ウェブ検索",
|
||||||
"edit": "モデルを編集"
|
"edit": "モデルを編集",
|
||||||
|
"no_matches": "利用可能なモデルがありません"
|
||||||
},
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"expand": "ダイアログを展開",
|
"expand": "ダイアログを展開",
|
||||||
|
|||||||
@ -479,7 +479,8 @@
|
|||||||
},
|
},
|
||||||
"vision": "Визуальные",
|
"vision": "Визуальные",
|
||||||
"websearch": "Веб-поисковые",
|
"websearch": "Веб-поисковые",
|
||||||
"edit": "Редактировать модель"
|
"edit": "Редактировать модель",
|
||||||
|
"no_matches": "Нет доступных моделей"
|
||||||
},
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"expand": "Развернуть диалоговое окно",
|
"expand": "Развернуть диалоговое окно",
|
||||||
|
|||||||
@ -479,7 +479,8 @@
|
|||||||
},
|
},
|
||||||
"vision": "视觉",
|
"vision": "视觉",
|
||||||
"websearch": "联网",
|
"websearch": "联网",
|
||||||
"edit": "编辑模型"
|
"edit": "编辑模型",
|
||||||
|
"no_matches": "无可用模型"
|
||||||
},
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"expand": "伸缩对话框",
|
"expand": "伸缩对话框",
|
||||||
|
|||||||
@ -479,7 +479,8 @@
|
|||||||
},
|
},
|
||||||
"vision": "視覺",
|
"vision": "視覺",
|
||||||
"websearch": "網路搜尋",
|
"websearch": "網路搜尋",
|
||||||
"edit": "編輯模型"
|
"edit": "編輯模型",
|
||||||
|
"no_matches": "無可用模型"
|
||||||
},
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"expand": "伸縮對話框",
|
"expand": "伸縮對話框",
|
||||||
|
|||||||
@ -266,6 +266,44 @@ const MentionModelsButton: FC<Props> = ({ mentionModels, onMentionModel: onSelec
|
|||||||
}
|
}
|
||||||
}, [isOpen, selectedIndex, flatModelItems, mentionModels, menuDismissed])
|
}, [isOpen, selectedIndex, flatModelItems, mentionModels, menuDismissed])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updateScrollbarClass = () => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
if (menuRef.current) {
|
||||||
|
const hasScrollbar = menuRef.current.scrollHeight > menuRef.current.clientHeight
|
||||||
|
menuRef.current.classList.toggle('has-scrollbar', hasScrollbar)
|
||||||
|
menuRef.current.classList.toggle('no-scrollbar', !hasScrollbar)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update on initial render and whenever content changes
|
||||||
|
const observer = new MutationObserver(updateScrollbarClass)
|
||||||
|
const resizeObserver = new ResizeObserver(updateScrollbarClass)
|
||||||
|
|
||||||
|
if (menuRef.current) {
|
||||||
|
// Observe content changes
|
||||||
|
observer.observe(menuRef.current, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
attributes: true,
|
||||||
|
characterData: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// Observe size changes
|
||||||
|
resizeObserver.observe(menuRef.current)
|
||||||
|
|
||||||
|
// Initial check after a short delay to ensure DOM is ready
|
||||||
|
setTimeout(updateScrollbarClass, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
return () => {
|
||||||
|
observer.disconnect()
|
||||||
|
resizeObserver.disconnect()
|
||||||
|
}
|
||||||
|
}, [isOpen, searchText, flatModelItems.length]) // Add dependencies that affect content
|
||||||
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<div ref={menuRef} className="ant-dropdown-menu">
|
<div ref={menuRef} className="ant-dropdown-menu">
|
||||||
{flatModelItems.length > 0 ? (
|
{flatModelItems.length > 0 ? (
|
||||||
@ -328,72 +366,145 @@ const MentionModelsButton: FC<Props> = ({ mentionModels, onMentionModel: onSelec
|
|||||||
}
|
}
|
||||||
|
|
||||||
const DropdownMenuStyle = createGlobalStyle`
|
const DropdownMenuStyle = createGlobalStyle`
|
||||||
|
/* Apply background to all animation states */
|
||||||
|
.ant-dropdown,
|
||||||
|
.ant-slide-up-enter .ant-dropdown-menu,
|
||||||
|
.ant-slide-up-appear .ant-dropdown-menu,
|
||||||
|
.ant-slide-up-leave .ant-dropdown-menu,
|
||||||
|
.ant-slide-up-enter-active .ant-dropdown-menu,
|
||||||
|
.ant-slide-up-appear-active .ant-dropdown-menu,
|
||||||
|
.ant-slide-up-leave-active .ant-dropdown-menu {
|
||||||
|
background: rgba(var(--color-base-rgb), 0.65) !important;
|
||||||
|
backdrop-filter: blur(35px) saturate(150%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.mention-models-dropdown {
|
.mention-models-dropdown {
|
||||||
|
&.ant-dropdown {
|
||||||
|
animation-duration: 0.15s !important;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-dropdown-menu {
|
.ant-dropdown-menu {
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
padding: 4px 0;
|
padding: 4px 12px;
|
||||||
margin-bottom: 40px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
background: rgba(var(--color-base-rgb), 0.65) !important;
|
||||||
|
backdrop-filter: blur(35px) saturate(150%) !important;
|
||||||
|
border: 0.5px solid rgba(var(--color-border-rgb), 0.3);
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.15),
|
||||||
|
0 4px 16px rgba(0, 0, 0, 0.15),
|
||||||
|
0 2px 8px rgba(0, 0, 0, 0.12),
|
||||||
|
inset 0 0 0 0.5px rgba(255, 255, 255, 0.1);
|
||||||
|
transform-origin: top;
|
||||||
|
will-change: transform, opacity;
|
||||||
|
transition: all 0.15s cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||||
|
|
||||||
|
&.no-scrollbar {
|
||||||
|
padding-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-scrollbar {
|
||||||
|
padding-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scrollbar styles
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 14px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
border-radius: 10px;
|
border: 4px solid transparent;
|
||||||
background: var(--color-scrollbar-thumb);
|
background-clip: padding-box;
|
||||||
|
border-radius: 7px;
|
||||||
|
background-color: transparent;
|
||||||
|
min-height: 50px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover::-webkit-scrollbar-thumb {
|
||||||
background: var(--color-scrollbar-thumb-hover);
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
border: 4px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb:active {
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
border: 3px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-track {
|
&::-webkit-scrollbar-track {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
border-radius: 7px;
|
||||||
|
|
||||||
.no-results {
|
|
||||||
padding: 8px 12px;
|
|
||||||
color: var(--color-text-3);
|
|
||||||
cursor: default;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // Apply margin to the last group
|
||||||
|
// .ant-dropdown-menu-item-group:last-child {
|
||||||
|
// margin-bottom: 40px;
|
||||||
|
// }
|
||||||
|
|
||||||
.ant-dropdown-menu-item-group {
|
.ant-dropdown-menu-item-group {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-dropdown-menu-item-group-title {
|
.ant-dropdown-menu-item-group-title {
|
||||||
padding: 5px 12px;
|
padding: 5px 12px;
|
||||||
color: var(--color-text-3);
|
color: var(--color-text-3);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle no-results case margin
|
||||||
|
.no-results {
|
||||||
|
padding: 8px 12px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
cursor: default;
|
||||||
|
font-size: 13px;
|
||||||
|
opacity: 0.8;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-dropdown-menu-item {
|
.ant-dropdown-menu-item {
|
||||||
padding: 5px 12px;
|
padding: 5px 12px;
|
||||||
|
margin: 0 -12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--color-hover);
|
background: rgba(var(--color-hover-rgb), 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ant-dropdown-menu-item-selected {
|
&.ant-dropdown-menu-item-selected {
|
||||||
background-color: var(--color-primary-bg);
|
background-color: rgba(var(--color-primary-rgb), 0.12);
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-dropdown-menu-item-icon {
|
.ant-dropdown-menu-item-icon {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -403,7 +514,7 @@ const ModelItem = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
@ -425,15 +536,15 @@ const ModelNameRow = styled.div`
|
|||||||
const PinIcon = styled.span.attrs({ className: 'pin-icon' })<{ $isPinned: boolean }>`
|
const PinIcon = styled.span.attrs({ className: 'pin-icon' })<{ $isPinned: boolean }>`
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
opacity: ${(props) => (props.$isPinned ? 1 : 'inherit')};
|
opacity: ${(props) => (props.$isPinned ? 0.9 : 0)};
|
||||||
transition: opacity 0.2s;
|
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
right: 0;
|
right: 0;
|
||||||
color: ${(props) => (props.$isPinned ? 'var(--color-primary)' : 'inherit')};
|
color: ${(props) => (props.$isPinned ? 'var(--color-primary)' : 'inherit')};
|
||||||
transform: ${(props) => (props.$isPinned ? 'rotate(-45deg)' : 'none')};
|
transform: ${(props) => (props.$isPinned ? 'rotate(-45deg)' : 'none')};
|
||||||
opacity: 0;
|
font-size: 13px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1 !important;
|
opacity: ${(props) => (props.$isPinned ? 1 : 0.7)} !important;
|
||||||
color: ${(props) => (props.$isPinned ? 'var(--color-primary)' : 'inherit')};
|
color: ${(props) => (props.$isPinned ? 'var(--color-primary)' : 'inherit')};
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user