refactor(mcp settings): enhance NpxSearch component layout and styling (#4053)
* refactor: mcp setting ui refactor * refactor(mcp settings): enhance NpxSearch component layout and styling
This commit is contained in:
parent
5712a58a5e
commit
eeb537048b
@ -8,6 +8,7 @@ import { Button, Card, Flex, Input, Space, Spin, Tag, Typography } from 'antd'
|
|||||||
import { npxFinder } from 'npx-scope-finder'
|
import { npxFinder } from 'npx-scope-finder'
|
||||||
import { type FC, useState } from 'react'
|
import { type FC, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import styled, { css } from 'styled-components'
|
||||||
|
|
||||||
import { SettingDivider, SettingGroup, SettingTitle } from '..'
|
import { SettingDivider, SettingGroup, SettingTitle } from '..'
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ let _searchResults: SearchResult[] = []
|
|||||||
const NpxSearch: FC = () => {
|
const NpxSearch: FC = () => {
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { Paragraph, Text, Link } = Typography
|
const { Text, Link } = Typography
|
||||||
|
|
||||||
// Add new state variables for npm scope search
|
// Add new state variables for npm scope search
|
||||||
const [npmScope, setNpmScope] = useState('@modelcontextprotocol')
|
const [npmScope, setNpmScope] = useState('@modelcontextprotocol')
|
||||||
@ -87,42 +88,44 @@ const NpxSearch: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingGroup theme={theme}>
|
<SettingGroup theme={theme} css={SettingGroupCss}>
|
||||||
<SettingTitle>{t('settings.mcp.npx_list.title')}</SettingTitle>
|
<div>
|
||||||
<SettingDivider />
|
<SettingTitle>
|
||||||
<Paragraph type="secondary" style={{ margin: '0 0 10px 0' }}>
|
{t('settings.mcp.npx_list.title')} <Text type="secondary">{t('settings.mcp.npx_list.desc')}</Text>
|
||||||
{t('settings.mcp.npx_list.desc')}
|
</SettingTitle>
|
||||||
</Paragraph>
|
<SettingDivider />
|
||||||
|
|
||||||
<Space direction="vertical" style={{ width: '100%' }}>
|
<Space direction="vertical" style={{ width: '100%' }}>
|
||||||
<Space.Compact style={{ width: '100%', marginBottom: 10 }}>
|
<Space.Compact style={{ width: '100%', marginBottom: 10 }}>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('settings.mcp.npx_list.scope_placeholder')}
|
placeholder={t('settings.mcp.npx_list.scope_placeholder')}
|
||||||
value={npmScope}
|
value={npmScope}
|
||||||
onChange={(e) => setNpmScope(e.target.value)}
|
onChange={(e) => setNpmScope(e.target.value)}
|
||||||
onPressEnter={handleNpmSearch}
|
onPressEnter={handleNpmSearch}
|
||||||
/>
|
/>
|
||||||
<Button icon={<SearchOutlined />} onClick={handleNpmSearch} disabled={searchLoading}>
|
<Button icon={<SearchOutlined />} onClick={handleNpmSearch} disabled={searchLoading}>
|
||||||
{t('settings.mcp.npx_list.search')}
|
{t('settings.mcp.npx_list.search')}
|
||||||
</Button>
|
</Button>
|
||||||
</Space.Compact>
|
</Space.Compact>
|
||||||
|
<HStack alignItems="center" mt="-5px" mb="5px">
|
||||||
<HStack alignItems="center" mt="-5px" mb="5px">
|
{npmScopes.map((scope) => (
|
||||||
{npmScopes.map((scope) => (
|
<Tag
|
||||||
<Tag
|
key={scope}
|
||||||
key={scope}
|
onClick={() => {
|
||||||
onClick={() => {
|
if (!searchLoading) {
|
||||||
if (!searchLoading) {
|
setNpmScope(scope)
|
||||||
setNpmScope(scope)
|
setTimeout(handleNpmSearch, 100)
|
||||||
setTimeout(handleNpmSearch, 100)
|
}
|
||||||
}
|
}}
|
||||||
}}
|
style={{ cursor: searchLoading ? 'not-allowed' : 'pointer' }}>
|
||||||
style={{ cursor: searchLoading ? 'not-allowed' : 'pointer' }}>
|
{scope}
|
||||||
{scope}
|
</Tag>
|
||||||
</Tag>
|
))}
|
||||||
))}
|
</HStack>
|
||||||
</HStack>
|
</Space>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ResultList>
|
||||||
{searchLoading ? (
|
{searchLoading ? (
|
||||||
<div style={{ textAlign: 'center', padding: '20px' }}>
|
<div style={{ textAlign: 'center', padding: '20px' }}>
|
||||||
<Spin />
|
<Spin />
|
||||||
@ -139,7 +142,7 @@ const NpxSearch: FC = () => {
|
|||||||
}
|
}
|
||||||
extra={
|
extra={
|
||||||
<Flex>
|
<Flex>
|
||||||
<Tag bordered={false} color="magenta">
|
<Tag bordered={false} color="processing">
|
||||||
v{record.version}
|
v{record.version}
|
||||||
</Tag>
|
</Tag>
|
||||||
<Button
|
<Button
|
||||||
@ -162,22 +165,38 @@ const NpxSearch: FC = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
}>
|
}>
|
||||||
<Space direction="vertical" size="small">
|
<Space direction="vertical" size="small">
|
||||||
<Text ellipsis={{ tooltip: true }}>{record.description}</Text>
|
<Text>{record.description}</Text>
|
||||||
<Text ellipsis={{ tooltip: true }} type="secondary">
|
<Text type="secondary">
|
||||||
{t('settings.mcp.npx_list.usage')}: {record.usage}
|
{t('settings.mcp.npx_list.usage')}: {record.usage}
|
||||||
</Text>
|
</Text>
|
||||||
<Text ellipsis={{ tooltip: true }}>
|
<Link href={record.npmLink} target="_blank" rel="noopener noreferrer">
|
||||||
<Link href={record.npmLink} target="_blank" rel="noopener noreferrer">
|
{record.npmLink}
|
||||||
{record.npmLink}
|
</Link>
|
||||||
</Link>
|
|
||||||
</Text>
|
|
||||||
</Space>
|
</Space>
|
||||||
</Card>
|
</Card>
|
||||||
))
|
))
|
||||||
) : null}
|
) : null}
|
||||||
</Space>
|
</ResultList>
|
||||||
</SettingGroup>
|
</SettingGroup>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SettingGroupCss = css`
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
`
|
||||||
|
|
||||||
|
const ResultList = styled.div`
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
width: calc(100% + 10px);
|
||||||
|
padding-right: 4px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
`
|
||||||
|
|
||||||
export default NpxSearch
|
export default NpxSearch
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { ThemeMode } from '@renderer/types'
|
import { ThemeMode } from '@renderer/types'
|
||||||
import { Divider } from 'antd'
|
import { Divider } from 'antd'
|
||||||
import Link from 'antd/es/typography/Link'
|
import Link from 'antd/es/typography/Link'
|
||||||
import styled from 'styled-components'
|
import styled, { CSSProp } from 'styled-components'
|
||||||
|
|
||||||
export const SettingContainer = styled.div<{ theme?: ThemeMode }>`
|
export const SettingContainer = styled.div<{ theme?: ThemeMode }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -80,7 +80,7 @@ export const SettingHelpLink = styled(Link)`
|
|||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
`
|
`
|
||||||
|
|
||||||
export const SettingGroup = styled.div<{ theme?: ThemeMode }>`
|
export const SettingGroup = styled.div<{ theme?: ThemeMode; css?: CSSProp }>`
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 0.5px solid var(--color-border);
|
border: 0.5px solid var(--color-border);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user