Problem
console/src/app/AppLayout/AppLayout.tsx is a 277-line monolith that mixes several unrelated concerns:
- Theme management (lines 43-152): dark/light state, localStorage persistence, OS preference listener, CSS class toggle
- Help dropdown (lines 53-82, 159-182): link definitions, dropdown state, JSX
- User dropdown (lines 84-101, 194-213): logout handler, dropdown state, JSX
- Sidebar (lines 103-125, 256-262): responsive open/close, resize listener
- Masthead / branding (lines 219-254): logo, title, toggle button
This makes the component hard to navigate and modify. For example, changing theme behavior requires scanning past unrelated dropdown logic.
Current Structure
AppLayout
├── State: isSidebarOpen, isHelpMenuOpen, isAboutModalOpen, isUserDropdownOpen, isDarkTheme
├── Data: defaultHelpLinks, helpDropdownItems, userDropdownItems
├── Handlers: handleLogout, onUserDropdownToggle/Select, onResize, onSidebarToggle, toggleTheme
├── Effects: resize listener, theme class toggle, OS preference listener
├── JSX vars: headerToolbar, header, sidebar
└── Return: <Page> + <AboutModalComponent>
Proposed Solution
Extract three self-contained subcomponents into console/src/app/AppLayout/:
1. ThemeToggle.tsx (~40 lines)
Owns isDarkTheme state, localStorage persistence, OS preference listener, and the toggle button JSX.
interface ThemeToggleProps {}
export const ThemeToggle: React.FC<ThemeToggleProps> = () => {
const [isDarkTheme, setIsDarkTheme] = useState(() => { ... });
// effects for class toggle and media query listener
return (
<Tooltip content={...}>
<MenuToggle variant="plain" onClick={toggleTheme} ...>
{isDarkTheme ? <SunIcon /> : <MoonIcon />}
</MenuToggle>
</Tooltip>
);
};
2. HelpMenu.tsx (~50 lines)
Owns isHelpMenuOpen state, link definitions, and the Dropdown JSX. Also renders AboutModalComponent since it's triggered from here.
export const HelpMenu: React.FC = () => {
const [isHelpMenuOpen, setIsHelpMenuOpen] = useState(false);
const [isAboutModalOpen, setIsAboutModalOpen] = useState(false);
// ...
return (
<>
<Dropdown ...>{helpDropdownItems}</Dropdown>
<AboutModalComponent isOpen={isAboutModalOpen} onClose={...} />
</>
);
};
3. UserMenu.tsx (~40 lines)
Owns isUserDropdownOpen state, logout handler, and the Dropdown JSX.
export const UserMenu: React.FC = () => {
const { userEmail, setUserEmail } = useUser();
const [isUserDropdownOpen, setIsUserDropdownOpen] = useState(false);
// ...
return <Dropdown ...>{userDropdownItems}</Dropdown>;
};
Result in AppLayout
After extraction, AppLayout shrinks to ~100 lines handling only page structure and sidebar:
const AppLayout: React.FC<IAppLayout> = ({ children }) => {
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
// resize effect
const headerToolbar = (
<Toolbar>
<ToolbarContent>
<ToolbarGroup align={{ default: 'alignEnd' }}>
<ToolbarItem><HelpMenu /></ToolbarItem>
<ToolbarItem><ThemeToggle /></ToolbarItem>
<ToolbarItem><UserMenu /></ToolbarItem>
</ToolbarGroup>
</ToolbarContent>
</Toolbar>
);
// masthead, sidebar, return <Page>
};
Files to Create
console/src/app/AppLayout/ThemeToggle.tsx
console/src/app/AppLayout/HelpMenu.tsx
console/src/app/AppLayout/UserMenu.tsx
Files to Modify
console/src/app/AppLayout/AppLayout.tsx — remove extracted code, import new components
Problem
console/src/app/AppLayout/AppLayout.tsxis a 277-line monolith that mixes several unrelated concerns:This makes the component hard to navigate and modify. For example, changing theme behavior requires scanning past unrelated dropdown logic.
Current Structure
Proposed Solution
Extract three self-contained subcomponents into
console/src/app/AppLayout/:1.
ThemeToggle.tsx(~40 lines)Owns
isDarkThemestate, localStorage persistence, OS preference listener, and the toggle button JSX.2.
HelpMenu.tsx(~50 lines)Owns
isHelpMenuOpenstate, link definitions, and the Dropdown JSX. Also rendersAboutModalComponentsince it's triggered from here.3.
UserMenu.tsx(~40 lines)Owns
isUserDropdownOpenstate, logout handler, and the Dropdown JSX.Result in AppLayout
After extraction,
AppLayoutshrinks to ~100 lines handling only page structure and sidebar:Files to Create
console/src/app/AppLayout/ThemeToggle.tsxconsole/src/app/AppLayout/HelpMenu.tsxconsole/src/app/AppLayout/UserMenu.tsxFiles to Modify
console/src/app/AppLayout/AppLayout.tsx— remove extracted code, import new components