chore: update hub UI (#4734)

* chore: update hub ui based feedback

* chore: update hub ui

* chore: code block ui

* chore: update bg color

* chore: decrease margin codeblock
This commit is contained in:
Faisal Amir 2025-02-25 14:37:15 +07:00 committed by GitHub
parent 99f324286b
commit 51f8c96a57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 48 additions and 9 deletions

View File

@ -3,6 +3,8 @@ import { useCallback, useMemo } from 'react'
import { Button, Tooltip } from '@janhq/joi' import { Button, Tooltip } from '@janhq/joi'
import { useAtomValue, useSetAtom } from 'jotai' import { useAtomValue, useSetAtom } from 'jotai'
import { twMerge } from 'tailwind-merge'
import { MainViewState } from '@/constants/screens' import { MainViewState } from '@/constants/screens'
import { useCreateNewThread } from '@/hooks/useCreateNewThread' import { useCreateNewThread } from '@/hooks/useCreateNewThread'
@ -22,8 +24,9 @@ interface Props {
id: string id: string
theme?: 'primary' | 'ghost' | 'icon' | 'destructive' | undefined theme?: 'primary' | 'ghost' | 'icon' | 'destructive' | undefined
variant?: 'solid' | 'soft' | 'outline' | undefined variant?: 'solid' | 'soft' | 'outline' | undefined
className?: string
} }
const ModelDownloadButton = ({ id, theme, variant }: Props) => { const ModelDownloadButton = ({ id, theme, variant, className }: Props) => {
const { downloadModel } = useDownloadModel() const { downloadModel } = useDownloadModel()
const downloadingModels = useAtomValue(getDownloadingModelAtom) const downloadingModels = useAtomValue(getDownloadingModelAtom)
const downloadedModels = useAtomValue(downloadedModelsAtom) const downloadedModels = useAtomValue(downloadedModelsAtom)
@ -59,7 +62,8 @@ const ModelDownloadButton = ({ id, theme, variant }: Props) => {
const defaultButton = ( const defaultButton = (
<Button <Button
theme={theme ? theme : 'primary'} theme={theme ? theme : 'primary'}
variant={variant ? variant : 'solid'} // variant={variant ? variant : 'solid'}
className={twMerge('min-w-[70px]', className)}
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
onDownloadClick() onDownloadClick()

View File

@ -1,12 +1,16 @@
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
import { ModelSource } from '@janhq/core' import Image from 'next/image'
import { InferenceEngine, ModelSource } from '@janhq/core'
import { Button, Tooltip, Dropdown, Badge } from '@janhq/joi' import { Button, Tooltip, Dropdown, Badge } from '@janhq/joi'
import { useAtomValue, useSetAtom } from 'jotai' import { useAtomValue, useSetAtom } from 'jotai'
import { ChevronDownIcon } from 'lucide-react' import { ChevronDownIcon } from 'lucide-react'
import { twMerge } from 'tailwind-merge'
import ModalCancelDownload from '@/containers/ModalCancelDownload' import ModalCancelDownload from '@/containers/ModalCancelDownload'
import { MainViewState } from '@/constants/screens' import { MainViewState } from '@/constants/screens'
@ -18,6 +22,7 @@ import { useSettings } from '@/hooks/useSettings'
import { toGigabytes } from '@/utils/converter' import { toGigabytes } from '@/utils/converter'
import { getLogoEngine } from '@/utils/modelEngine'
import { extractModelName } from '@/utils/modelSource' import { extractModelName } from '@/utils/modelSource'
import { fuzzySearch } from '@/utils/search' import { fuzzySearch } from '@/utils/search'
@ -167,9 +172,23 @@ const ModelItemHeader = ({ model, onSelectedModel }: Props) => {
<div className="flex items-center justify-between py-2"> <div className="flex items-center justify-between py-2">
<div className="group flex cursor-pointer items-center gap-2"> <div className="group flex cursor-pointer items-center gap-2">
<span <span
className="line-clamp-1 text-base font-medium capitalize group-hover:text-blue-500 group-hover:underline" className={twMerge(
'line-clamp-1 text-base font-medium capitalize group-hover:text-blue-500 group-hover:underline',
model.type === 'cloud' && 'flex items-center gap-x-2'
)}
onClick={onSelectedModel} onClick={onSelectedModel}
> >
{model.type === 'cloud' && (
<>
<Image
className="h-6 w-6 flex-shrink-0"
width={48}
height={48}
src={getLogoEngine(model.id as InferenceEngine) || ''}
alt="logo"
/>
</>
)}
{extractModelName(model.metadata?.id)} {extractModelName(model.metadata?.id)}
</span> </span>
</div> </div>

View File

@ -14,6 +14,8 @@ import {
import Spinner from '@/containers/Loader/Spinner' import Spinner from '@/containers/Loader/Spinner'
import ModelDownloadButton from '@/containers/ModelDownloadButton' import ModelDownloadButton from '@/containers/ModelDownloadButton'
import ModelLabel from '@/containers/ModelLabel'
import { MainViewState } from '@/constants/screens' import { MainViewState } from '@/constants/screens'
import { useRefreshModelList } from '@/hooks/useEngineManagement' import { useRefreshModelList } from '@/hooks/useEngineManagement'
@ -146,6 +148,7 @@ const ModelPage = ({ model, onGoBack }: Props) => {
</th> </th>
{model.type !== 'cloud' && ( {model.type !== 'cloud' && (
<> <>
<th></th>
<th className="hidden max-w-32 px-6 py-3 text-left text-sm font-semibold sm:table-cell"> <th className="hidden max-w-32 px-6 py-3 text-left text-sm font-semibold sm:table-cell">
Format Format
</th> </th>
@ -201,6 +204,9 @@ const ModelPage = ({ model, onGoBack }: Props) => {
</td> </td>
{model.type !== 'cloud' && ( {model.type !== 'cloud' && (
<> <>
<td>
<ModelLabel size={item.size} compact />
</td>
<td className="hidden px-6 py-4 sm:table-cell"> <td className="hidden px-6 py-4 sm:table-cell">
GGUF GGUF
</td> </td>
@ -215,7 +221,11 @@ const ModelPage = ({ model, onGoBack }: Props) => {
<ModelDownloadButton <ModelDownloadButton
id={item.id} id={item.id}
theme={i === 0 ? 'primary' : 'ghost'} theme={i === 0 ? 'primary' : 'ghost'}
variant={i === 0 ? 'solid' : 'outline'} className={
i !== 0
? '!bg-[hsla(var(--secondary-bg))]'
: ''
}
/> />
)} )}
</td> </td>

View File

@ -79,7 +79,7 @@ const filterOptions = [
}, },
] ]
const hubCompatibleAtom = atom(false) const hubCompatibleAtom = atom(true)
const HubScreen = () => { const HubScreen = () => {
const { sources } = useGetModelSources() const { sources } = useGetModelSources()
@ -450,7 +450,7 @@ const HubScreen = () => {
{/* Filters and Model List */} {/* Filters and Model List */}
<div className="ml-4 mt-8 flex h-full w-full flex-row"> <div className="ml-4 mt-8 flex h-full w-full flex-row">
{/* Filters */} {/* Filters */}
<div className="sticky top-10 mr-6 hidden h-full w-[200px] shrink-0 flex-col md:flex"> <div className="sticky top-8 mr-6 hidden h-full w-[200px] shrink-0 flex-col md:flex">
<div className="flex w-full flex-row justify-between"> <div className="flex w-full flex-row justify-between">
Filters Filters
<button <button

View File

@ -107,7 +107,6 @@ export const MarkdownTextMessage = memo(
'code-block', 'code-block',
'group/item', 'group/item',
'relative', 'relative',
'my-4',
'overflow-auto', 'overflow-auto',
], ],
}, },

View File

@ -60,7 +60,6 @@
border-bottom-left-radius: 0.4rem; border-bottom-left-radius: 0.4rem;
border-bottom-right-radius: 0.4rem; border-bottom-right-radius: 0.4rem;
color: #f8f8f2; color: #f8f8f2;
background: hsla(var(--app-code-block)) !important;
} }
pre { pre {

View File

@ -51,6 +51,8 @@
overflow-x: auto; overflow-x: auto;
font-size: 0.9rem; font-size: 0.9rem;
margin: 1rem 0; margin: 1rem 0;
padding: 16px;
background-color: hsla(var(--app-code-block)) !important;
} }
/* Tables */ /* Tables */

View File

@ -28,4 +28,10 @@
blockquote { blockquote {
@apply inline-flex flex-col border-s-4 border-[hsla(var(--primary-bg))] bg-[hsla(var(--primary-bg-soft))] px-4 py-2; @apply inline-flex flex-col border-s-4 border-[hsla(var(--primary-bg))] bg-[hsla(var(--primary-bg-soft))] px-4 py-2;
} }
.markdown-content pre {
margin-top: 0 !important;
border-top-left-radius: 0 !important;
border-top-right-radius: 0 !important;
}
} }