🔧 refactor(UI): Consolidate dropdown styles and remove global styles

- Remove global style components from MentionModelsButton and MCPToolsButton
- Move dropdown styles to a centralized SCSS file
- Refactor components to use styled-components for localized styling
- Improve code organization and reduce redundant styling
- Adjust table column widths in MCPSettings for better layout
- Simplify dropdown rendering by removing unnecessary fragments
This commit is contained in:
kangfenmao 2025-03-08 00:34:02 +08:00
parent d714a53dc6
commit 602a6a5f66
4 changed files with 238 additions and 284 deletions

View File

@ -53,3 +53,142 @@
background-color: initial !important;
}
}
.mention-models-dropdown {
&.ant-dropdown {
background: rgba(var(--color-base-rgb), 0.65) !important;
backdrop-filter: blur(35px) saturate(150%) !important;
animation-duration: 0.15s !important;
}
/* 移动其他样式到 mention-models-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;
}
.ant-dropdown-menu {
/* 保持原有的下拉菜单样式,但限定在 mention-models-dropdown 类下 */
max-height: 400px;
overflow-y: auto;
overflow-x: hidden;
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, var(--inner-glow-opacity, 0.1));
transform-origin: top;
will-change: transform, opacity;
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
margin-bottom: 0;
&.no-scrollbar {
padding-right: 12px;
}
&.has-scrollbar {
padding-right: 2px;
}
// Scrollbar styles
&::-webkit-scrollbar {
width: 14px;
height: 6px;
}
&::-webkit-scrollbar-thumb {
border: 4px solid transparent;
background-clip: padding-box;
border-radius: 7px;
background-color: var(--color-scrollbar-thumb);
min-height: 50px;
transition: all 0.2s;
}
&:hover::-webkit-scrollbar-thumb {
background-color: var(--color-scrollbar-thumb);
}
&::-webkit-scrollbar-thumb:hover {
background-color: var(--color-scrollbar-thumb-hover);
}
&::-webkit-scrollbar-thumb:active {
background-color: var(--color-scrollbar-thumb-hover);
}
&::-webkit-scrollbar-track {
background: transparent;
border-radius: 7px;
}
}
.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 cubic-bezier(0.4, 0, 0.2, 1);
display: flex;
align-items: center;
gap: 8px;
border-radius: 6px;
font-size: 13px;
&:hover {
background: rgba(var(--color-hover-rgb), 0.5);
}
&.ant-dropdown-menu-item-selected {
background-color: rgba(var(--color-primary-rgb), 0.12);
color: var(--color-primary);
}
.ant-dropdown-menu-item-icon {
margin-right: 0;
opacity: 0.9;
}
}
}

View File

