Skip to content

Remove "account" dropdown', add notifications dropdown#3365

Open
TehShrike wants to merge 18 commits intomainfrom
2026-03-19-notifications-and-remove-account-menu
Open

Remove "account" dropdown', add notifications dropdown#3365
TehShrike wants to merge 18 commits intomainfrom
2026-03-19-notifications-and-remove-account-menu

Conversation

@TehShrike
Copy link
Copy Markdown
Collaborator

@TehShrike TehShrike commented Mar 23, 2026

Description

CleanShot 2026-03-23 at 10 07 46@2x CleanShot 2026-03-26 at 09 39 24@2x CleanShot 2026-03-26 at 09 40 13@2x CleanShot 2026-03-26 at 09 37 08@2x
  • "Logout" and the theme changer are in the side nav now.
    • The theme changer still only toggles between light and dark, though passing the theme types through the nav component did push me to change use-theme slightly in a way that will make it more straightforward to change the theme to "system" in the future.
    • The side-nav items can have an onClick instead of a to (href) now
  • there are three severity colors: green (invitations), yellow (tenant resource usage >= the alarm value), red (tenant resource useage >= the limit)
  • New invitations no longer cause you to be immediately redirected to the invitation screen (unless you don't belong to an organization/tenant and have been invited to one)

Note: the resource limits for all tenants are being fetched right now, which requires a request per tenant. We should probably add an endpoint that lets you see your limits for all tenants. We could make it so that you only see notifications for limits on the current active tenant, but that seems weird to me, since the top nav/notification UI feels "global", and presumably most users are responsible for all the tenants they belong to to some degree.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Documentation change (pure documentation change)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking changes to code which doesn't change any behaviour)
  • CI (any automation pipeline changes)
  • Chore (changes which are not directly related to any business logic)
  • Test changes (add, refactor, improve or change a test)
  • This change requires a documentation update

What's Changed

  • Add a list of tasks or features here...

- items in the side nav can now expose an `onClick` instead of just a `to`
- renamed the "activeTo" side nav item option to "displayAsActiveWhenThisRouteIsMatched" to increase my understanding
- the theme hook now exposes a currentlyVisibleTheme value which is either "dark" or "light", as opposed to the existing theme value which can also be "system" – at some point we should probably make the toggle function toggle through all 3 possible values, but I'll settle for this incremental improvement for now
- notification dropdown wider
- move more important text earlier in the notification message
- kill some passive voice in the process
- put notification message in title so you can see it on hover
@TehShrike TehShrike requested a review from mrkaye97 March 23, 2026 15:39
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 23, 2026

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

Project Deployment Actions Updated (UTC)
hatchet-docs Ready Ready Preview, Comment Mar 26, 2026 4:03pm

Request Review

@promptless-for-oss
Copy link
Copy Markdown

📝 Documentation updates detected!

New suggestion: Document dashboard notifications dropdown for invites and resource limits


Tip: Enable auto-create PR in your Docs Collection to publish suggestions automatically 🤖

Copy link
Copy Markdown
Contributor

@mrkaye97 mrkaye97 left a comment

Choose a reason for hiding this comment

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

a couple small UI things!

  1. I think we should put the logout button either next to or above/below the help button on the bottom of the side nav
  2. Small and annoying thing, but I wonder if we should nest the change theme button under general settings just for UI consistency :( Not great, hoping to improve the settings sidebar view thingy in general soon
  3. It'd be great if we had some way to check if you finished the initial onboarding flow (maybe we can see if you have any workers / workflows / runs already as a hack), and if you haven't completed it, then have a notification / CTA telling you to do that. then we can also remove the overview tab from the sidebar which I really dislike since it's irrelevant for 95% of cases. WDYT?

Comment on lines +28 to +32
const getThemeToDisplay = (theme: SelectableTheme): DisplayableTheme => {
if (theme === 'system') {
return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks for the fix here!

return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we should use a shadcn button here if we can (no worries if it's too much of an issue to do that while also matching the designs)

Comment on lines +7 to +18
export const useNotifications = () => {
const resourceLimits = useResourceLimitNotifications();
const invites = useInviteNotifications();

const notifications = useMemo(
() =>
[...resourceLimits.notifications, ...invites.notifications].sort(
(a, b) => (b.timestamp > a.timestamp ? 1 : -1),
),
[resourceLimits.notifications, invites.notifications],
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this is great 👍 should make it really easy for us to plug additional stuff

Comment on lines +14 to +21
const resourceLabels: Record<TenantResource, string> = {
[TenantResource.WORKER]: 'Total Workers',
[TenantResource.WORKER_SLOT]: 'Concurrency Slots',
[TenantResource.EVENT]: 'Events',
[TenantResource.TASK_RUN]: 'Task Runs',
[TenantResource.CRON]: 'Cron Triggers',
[TenantResource.SCHEDULE]: 'Schedule Triggers',
[TenantResource.INCOMING_WEBHOOK]: 'Incoming Webhooks',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

small thing: as I refactor more stuff in the codebase, I've been trying to use switch statements with an exhaustiveness check for this sort of thing as opposed to a map, so we don't need to handle the not found case implicitly. e.g.:

Suggested change
const resourceLabels: Record<TenantResource, string> = {
[TenantResource.WORKER]: 'Total Workers',
[TenantResource.WORKER_SLOT]: 'Concurrency Slots',
[TenantResource.EVENT]: 'Events',
[TenantResource.TASK_RUN]: 'Task Runs',
[TenantResource.CRON]: 'Cron Triggers',
[TenantResource.SCHEDULE]: 'Schedule Triggers',
[TenantResource.INCOMING_WEBHOOK]: 'Incoming Webhooks',
const resourceTypeToLabel = (resource: TenantResource): string => {
switch (resource) {
case ...
...
default:
const exhaustive: never = resource; // should never be non-never
throw ...
}
}

(typed this in Github, not sure if it'd compile but you get the idea :P )

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

So as it is now, the type system catches it if there is any unhandled TenantResource – if you comment out any of those lines , there's a type error down at resourceLabels[limit.resource].

I think TypeScript got smarter about map key types like this at some point a little bit back.

Personally in the case where I want to assert that there should never be a default case I like to use the type system to see it earlier.

Tangentially, this doesn't change much, but I also appreciate this pattern:

const resourceLabels = {
  [TenantResource.WORKER]: 'Total Workers',
  [TenantResource.WORKER_SLOT]: 'Concurrency Slots',
  [TenantResource.EVENT]: 'Events',
  [TenantResource.TASK_RUN]: 'Task Runs',
  [TenantResource.CRON]: 'Cron Triggers',
  [TenantResource.SCHEDULE]: 'Schedule Triggers',
  [TenantResource.INCOMING_WEBHOOK]: 'Incoming Webhooks',
} satisfies Record<TenantResource, string>

because then if you comment out one of those lines, not only do you get the type error down where resourceLabels is accessed, but you also get an error right there where the mapping is defined.

I have some preference for the mapping over the switch statement as long as I can get the early warning, but it's not a big deal, I'm happy to change it if you prefer the switch statements in general.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah great stuff! No, either of these is good for me, as long as we get type errors instead of runtime errors if there’s a missing case, thanks for clarifying!

const notifications = useMemo(
() =>
tenants.flatMap((tenant, i) =>
(resourcePolicyQueries[i]?.data?.limits ?? [])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

flagging b/c this always sets of alarm bells 😅 - are we sure the tenants are guaranteed to be ordered the same as the resourcePolicyQueries?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

So because the queries passed to useQueries is based on tenants.map, the indexes should be identical.

I don't particularly like this either – it reads too low-level than something I'd like to be composing here. I could override the queries.tenantResourcePolicy.get query above so that the query data includes the tenant id along with the policy results, and then use that to get the relevant tenant, but that feels a little awkward too.

I think the main thing that needs to happen is an endpoint that returns the resource policies for all tenants in one go, including their tenantIds.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sounds good, works for me as long as it works as we intend :)

@TehShrike
Copy link
Copy Markdown
Collaborator Author

I think we should put the logout button either next to or above/below the help button on the bottom of the side nav

Yeah, that makes sense, though I often find the "help" area eating into the vertical space on the sidebar a bit already – I'll probably try to reduce the vertical padding, at least.

Small and annoying thing, but I wonder if we should nest the change theme button under general settings just for UI consistency :( Not great, hoping to improve the settings sidebar view thingy in general soon

Yeah, fair enough. I can put theme under there with everything else – but maybe until a better categorization system comes along it would be okay to put everything at the top level, even if we recategorize everything soon after? Putting it behind a click doesn't do much.

It'd be great if we had some way to check if you finished the initial onboarding flow (maybe we can see if you have any workers / workflows / runs already as a hack), and if you haven't completed it, then have a notification / CTA telling you to do that. then we can also remove the overview tab from the sidebar which I really dislike since it's irrelevant for 95% of cases. WDYT?

I like the idea of supplanting the overview screen in the side nav – we do still force users to create a new tenant/organization if they don't have one and they don't have any invites, so until we change that they wouldn't ever see an onboarding notification for it.

Maybe if they don't have an API token, we could give them an onboarding notification that takes them to a "install the CLI + add a hatchet CLI profile" page?

@mrkaye97
Copy link
Copy Markdown
Contributor

but maybe until a better categorization system comes along it would be okay to put everything at the top level, even if we recategorize everything soon after? Putting it behind a click doesn't do much.

I'm in favor of this - let's at least give it a shot and see how it looks (we discussed a bit in Slack yesterday, because I'd proposed the same)

Maybe if they don't have an API token, we could give them an onboarding notification that takes them to a "install the CLI + add a hatchet CLI profile" page?

I feel like the simplest thing here would be to check if they have a token and maybe if they have some combination of workers / workflows / task runs and then link them to the current overview just so we don't need to rework that at all, but I agree in the future that linking to something more specific would be better

also make the theme button not stand out so much
if the user has one tenant and no workflows and no api keys, show them a notification that redirects them to the onboarding screen
07 isn't relevant now, its case is covered by 05 and 08
@TehShrike
Copy link
Copy Markdown
Collaborator Author

The 05 Cypress test is failing in CI, but it passes on my machine.

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