refactor(sidebar): group nav into sidebarGroups instead of slice(0,3)+slice(3) (P2-27)

Move Core vs Collaborate grouping from implicit array index to explicit
sidebarGroups NavGroup[] structure surfaced from useUIController.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-16 22:55:58 -04:00
1 parent 32687033fc
commit 0845187672
3 files changed
+29 -19

No files matched your search

+1 -1
View File
@@ -170,7 +170,7 @@ export function App() {
setSidebarCollapsed={ui.setSidebarCollapsed} setSidebarCollapsed={ui.setSidebarCollapsed}
section={ui.section} section={ui.section}
setSection={ui.setSection} setSection={ui.setSection}
sidebarNav={ui.sidebarNav} sidebarGroups={ui.sidebarGroups}
navBadges={company.navBadges} navBadges={company.navBadges}
companySwitcherOpen={ui.companySwitcherOpen} companySwitcherOpen={ui.companySwitcherOpen}
setCompanySwitcherOpen={ui.setCompanySwitcherOpen} setCompanySwitcherOpen={ui.setCompanySwitcherOpen}
+15 -3
View File
@@ -23,12 +23,16 @@ import type { AppLocale } from "@shared/locale";
type NavItemDef = { id: SectionId; labelKey: string; icon: typeof SquaresFour }; type NavItemDef = { id: SectionId; labelKey: string; icon: typeof SquaresFour };
export type NavItem = { id: SectionId; label: string; icon: typeof SquaresFour }; export type NavItem = { id: SectionId; label: string; icon: typeof SquaresFour };
export type NavGroup = { items: NavItem[] };
export type PaletteAction = { key: string; section: SectionId; entityId?: string }; export type PaletteAction = { key: string; section: SectionId; entityId?: string };
const sidebarNavDefs: NavItemDef[] = [ const sidebarCoreDefs: NavItemDef[] = [
{ id: "overview", labelKey: "nav.overview", icon: SquaresFour }, { id: "overview", labelKey: "nav.overview", icon: SquaresFour },
{ id: "inbox", labelKey: "nav.inbox", icon: Tray }, { id: "inbox", labelKey: "nav.inbox", icon: Tray },
{ id: "communication", labelKey: "nav.communication", icon: ChatCircle }, { id: "communication", labelKey: "nav.communication", icon: ChatCircle },
];
const sidebarCollaborateDefs: NavItemDef[] = [
{ id: "tasks", labelKey: "nav.work", icon: ListChecks }, { id: "tasks", labelKey: "nav.work", icon: ListChecks },
{ id: "approvals", labelKey: "nav.approvals", icon: ShieldCheck }, { id: "approvals", labelKey: "nav.approvals", icon: ShieldCheck },
{ id: "agents", labelKey: "nav.agents", icon: UsersThree }, { id: "agents", labelKey: "nav.agents", icon: UsersThree },
@@ -51,10 +55,17 @@ export function useUIController() {
const locale = useAppStore((s) => s.locale); const locale = useAppStore((s) => s.locale);
const t = useMemo(() => createTranslator(locale), [locale]); const t = useMemo(() => createTranslator(locale), [locale]);
const sidebarNav: NavItem[] = useMemo( const sidebarGroups: NavGroup[] = useMemo(
() => sidebarNavDefs.map((item) => ({ id: item.id, label: t(item.labelKey), icon: item.icon })), () => [
{ items: sidebarCoreDefs.map((item) => ({ id: item.id, label: t(item.labelKey), icon: item.icon })) },
{ items: sidebarCollaborateDefs.map((item) => ({ id: item.id, label: t(item.labelKey), icon: item.icon })) },
],
[t], [t],
); );
const sidebarNav: NavItem[] = useMemo(
() => sidebarGroups.flatMap((group) => group.items),
[sidebarGroups],
);
const navItems: NavItem[] = useMemo( const navItems: NavItem[] = useMemo(
() => () =>
sidebarNav sidebarNav
@@ -160,6 +171,7 @@ export function useUIController() {
t, t,
handleLocaleChange, handleLocaleChange,
sidebarNav, sidebarNav,
sidebarGroups,
navItems, navItems,
section, section,
setSection, setSection,
+13 -15
View File
@@ -12,6 +12,7 @@ import { SectionButton } from "../components/ui";
import { NEW_ENTITY_ID } from "../lib/constants"; import { NEW_ENTITY_ID } from "../lib/constants";
type NavItem = { id: SectionId; label: string; icon: typeof Gear }; type NavItem = { id: SectionId; label: string; icon: typeof Gear };
type NavGroup = { items: NavItem[] };
interface SidebarViewProps { interface SidebarViewProps {
isMac: boolean; isMac: boolean;
@@ -19,7 +20,7 @@ interface SidebarViewProps {
setSidebarCollapsed: (value: boolean) => void; setSidebarCollapsed: (value: boolean) => void;
section: SectionId; section: SectionId;
setSection: (section: SectionId) => void; setSection: (section: SectionId) => void;
sidebarNav: NavItem[]; sidebarGroups: NavGroup[];
navBadges: Partial<Record<SectionId, { count: number; tone: "default" | "warn" | "danger" }>>; navBadges: Partial<Record<SectionId, { count: number; tone: "default" | "warn" | "danger" }>>;
companySwitcherOpen: boolean; companySwitcherOpen: boolean;
setCompanySwitcherOpen: (value: boolean) => void; setCompanySwitcherOpen: (value: boolean) => void;
@@ -39,7 +40,7 @@ export function SidebarView({
setSidebarCollapsed, setSidebarCollapsed,
section, section,
setSection, setSection,
sidebarNav, sidebarGroups,
navBadges, navBadges,
companySwitcherOpen, companySwitcherOpen,
setCompanySwitcherOpen, setCompanySwitcherOpen,
@@ -152,19 +153,16 @@ export function SidebarView({
</div> </div>
)} )}
<nav aria-label="Main navigation" className={`flex-1 overflow-y-auto pb-3 ${sidebarCollapsed ? "px-1.5 pt-2" : "px-3 pt-2"}`}> <nav aria-label="Main navigation" className={`flex-1 overflow-y-auto pb-3 ${sidebarCollapsed ? "px-1.5 pt-2" : "px-3 pt-2"}`}>
{/* Core: Overview, Team, Work */} {sidebarGroups.map((group, idx) => (
<div className="space-y-0.5"> <div key={idx}>
{sidebarNav.slice(0, 3).map((item) => ( {idx > 0 ? <div className={`my-2 border-t border-border ${sidebarCollapsed ? "mx-1" : "mx-2"}`} /> : null}
<SectionButton key={item.id} active={section === item.id} label={item.label} icon={item.icon} onClick={() => setSection(item.id)} badge={navBadges[item.id]?.count} badgeTone={navBadges[item.id]?.tone} collapsed={sidebarCollapsed} /> <div className="space-y-0.5">
))} {group.items.map((item) => (
</div> <SectionButton key={item.id} active={section === item.id} label={item.label} icon={item.icon} onClick={() => setSection(item.id)} badge={navBadges[item.id]?.count} badgeTone={navBadges[item.id]?.tone} collapsed={sidebarCollapsed} />
<div className={`my-2 border-t border-border ${sidebarCollapsed ? "mx-1" : "mx-2"}`} /> ))}
{/* Collaborate & Extend: Communication, Skills, Documents, Approvals, Social */} </div>
<div className="space-y-0.5"> </div>
{sidebarNav.slice(3).map((item) => ( ))}
<SectionButton key={item.id} active={section === item.id} label={item.label} icon={item.icon} onClick={() => setSection(item.id)} badge={navBadges[item.id]?.count} badgeTone={navBadges[item.id]?.tone} collapsed={sidebarCollapsed} />
))}
</div>
</nav> </nav>
<div className={`border-t border-border py-2 ${sidebarCollapsed ? "px-1.5" : "px-3"}`}> <div className={`border-t border-border py-2 ${sidebarCollapsed ? "px-1.5" : "px-3"}`}>
<SectionButton <SectionButton