mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-28 05:11:24 +08:00
feat: add Radix UI radio group component and update MCP settings UI
- Introduced a new RadioGroup component using Radix UI for better UI consistency. - Updated MCPProviderSettings to utilize the new RadioGroup and adjusted button styles for improved UX. - Added Radix UI radio group dependency to package.json and yarn.lock.
This commit is contained in:
parent
3417acafe2
commit
d2b6433609
@ -49,6 +49,7 @@
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@radix-ui/react-dialog": "^1.1.15",
|
||||
"@radix-ui/react-popover": "^1.1.15",
|
||||
"@radix-ui/react-radio-group": "^1.3.8",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-use-controllable-state": "^1.2.2",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
|
||||
28
packages/ui/src/components/ui/radio-group.tsx
Normal file
28
packages/ui/src/components/ui/radio-group.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import { cn } from '@cherrystudio/ui/utils/index'
|
||||
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'
|
||||
import { CircleIcon } from 'lucide-react'
|
||||
import * as React from 'react'
|
||||
|
||||
function RadioGroup({ className, ...props }: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
|
||||
return <RadioGroupPrimitive.Root data-slot="radio-group" className={cn('grid gap-3', className)} {...props} />
|
||||
}
|
||||
|
||||
function RadioGroupItem({ className, ...props }: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
|
||||
return (
|
||||
<RadioGroupPrimitive.Item
|
||||
data-slot="radio-group-item"
|
||||
className={cn(
|
||||
'border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className
|
||||
)}
|
||||
{...props}>
|
||||
<RadioGroupPrimitive.Indicator
|
||||
data-slot="radio-group-indicator"
|
||||
className="relative flex items-center justify-center">
|
||||
<CircleIcon className="fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" />
|
||||
</RadioGroupPrimitive.Indicator>
|
||||
</RadioGroupPrimitive.Item>
|
||||
)
|
||||
}
|
||||
|
||||
export { RadioGroup, RadioGroupItem }
|
||||
@ -1,7 +1,7 @@
|
||||
import { Flex, RowFlex } from '@cherrystudio/ui'
|
||||
import { Button, Flex, RowFlex } from '@cherrystudio/ui'
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import type { MCPServer } from '@renderer/types'
|
||||
import { Button, Divider, Input, Space } from 'antd'
|
||||
import { Divider, Input, Space } from 'antd'
|
||||
import Link from 'antd/es/typography/Link'
|
||||
import { SquareArrowOutUpRight } from 'lucide-react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
@ -17,7 +17,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const McpProviderSettings: React.FC<Props> = ({ provider, existingServers }) => {
|
||||
const { addMCPServer, updateMCPServer } = useMCPServers()
|
||||
const { addMCPServer } = useMCPServers()
|
||||
const [isFetching, setIsFetching] = useState(false)
|
||||
const [token, setToken] = useState<string>('')
|
||||
const [availableServers, setAvailableServers] = useState<MCPServer[]>([])
|
||||
@ -64,11 +64,13 @@ const McpProviderSettings: React.FC<Props> = ({ provider, existingServers }) =>
|
||||
<ProviderName>{provider.name}</ProviderName>
|
||||
{provider.discoverUrl && (
|
||||
<Link target="_blank" href={provider.discoverUrl} style={{ display: 'flex' }}>
|
||||
<Button type="text" size="small" icon={<SquareArrowOutUpRight size={14} />} />
|
||||
<Button variant="flat" size="sm">
|
||||
<SquareArrowOutUpRight size={14} />
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
</Flex>
|
||||
<Button type="primary" onClick={handleFetch} loading={isFetching} disabled={isFetchDisabled}>
|
||||
<Button variant="solid" onClick={handleFetch} isLoading={isFetching} isDisabled={isFetchDisabled}>
|
||||
{t('settings.mcp.fetch.button', 'Fetch Servers')}
|
||||
</Button>
|
||||
</ProviderHeader>
|
||||
@ -105,19 +107,18 @@ const McpProviderSettings: React.FC<Props> = ({ provider, existingServers }) =>
|
||||
<ServerDescription>{server.description}</ServerDescription>
|
||||
</ServerInfo>
|
||||
{(() => {
|
||||
const isAlreadyAdded = existingServers.some(existing => existing.id === server.id)
|
||||
const isAlreadyAdded = existingServers.some((existing) => existing.id === server.id)
|
||||
return (
|
||||
<Button
|
||||
type={isAlreadyAdded ? 'default' : 'primary'}
|
||||
size="small"
|
||||
variant={isAlreadyAdded ? 'bordered' : 'solid'}
|
||||
size="sm"
|
||||
disabled={isAlreadyAdded}
|
||||
onClick={() => {
|
||||
if (!isAlreadyAdded) {
|
||||
addMCPServer(server)
|
||||
window.toast.success(t('settings.mcp.server.added', 'MCP server added'))
|
||||
}
|
||||
}}
|
||||
>
|
||||
}}>
|
||||
{isAlreadyAdded ? t('settings.mcp.server.added', 'Added') : t('settings.mcp.add.server', 'Add')}
|
||||
</Button>
|
||||
)
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import type { MCPServer } from '@renderer/types'
|
||||
|
||||
import { getAI302Token, saveAI302Token, syncAi302Servers } from './302ai'
|
||||
import { getBailianToken, saveBailianToken, syncBailianServers } from './bailian'
|
||||
import { getTokenLanYunToken, LANYUN_KEY_HOST, saveTokenLanYunToken, syncTokenLanYunServers } from './lanyun'
|
||||
import { getModelScopeToken, MODELSCOPE_HOST, saveModelScopeToken, syncModelScopeServers } from './modelscope'
|
||||
import { getTokenFluxToken, saveTokenFluxToken, syncTokenFluxServers, TOKENFLUX_HOST } from './tokenflux'
|
||||
import type { MCPServer } from '@renderer/types'
|
||||
|
||||
export interface ProviderConfig {
|
||||
key: string
|
||||
@ -73,4 +74,4 @@ export const providers: ProviderConfig[] = [
|
||||
saveToken: saveBailianToken,
|
||||
syncServers: syncBailianServers
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@ -17,7 +17,7 @@ export const MCPRoutes = {
|
||||
tokenflux: '/settings/mcp/tokenflux',
|
||||
lanyun: '/settings/mcp/lanyun',
|
||||
'302ai': '/settings/mcp/302ai',
|
||||
bailian: '/settings/mcp/bailian',
|
||||
bailian: '/settings/mcp/bailian'
|
||||
} as const
|
||||
|
||||
/**
|
||||
@ -48,4 +48,4 @@ export function getMCPServerSettingsRoute(serverId: string): string {
|
||||
}
|
||||
|
||||
// 类型定义
|
||||
export type MCPPage = keyof typeof MCPRoutes
|
||||
export type MCPPage = keyof typeof MCPRoutes
|
||||
|
||||
42
yarn.lock
42
yarn.lock
@ -1920,6 +1920,7 @@ __metadata:
|
||||
"@heroui/react": "npm:^2.8.4"
|
||||
"@radix-ui/react-dialog": "npm:^1.1.15"
|
||||
"@radix-ui/react-popover": "npm:^1.1.15"
|
||||
"@radix-ui/react-radio-group": "npm:^1.3.8"
|
||||
"@radix-ui/react-slot": "npm:^1.2.3"
|
||||
"@radix-ui/react-use-controllable-state": "npm:^1.2.2"
|
||||
"@storybook/addon-docs": "npm:^9.1.6"
|
||||
@ -7323,6 +7324,34 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-radio-group@npm:^1.3.8":
|
||||
version: 1.3.8
|
||||
resolution: "@radix-ui/react-radio-group@npm:1.3.8"
|
||||
dependencies:
|
||||
"@radix-ui/primitive": "npm:1.1.3"
|
||||
"@radix-ui/react-compose-refs": "npm:1.1.2"
|
||||
"@radix-ui/react-context": "npm:1.1.2"
|
||||
"@radix-ui/react-direction": "npm:1.1.1"
|
||||
"@radix-ui/react-presence": "npm:1.1.5"
|
||||
"@radix-ui/react-primitive": "npm:2.1.3"
|
||||
"@radix-ui/react-roving-focus": "npm:1.1.11"
|
||||
"@radix-ui/react-use-controllable-state": "npm:1.2.2"
|
||||
"@radix-ui/react-use-previous": "npm:1.1.1"
|
||||
"@radix-ui/react-use-size": "npm:1.1.1"
|
||||
peerDependencies:
|
||||
"@types/react": "*"
|
||||
"@types/react-dom": "*"
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
"@types/react":
|
||||
optional: true
|
||||
"@types/react-dom":
|
||||
optional: true
|
||||
checksum: 10c0/23af8e8b833da1fc4aa4e67c3607dedee4fc5b39278d2e2b820bec7f7b3c0891b006a8a35c57ba436ddf18735bbd8dad9a598d14632a328753a875fde447975c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-roving-focus@npm:1.1.11":
|
||||
version: 1.1.11
|
||||
resolution: "@radix-ui/react-roving-focus@npm:1.1.11"
|
||||
@ -7437,6 +7466,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-use-previous@npm:1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "@radix-ui/react-use-previous@npm:1.1.1"
|
||||
peerDependencies:
|
||||
"@types/react": "*"
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
"@types/react":
|
||||
optional: true
|
||||
checksum: 10c0/52f1089d941491cd59b7f52a5679a14e9381711419a0557ce0f3bc9a4c117078224efec54dcced41a3653a13a386a7b6ec75435d61a273e8b9f5d00235f2b182
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@radix-ui/react-use-rect@npm:1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "@radix-ui/react-use-rect@npm:1.1.1"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user