feat: no data placeholder

This commit is contained in:
Joel 2025-06-27 10:36:54 +08:00
parent d114485abd
commit bc1e4c88e0
8 changed files with 150 additions and 0 deletions

View File

@ -0,0 +1,7 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M28.0049 16C28.0049 20.4183 24.4231 24 20.0049 24C15.5866 24 12.0049 20.4183 12.0049 16C12.0049 11.5817 15.5866 8 20.0049 8C24.4231 8 28.0049 11.5817 28.0049 16Z" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.00488 16H6.67155" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.00488 9.33334H8.00488" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.00488 22.6667H8.00488" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M26 22L29.3333 25.3333" stroke="#676F83" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 823 B

View File

@ -0,0 +1,77 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "32",
"height": "32",
"viewBox": "0 0 32 32",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M28.0049 16C28.0049 20.4183 24.4231 24 20.0049 24C15.5866 24 12.0049 20.4183 12.0049 16C12.0049 11.5817 15.5866 8 20.0049 8C24.4231 8 28.0049 11.5817 28.0049 16Z",
"stroke": "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M4.00488 16H6.67155",
"stroke": "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M4.00488 9.33334H8.00488",
"stroke": "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M4.00488 22.6667H8.00488",
"stroke": "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M26 22L29.3333 25.3333",
"stroke": "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
},
"name": "SearchMenu"
}

View File

@ -0,0 +1,20 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './SearchMenu.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconData } from '@/app/components/base/icons/IconBase'
const Icon = (
{
ref,
...props
}: React.SVGProps<SVGSVGElement> & {
ref?: React.RefObject<React.MutableRefObject<HTMLOrSVGElement>>;
},
) => <IconBase {...props} ref={ref} data={data as IconData} />
Icon.displayName = 'SearchMenu'
export default Icon

View File

@ -19,6 +19,7 @@ export { default as Pin01 } from './Pin01'
export { default as Pin02 } from './Pin02'
export { default as Plus02 } from './Plus02'
export { default as Refresh } from './Refresh'
export { default as SearchMenu } from './SearchMenu'
export { default as Settings01 } from './Settings01'
export { default as Settings04 } from './Settings04'
export { default as Target04 } from './Target04'

View File

@ -0,0 +1,31 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import cn from '@/utils/classnames'
import { Group } from '@/app/components/base/icons/src/vender/other'
import { SearchMenu } from '@/app/components/base/icons/src/vender/line/general'
import { useTranslation } from 'react-i18next'
type Props = {
className: string
noPlugins?: boolean
}
const NoDataPlaceholder: FC<Props> = ({
className,
noPlugins,
}) => {
const { t } = useTranslation()
const icon = noPlugins ? (<Group className='size-6 text-text-quaternary' />) : (<SearchMenu className='size-8 text-text-tertiary' />)
const text = t(`plugin.autoUpdate.noPluginPlaceholder.${noPlugins ? 'noInstalled' : 'noFound'}`)
return (
<div className={cn('flex items-center justify-center', className)}>
<div className='flex flex-col items-center'>
{icon}
<div className='system-sm-regular mt-2 text-text-tertiary'>{text}</div>
</div>
</div>
)
}
export default React.memo(NoDataPlaceholder)

View File

@ -13,6 +13,7 @@ import { useTranslation } from 'react-i18next'
import cn from '@/utils/classnames'
import ToolItem from './tool-item'
import Loading from '@/app/components/base/loading'
import NoDataPlaceholder from './no-data-placeholder'
type Props = {
trigger: React.ReactNode
@ -100,6 +101,10 @@ const ToolPicker: FC<Props> = ({
</div>
)
const noData = (
<NoDataPlaceholder className='h-[396px]' noPlugins={!query} />
)
return (
<PortalToFollowElem
placement='top'
@ -145,6 +150,7 @@ const ToolPicker: FC<Props> = ({
</div>
</div>
{!isLoading && list.length > 0 && listContent}
{!isLoading && list.length === 0 && noData}
{isLoading && loadingContent}
</div>
</PortalToFollowElemContent>

View File

@ -156,6 +156,10 @@ const translation = {
downgrade: 'Downgrade anyway',
exclude: 'Exclude from auto-update',
},
noPluginPlaceholder: {
noFound: 'No plugins were found',
noInstalled: 'No plugins installed',
},
},
pluginInfoModal: {
title: 'Plugin info',

View File

@ -156,6 +156,10 @@ const translation = {
downgrade: '仍然降级',
exclude: '从自动更新中排除',
},
noPluginPlaceholder: {
noFound: '未找到插件',
noInstalled: '未安装插件',
},
},
pluginInfoModal: {
title: '插件信息',