setExpanded(false)}
+ aria-label="Close API key details"
+ />
+ )}
+
+
+ {/* COLLAPSED STATE - Always rendered to maintain layout space */}
+
+
+ {/* EXPANDED STATE - Rendered as overlay when expanded */}
+ {ui.expanded && (
+
+ {/* Header */}
+
+
+
+ {apiKeyValidated ? 'API Key Active' : 'Enter API Key'}
+
+ {apiKeyValidated && apiKeyInfo && (
+
+ {apiKeyInfo.organizationSlug} / {apiKeyInfo.projectSlug}
+
+ )}
+
+
+
+
+ {/* API Key Input/Display */}
+
+
+
+
setApiKey(e.target.value)}
+ onKeyDown={handleKeyDown}
+ placeholder="Enter your API key"
+ disabled={apiKeyValidated}
+ className={`flex-1 px-4 bg-slate-800 border border-slate-700 rounded-lg text-gray-300 font-mono placeholder:text-gray-600 focus:outline-none focus:ring-2 focus:ring-purple-500/50 focus:border-purple-500 disabled:opacity-50 disabled:cursor-not-allowed transition-all ${
+ isMobileContext ? 'py-3 text-base' : 'py-2 text-sm'
+ }`}
+ />
+
+
+
+
+ {/* Error Message */}
+ {apiKeyError && (
+
+ )}
+
+ {/* Actions */}
+
+ {!apiKeyValidated ? (
+
+ ) : (
+
+ )}
+
+
+ {/* Helper Text */}
+ {!apiKeyValidated && (
+
+ Press Enter or click Validate to verify your API key
+
+ )}
+
+ )}
+
+ >
+ );
+}
diff --git a/apps/landing/src/components/shared/SubsectionNav.tsx b/apps/landing/src/components/shared/SubsectionNav.tsx
index 33ce3aa..4c24e8c 100644
--- a/apps/landing/src/components/shared/SubsectionNav.tsx
+++ b/apps/landing/src/components/shared/SubsectionNav.tsx
@@ -7,7 +7,6 @@
* Features:
* - Dark nav bar with decorative wave line
* - Active state indicator (purple color)
- * - Optional API Key input on the right
* - Responsive (hamburger menu on mobile)
* - Three-column layout matching docs structure
* - Customizable left/right slots
@@ -19,13 +18,12 @@
*
}
* rightSlot={
}
* />
*/
-import { useState, useEffect, useRef, ReactNode } from 'react';
+import { useState, ReactNode } from 'react';
import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout';
interface NavItem {
@@ -39,212 +37,19 @@ interface SubsectionNavProps {
ctaText?: string;
ctaHref?: string;
onCtaClick?: () => void;
- showApiKeyInput?: boolean;
/** Optional content for left column (w-64, hidden until lg) */
leftSlot?: ReactNode;
- /** Optional content for right column (w-56, hidden until xl). If not provided and showApiKeyInput is true, API key input is used. */
+ /** Optional content for right column (w-56, hidden until xl) */
rightSlot?: ReactNode;
}
-const API_KEY_STORAGE = 'banatie_docs_api_key';
-
-export const SubsectionNav = ({
- items,
- currentPath,
- showApiKeyInput = false,
- leftSlot,
- rightSlot,
-}: SubsectionNavProps) => {
+export const SubsectionNav = ({ items, currentPath, leftSlot, rightSlot }: SubsectionNavProps) => {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
- const [apiKey, setApiKey] = useState('');
- const [isApiKeyExpanded, setIsApiKeyExpanded] = useState(false);
- const [keyVisible, setKeyVisible] = useState(false);
- const dropdownRef = useRef
(null);
const isActive = (href: string) => currentPath.startsWith(href);
- // Load API key from localStorage
- useEffect(() => {
- if (showApiKeyInput) {
- const stored = localStorage.getItem(API_KEY_STORAGE);
- if (stored) setApiKey(stored);
- }
- }, [showApiKeyInput]);
-
- // Handle API key changes
- const handleApiKeyChange = (value: string) => {
- setApiKey(value);
- if (value) {
- localStorage.setItem(API_KEY_STORAGE, value);
- } else {
- localStorage.removeItem(API_KEY_STORAGE);
- }
-
- // Dispatch event to notify widgets
- window.dispatchEvent(new CustomEvent('apiKeyChanged', { detail: value }));
- };
-
- // Handle clear API key
- const handleClear = () => {
- setApiKey('');
- localStorage.removeItem(API_KEY_STORAGE);
- window.dispatchEvent(new CustomEvent('apiKeyChanged', { detail: '' }));
- };
-
- // Close dropdown when clicking outside
- useEffect(() => {
- const handleClickOutside = (event: MouseEvent) => {
- if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
- setIsApiKeyExpanded(false);
- }
- };
-
- if (isApiKeyExpanded) {
- document.addEventListener('mousedown', handleClickOutside);
- }
-
- return () => {
- document.removeEventListener('mousedown', handleClickOutside);
- };
- }, [isApiKeyExpanded]);
-
- // Listen for custom event to expand API key from widgets
- useEffect(() => {
- const handleExpandApiKey = () => {
- setIsApiKeyExpanded(true);
- // Scroll to top to show nav
- window.scrollTo({ top: 0, behavior: 'smooth' });
- };
-
- window.addEventListener('expandApiKeyInput', handleExpandApiKey);
-
- return () => {
- window.removeEventListener('expandApiKeyInput', handleExpandApiKey);
- };
- }, []);
-
- // Desktop API Key Input Component
- const apiKeyComponent = showApiKeyInput && (
-
-
-
- {/* Dropdown Card */}
- {isApiKeyExpanded && (
-
-
-
-
API Key
-
- Enter once, use across all examples
-
-
-
-
-
-
-
-
-
handleApiKeyChange(e.target.value)}
- placeholder="Enter your API key"
- className="flex-1 px-3 py-2 bg-slate-800 border border-slate-700 focus:border-purple-500 focus:ring-1 focus:ring-purple-500 rounded-lg text-sm text-gray-300 font-mono placeholder-gray-500 focus:outline-none transition-colors"
- />
-
-
-
- {apiKey && (
-
- )}
-
-
-
-
Stored locally in your browser
-
-
- )}
-
- );
-
return (
-
- {/* Mobile Menu Button */}
-