Merge branch 'chore/format-busy-overlay-followup' into dev
This commit is contained in:
@@ -101,79 +101,79 @@ export const AppShell = () => {
|
|||||||
<NotificationProvider>
|
<NotificationProvider>
|
||||||
<EventToastBridge />
|
<EventToastBridge />
|
||||||
<div className="shell">
|
<div className="shell">
|
||||||
<header className="shell-header">
|
<header className="shell-header">
|
||||||
<Link className="brand" to="/">
|
<Link className="brand" to="/">
|
||||||
Headquarter
|
Headquarter
|
||||||
|
</Link>
|
||||||
|
<div className="header-actions">
|
||||||
|
<NotificationCenter isMobileTerminal={isMobileTerminal} />
|
||||||
|
<Link className="user-chip" to="/profile">
|
||||||
|
{user?.name ?? "User"}
|
||||||
</Link>
|
</Link>
|
||||||
<div className="header-actions">
|
<button
|
||||||
<NotificationCenter isMobileTerminal={isMobileTerminal} />
|
className="ghost-button"
|
||||||
<Link className="user-chip" to="/profile">
|
onClick={() => {
|
||||||
{user?.name ?? "User"}
|
void logout();
|
||||||
</Link>
|
}}
|
||||||
<button
|
type="button"
|
||||||
className="ghost-button"
|
>
|
||||||
onClick={() => {
|
<Icon name="logout" size="sm" />
|
||||||
void logout();
|
Logout
|
||||||
}}
|
</button>
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<Icon name="logout" size="sm" />
|
|
||||||
Logout
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div className="shell-body">
|
|
||||||
{!isMobile && (
|
|
||||||
<aside className="shell-nav" aria-label="Primary navigation">
|
|
||||||
{NAV_ITEMS.map((item) => {
|
|
||||||
const activeCount = sessions.filter(
|
|
||||||
(s) => s.status === "running",
|
|
||||||
).length;
|
|
||||||
return (
|
|
||||||
<NavLink
|
|
||||||
key={item.to}
|
|
||||||
to={item.to}
|
|
||||||
className={({ isActive }) =>
|
|
||||||
isActive ? "nav-item nav-item-active" : "nav-item"
|
|
||||||
}
|
|
||||||
end={item.to === "/"}
|
|
||||||
>
|
|
||||||
<Icon name={item.icon} size="sm" />
|
|
||||||
{item.label}
|
|
||||||
{item.badge === "sessions" && activeCount > 0 && (
|
|
||||||
<span className="nav-badge">{activeCount}</span>
|
|
||||||
)}
|
|
||||||
</NavLink>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
{sessions.length > 0 && (
|
|
||||||
<>
|
|
||||||
<div className="nav-divider" />
|
|
||||||
<div className="nav-section-title">Live sessions</div>
|
|
||||||
{sessions.map((session) => (
|
|
||||||
<SessionItem key={session.id} session={session} />
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</aside>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<main className={`shell-content ${isMobile ? "mobile" : ""}`}>
|
|
||||||
<Outlet />
|
|
||||||
</main>
|
|
||||||
</div>
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
{isMobile && (
|
<div className="shell-body">
|
||||||
<MobileNav
|
{!isMobile && (
|
||||||
sessionCount={
|
<aside className="shell-nav" aria-label="Primary navigation">
|
||||||
sessions.filter((s) => s.status === "running").length
|
{NAV_ITEMS.map((item) => {
|
||||||
}
|
const activeCount = sessions.filter(
|
||||||
/>
|
(s) => s.status === "running",
|
||||||
|
).length;
|
||||||
|
return (
|
||||||
|
<NavLink
|
||||||
|
key={item.to}
|
||||||
|
to={item.to}
|
||||||
|
className={({ isActive }) =>
|
||||||
|
isActive ? "nav-item nav-item-active" : "nav-item"
|
||||||
|
}
|
||||||
|
end={item.to === "/"}
|
||||||
|
>
|
||||||
|
<Icon name={item.icon} size="sm" />
|
||||||
|
{item.label}
|
||||||
|
{item.badge === "sessions" && activeCount > 0 && (
|
||||||
|
<span className="nav-badge">{activeCount}</span>
|
||||||
|
)}
|
||||||
|
</NavLink>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
{sessions.length > 0 && (
|
||||||
|
<>
|
||||||
|
<div className="nav-divider" />
|
||||||
|
<div className="nav-section-title">Live sessions</div>
|
||||||
|
{sessions.map((session) => (
|
||||||
|
<SessionItem key={session.id} session={session} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</aside>
|
||||||
)}
|
)}
|
||||||
<StartToolFAB />
|
|
||||||
|
<main className={`shell-content ${isMobile ? "mobile" : ""}`}>
|
||||||
|
<Outlet />
|
||||||
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{isMobile && (
|
||||||
|
<MobileNav
|
||||||
|
sessionCount={
|
||||||
|
sessions.filter((s) => s.status === "running").length
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<StartToolFAB />
|
||||||
|
</div>
|
||||||
</NotificationProvider>
|
</NotificationProvider>
|
||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
</EventProvider>
|
</EventProvider>
|
||||||
|
|||||||
@@ -11,10 +11,13 @@ export function LoadingOverlay({ visible, label }: LoadingOverlayProps) {
|
|||||||
return (
|
return (
|
||||||
<div className="loading-overlay" aria-live="polite">
|
<div className="loading-overlay" aria-live="polite">
|
||||||
<div className="loading-overlay-content">
|
<div className="loading-overlay-content">
|
||||||
<Icon name="loading" size="lg" className="icon-spin" ariaLabel={label} />
|
<Icon
|
||||||
{label && (
|
name="loading"
|
||||||
<span className="loading-overlay-label">{label}</span>
|
size="lg"
|
||||||
)}
|
className="icon-spin"
|
||||||
|
ariaLabel={label}
|
||||||
|
/>
|
||||||
|
{label && <span className="loading-overlay-label">{label}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ describe("HomePage", () => {
|
|||||||
render(
|
render(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<SessionsProvider>
|
<SessionsProvider>
|
||||||
<HomePage />
|
<HomePage />
|
||||||
</SessionsProvider>
|
</SessionsProvider>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
@@ -78,7 +78,7 @@ describe("HomePage", () => {
|
|||||||
render(
|
render(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<SessionsProvider>
|
<SessionsProvider>
|
||||||
<HomePage />
|
<HomePage />
|
||||||
</SessionsProvider>
|
</SessionsProvider>
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user