@ -3,7 +3,7 @@ import { MCPServer } from '@renderer/types'
import { Dropdown, Switch, Tooltip } from 'antd'
import { FC, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { createGlobalStyle } from 'styled-components'
import styled from 'styled-components'
interface Props {
enabledMCPs: MCPServer[]
@ -43,7 +43,7 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, onEnableMCP, ToolbarButton })
const menu = (
<div ref={menuRef} className="ant-dropdown-menu">
<div className="dropdown-header">
<DropdownHeader className="dropdown-header">
<div className="header-content">
<h4>{t('settings.mcp.title')}</h4>
<div className="enable-all-container">
@ -51,12 +51,12 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, onEnableMCP, ToolbarButton })
<Switch size="small" checked={enableAll} onChange={setEnableAll} />
</div>
</div>
</div>
</DropdownHeader>
{mcpServers.length > 0 ? (
mcpServers
.filter((s) => s.isActive)
.map((server) => (
<div key={server.name} className="ant-dropdown-menu-item mcp-server-item">
<McpServerItems key={server.name} className="ant-dropdown-menu-item">
<div className="server-info">
<div className="server-name">{server.name}</div>
{server.description && (
@ -67,7 +67,7 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, onEnableMCP, ToolbarButton })
{server.baseUrl && <div className="server-url">{server.baseUrl}</div>}
</div>
<Switch size="small" checked={enabledMCPs.includes(server)} onChange={() => onEnableMCP(server)} />
</div>
</McpServerItems>
))
) : (
<div className="ant-dropdown-menu-item-group">
@ -78,8 +78,6 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, onEnableMCP, ToolbarButton })
)
return (
<>
<DropdownMenuStyle />
<Dropdown
dropdownRender={() => menu}
trigger={['click']}
@ -92,80 +90,10 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, onEnableMCP, ToolbarButton })
</ToolbarButton>
</Tooltip>
</Dropdown>
</>
)
}
const DropdownMenuStyle = createGlobalStyle`
.mention-models-dropdown {
.ant-dropdown-menu {
max-height: 400px;
overflow-y: auto;
overflow-x: hidden;
padding: 4px 0;
margin-bottom: 40px;
position: relative;
&::-webkit-scrollbar {
width: 6px;
height: 6px;
}
&::-webkit-scrollbar-thumb {
border-radius: 10px;
background: var(--color-scrollbar-thumb);
&:hover {
background: var(--color-scrollbar-thumb-hover);
}
}
&::-webkit-scrollbar-track {
background: transparent;
}
.no-results {
padding: 8px 12px;
color: var(--color-text-3);
cursor: default;
font-size: 14px;
&:hover {
background: none;
}
}
.dropdown-header {
padding: 8px 12px;
border-bottom: 1px solid var(--color-border);
margin-bottom: 4px;
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
}
h4 {
margin: 0;
color: var(--color-text-1);
font-size: 14px;
font-weight: 500;
}
.enable-all-container {
display: flex;
align-items: center;
gap: 8px;
.enable-all-label {
font-size: 12px;
color: var(--color-text-3);
}
}
}
.mcp-server-item {
const McpServerItems = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
@ -196,7 +124,35 @@ const DropdownMenuStyle = createGlobalStyle`
margin-top: 2px;
}
}
`
const DropdownHeader = styled.div`
padding: 8px 12px;
border-bottom: 1px solid var(--color-border);
margin-bottom: 4px;
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
}
h4 {
margin: 0;
color: var(--color-text-1);
font-size: 14px;
font-weight: 500;
}
.enable-all-container {
display: flex;
align-items: center;
gap: 8px;
.enable-all-label {
font-size: 12px;
color: var(--color-text-3);
}
}
`

View File

@ -10,7 +10,7 @@ import { Avatar, Dropdown, Tooltip } from 'antd'
import { first, sortBy } from 'lodash'
import { FC, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled, { createGlobalStyle } from 'styled-components'
import styled from 'styled-components'
interface Props {
mentionModels: Model[]
@ -348,8 +348,6 @@ const MentionModelsButton: FC<Props> = ({ mentionModels, onMentionModel: onSelec
)
return (
<>
<DropdownMenuStyle />
<Dropdown
overlayStyle={{ marginBottom: 20 }}
dropdownRender={() => menu}
@ -366,151 +364,9 @@ const MentionModelsButton: FC<Props> = ({ mentionModels, onMentionModel: onSelec
</ToolbarButton>
</Tooltip>
</Dropdown>
</>
)
}
const DropdownMenuStyle = createGlobalStyle`
/* 将样式限定在 mention-models-dropdown 类下 */
.mention-models-dropdown {
&.ant-dropdown {
background: rgba(var(--color-base-rgb), 0.65) !important;
backdrop-filter: blur(35px) saturate(150%) !important;
animation-duration: 0.15s !important;
}
/* 移动其他样式到 mention-models-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;
}
.ant-dropdown-menu {
/* 保持原有的下拉菜单样式,但限定在 mention-models-dropdown 类下 */
max-height: 400px;
overflow-y: auto;
overflow-x: hidden;
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, var(--inner-glow-opacity, 0.1));
transform-origin: top;
will-change: transform, opacity;
transition: all 0.15s cubic-bezier(0.4, 0.0, 0.2, 1);
margin-bottom: 0;
&.no-scrollbar {
padding-right: 12px;
}
&.has-scrollbar {
padding-right: 2px;
}
// Scrollbar styles
&::-webkit-scrollbar {
width: 14px;
height: 6px;
}
&::-webkit-scrollbar-thumb {
border: 4px solid transparent;
background-clip: padding-box;
border-radius: 7px;
background-color: var(--color-scrollbar-thumb);
min-height: 50px;
transition: all 0.2s;
}
&:hover::-webkit-scrollbar-thumb {
background-color: var(--color-scrollbar-thumb);
}
&::-webkit-scrollbar-thumb:hover {
background-color: var(--color-scrollbar-thumb-hover);
}
&::-webkit-scrollbar-thumb:active {
background-color: var(--color-scrollbar-thumb-hover);
}
&::-webkit-scrollbar-track {
background: transparent;
border-radius: 7px;
}
}
.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 cubic-bezier(0.4, 0.0, 0.2, 1);
display: flex;
align-items: center;
gap: 8px;
border-radius: 6px;
font-size: 13px;
&:hover {
background: rgba(var(--color-hover-rgb), 0.5);
}
&.ant-dropdown-menu-item-selected {
background-color: rgba(var(--color-primary-rgb), 0.12);
color: var(--color-primary);
}
.ant-dropdown-menu-item-icon {
margin-right: 0;
opacity: 0.9;
}
}
}
`
const ModelItem = styled.div`
display: flex;
align-items: center;

