From 76c4ac6c7aef7832b38ce6da00bc6601ae9e39c6 Mon Sep 17 00:00:00 2001 From: ramlal-01 Date: Sun, 24 May 2026 23:24:43 +0530 Subject: [PATCH 1/3] fix: resolve shortcuts panel hover flickering issue --- .env.example | 2 +- src/components/DashboardHeader.tsx | 3 +- src/components/KeyboardShortcuts.tsx | 23 +++++- src/components/ShortcutsModal.tsx | 114 +++++++++++++-------------- 4 files changed, 79 insertions(+), 63 deletions(-) diff --git a/.env.example b/.env.example index fe6319ad..35abfa2c 100644 --- a/.env.example +++ b/.env.example @@ -52,4 +52,4 @@ UPSTASH_REDIS_REST_TOKEN=your_upstash_redis_rest_token # AI Mentor widget). Without this key the widget still works and shows # rule-based insights only. # console.anthropic.com → API Keys -ANTHROPIC_API_KEY=sk-ant-... +ANTHROPIC_API_KEY=sk-ant-... \ No newline at end of file diff --git a/src/components/DashboardHeader.tsx b/src/components/DashboardHeader.tsx index 764b691c..3810a68e 100644 --- a/src/components/DashboardHeader.tsx +++ b/src/components/DashboardHeader.tsx @@ -70,8 +70,9 @@ export default function DashboardHeader() {
+
- +
diff --git a/src/components/KeyboardShortcuts.tsx b/src/components/KeyboardShortcuts.tsx index 59577f18..724eb2cb 100644 --- a/src/components/KeyboardShortcuts.tsx +++ b/src/components/KeyboardShortcuts.tsx @@ -10,6 +10,7 @@ export default function KeyboardShortcuts() { const [announcement, setAnnouncement] = useState(""); const { theme, toggleTheme } = useTheme(); const keyboardToggleRef = useRef(false); + const shortcutsRef = useRef(null); useEffect(() => { if (keyboardToggleRef.current && theme !== undefined) { @@ -59,17 +60,33 @@ export default function KeyboardShortcuts() { }; }, [toggleTheme]); + useEffect(() => { + function handleClickOutside(e: MouseEvent) { + if ( + shortcutsRef.current && + !shortcutsRef.current.contains(e.target as Node) + ) { + setIsOpen(false); + } + } + + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); + return ( - <> +
{announcement}
setIsOpen(false)} /> - +
); } \ No newline at end of file diff --git a/src/components/ShortcutsModal.tsx b/src/components/ShortcutsModal.tsx index be910d6a..07ec8415 100644 --- a/src/components/ShortcutsModal.tsx +++ b/src/components/ShortcutsModal.tsx @@ -19,16 +19,17 @@ const SHORTCUTS: ShortcutItem[] = [ { key: "?", action: "Show shortcuts" }, ]; -export default function ShortcutsModal({ isOpen, onClose}: ShortcutsModalProps) { +export default function ShortcutsModal({ + isOpen, + onClose, +}: ShortcutsModalProps) { const modalRef = useRef(null); const closeBtnRef = useRef(null); useEffect(() => { if (!isOpen) return; - if (closeBtnRef.current) { - closeBtnRef.current.focus(); - } + closeBtnRef.current?.focus(); const handleKeyDown = (e: KeyboardEvent) => { if (e.key === "Escape") { @@ -48,16 +49,12 @@ export default function ShortcutsModal({ isOpen, onClose}: ShortcutsModalProps) const firstElement = focusableElements[0]; const lastElement = focusableElements[focusableElements.length - 1]; - if (e.shiftKey) { - if (document.activeElement === firstElement) { - lastElement.focus(); - e.preventDefault(); - } - } else { - if (document.activeElement === lastElement) { - firstElement.focus(); - e.preventDefault(); - } + if (e.shiftKey && document.activeElement === firstElement) { + lastElement.focus(); + e.preventDefault(); + } else if (!e.shiftKey && document.activeElement === lastElement) { + firstElement.focus(); + e.preventDefault(); } } }; @@ -72,52 +69,53 @@ export default function ShortcutsModal({ isOpen, onClose}: ShortcutsModalProps) return (
-
e.stopPropagation()} - > -
- - -
- -
- {SHORTCUTS.map((item) => ( -
- {item.action} - - {item.key} - -
- ))} -
- -
- +
+ +
+ {SHORTCUTS.map((item) => ( +
- Got it - -
+ + {item.action} + + + {item.key} + +
+ ))} +
+ +
+
); From 0e39fab9e9df7ab6b6cf5fc1b851b8f0d7f0aa6b Mon Sep 17 00:00:00 2001 From: ramlal-01 Date: Sun, 24 May 2026 23:33:56 +0530 Subject: [PATCH 2/3] chore: remove .env.example and from tracking --- .env.example | 55 ---------------------------------------------------- 1 file changed, 55 deletions(-) delete mode 100644 .env.example diff --git a/.env.example b/.env.example deleted file mode 100644 index 35abfa2c..00000000 --- a/.env.example +++ /dev/null @@ -1,55 +0,0 @@ -# ------------------------------------------------------- -# Supabase -# Project Settings → API → Project URL -NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co - -# Project Settings → API → anon / public key -NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key - -# Project Settings → API → service_role secret (server-side only — never expose client-side) -SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key - -# ------------------------------------------------------- -# NextAuth -# The URL your app is running on -NEXTAUTH_URL=http://localhost:3000 - -# Generate with: openssl rand -base64 32 -NEXTAUTH_SECRET=your_nextauth_secret - -# ------------------------------------------------------- -# GitHub OAuth App -# github.com/settings/applications/new → Client ID -GITHUB_ID=your_github_oauth_client_id - -# github.com/settings/applications/new → Client Secret -GITHUB_SECRET=your_github_oauth_client_secret - -# ------------------------------------------------------- -# GitHub Webhook (optional — enables real-time metric refresh on push) -# Generate with: openssl rand -hex 32 -GITHUB_WEBHOOK_SECRET=your_github_webhook_secret - -# ------------------------------------------------------- -# GitHub Personal Access Token (optional — increases API rate limits) -# github.com/settings/tokens → Fine-grained or classic PAT -GITHUB_TOKEN=your_github_personal_access_token - -# ------------------------------------------------------- -# Encryption key — required for OAuth token encryption in src/lib/crypto.ts -# Without this the app crashes on first OAuth callback -# Generate with: openssl rand -hex 32 -ENCRYPTION_KEY=your_32_byte_hex_encryption_key - -# ------------------------------------------------------- -# Upstash Redis (optional — used for caching; app degrades gracefully without it) -# upstash.com → Create Database → REST API -UPSTASH_REDIS_REST_URL=your_upstash_redis_rest_url -UPSTASH_REDIS_REST_TOKEN=your_upstash_redis_rest_token - -# ------------------------------------------------------- -# Anthropic Claude (optional — enables AI-generated weekly summaries in the -# AI Mentor widget). Without this key the widget still works and shows -# rule-based insights only. -# console.anthropic.com → API Keys -ANTHROPIC_API_KEY=sk-ant-... \ No newline at end of file From d017c91910dd669c8e20c24e5dd336d747374252 Mon Sep 17 00:00:00 2001 From: ramlal-01 Date: Mon, 25 May 2026 00:57:22 +0530 Subject: [PATCH 3/3] restore .env.example file --- .env.example | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..fe6319ad --- /dev/null +++ b/.env.example @@ -0,0 +1,55 @@ +# ------------------------------------------------------- +# Supabase +# Project Settings → API → Project URL +NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co + +# Project Settings → API → anon / public key +NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key + +# Project Settings → API → service_role secret (server-side only — never expose client-side) +SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key + +# ------------------------------------------------------- +# NextAuth +# The URL your app is running on +NEXTAUTH_URL=http://localhost:3000 + +# Generate with: openssl rand -base64 32 +NEXTAUTH_SECRET=your_nextauth_secret + +# ------------------------------------------------------- +# GitHub OAuth App +# github.com/settings/applications/new → Client ID +GITHUB_ID=your_github_oauth_client_id + +# github.com/settings/applications/new → Client Secret +GITHUB_SECRET=your_github_oauth_client_secret + +# ------------------------------------------------------- +# GitHub Webhook (optional — enables real-time metric refresh on push) +# Generate with: openssl rand -hex 32 +GITHUB_WEBHOOK_SECRET=your_github_webhook_secret + +# ------------------------------------------------------- +# GitHub Personal Access Token (optional — increases API rate limits) +# github.com/settings/tokens → Fine-grained or classic PAT +GITHUB_TOKEN=your_github_personal_access_token + +# ------------------------------------------------------- +# Encryption key — required for OAuth token encryption in src/lib/crypto.ts +# Without this the app crashes on first OAuth callback +# Generate with: openssl rand -hex 32 +ENCRYPTION_KEY=your_32_byte_hex_encryption_key + +# ------------------------------------------------------- +# Upstash Redis (optional — used for caching; app degrades gracefully without it) +# upstash.com → Create Database → REST API +UPSTASH_REDIS_REST_URL=your_upstash_redis_rest_url +UPSTASH_REDIS_REST_TOKEN=your_upstash_redis_rest_token + +# ------------------------------------------------------- +# Anthropic Claude (optional — enables AI-generated weekly summaries in the +# AI Mentor widget). Without this key the widget still works and shows +# rule-based insights only. +# console.anthropic.com → API Keys +ANTHROPIC_API_KEY=sk-ant-...