aboutsummaryrefslogtreecommitdiff
path: root/src/components/ActivityBar
diff options
context:
space:
mode:
authorzwlucas <lucas.fariamo08@gmail.com>2026-06-05 20:52:54 +0000
committerzwlucas <lucas.fariamo08@gmail.com>2026-06-05 20:52:54 +0000
commit09f964451d7d92e9891430ec4595c1276d486aab (patch)
tree28da4483f5c28924a8c47fceb648b1baebe88224 /src/components/ActivityBar
downloadyace-master.tar.gz
yace-master.zip
feat: uploadHEADmaster
Signed-off-by: zwlucas <lucas.fariamo08@gmail.com>
Diffstat (limited to 'src/components/ActivityBar')
-rw-r--r--src/components/ActivityBar/ActivityBar.tsx147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/components/ActivityBar/ActivityBar.tsx b/src/components/ActivityBar/ActivityBar.tsx
new file mode 100644
index 0000000..7f96b5c
--- /dev/null
+++ b/src/components/ActivityBar/ActivityBar.tsx
@@ -0,0 +1,147 @@
+import { useLayoutStore, type ActivityView } from '@/stores/useLayoutStore'
+import { useThemeStore } from '@/stores/useThemeStore'
+
+interface ActivityItem {
+ view: ActivityView
+ label: string
+}
+
+function ExplorerIcon() {
+ return (
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+ <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />
+ </svg>
+ )
+}
+
+function SearchIcon() {
+ return (
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+ <circle cx="11" cy="11" r="8" />
+ <line x1="21" y1="21" x2="16.65" y2="16.65" />
+ </svg>
+ )
+}
+
+function ExtensionsIcon() {
+ return (
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+ <path d="M4 11a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2z" />
+ <path d="M15 11a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2z" />
+ <path d="M15 22a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2z" />
+ <path d="M4 22a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2z" />
+ </svg>
+ )
+}
+
+function SettingsIcon() {
+ return (
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+ <circle cx="12" cy="12" r="3" />
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" />
+ </svg>
+ )
+}
+
+function MoonIcon() {
+ return (
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
+ </svg>
+ )
+}
+
+function SunIcon() {
+ return (
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
+ <circle cx="12" cy="12" r="5" />
+ <line x1="12" y1="1" x2="12" y2="3" />
+ <line x1="12" y1="21" x2="12" y2="23" />
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
+ <line x1="1" y1="12" x2="3" y2="12" />
+ <line x1="21" y1="12" x2="23" y2="12" />
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
+ </svg>
+ )
+}
+
+const activities: ActivityItem[] = [
+ { view: 'explorer', label: 'Explorer' },
+ { view: 'search', label: 'Search' },
+ { view: 'extensions', label: 'Extensions' },
+]
+
+const bottomActivities: ActivityItem[] = [
+ { view: 'settings', label: 'Settings' },
+]
+
+const iconMap: Record<string, typeof ExplorerIcon> = {
+ explorer: ExplorerIcon,
+ search: SearchIcon,
+ extensions: ExtensionsIcon,
+ settings: SettingsIcon,
+}
+
+function ActivityButton({ item, isActive, setActiveView }: { item: ActivityItem; isActive: boolean; setActiveView: (view: ActivityView | null) => void }) {
+ const IconComponent = iconMap[item.view] || ExplorerIcon
+
+ return (
+ <button
+ role="tab"
+ aria-label={item.label}
+ aria-current={isActive ? 'true' : undefined}
+ className="relative flex items-center justify-center w-10 h-10 rounded-lg transition-all duration-fast hover:bg-panel-hover"
+ style={{ color: isActive ? 'var(--color-text-primary)' : 'var(--color-text-muted)' }}
+ onClick={() => setActiveView(item.view)}
+ title={item.label}
+ >
+ {isActive && (
+ <span className="absolute left-0 w-[3px] h-6 rounded-r-sm bg-accent" style={{ left: '-4px' }} />
+ )}
+ <span className={isActive ? '' : 'opacity-50 group-hover:opacity-80 transition-opacity duration-fast'}>
+ <IconComponent />
+ </span>
+ </button>
+ )
+}
+
+export default function ActivityBar() {
+ const activeView = useLayoutStore((s) => s.activeView)
+ const setActiveView = useLayoutStore((s) => s.setActiveView)
+ const theme = useThemeStore((s) => s.theme)
+ const toggleTheme = useThemeStore((s) => s.toggleTheme)
+
+ return (
+ <div className="flex flex-col items-center pt-2 gap-1 w-12 shrink-0 bg-activity-bg select-none group" role="tablist" aria-label="Main navigation">
+ {activities.map((item) => (
+ <ActivityButton
+ key={item.view}
+ item={item}
+ isActive={activeView === item.view}
+ setActiveView={setActiveView}
+ />
+ ))}
+
+ <div className="flex-1" />
+
+ {bottomActivities.map((item) => (
+ <ActivityButton
+ key={item.view}
+ item={item}
+ isActive={activeView === item.view}
+ setActiveView={setActiveView}
+ />
+ ))}
+
+ <button
+ className="flex items-center justify-center w-10 h-10 rounded-lg transition-all duration-fast hover:bg-panel-hover text-text-muted hover:text-text-primary mb-2"
+ onClick={toggleTheme}
+ title={`Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`}
+ >
+ {theme === 'dark' ? <SunIcon /> : <MoonIcon />}
+ </button>
+ </div>
+ )
+}