124 lines
3.7 KiB
TypeScript
124 lines
3.7 KiB
TypeScript
import Link from 'next/link'
|
|
import { ConditionalPublishButton } from './ConditionalPublishButton'
|
|
import { LanguageSelector } from './LanguageSelector'
|
|
import { t } from '@/lib/i18n'
|
|
import { KeyIndicator } from './KeyIndicator'
|
|
|
|
function GitIcon(): React.ReactElement {
|
|
return (
|
|
<svg
|
|
className="w-5 h-5"
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path d="M23.546 10.93L13.067.452c-.604-.603-1.582-.603-2.188 0L8.708 2.627l2.76 2.76c.645-.215 1.379-.07 1.889.441.516.515.658 1.258.438 1.9l2.658 2.66c.645-.223 1.387-.078 1.9.435.721.72.721 1.884 0 2.604-.719.719-1.881.719-2.6 0-.539-.541-.674-1.337-.404-1.996L12.86 8.955v6.525c.176.086.342.203.488.348.713.721.713 1.883 0 2.6-.719.721-1.884.721-2.599 0-.719-.719-.719-1.879 0-2.598.182-.18.387-.316.605-.406V8.835c-.217-.091-.424-.222-.6-.401-.545-.545-.676-1.342-.396-2.009L7.496 3.866.45 10.913c-.6.605-.6 1.584 0 2.189l10.484 10.481c.604.604 1.582.604 2.186 0l10.43-10.43c.605-.603.605-1.584 0-2.189z" />
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function DocsIcon(): React.ReactElement {
|
|
return (
|
|
<svg
|
|
className="w-5 h-5"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
|
<polyline points="14 2 14 8 20 8" />
|
|
<line x1="16" y1="13" x2="8" y2="13" />
|
|
<line x1="16" y1="17" x2="8" y2="17" />
|
|
<polyline points="10 9 9 9 8 9" />
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function FundingIcon(): React.ReactElement {
|
|
return (
|
|
<svg
|
|
className="w-5 h-5"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<line x1="12" y1="1" x2="12" y2="23" />
|
|
<path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" />
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
export function PageHeader(): React.ReactElement {
|
|
return (
|
|
<header role="navigation" className="bg-cyber-dark border-b border-neon-cyan/30 shadow-glow-cyan">
|
|
<div className="max-w-4xl mx-auto px-4 py-4 flex justify-between items-center">
|
|
<HeaderLeft />
|
|
<HeaderRight />
|
|
</div>
|
|
</header>
|
|
)
|
|
}
|
|
|
|
function HeaderLeft(): React.ReactElement {
|
|
return (
|
|
<div className="flex items-center gap-2">
|
|
<Link href="/" className="text-2xl font-bold text-neon-cyan text-glow-cyan font-mono hover:text-neon-green transition-colors">
|
|
{t('home.title')}
|
|
</Link>
|
|
<HeaderLinks />
|
|
<KeyIndicator />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function HeaderLinks(): React.ReactElement {
|
|
return (
|
|
<>
|
|
<Link
|
|
href="/docs"
|
|
className="text-cyber-accent hover:text-neon-cyan transition-colors"
|
|
title={t('nav.documentation')}
|
|
aria-label={t('nav.documentation')}
|
|
>
|
|
<DocsIcon />
|
|
</Link>
|
|
<Link
|
|
href="/funding"
|
|
className="text-cyber-accent hover:text-neon-cyan transition-colors"
|
|
title={t('funding.title')}
|
|
aria-label={t('funding.title')}
|
|
>
|
|
<FundingIcon />
|
|
</Link>
|
|
<a
|
|
href="https://git.4nkweb.com/4nk/story-research-zapwall"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-cyber-accent hover:text-neon-cyan transition-colors"
|
|
title={t('common.repositoryGit')}
|
|
aria-label={t('common.repositoryGit')}
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<GitIcon />
|
|
</a>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function HeaderRight(): React.ReactElement {
|
|
return (
|
|
<div className="flex items-center gap-4">
|
|
<LanguageSelector />
|
|
<ConditionalPublishButton />
|
|
</div>
|
|
)
|
|
}
|