Files
WooNooW/admin-spa/src/components/nav/SubmenuBar.tsx
dwindown 39a215c188 fix: Sticky submenu + emoji flags instead of images
1. Made Settings Submenu Sticky 
   Problem: Settings submenu wasn't sticky like Dashboard
   Solution: Added sticky positioning to SubmenuBar

   Added classes:
   - sticky top-0 z-20
   - bg-background/95 backdrop-blur
   - supports-[backdrop-filter]:bg-background/60

   Result:  Settings submenu now stays at top when scrolling

2. Switched to Emoji Flags 
   Problem: Base64 images not showing in select options
   Better Solution: Use native emoji flags

   Benefits:
   -  No image loading required
   -  Native OS rendering
   -  Smaller bundle size
   -  Better performance
   -  Always works (no broken images)

   Implementation:
   function countryCodeToEmoji(countryCode: string): string {
     const codePoints = countryCode
       .toUpperCase()
       .split('')
       .map(char => 127397 + char.charCodeAt(0));
     return String.fromCodePoint(...codePoints);
   }

   // AE → 🇦🇪
   // US → 🇺🇸
   // ID → 🇮🇩

3. Updated Currency Select 
   Before: [Image] United Arab Emirates dirham (AED)
   After:  🇦🇪 United Arab Emirates dirham (AED)

   - Emoji flag in label
   - No separate icon prop needed
   - Works immediately

4. Updated Store Summary 
   Before: [Image] Your store is located in Indonesia
   After:  🇮🇩 Your store is located in Indonesia

   - Dynamic emoji flag based on currency
   - Cleaner implementation
   - No image loading

5. Simplified SearchableSelect 
   - Removed icon prop (not needed with emoji)
   - Removed image rendering code
   - Simpler component API

Files Modified:
- SubmenuBar.tsx: Added sticky positioning
- Store.tsx: Emoji flags + helper function
- searchable-select.tsx: Removed icon support

Why Emoji > Images:
 Universal support (all modern browsers/OS)
 No loading time
 No broken images
 Smaller code
 Native rendering
 Accessibility friendly
2025-11-06 12:08:04 +07:00

50 lines
1.8 KiB
TypeScript

import React from 'react';
import { Link, useLocation } from 'react-router-dom';
import type { SubItem } from '@/nav/tree';
type Props = { items?: SubItem[] };
export default function SubmenuBar({ items = [] }: Props) {
// Always call hooks first
const { pathname } = useLocation();
// Single source of truth: props.items. No fallbacks, no demos, no path-based defaults
if (items.length === 0) return null;
return (
<div data-submenubar className="border-b border-border bg-background md:bg-background/95 md:backdrop-blur md:supports-[backdrop-filter]:bg-background/60 sticky top-0 z-20">
<div className="px-4 py-2">
<div className="flex gap-2 overflow-x-auto no-scrollbar">
{items.map((it) => {
const key = `${it.label}-${it.path || it.href}`;
// Fix: Always use exact match to prevent first submenu from being always active
const isActive = !!it.path && pathname === it.path;
const cls = [
'inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 border text-sm whitespace-nowrap',
'focus:outline-none focus:ring-0 focus:shadow-none',
isActive ? 'bg-accent text-accent-foreground' : 'hover:bg-accent hover:text-accent-foreground',
].join(' ');
if (it.mode === 'spa' && it.path) {
return (
<Link key={key} to={it.path} className={cls} data-discover>
{it.label}
</Link>
);
}
if (it.mode === 'bridge' && it.href) {
return (
<a key={key} href={it.href} className={cls} data-discover>
{it.label}
</a>
);
}
return null;
})}
</div>
</div>
</div>
);
}