Skip to content

Feat: Remove "account" dropdown, add notifications dropdown#3665

Merged
mrkaye97 merged 2 commits intomainfrom
revert-3664-revert-3365-2026-03-19-notifications-and-remove-account-menu
Apr 22, 2026
Merged

Feat: Remove "account" dropdown, add notifications dropdown#3665
mrkaye97 merged 2 commits intomainfrom
revert-3664-revert-3365-2026-03-19-notifications-and-remove-account-menu

Conversation

@mrkaye97
Copy link
Copy Markdown
Contributor

Re-applies #3365

Copilot AI review requested due to automatic review settings April 22, 2026 00:29
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hatchet-docs Ready Ready Preview, Comment Apr 22, 2026 2:17pm

Request Review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Re-applies the UI change from #3365 by removing the top-nav “account” dropdown and introducing a notifications dropdown, while relocating logout + theme toggling into the v1 sidebar and adjusting onboarding redirect behavior to be less disruptive.

Changes:

  • Replace the top-nav account dropdown with a notifications dropdown powered by new notification hooks (invites, onboarding hints, resource limit status).
  • Move logout + theme toggling into the v1 sidebar (including support for sidebar items that perform actions instead of navigation).
  • Refine onboarding redirects so users are only forced onto the invites screen in specific “must accept invite now” scenarios; update Cypress tests accordingly.

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
frontend/app/src/providers/user-universe.tsx Adds a shared logout mutation to the user-universe provider for use by navigation UI.
frontend/app/src/pages/main/v1/workflow-runs-v1/components/task-runs-table/table-actions.tsx Adds a React key for a rendered bulk-actions container.
frontend/app/src/pages/main/v1/tenant-settings/resource-limits/components/resource-limit-columns.tsx Uses shared resource-limit status logic for indicator coloring.
frontend/app/src/pages/main/v1/task-runs-v1/actions.tsx Adjusts tooltip trigger to use asChild for correct composition.
frontend/app/src/pages/main/v1/side-nav-items.tsx Reworks settings items and adds a theme toggle as an action item.
frontend/app/src/pages/main/v1/index.tsx Wires theme toggle + logout into the v1 sidebar.
frontend/app/src/pages/authenticated.tsx Updates onboarding redirect logic around pending invites.
frontend/app/src/lib/resource-limit-status.ts New helper for classifying resource usage as ok/warn/exhausted.
frontend/app/src/hooks/use-pending-invites.ts Improves typing and reduces polling frequency.
frontend/app/src/hooks/notifications/types.ts Defines notification types/colors for the new notifications system.
frontend/app/src/hooks/notifications/resource-limits.ts Generates notifications from per-tenant resource policy limits.
frontend/app/src/hooks/notifications/onboarding.ts Generates a “get started” notification for a minimal onboarding state.
frontend/app/src/hooks/notifications/invites.ts Generates notifications for tenant/org invites.
frontend/app/src/hooks/notifications/index.ts Aggregates + sorts notifications across sources.
frontend/app/src/devtools.tsx Raises devtools popover stacking context via z-index.
frontend/app/src/components/v1/nav/top-nav.tsx Removes account dropdown and renders the new notifications dropdown.
frontend/app/src/components/v1/nav/sidebar-buttons.tsx Adjusts primary sidebar action button props/styling (introduces muted).
frontend/app/src/components/v1/nav/side-nav.tsx Adds logout button(s), supports action-only sidebar items, updates active-route logic.
frontend/app/src/components/v1/nav/notifications.tsx New notifications dropdown UI component.
frontend/app/src/components/v1/nav/help-dropdown.tsx Updates usage after sidebar button prop changes.
frontend/app/src/components/hooks/use-theme.tsx Adds currentlyVisibleTheme to support UI that needs the displayed theme.
frontend/app/cypress/e2e/layout/viewports.cy.ts Updates layout smoke assertions to reflect navbar changes.
frontend/app/cypress/e2e/layout/v1-sidebar-resize-collapse.cy.ts Updates sidebar behavior expectations (settings always visible; no flyout).
frontend/app/cypress/e2e/auth/08-tenant-invite-decline.cy.ts Updates flow to use notifications UI and new logout location.
frontend/app/cypress/e2e/auth/07-create-tenant-invites-redirect.cy.ts Removes a redirect test that no longer matches intended behavior.
frontend/app/cypress/e2e/auth/06-tenant-switching.cy.ts Updates logout interaction to the new sidebar button.
frontend/app/cypress/e2e/auth/05-tenant-invite-accept.cy.ts Updates invite acceptance flow to use notifications UI and new logout location.
frontend/app/cypress/e2e/auth/02-logout.cy.ts Updates logout interaction to the new sidebar button.
frontend/app/cypress/e2e/auth/01-login.cy.ts Updates post-login assertion to a stable element given dropdown removal.


