Files
lms-fe/src/renderer/src/features/workspace/WorkspaceNav.tsx
T

123 lines
5.3 KiB
TypeScript

import { t, useLocaleRender } from '../../i18n'
import { Code2, FileCode2, GitBranch, Network, Radio, Search, Settings, Terminal } from 'lucide-react'
import type React from 'react'
export type WorkspaceActivity = 'modules' | 'ros-connections' | 'workspace' | 'search' | 'logs' | 'examples' | 'git' | 'settings'
type WorkspaceNavProps = {
dark: boolean
workspaceActive: boolean
activeActivity: WorkspaceActivity
selectedModuleExists: boolean
installedGitModuleCount: number
teamProject: boolean
moduleTabCount: number
gitChangedFileCount: number
workspaceNavFlash: boolean
onSelect: (activity: WorkspaceActivity) => void
}
const WORKSPACE_NAV_ITEMS: Array<{
id: WorkspaceActivity
Icon: typeof Network
label: string
}> = [
{ id: 'modules', Icon: Network, label: '모듈 리스트' },
{ id: 'ros-connections', Icon: Radio, label: 'ROS 연결상태' },
{ id: 'workspace', Icon: Code2, label: '코드 편집' },
{ id: 'search', Icon: Search, label: '검색' },
{ id: 'logs', Icon: Terminal, label: '로그' },
{ id: 'examples', Icon: FileCode2, label: '예제 코드' },
{ id: 'git', Icon: GitBranch, label: '소스 제어' },
{ id: 'settings', Icon: Settings, label: '설정' }
]
export default function WorkspaceNav({
dark,
workspaceActive,
activeActivity,
selectedModuleExists,
installedGitModuleCount,
teamProject,
moduleTabCount,
gitChangedFileCount,
workspaceNavFlash,
onSelect
}: WorkspaceNavProps): React.JSX.Element {
useLocaleRender()
const tooltipClassName = [
'pointer-events-none absolute left-11 top-1/2 z-50 hidden -translate-y-1/2 whitespace-nowrap rounded-md border px-2 py-1 text-[11px] font-semibold shadow-[0_10px_24px_rgba(0,0,0,0.24)] group-hover:block',
dark ? 'border-white/10 bg-[#303030] text-white/78' : 'border-[#d8dee9] bg-white text-[#4f596b]'
].join(' ')
return (
<nav
data-help="workspace-nav"
className={['relative z-30 flex flex-col items-center gap-3 overflow-visible border-r py-3', dark ? 'border-white/10 bg-[#303030] text-white/65' : 'border-[#cbbdde] bg-[linear-gradient(180deg,#e6ddf1_0%,#e8e1f2_55%,#e4eef7_100%)] text-[#475569]'].join(' ')}
style={workspaceActive ? { gridColumn: 3, gridRow: '1 / span 2' } : { gridColumn: 3, gridRow: 1 }}
>
{WORKSPACE_NAV_ITEMS.map(({ id, Icon, label }) => {
const active = activeActivity === id
const selectable = id === 'modules' ||
id === 'ros-connections' ||
id === 'workspace' ||
id === 'examples' ||
id === 'settings' ||
(id === 'git' && (teamProject || installedGitModuleCount > 0)) ||
((id === 'search' || id === 'logs') && selectedModuleExists)
return (
<button
key={id}
type="button"
aria-label={t(label)}
onClick={() => {
if (!selectable) return
onSelect(id)
}}
className={[
'group relative z-0 grid h-8 w-8 place-items-center overflow-visible rounded-lg transition',
selectable ? 'cursor-pointer' : 'cursor-default opacity-55',
active
? dark
? 'bg-[#2563eb]/32 text-white'
: 'bg-[#c7d9f8] text-[#1e40af]'
: dark
? selectable ? 'hover:bg-white/10 hover:text-white' : ''
: selectable ? 'hover:bg-[#d1dae7] hover:text-[#111520]' : ''
].join(' ')}
>
{id === 'workspace' && workspaceNavFlash && (
<>
<span className={['pointer-events-none absolute inset-[-3px] rounded-xl border animate-ping', dark ? 'border-white/70 shadow-[0_0_18px_rgba(255,255,255,0.28)]' : 'border-[#7c3aed]/70 shadow-[0_0_12px_rgba(124,58,237,0.22)]'].join(' ')} />
<span className={['pointer-events-none absolute inset-0 rounded-lg animate-pulse', dark ? 'bg-[#60a5fa]/18 shadow-[0_0_18px_rgba(96,165,250,0.38)]' : 'bg-[#7c3aed]/15 shadow-[0_0_12px_rgba(124,58,237,0.18)]'].join(' ')} />
</>
)}
<Icon
size={17}
className={[
'relative z-10',
id === 'modules' ? 'translate-x-[0.5px]' : '',
id === 'workspace' && workspaceNavFlash ? (dark ? 'text-[#b8d7ff]' : 'text-[#5b21b6]') : ''
].join(' ')}
/>
{id === 'workspace' && moduleTabCount > 0 && (
<span className="absolute -right-1 -top-1 z-20 flex h-4 min-w-4 items-center justify-center rounded-full bg-[#2563eb] px-1 pt-px text-center text-[10px] font-bold leading-4 text-white shadow-[0_0_10px_rgba(37,99,235,0.42)]">
<span className="translate-x-[0.5px]">{moduleTabCount}</span>
</span>
)}
{id === 'git' && gitChangedFileCount > 0 && (
<span className="absolute -right-1 -top-1 z-20 flex h-4 min-w-4 items-center justify-center rounded-full bg-[#2563eb] px-1 pt-px text-center text-[10px] font-bold leading-4 text-white shadow-[0_0_10px_rgba(37,99,235,0.42)]">
<span className="translate-x-[0.5px]">{gitChangedFileCount > 9 ? '9+' : gitChangedFileCount}</span>
</span>
)}
<span className={tooltipClassName}>
{t(label)}
</span>
</button>
)
})}
</nav>
)
}