mirror of
https://github.com/langgenius/dify.git
synced 2026-06-07 16:32:01 +08:00
fix(web): clean up header logo accessibility (#36567)
This commit is contained in:
parent
ffd336cfe8
commit
1e9c94b788
@ -5,6 +5,7 @@ import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import DifyLogo from '@/app/components/base/logo/dify-logo'
|
||||
import Link from '@/next/link'
|
||||
import { useRouter } from '@/next/navigation'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import Avatar from './avatar'
|
||||
@ -17,21 +18,26 @@ const Header = () => {
|
||||
const goToStudio = useCallback(() => {
|
||||
router.push('/apps')
|
||||
}, [router])
|
||||
const logoLabel = systemFeatures.branding.enabled && systemFeatures.branding.application_title ? systemFeatures.branding.application_title : 'Dify'
|
||||
|
||||
return (
|
||||
<div className="flex flex-1 items-center justify-between px-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex cursor-pointer items-center" onClick={goToStudio}>
|
||||
<Link
|
||||
href="/apps"
|
||||
className="flex items-center rounded-sm hover:opacity-80 focus-visible:ring-1 focus-visible:ring-components-input-border-active focus-visible:outline-hidden"
|
||||
aria-label={logoLabel}
|
||||
>
|
||||
{systemFeatures.branding.enabled && systemFeatures.branding.login_page_logo
|
||||
? (
|
||||
<img
|
||||
src={systemFeatures.branding.login_page_logo}
|
||||
className="block h-[22px] w-auto object-contain"
|
||||
alt="Dify logo"
|
||||
alt=""
|
||||
/>
|
||||
)
|
||||
: <DifyLogo />}
|
||||
</div>
|
||||
: <DifyLogo alt="" />}
|
||||
</Link>
|
||||
<div className="h-4 w-px origin-center rotate-[11.31deg] bg-divider-regular" />
|
||||
<p className="relative mt-[-2px] title-3xl-semi-bold text-text-primary">{t('account.account', { ns: 'common' })}</p>
|
||||
</div>
|
||||
|
||||
@ -58,6 +58,12 @@ describe('DifyLogo', () => {
|
||||
const img = screen.getByRole('img', { name: /dify logo/i })
|
||||
expect(img).toHaveClass('custom-test-class')
|
||||
})
|
||||
|
||||
it('applies custom alt text', () => {
|
||||
const { container } = render(<DifyLogo alt="" />)
|
||||
const img = container.querySelector('img')
|
||||
expect(img).toHaveAttribute('alt', '')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Theme behavior', () => {
|
||||
|
||||
@ -23,12 +23,14 @@ type DifyLogoProps = {
|
||||
style?: LogoStyle
|
||||
size?: LogoSize
|
||||
className?: string
|
||||
alt?: string
|
||||
}
|
||||
|
||||
const DifyLogo: FC<DifyLogoProps> = ({
|
||||
style = 'default',
|
||||
size = 'medium',
|
||||
className,
|
||||
alt = 'Dify logo',
|
||||
}) => {
|
||||
const { theme } = useTheme()
|
||||
const themedStyle = (theme === 'dark' && style === 'default') ? 'monochromeWhite' : style
|
||||
@ -37,7 +39,7 @@ const DifyLogo: FC<DifyLogoProps> = ({
|
||||
<img
|
||||
src={`${basePath}${logoPathMap[themedStyle]}`}
|
||||
className={cn('block object-contain', logoSizeMap[size], className)}
|
||||
alt="Dify logo"
|
||||
alt={alt}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { ReactElement } from 'react'
|
||||
import type { AnchorHTMLAttributes, ReactElement } from 'react'
|
||||
import { fireEvent, screen } from '@testing-library/react'
|
||||
import { vi } from 'vitest'
|
||||
import { renderWithSystemFeatures } from '@/__tests__/utils/mock-system-features'
|
||||
@ -55,7 +55,7 @@ vi.mock('@/context/workspace-context-provider', () => ({
|
||||
}))
|
||||
|
||||
vi.mock('@/next/link', () => ({
|
||||
default: ({ children, href }: { children?: React.ReactNode, href?: string }) => <a href={href}>{children}</a>,
|
||||
default: ({ children, href, ...props }: AnchorHTMLAttributes<HTMLAnchorElement> & { href?: string }) => <a href={href} {...props}>{children}</a>,
|
||||
}))
|
||||
|
||||
let mockIsWorkspaceEditor = false
|
||||
@ -122,7 +122,9 @@ describe('Header', () => {
|
||||
it('should render header with main nav components', () => {
|
||||
renderHeader()
|
||||
|
||||
expect(screen.getByRole('img', { name: /dify logo/i })).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: 'Dify' })).toHaveAttribute('href', '/apps')
|
||||
expect(screen.queryByRole('heading', { level: 1 })).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('img', { name: /dify logo/i })).not.toBeInTheDocument()
|
||||
expect(screen.getByTestId('workplace-selector')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('app-nav')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('account-dropdown')).toBeInTheDocument()
|
||||
@ -166,7 +168,7 @@ describe('Header', () => {
|
||||
mockMedia = 'mobile'
|
||||
renderHeader()
|
||||
|
||||
expect(screen.getByRole('img', { name: /dify logo/i })).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: 'Dify' })).toHaveAttribute('href', '/apps')
|
||||
expect(screen.queryByTestId('env-nav')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -177,8 +179,8 @@ describe('Header', () => {
|
||||
|
||||
renderHeader()
|
||||
|
||||
expect(screen.getByText('Acme Workspace')).toBeInTheDocument()
|
||||
expect(screen.getByRole('img', { name: /logo/i })).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: 'Acme Workspace' })).toHaveAttribute('href', '/apps')
|
||||
expect(screen.queryByRole('img', { name: /logo/i })).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('img', { name: /dify logo/i })).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -189,18 +191,18 @@ describe('Header', () => {
|
||||
|
||||
renderHeader()
|
||||
|
||||
expect(screen.getByText('Custom Title')).toBeInTheDocument()
|
||||
expect(screen.getByRole('img', { name: /dify logo/i })).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: 'Custom Title' })).toHaveAttribute('href', '/apps')
|
||||
expect(screen.queryByRole('img', { name: /dify logo/i })).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show default Dify text when branding enabled but no application_title', () => {
|
||||
it('should use default Dify link label when branding enabled but no application_title', () => {
|
||||
mockBrandingEnabled = true
|
||||
mockBrandingTitle = null
|
||||
mockBrandingLogo = null
|
||||
|
||||
renderHeader()
|
||||
|
||||
expect(screen.getByText('Dify')).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: 'Dify' })).toHaveAttribute('href', '/apps')
|
||||
})
|
||||
|
||||
it('should show dataset nav for editor who is not dataset operator', () => {
|
||||
|
||||
@ -44,21 +44,23 @@ const Header = () => {
|
||||
setShowAccountSettingModal({ payload: ACCOUNT_SETTING_TAB.BILLING })
|
||||
}, [isFreePlan, setShowAccountSettingModal, setShowPricingModal])
|
||||
|
||||
const logoLabel = isBrandingEnabled && systemFeatures.branding.application_title ? systemFeatures.branding.application_title : 'Dify'
|
||||
const renderLogo = () => (
|
||||
<h1>
|
||||
<Link href="/apps" className="flex h-8 shrink-0 items-center justify-center overflow-hidden px-0.5 indent-[-9999px] whitespace-nowrap">
|
||||
{isBrandingEnabled && systemFeatures.branding.application_title ? systemFeatures.branding.application_title : 'Dify'}
|
||||
{systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
|
||||
? (
|
||||
<img
|
||||
src={systemFeatures.branding.workspace_logo}
|
||||
className="block h-[22px] w-auto object-contain"
|
||||
alt="logo"
|
||||
/>
|
||||
)
|
||||
: <DifyLogo />}
|
||||
</Link>
|
||||
</h1>
|
||||
<Link
|
||||
href="/apps"
|
||||
className="flex h-8 shrink-0 items-center justify-center overflow-hidden rounded-sm px-0.5 hover:opacity-80 focus-visible:ring-1 focus-visible:ring-components-input-border-active focus-visible:outline-hidden"
|
||||
aria-label={logoLabel}
|
||||
>
|
||||
{systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
|
||||
? (
|
||||
<img
|
||||
src={systemFeatures.branding.workspace_logo}
|
||||
className="block h-[22px] w-auto object-contain"
|
||||
alt=""
|
||||
/>
|
||||
)
|
||||
: <DifyLogo alt="" />}
|
||||
</Link>
|
||||
)
|
||||
|
||||
if (isMobile) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user