const logoutMutation = useMutation({
mutationKey: ['user:update:logout'],
mutationFn: async () => {
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logoutMutation always calls api.userUpdateLogout(), ignoring isControlPlaneEnabled. In control-plane mode this will hit the wrong endpoint (the existing useUserApi().userUpdateLogoutMutation() switches between controlPlaneApi.cloudUserUpdateLogout() and api.userUpdateLogout()). Please route the logout request through the control-plane API when enabled (or reuse useUserApi).

Suggested change
mutationFn: async () => {
mutationFn: async () => {
if (isControlPlaneEnabled) {
await controlPlaneApi.cloudUserUpdateLogout();
return;
}

Copilot uses AI. Check for mistakes.
Comment on lines +150 to +156
const logoutMutation = useMutation({
mutationKey: ['user:update:logout'],
mutationFn: async () => {
await api.userUpdateLogout();
},
onSuccess: () => {
invalidate();
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On logout success this only resets the user-universe queries. Other parts of the app (e.g. AuthenticatedInner inactivity logout) call queryClient.clear() to avoid leaving authenticated data in the cache after logging out. Consider clearing the React Query cache (or at least removing user-scoped queries) here as well to prevent stale data being shown after logout / on re-login in the same session.

Suggested change
const logoutMutation = useMutation({
mutationKey: ['user:update:logout'],
mutationFn: async () => {
await api.userUpdateLogout();
},
onSuccess: () => {
invalidate();
const clearQueryCache = useCallback(() => {
// Logout changes the authorization boundary, so retaining any cached
// authenticated query data risks showing stale data after redirect or re-login.
queryClient.clear();
}, [queryClient]);
const logoutMutation = useMutation({
mutationKey: ['user:update:logout'],
mutationFn: async () => {
await api.userUpdateLogout();
},
onSuccess: () => {
clearQueryCache();

Copilot uses AI. Check for mistakes.
Comment on lines 426 to 436
onClick={() => {
navigate({
to: item.to,
params: commonParams,
});
if ('onClick' in item) {
item.onClick();
return;
} else {
navigate({
to: item.to,
params: commonParams,
});
}
onNavLinkClick();
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For SideNavItems that use onClick, the handler returns early and never calls onNavLinkClick(). On narrow viewports this means the sidebar overlay won’t close after clicking action items like the theme toggle, which is inconsistent with navigation items and can leave the UI obstructed. Consider calling onNavLinkClick() after item.onClick() as well (or explicitly document/encode which actions should keep the sidebar open).

Copilot uses AI. Check for mistakes.
const navigate = useNavigate();
const count = notifications.length;
const mostSevere = count > 0 ? getMostSevereColor(notifications) : null;
const ariaLabel = `${count} notification${count !== 1 ? 's' : ''} for ${currentUser?.email ?? ''}`;
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ariaLabel can render with a trailing "for " when currentUser?.email is not available (e.g. during initial load), which is awkward for screen readers/tooltips. Consider omitting the "for …" suffix unless an email is present.

Suggested change
const ariaLabel = `${count} notification${count !== 1 ? 's' : ''} for ${currentUser?.email ?? ''}`;
const notificationLabel = `${count} notification${count !== 1 ? 's' : ''}`;
const ariaLabel = currentUser?.email
? `${notificationLabel} for ${currentUser.email}`
: notificationLabel;

Copilot uses AI. Check for mistakes.
Comment on lines +43 to 58
const [theme, setTheme] = useState<SelectableTheme>(
() => (localStorage.getItem(storageKey) as SelectableTheme) || defaultTheme,
);

const [currentlyVisibleTheme, setCurrentlyVisibleTheme] =
useState<DisplayableTheme>('light');

useEffect(() => {
const root = window.document.documentElement;

root.classList.remove('light', 'dark');

if (theme === 'system') {
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)')
.matches
? 'dark'
: 'light';

root.classList.add(systemTheme);
return;
}

root.classList.add(theme);
const themeToDisplay = getThemeToDisplay(theme);
setCurrentlyVisibleTheme(themeToDisplay);
root.classList.add(themeToDisplay);
}, [theme]);
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currentlyVisibleTheme is initialized to 'light' and only corrected in an effect. If the saved theme is dark (or system preference is dark), components that read currentlyVisibleTheme (e.g. the sidebar label/icon) will briefly render the wrong theme on first paint. Initializing this state from the initial theme value (and matchMedia when needed) would avoid the flicker.

Copilot uses AI. Check for mistakes.
@mrkaye97 mrkaye97 merged commit a1861dc into main Apr 22, 2026
27 checks passed
@mrkaye97 mrkaye97 deleted the revert-3664-revert-3365-2026-03-19-notifications-and-remove-account-menu branch April 22, 2026 14:20
wsehl pushed a commit to wsehl/hatchet that referenced this pull request Apr 23, 2026
…dev#3665)

* Revert "Revert "Remove "account" dropdown', add notifications dropdown (hatchet-dev#3365…"

This reverts commit b26f536.

* fix: couple copilot comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants