This commit is contained in:
2025-12-01 17:21:38 +08:00
parent 32fee2b8ab
commit fab8c13cb3
7511 changed files with 996300 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
'use client'
import type { FC } from 'react'
import classNames from '@/utils/classnames'
import useTheme from '@/hooks/use-theme'
import { basePath } from '@/utils/var'
export type LogoStyle = 'default' | 'monochromeWhite'
export const logoPathMap: Record<LogoStyle, string> = {
default: '/logo/logo.svg',
monochromeWhite: '/logo/logo-monochrome-white.svg',
}
export type LogoSize = 'large' | 'medium' | 'small'
export const logoSizeMap: Record<LogoSize, string> = {
large: 'w-16 h-7',
medium: 'w-12 h-[22px]',
small: 'w-9 h-4',
}
type DifyLogoProps = {
style?: LogoStyle
size?: LogoSize
className?: string
}
const DifyLogo: FC<DifyLogoProps> = ({
style = 'default',
size = 'medium',
className,
}) => {
const { theme } = useTheme()
const themedStyle = (theme === 'dark' && style === 'default') ? 'monochromeWhite' : style
return (
<img
src={`${basePath}${logoPathMap[themedStyle]}`}
className={classNames('block object-contain', logoSizeMap[size], className)}
alt='Dify logo'
/>
)
}
export default DifyLogo

View File

@@ -0,0 +1,82 @@
import type { Meta, StoryObj } from '@storybook/nextjs'
import { ThemeProvider } from 'next-themes'
import type { ReactNode } from 'react'
import DifyLogo from './dify-logo'
import LogoSite from './logo-site'
import LogoEmbeddedChatHeader from './logo-embedded-chat-header'
import LogoEmbeddedChatAvatar from './logo-embedded-chat-avatar'
const meta = {
title: 'Base/General/Logo',
component: DifyLogo,
parameters: {
layout: 'centered',
docs: {
description: {
component: 'Brand assets rendered in different contexts. DifyLogo adapts to the active theme while other variants target specific surfaces.',
},
},
},
args: {
size: 'medium',
style: 'default',
},
argTypes: {
size: {
control: 'radio',
options: ['large', 'medium', 'small'],
},
style: {
control: 'radio',
options: ['default', 'monochromeWhite'],
},
},
tags: ['autodocs'],
} satisfies Meta<typeof DifyLogo>
export default meta
type Story = StoryObj<typeof meta>
const ThemePreview = ({ theme, children }: { theme: 'light' | 'dark'; children: ReactNode }) => {
return (
<ThemeProvider attribute="data-theme" forcedTheme={theme} enableSystem={false}>
<div
className={'min-w-[320px] rounded-2xl border border-divider-subtle bg-background-default-subtle p-6 shadow-sm'}
>
{children}
</div>
</ThemeProvider>
)
}
export const Playground: Story = {
render: ({ size, style }) => {
return (
<ThemePreview theme="dark">
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-2">
<span className="text-xs uppercase tracking-[0.18em] text-text-tertiary">Primary logo</span>
<div className="flex items-center justify-between rounded-xl border border-divider-subtle bg-background-default p-4">
<DifyLogo size={size} style={style} />
<code className="text-[11px] text-text-tertiary">{`size="${size}" | style="${style}"`}</code>
</div>
</div>
<div className="grid gap-4 sm:grid-cols-2">
<div className="flex flex-col gap-2 rounded-xl border border-divider-subtle bg-background-default p-4">
<span className="text-[11px] font-medium uppercase tracking-[0.1em] text-text-tertiary">Site favicon</span>
<LogoSite />
</div>
<div className="flex flex-col gap-2 rounded-xl border border-divider-subtle bg-background-default p-4">
<span className="text-[11px] font-medium uppercase tracking-[0.1em] text-text-tertiary">Embedded header</span>
<LogoEmbeddedChatHeader />
</div>
<div className="flex flex-col gap-2 rounded-xl border border-divider-subtle bg-background-default p-4 sm:col-span-2">
<span className="text-[11px] font-medium uppercase tracking-[0.1em] text-text-tertiary">Embedded avatar</span>
<LogoEmbeddedChatAvatar className="border-divider-strong rounded-2xl border" />
</div>
</div>
</div>
</ThemePreview>
)
},
}

View File

@@ -0,0 +1,19 @@
import type { FC } from 'react'
import { basePath } from '@/utils/var'
type LogoEmbeddedChatAvatarProps = {
className?: string
}
const LogoEmbeddedChatAvatar: FC<LogoEmbeddedChatAvatarProps> = ({
className,
}) => {
return (
<img
src={`${basePath}/logo/logo-embedded-chat-avatar.png`}
className={`block h-10 w-10 ${className}`}
alt='logo'
/>
)
}
export default LogoEmbeddedChatAvatar

View File

@@ -0,0 +1,24 @@
import classNames from '@/utils/classnames'
import type { FC } from 'react'
import { basePath } from '@/utils/var'
type LogoEmbeddedChatHeaderProps = {
className?: string
}
const LogoEmbeddedChatHeader: FC<LogoEmbeddedChatHeaderProps> = ({
className,
}) => {
return <picture>
<source media="(resolution: 1x)" srcSet='/logo/logo-embedded-chat-header.png' />
<source media="(resolution: 2x)" srcSet='/logo/logo-embedded-chat-header@2x.png' />
<source media="(resolution: 3x)" srcSet='/logo/logo-embedded-chat-header@3x.png' />
<img
src={`${basePath}/logo/logo-embedded-chat-header.png`}
alt='logo'
className={classNames('block h-6 w-auto', className)}
/>
</picture>
}
export default LogoEmbeddedChatHeader

View File

@@ -0,0 +1,22 @@
'use client'
import type { FC } from 'react'
import { basePath } from '@/utils/var'
import classNames from '@/utils/classnames'
type LogoSiteProps = {
className?: string
}
const LogoSite: FC<LogoSiteProps> = ({
className,
}) => {
return (
<img
src={`${basePath}/logo/logo.png`}
className={classNames('block h-[24.5px] w-[22.651px]', className)}
alt='logo'
/>
)
}
export default LogoSite