View File

@ -189,20 +189,20 @@ const MCPSettings: FC = () => {
title: t('settings.mcp.name'),
dataIndex: 'name',
key: 'name',
width: '10%',
width: '300px',
render: (text: string, record: MCPServer) => <Text strong={record.isActive}>{text}</Text>
},
{
title: t('settings.mcp.type'),
key: 'type',
width: '5%',
width: '100px',
render: (_: any, record: MCPServer) => <Tag color="cyan">{record.baseUrl ? 'SSE' : 'STDIO'}</Tag>
},
{
title: t('settings.mcp.description'),
dataIndex: 'description',
key: 'description',
width: '50%',
width: 'auto',
render: (text: string) => {
if (!text) {
return (
@ -231,7 +231,7 @@ const MCPSettings: FC = () => {
title: t('settings.mcp.active'),
dataIndex: 'isActive',
key: 'isActive',
width: '5%',
width: '100px',
render: (isActive: boolean, record: MCPServer) => (
<Switch checked={isActive} onChange={(checked) => handleToggleActive(record.name, checked)} />
)
@ -239,7 +239,7 @@ const MCPSettings: FC = () => {
{
title: t('settings.mcp.actions'),
key: 'actions',
width: '10%',
width: '100px',
render: (_: any, record: MCPServer) => (
<Space>
<Tooltip title={t('common.edit')}>
@ -283,7 +283,10 @@ const MCPSettings: FC = () => {
</Text>
</div>
<Card bordered={false} style={{ background: theme === 'dark' ? '#1f1f1f' : '#fff' }}>
<Card
bordered={false}
style={{ background: theme === 'dark' ? '#1f1f1f' : '#fff' }}
styles={{ body: { padding: 0 } }}>
<Table
dataSource={mcpServers}
columns={columns}
@ -350,11 +353,11 @@ const MCPSettings: FC = () => {
</Form.Item>
<Form.Item name="args" label={t('settings.mcp.args')} tooltip={t('settings.mcp.argsTooltip')}>
<TextArea rows={3} placeholder="arg1\narg2" style={{ fontFamily: 'monospace' }} />
<TextArea rows={3} placeholder={`arg1\narg2`} style={{ fontFamily: 'monospace' }} />
</Form.Item>
<Form.Item name="env" label={t('settings.mcp.env')} tooltip={t('settings.mcp.envTooltip')}>
<TextArea rows={3} placeholder="KEY1=value1\nKEY2=value2" style={{ fontFamily: 'monospace' }} />
<TextArea rows={3} placeholder={`KEY1=value1\nKEY2=value2`} style={{ fontFamily: 'monospace' }} />
</Form.Item>
</>
)}