diff --git a/apps/web/modules/shell/Kbar.tsx b/apps/web/modules/shell/Kbar.tsx index e848f8d0bd..053dabc4cc 100644 --- a/apps/web/modules/shell/Kbar.tsx +++ b/apps/web/modules/shell/Kbar.tsx @@ -1,3 +1,9 @@ +import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; +import { isMac } from "@calcom/lib/isMac"; +import { trpc } from "@calcom/trpc/react"; +import { Icon } from "@calcom/ui/components/icon"; +import { Tooltip } from "@calcom/ui/components/tooltip"; import type { Action } from "kbar"; import { KBarAnimator, @@ -12,14 +18,7 @@ import { } from "kbar"; import { useRouter } from "next/navigation"; import type { ReactNode } from "react"; -import { useMemo } from "react"; - -import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { isMac } from "@calcom/lib/isMac"; -import { trpc } from "@calcom/trpc/react"; -import { Icon } from "@calcom/ui/components/icon"; -import { Tooltip } from "@calcom/ui/components/tooltip"; +import { useEffect, useMemo } from "react"; type ShortcutArrayType = { shortcuts?: string[]; @@ -49,26 +48,165 @@ const getApps: AppAction[] = Object.values(appStoreMetadata).map(({ name, slug } })); const KBAR_ACTION_CONFIGS: ActionConfig[] = [ - { id: "workflows", name: "workflows", section: "workflows", shortcut: ["w", "f"], keywords: "workflows automation", href: "/workflows" }, - { id: "event-types", name: "event_types_page_title", section: "event_types_page_title", shortcut: ["e", "t"], keywords: "event types", href: "/event-types" }, - { id: "app-store", name: "app_store", section: "apps", shortcut: ["a", "s"], keywords: "app store", href: "/apps" }, - { id: "upcoming-bookings", name: "upcoming", section: "bookings", shortcut: ["u", "b"], keywords: "upcoming bookings", href: "/bookings/upcoming" }, - { id: "recurring-bookings", name: "recurring", section: "bookings", shortcut: ["r", "b"], keywords: "recurring bookings", href: "/bookings/recurring" }, - { id: "past-bookings", name: "past", section: "bookings", shortcut: ["p", "b"], keywords: "past bookings", href: "/bookings/past" }, - { id: "cancelled-bookings", name: "cancelled", section: "bookings", shortcut: ["c", "b"], keywords: "cancelled bookings", href: "/bookings/cancelled" }, - { id: "schedule", name: "availability", section: "availability", shortcut: ["s", "a"], keywords: "schedule availability", href: "/availability" }, - { id: "profile", name: "profile", section: "profile", shortcut: ["p", "s"], keywords: "setting profile", href: "/settings/my-account/profile" }, - { id: "avatar", name: "change_avatar", section: "profile", shortcut: ["c", "a"], keywords: "remove change modify avatar", href: "/settings/my-account/profile" }, - { id: "timezone", name: "timezone", section: "profile", shortcut: ["c", "t"], keywords: "change modify timezone", href: "/settings/my-account/general" }, - { id: "brand-color", name: "brand_color", section: "profile", shortcut: ["b", "c"], keywords: "change modify brand color", href: "/settings/my-account/appearance" }, - { id: "teams", name: "teams", shortcut: ["t", "s"], keywords: "add manage modify team", href: "/settings/teams" }, - { id: "password", name: "change_password", section: "security", shortcut: ["c", "p"], keywords: "change modify password", href: "/settings/security/password" }, - { id: "two-factor", name: "two_factor_auth", section: "security", shortcut: ["t", "f", "a"], keywords: "two factor authentication", href: "/settings/security/two-factor-auth" }, - { id: "impersonation", name: "user_impersonation_heading", section: "security", shortcut: ["u", "i"], keywords: "user impersonation", href: "/settings/security/impersonation" }, - { id: "license", name: "choose_a_license", section: "admin", shortcut: ["u", "l"], keywords: "license", href: "/auth/setup?step=1" }, - { id: "webhooks", name: "Webhooks", section: "developer", shortcut: ["w", "h"], keywords: "webhook automation", href: "/settings/developer/webhooks" }, - { id: "api-keys", name: "api_keys", section: "developer", shortcut: ["a", "p", "i"], keywords: "api keys", href: "/settings/developer/api-keys" }, - { id: "billing", name: "manage_billing", section: "billing", shortcut: ["m", "b"], keywords: "billing view manage", href: "/settings/billing" }, + { + id: "workflows", + name: "workflows", + section: "workflows", + shortcut: ["w", "f"], + keywords: "workflows automation", + href: "/workflows", + }, + { + id: "event-types", + name: "event_types_page_title", + section: "event_types_page_title", + shortcut: ["e", "t"], + keywords: "event types", + href: "/event-types", + }, + { + id: "app-store", + name: "app_store", + section: "apps", + shortcut: ["a", "s"], + keywords: "app store", + href: "/apps", + }, + { + id: "upcoming-bookings", + name: "upcoming", + section: "bookings", + shortcut: ["u", "b"], + keywords: "upcoming bookings", + href: "/bookings/upcoming", + }, + { + id: "recurring-bookings", + name: "recurring", + section: "bookings", + shortcut: ["r", "b"], + keywords: "recurring bookings", + href: "/bookings/recurring", + }, + { + id: "past-bookings", + name: "past", + section: "bookings", + shortcut: ["p", "b"], + keywords: "past bookings", + href: "/bookings/past", + }, + { + id: "cancelled-bookings", + name: "cancelled", + section: "bookings", + shortcut: ["c", "b"], + keywords: "cancelled bookings", + href: "/bookings/cancelled", + }, + { + id: "schedule", + name: "availability", + section: "availability", + shortcut: ["s", "a"], + keywords: "schedule availability", + href: "/availability", + }, + { + id: "profile", + name: "profile", + section: "profile", + shortcut: ["p", "s"], + keywords: "setting profile", + href: "/settings/my-account/profile", + }, + { + id: "avatar", + name: "change_avatar", + section: "profile", + shortcut: ["c", "a"], + keywords: "remove change modify avatar", + href: "/settings/my-account/profile", + }, + { + id: "timezone", + name: "timezone", + section: "profile", + shortcut: ["c", "t"], + keywords: "change modify timezone", + href: "/settings/my-account/general", + }, + { + id: "brand-color", + name: "brand_color", + section: "profile", + shortcut: ["b", "c"], + keywords: "change modify brand color", + href: "/settings/my-account/appearance", + }, + { + id: "teams", + name: "teams", + shortcut: ["t", "s"], + keywords: "add manage modify team", + href: "/settings/teams", + }, + { + id: "password", + name: "change_password", + section: "security", + shortcut: ["c", "p"], + keywords: "change modify password", + href: "/settings/security/password", + }, + { + id: "two-factor", + name: "two_factor_auth", + section: "security", + shortcut: ["t", "f", "a"], + keywords: "two factor authentication", + href: "/settings/security/two-factor-auth", + }, + { + id: "impersonation", + name: "user_impersonation_heading", + section: "security", + shortcut: ["u", "i"], + keywords: "user impersonation", + href: "/settings/security/impersonation", + }, + { + id: "license", + name: "choose_a_license", + section: "admin", + shortcut: ["u", "l"], + keywords: "license", + href: "/auth/setup?step=1", + }, + { + id: "webhooks", + name: "Webhooks", + section: "developer", + shortcut: ["w", "h"], + keywords: "webhook automation", + href: "/settings/developer/webhooks", + }, + { + id: "api-keys", + name: "api_keys", + section: "developer", + shortcut: ["a", "p", "i"], + keywords: "api keys", + href: "/settings/developer/api-keys", + }, + { + id: "billing", + name: "manage_billing", + section: "billing", + shortcut: ["m", "b"], + keywords: "billing view manage", + href: "/settings/billing", + }, ]; function buildKbarActions(push: (href: string) => void): Action[] { @@ -145,16 +283,16 @@ const KBarContent = (): JSX.Element => { return ( - -
- + +
+
-
+
{t("navigate")} @@ -164,7 +302,7 @@ const KBarContent = (): JSX.Element => { {t("close")}
-
+
); @@ -189,7 +327,7 @@ const KBarTrigger = (): JSX.Element | null => { @@ -205,7 +343,7 @@ function DisplayShortcuts(item: ShortcutArrayType): JSX.Element { return ( + className="rounded-sm border bg-default px-2 py-1 text-emphasis transition hover:bg-subtle"> {shortcut} ); @@ -221,7 +359,7 @@ type RenderItemProps = { function renderResultItem(item: string | Action, active: boolean, t: (key: string) => string): JSX.Element { if (typeof item === "string") { - return
{t(item)}
; + return
{t(item)}
; } let background = "var(--cal-bg-default)"; @@ -241,10 +379,48 @@ function renderResultItem(item: string | Action, active: boolean, t: (key: strin ); } +function NoResultsFound({ searchQuery }: { searchQuery: string }): JSX.Element { + const { t } = useLocale(); + const helpUrl = `https://cal.com/help/welcome?search=${encodeURIComponent(searchQuery)}`; + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent): void => { + if (event.key === "Enter") { + window.open(helpUrl, "_blank", "noopener,noreferrer"); + } + }; + + document.addEventListener("keydown", handleKeyDown); + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, [helpUrl]); + + return ( + + ); +} + function RenderResults(): JSX.Element { const { results } = useMatches(); + const { searchQuery } = useKBar((state) => ({ searchQuery: state.searchQuery })); const { t } = useLocale(); + if (results.length === 0 && searchQuery.trim().length > 0) { + return ; + } + return (