diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index b0a7bada..371dc34b 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -459,6 +459,7 @@ "embedding_model": "Embedding Model", "embedding_model_tooltip": "Add in Settings->Model Provider->Manage", "free": "Free", + "no_matches": "No models available", "parameter_name": "Parameter Name", "parameter_type": { "boolean": "Boolean", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index b36eaeec..9672824a 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -479,7 +479,8 @@ }, "vision": "画像", "websearch": "ウェブ検索", - "edit": "モデルを編集" + "edit": "モデルを編集", + "no_matches": "利用可能なモデルがありません" }, "navbar": { "expand": "ダイアログを展開", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 73c075a3..b693ff70 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -479,7 +479,8 @@ }, "vision": "Визуальные", "websearch": "Веб-поисковые", - "edit": "Редактировать модель" + "edit": "Редактировать модель", + "no_matches": "Нет доступных моделей" }, "navbar": { "expand": "Развернуть диалоговое окно", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index d8f14193..67880149 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -479,7 +479,8 @@ }, "vision": "视觉", "websearch": "联网", - "edit": "编辑模型" + "edit": "编辑模型", + "no_matches": "无可用模型" }, "navbar": { "expand": "伸缩对话框", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 5cda5203..5d16d4bb 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -479,7 +479,8 @@ }, "vision": "視覺", "websearch": "網路搜尋", - "edit": "編輯模型" + "edit": "編輯模型", + "no_matches": "無可用模型" }, "navbar": { "expand": "伸縮對話框", diff --git a/src/renderer/src/pages/home/Inputbar/MentionModelsButton.tsx b/src/renderer/src/pages/home/Inputbar/MentionModelsButton.tsx index 75e1267e..249f1cda 100644 --- a/src/renderer/src/pages/home/Inputbar/MentionModelsButton.tsx +++ b/src/renderer/src/pages/home/Inputbar/MentionModelsButton.tsx @@ -266,6 +266,44 @@ const MentionModelsButton: FC = ({ mentionModels, onMentionModel: onSelec } }, [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 = (
{flatModelItems.length > 0 ? ( @@ -328,72 +366,145 @@ const MentionModelsButton: FC = ({ mentionModels, onMentionModel: onSelec } 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 { + &.ant-dropdown { + animation-duration: 0.15s !important; + margin-top: 4px; + } + .ant-dropdown-menu { max-height: 400px; overflow-y: auto; overflow-x: hidden; - padding: 4px 0; - margin-bottom: 40px; + padding: 4px 12px; 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 { - width: 6px; + width: 14px; height: 6px; } &::-webkit-scrollbar-thumb { - border-radius: 10px; - background: var(--color-scrollbar-thumb); + border: 4px solid transparent; + background-clip: padding-box; + border-radius: 7px; + background-color: transparent; + min-height: 50px; + transition: all 0.2s; + } - &:hover { - background: var(--color-scrollbar-thumb-hover); - } + &:hover::-webkit-scrollbar-thumb { + 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 { background: transparent; - } - - .no-results { - padding: 8px 12px; - color: var(--color-text-3); - cursor: default; - font-size: 14px; - - &:hover { - background: none; - } + border-radius: 7px; } } + // // Apply margin to the last group + // .ant-dropdown-menu-item-group:last-child { + // margin-bottom: 40px; + // } + .ant-dropdown-menu-item-group { + margin-bottom: 4px; + + &:not(:first-child) { + margin-top: 4px; + } + .ant-dropdown-menu-item-group-title { padding: 5px 12px; color: var(--color-text-3); 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 { padding: 5px 12px; + margin: 0 -12px; cursor: pointer; - transition: all 0.3s; + transition: all 0.3s cubic-bezier(0.4, 0.0, 0.2, 1); display: flex; align-items: center; gap: 8px; + border-radius: 6px; + font-size: 13px; &:hover { - background: var(--color-hover); + background: rgba(var(--color-hover-rgb), 0.5); } &.ant-dropdown-menu-item-selected { - background-color: var(--color-primary-bg); + background-color: rgba(var(--color-primary-rgb), 0.12); color: var(--color-primary); } .ant-dropdown-menu-item-icon { margin-right: 0; + opacity: 0.9; } } } @@ -403,7 +514,7 @@ const ModelItem = styled.div` display: flex; align-items: center; justify-content: space-between; - font-size: 14px; + font-size: 13px; width: 100%; min-width: 200px; gap: 16px; @@ -425,15 +536,15 @@ const ModelNameRow = styled.div` const PinIcon = styled.span.attrs({ className: 'pin-icon' })<{ $isPinned: boolean }>` margin-left: auto; padding: 0 8px; - opacity: ${(props) => (props.$isPinned ? 1 : 'inherit')}; - transition: opacity 0.2s; + opacity: ${(props) => (props.$isPinned ? 0.9 : 0)}; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); right: 0; color: ${(props) => (props.$isPinned ? 'var(--color-primary)' : 'inherit')}; transform: ${(props) => (props.$isPinned ? 'rotate(-45deg)' : 'none')}; - opacity: 0; + font-size: 13px; &:hover { - opacity: 1 !important; + opacity: ${(props) => (props.$isPinned ? 1 : 0.7)} !important; color: ${(props) => (props.$isPinned ? 'var(--color-primary)' : 'inherit')}; } `