@adlas/create-app 1.0.51 → 1.0.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -45,6 +45,7 @@ mcp__figma-dev-mode-mcp-server__get_design_context({
|
|
|
45
45
|
9. **Follow project structure** - Place files in correct locations as defined below
|
|
46
46
|
10. **Match coding patterns** - Use the same patterns found in existing code
|
|
47
47
|
11. **Type safety first** - Use TypeScript strictly, no `any` types
|
|
48
|
+
12. **❌ NEVER run build** - Do NOT run `pnpm build` or `pnpm lint` commands. The user will run these manually
|
|
48
49
|
|
|
49
50
|
---
|
|
50
51
|
|
|
@@ -78,13 +79,16 @@ export const Button = extendVariants(HeroUIButton, {
|
|
|
78
79
|
variants: {
|
|
79
80
|
color: {
|
|
80
81
|
// ✅ Use theme colors from hero.ts, NOT custom colors
|
|
81
|
-
primary: 'bg-primary text-black',
|
|
82
|
+
primary: 'bg-primary-500 text-black',
|
|
82
83
|
},
|
|
83
84
|
size: {
|
|
84
|
-
sm: 'h-
|
|
85
|
+
sm: 'h-10 px-4 text-sm',
|
|
85
86
|
md: 'h-10 px-4 text-sm',
|
|
86
87
|
lg: 'h-12 px-6 text-base',
|
|
87
88
|
},
|
|
89
|
+
radius: {
|
|
90
|
+
full: 'rounded-full',
|
|
91
|
+
},
|
|
88
92
|
},
|
|
89
93
|
defaultVariants: {
|
|
90
94
|
size: 'md',
|
|
@@ -166,16 +170,17 @@ const Button = extendVariants(HerouiButton, {
|
|
|
166
170
|
|
|
167
171
|
// In component usage:
|
|
168
172
|
<Button
|
|
169
|
-
color="primary" // ✅
|
|
170
|
-
|
|
173
|
+
color="primary" // ✅ Configured variant
|
|
174
|
+
size="sm" // ✅ Configured variant (can omit if md is default)
|
|
175
|
+
radius="full" // ✅ Configured radius variant
|
|
171
176
|
className="mt-4 hidden lg:block" // ✅ Layout utilities only
|
|
172
177
|
>
|
|
173
178
|
{t('navbar.bookDemo')} // ✅ i18n text
|
|
174
179
|
</Button>
|
|
175
|
-
// Note:
|
|
180
|
+
// Note: Omit props that match defaultVariants to keep code clean
|
|
176
181
|
|
|
177
182
|
// Using size prop when you need different size:
|
|
178
|
-
<Button color="primary" size="lg"> // ✅ Override default size
|
|
183
|
+
<Button color="primary" size="lg" radius="full"> // ✅ Override default size
|
|
179
184
|
Large Button
|
|
180
185
|
</Button>
|
|
181
186
|
|
|
@@ -339,6 +344,86 @@ import { Button } from '@/components/ui';
|
|
|
339
344
|
- ✅ className ONLY for layout (`hidden`, `lg:flex`, `bg-black`)
|
|
340
345
|
- ❌ DON'T use custom `<header>` or `<nav>` tags
|
|
341
346
|
|
|
347
|
+
#### Dropdown Menus in Navbar
|
|
348
|
+
**CRITICAL**: Always use HeroUI Dropdown components for dropdown menus:
|
|
349
|
+
|
|
350
|
+
```tsx
|
|
351
|
+
import {
|
|
352
|
+
Dropdown,
|
|
353
|
+
DropdownTrigger,
|
|
354
|
+
DropdownMenu,
|
|
355
|
+
DropdownItem,
|
|
356
|
+
} from '@heroui/react';
|
|
357
|
+
import { Button, Icon } from '@/components/ui';
|
|
358
|
+
|
|
359
|
+
// Dropdown with menu items from config
|
|
360
|
+
{item.hasDropdown && item.items && item.items.length > 0 ? (
|
|
361
|
+
<Dropdown>
|
|
362
|
+
<DropdownTrigger>
|
|
363
|
+
<Button
|
|
364
|
+
variant="light"
|
|
365
|
+
endContent={<Icon name="ChevronDownIcon" className="size-5" />}
|
|
366
|
+
>
|
|
367
|
+
{t(item.labelKey)}
|
|
368
|
+
</Button>
|
|
369
|
+
</DropdownTrigger>
|
|
370
|
+
<DropdownMenu aria-label={t(item.labelKey)}>
|
|
371
|
+
{item.items.map(subItem => (
|
|
372
|
+
<DropdownItem key={subItem.key} href={subItem.href}>
|
|
373
|
+
{t(subItem.labelKey)}
|
|
374
|
+
</DropdownItem>
|
|
375
|
+
))}
|
|
376
|
+
</DropdownMenu>
|
|
377
|
+
</Dropdown>
|
|
378
|
+
) : (
|
|
379
|
+
<Button variant="light">
|
|
380
|
+
{t(item.labelKey)}
|
|
381
|
+
</Button>
|
|
382
|
+
)}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
**Example Menu Configuration** (`src/config/menuItems.ts`):
|
|
386
|
+
```tsx
|
|
387
|
+
export type MenuItem = {
|
|
388
|
+
key: string;
|
|
389
|
+
labelKey: 'product' | 'useCases' | 'resources' | 'company' | 'pricing';
|
|
390
|
+
href?: string;
|
|
391
|
+
hasDropdown?: boolean;
|
|
392
|
+
items?: Array<{
|
|
393
|
+
key: string;
|
|
394
|
+
labelKey: string;
|
|
395
|
+
href: string;
|
|
396
|
+
}>;
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
export const navbarMenuItems: MenuItem[] = [
|
|
400
|
+
{
|
|
401
|
+
key: 'product',
|
|
402
|
+
labelKey: 'product',
|
|
403
|
+
hasDropdown: true,
|
|
404
|
+
items: [
|
|
405
|
+
{ key: 'analytics', labelKey: 'navbar.analytics', href: NAVIGATION_URLS.ROOT },
|
|
406
|
+
{ key: 'dashboard', labelKey: 'navbar.dashboard', href: NAVIGATION_URLS.ROOT },
|
|
407
|
+
{ key: 'reports', labelKey: 'navbar.reports', href: NAVIGATION_URLS.ROOT },
|
|
408
|
+
],
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
key: 'pricing',
|
|
412
|
+
labelKey: 'pricing',
|
|
413
|
+
href: NAVIGATION_URLS.ROOT,
|
|
414
|
+
},
|
|
415
|
+
];
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**Key Points**:
|
|
419
|
+
- ✅ Always check `items && items.length > 0` before rendering dropdown
|
|
420
|
+
- ✅ Use `Icon` component with proper name (e.g., `ChevronDownIcon`)
|
|
421
|
+
- ✅ Use `endContent` prop for icons in buttons
|
|
422
|
+
- ✅ Add `aria-label` to DropdownMenu for accessibility
|
|
423
|
+
- ✅ Map menu items from config constants, never hardcode
|
|
424
|
+
- ✅ Use union types for `labelKey` to ensure type safety
|
|
425
|
+
- ❌ DON'T render dropdown without checking array exists
|
|
426
|
+
|
|
342
427
|
### Form Components
|
|
343
428
|
All located in `src/components/ui/`:
|
|
344
429
|
|
|
@@ -495,9 +580,15 @@ pnpm generate-icons
|
|
|
495
580
|
This command will:
|
|
496
581
|
- Convert all SVG files in `src/assets/icons/` to React components
|
|
497
582
|
- Place them in `src/components/icons/`
|
|
583
|
+
- **Automatically add "Icon" suffix** to all component names (configured in `svgr.config.mjs`)
|
|
498
584
|
- Auto-format and lint the generated code
|
|
499
585
|
- Update `src/components/icons/index.ts` with exports
|
|
500
586
|
|
|
587
|
+
**Icon Naming Convention**:
|
|
588
|
+
- SVG filename: `chevron-down.svg` or `chevron-down-icon.svg`
|
|
589
|
+
- Generated component: `ChevronDownIcon.tsx` (Icon suffix added automatically)
|
|
590
|
+
- The svgr config ensures ALL icons end with "Icon" suffix regardless of SVG filename
|
|
591
|
+
|
|
501
592
|
#### Step 4: Use in Code
|
|
502
593
|
|
|
503
594
|
**CORRECT USAGE**: Use the `Icon` component with `name` prop (PascalCase):
|
|
@@ -643,18 +734,28 @@ export const IMAGES = {
|
|
|
643
734
|
|
|
644
735
|
#### Step 5: Reference in Code
|
|
645
736
|
|
|
737
|
+
**CRITICAL: ALWAYS import and use IMAGES constant - NEVER hardcode paths**
|
|
738
|
+
|
|
646
739
|
```tsx
|
|
647
|
-
// Import from centralized constants
|
|
740
|
+
// ✅ CORRECT - Import from centralized constants
|
|
648
741
|
import { IMAGES } from '@/config/images';
|
|
649
742
|
import Image from 'next/image';
|
|
650
743
|
|
|
651
744
|
// Using Next.js Image component (recommended)
|
|
652
745
|
<Image
|
|
653
|
-
src={IMAGES.LOGOS.
|
|
654
|
-
alt="
|
|
655
|
-
width={
|
|
656
|
-
height={
|
|
657
|
-
|
|
746
|
+
src={IMAGES.LOGOS.BINA} // ✅ Use constant
|
|
747
|
+
alt="BINA"
|
|
748
|
+
width={54}
|
|
749
|
+
height={41}
|
|
750
|
+
className="h-10 w-auto"
|
|
751
|
+
/>
|
|
752
|
+
|
|
753
|
+
// ❌ WRONG - Hardcoded path
|
|
754
|
+
<Image
|
|
755
|
+
src="/images/logos/bina.png" // ❌ Don't hardcode
|
|
756
|
+
alt="BINA"
|
|
757
|
+
width={54}
|
|
758
|
+
height={41}
|
|
658
759
|
/>
|
|
659
760
|
|
|
660
761
|
// Using standard img tag (for SVGs with CSS control)
|
|
@@ -683,7 +784,8 @@ import Image from 'next/image';
|
|
|
683
784
|
- Import images as modules unless necessary
|
|
684
785
|
- Use base64 encoded images inline
|
|
685
786
|
- Forget to optimize images before adding
|
|
686
|
-
- Hardcode image paths directly in components
|
|
787
|
+
- **CRITICAL**: Hardcode image paths directly in components - MUST use `IMAGES` constant from `@/config/images`
|
|
788
|
+
- Use hardcoded strings like `src="/images/logos/bina.png"` - Use `src={IMAGES.LOGOS.BINA}` instead
|
|
687
789
|
|
|
688
790
|
**✅ DO**:
|
|
689
791
|
- Always place in `public/` directory
|
|
@@ -1033,25 +1135,62 @@ export function MyComponent() {
|
|
|
1033
1135
|
```
|
|
1034
1136
|
|
|
1035
1137
|
### Translations for ALL text
|
|
1138
|
+
|
|
1139
|
+
**CRITICAL: Specify namespace to avoid TypeScript errors**
|
|
1140
|
+
|
|
1036
1141
|
```tsx
|
|
1037
1142
|
import { useTranslations } from 'next-intl';
|
|
1038
1143
|
|
|
1039
1144
|
function MyComponent() {
|
|
1040
|
-
|
|
1145
|
+
// ✅ CORRECT - Specify namespace for type safety
|
|
1146
|
+
const t = useTranslations('namespace');
|
|
1041
1147
|
|
|
1042
1148
|
return (
|
|
1043
1149
|
<div>
|
|
1044
|
-
{/*
|
|
1150
|
+
{/* Now you can use keys directly without type errors */}
|
|
1045
1151
|
<h1>{t('welcome')}</h1>
|
|
1046
1152
|
<p>{t('description')}</p>
|
|
1153
|
+
</div>
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1047
1156
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1157
|
+
// ❌ WRONG - No namespace causes TypeScript errors with dynamic keys
|
|
1158
|
+
function BadComponent() {
|
|
1159
|
+
const t = useTranslations(); // Missing namespace
|
|
1160
|
+
|
|
1161
|
+
const items = [
|
|
1162
|
+
{ key: 'product', labelKey: 'navbar.product' }
|
|
1163
|
+
];
|
|
1164
|
+
|
|
1165
|
+
return (
|
|
1166
|
+
<div>
|
|
1167
|
+
{/* TypeScript error: Argument of type 'string' is not assignable */}
|
|
1168
|
+
{items.map(item => <p key={item.key}>{t(item.labelKey)}</p>)}
|
|
1050
1169
|
</div>
|
|
1051
1170
|
);
|
|
1052
1171
|
}
|
|
1053
1172
|
```
|
|
1054
1173
|
|
|
1174
|
+
**Type-Safe Translation Pattern:**
|
|
1175
|
+
```tsx
|
|
1176
|
+
// 1. Define translation key types in config
|
|
1177
|
+
export type MenuItem = {
|
|
1178
|
+
key: string;
|
|
1179
|
+
labelKey: 'product' | 'useCases' | 'resources'; // Union type of valid keys
|
|
1180
|
+
href?: string;
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
// 2. Use with namespace
|
|
1184
|
+
const t = useTranslations('navbar');
|
|
1185
|
+
|
|
1186
|
+
// 3. Access keys directly (type-safe)
|
|
1187
|
+
{menuItems.map(item => (
|
|
1188
|
+
<Button key={item.key}>
|
|
1189
|
+
{t(item.labelKey)} {/* No TypeScript error */}
|
|
1190
|
+
</Button>
|
|
1191
|
+
))}
|
|
1192
|
+
```
|
|
1193
|
+
|
|
1055
1194
|
### Form labels, placeholders, errors - ALL must use i18n
|
|
1056
1195
|
```tsx
|
|
1057
1196
|
import { useTranslations } from 'next-intl';
|
|
@@ -1169,11 +1308,15 @@ import { Navbar } from '@/components/layout';
|
|
|
1169
1308
|
<main>{children}</main>
|
|
1170
1309
|
```
|
|
1171
1310
|
|
|
1172
|
-
**Implementation details** (see `src/components/layout/Navbar.tsx`):
|
|
1173
|
-
- ✅ Uses HeroUI `Navbar`, `NavbarBrand`, `NavbarContent`, `NavbarItem`
|
|
1311
|
+
**Implementation details** (see `src/components/layout/Navbar.tsx` and `docs/NAVBAR_IMPLEMENTATION.md`):
|
|
1312
|
+
- ✅ Uses HeroUI `Navbar`, `NavbarBrand`, `NavbarContent`, `NavbarItem`, `Dropdown`
|
|
1174
1313
|
- ✅ Uses `Button` from `@/components/ui` with props (`color`, `size`, `variant`)
|
|
1314
|
+
- ✅ Uses `useTranslations('navbar')` with namespace for type safety
|
|
1315
|
+
- ✅ Menu items mapped from `src/config/menuItems.ts` with typed `labelKey`
|
|
1316
|
+
- ✅ Dropdown menus with HeroUI `Dropdown`, `DropdownTrigger`, `DropdownMenu`
|
|
1175
1317
|
- ✅ All styles via props, NO className for component styles
|
|
1176
1318
|
- ✅ className ONLY for layout utilities
|
|
1319
|
+
- ✅ NO `any` types - uses union types for translation keys
|
|
1177
1320
|
|
|
1178
1321
|
---
|
|
1179
1322
|
|
|
@@ -1185,11 +1328,12 @@ import { Navbar } from '@/components/layout';
|
|
|
1185
1328
|
3. ❌ **Icons**: Import individual icon components (e.g., `import { ChevronDownIcon }`) - MUST use `<Icon name="ChevronDownIcon" />`
|
|
1186
1329
|
4. ❌ **Icons**: Create manual icon components - MUST use `pnpm generate-icons` workflow
|
|
1187
1330
|
5. ❌ **Icons**: Use non-project icons (Lucide, Font Awesome, etc.)
|
|
1188
|
-
6. ❌ **
|
|
1189
|
-
7. ❌ **
|
|
1190
|
-
8. ❌ **
|
|
1191
|
-
9. ❌ **
|
|
1192
|
-
10. ❌ **Tailwind**: Use
|
|
1331
|
+
6. ❌ **Images**: Put logos/images in `src/` folder - MUST go in `public/`
|
|
1332
|
+
7. ❌ **Images**: Import images as modules unless necessary
|
|
1333
|
+
8. ❌ **Images**: **CRITICAL** - Hardcode image/video paths (e.g., `src="/images/logos/bina.png"`) - MUST use `IMAGES` constant
|
|
1334
|
+
9. ❌ **Images**: Use direct path strings anywhere - ALL paths MUST come from `@/config/images`
|
|
1335
|
+
10. ❌ **Tailwind**: Use arbitrary values when standard classes exist (e.g., `h-[40px]` → use `h-10`)
|
|
1336
|
+
11. ❌ **Tailwind**: Use custom values like `w-[100%]` (use `w-full`)
|
|
1193
1337
|
11. ❌ **Colors**: Use custom color values (e.g., `bg-[#19ffa3]`, `text-[#ff0000]`) - MUST use theme colors from hero.ts
|
|
1194
1338
|
12. ❌ **Colors**: Use hex, rgb, or hsl values inline - Use semantic color classes instead
|
|
1195
1339
|
13. ❌ **Text**: Hardcode ANY text - ALL text MUST use i18n translation keys
|
|
@@ -1203,23 +1347,28 @@ import { Navbar } from '@/components/layout';
|
|
|
1203
1347
|
21. ❌ **Imports**: Import from `@heroui/react` directly (use `@/components/ui` wrappers when available)
|
|
1204
1348
|
22. ❌ **Navigation**: Use HeroUI `Link` for internal navigation (use Next.js `Link` from `next/link`)
|
|
1205
1349
|
23. ❌ **Navigation**: Import `usePathname`, `useRouter` from wrong source (MUST use `next/navigation`)
|
|
1206
|
-
24. ❌ **TypeScript**: Use `any` type
|
|
1207
|
-
25. ❌ **
|
|
1208
|
-
26. ❌ **
|
|
1350
|
+
24. ❌ **TypeScript**: Use `any` type - Use union types and proper typing instead
|
|
1351
|
+
25. ❌ **i18n**: Use `useTranslations()` without namespace - MUST specify namespace for type safety
|
|
1352
|
+
26. ❌ **i18n**: Use dynamic translation keys without proper typing - Define union types for keys
|
|
1353
|
+
27. ❌ **Design**: Ignore responsive design (always implement mobile-first)
|
|
1354
|
+
28. ❌ **Forms**: Skip form validation (always use Zod schemas)
|
|
1355
|
+
29. ❌ **Dropdowns**: Render dropdown items without checking if items array exists/has length
|
|
1356
|
+
30. ❌ **Build**: Run `pnpm build` or `pnpm lint` commands - The user will run these manually
|
|
1209
1357
|
|
|
1210
1358
|
### ✅ DO
|
|
1211
1359
|
1. ✅ **Figma**: Use Figma MCP server with `get_design_context` and node-id from Figma URL
|
|
1212
1360
|
2. ✅ **Figma**: Extract node-id from URL (e.g., `node-id=8486-1580` → `"8486:1580"`)
|
|
1213
1361
|
3. ✅ **Icons**: Export SVG from Figma → `src/assets/icons/` → Run `pnpm generate-icons`
|
|
1214
1362
|
4. ✅ **Icons**: Use `<Icon name="IconName" />` pattern with PascalCase - NEVER import individual icon components
|
|
1215
|
-
5. ✅ **
|
|
1216
|
-
6. ✅ **
|
|
1217
|
-
7. ✅ **
|
|
1218
|
-
8. ✅ **
|
|
1219
|
-
9. ✅ **
|
|
1220
|
-
10. ✅ **
|
|
1221
|
-
11. ✅ **
|
|
1222
|
-
12. ✅ **Tailwind**: Use
|
|
1363
|
+
5. ✅ **Images**: Check `public/images/index.ts` BEFORE exporting from Figma
|
|
1364
|
+
6. ✅ **Images**: Check `public/images/logos/` directory for existing assets
|
|
1365
|
+
7. ✅ **Images**: Export SVG/PNG from Figma ONLY if not existing → Place in `public/images/` with organized folders
|
|
1366
|
+
8. ✅ **Images**: **CRITICAL** - Create/update `src/config/images.ts` with ALL image paths
|
|
1367
|
+
9. ✅ **Images**: **ALWAYS** import from `@/config/images` and use `IMAGES.LOGOS.BINA` (NEVER hardcode)
|
|
1368
|
+
10. ✅ **Images**: Add new images to centralized config immediately
|
|
1369
|
+
11. ✅ **Images**: Prefer SVG over PNG when source is vector
|
|
1370
|
+
12. ✅ **Tailwind**: Use standard classes (`h-10`, `p-6`, `text-sm` instead of arbitrary values)
|
|
1371
|
+
13. ✅ **Tailwind**: Use size utilities (`size-4`, `size-5`) for icons
|
|
1223
1372
|
13. ✅ **Colors**: Use theme colors from hero.ts (`bg-primary`, `text-primary-600`, `bg-success`)
|
|
1224
1373
|
14. ✅ **Colors**: Check hero.ts and globals.css for available colors before using custom values
|
|
1225
1374
|
15. ✅ **Navigation**: Use Next.js `Link` from `next/link` for internal navigation
|
|
@@ -1235,11 +1384,15 @@ import { Navbar } from '@/components/layout';
|
|
|
1235
1384
|
25. ✅ **Styling**: Omit props that match defaultVariants (e.g., don't write `size="md"` if `md` is default)
|
|
1236
1385
|
26. ✅ **Styling**: Use className ONLY for layout utilities (`mt-4`, `hidden`, `lg:flex`)
|
|
1237
1386
|
27. ✅ **Styling**: Use Tailwind CSS ONLY (utility classes)
|
|
1238
|
-
28. ✅ **TypeScript**: Implement strict typing with proper types
|
|
1239
|
-
29. ✅ **
|
|
1240
|
-
30. ✅ **
|
|
1241
|
-
31. ✅ **
|
|
1242
|
-
32. ✅ **
|
|
1387
|
+
28. ✅ **TypeScript**: Implement strict typing with proper types (NO `any`)
|
|
1388
|
+
29. ✅ **TypeScript**: Use union types for translation keys (e.g., `labelKey: 'product' | 'useCases'`)
|
|
1389
|
+
30. ✅ **i18n**: Specify namespace in `useTranslations('namespace')` for type safety
|
|
1390
|
+
31. ✅ **i18n**: Define typed keys in config to avoid dynamic string issues
|
|
1391
|
+
32. ✅ **Dropdowns**: Check array exists and has length before mapping (`items && items.length > 0`)
|
|
1392
|
+
33. ✅ **React**: Use `'use client'` directive for interactive components
|
|
1393
|
+
34. ✅ **Design**: Follow mobile-first responsive design
|
|
1394
|
+
35. ✅ **States**: Implement proper loading and error states
|
|
1395
|
+
36. ✅ **Patterns**: Follow existing code patterns and naming conventions
|
|
1243
1396
|
|
|
1244
1397
|
---
|
|
1245
1398
|
|
|
@@ -1384,11 +1537,14 @@ export const IMAGES = {
|
|
|
1384
1537
|
WEBSITE,
|
|
1385
1538
|
} as const;
|
|
1386
1539
|
|
|
1387
|
-
# 4. Use in code
|
|
1540
|
+
# 4. Use in code - ALWAYS use IMAGES constant
|
|
1388
1541
|
import { IMAGES } from '@/config/images';
|
|
1389
|
-
|
|
1390
|
-
#
|
|
1391
|
-
<Image src={IMAGES.LOGOS.
|
|
1542
|
+
|
|
1543
|
+
# ✅ CORRECT
|
|
1544
|
+
<Image src={IMAGES.LOGOS.BINA} alt="Logo" width={54} height={41} />
|
|
1545
|
+
|
|
1546
|
+
# ❌ WRONG - Hardcoded path
|
|
1547
|
+
<Image src="/images/logos/bina.png" alt="Logo" width={54} height={41} />
|
|
1392
1548
|
```
|
|
1393
1549
|
|
|
1394
1550
|
### Tailwind Standard Classes
|
|
@@ -1416,9 +1572,14 @@ text-lg = 18px text-3xl = 30px
|
|
|
1416
1572
|
import { MenuIcon, CloseIcon } from '@/components/icons';
|
|
1417
1573
|
<MenuIcon className="size-6 text-white" />
|
|
1418
1574
|
|
|
1419
|
-
// Logos (
|
|
1575
|
+
// Images & Logos (ALWAYS use IMAGES constant - NEVER hardcode)
|
|
1420
1576
|
import { IMAGES } from '@/config/images';
|
|
1421
|
-
|
|
1577
|
+
|
|
1578
|
+
// ✅ CORRECT
|
|
1579
|
+
<Image src={IMAGES.LOGOS.BINA} alt="Logo" width={54} height={41} />
|
|
1580
|
+
|
|
1581
|
+
// ❌ WRONG
|
|
1582
|
+
<Image src="/images/logos/bina.png" alt="Logo" />
|
|
1422
1583
|
|
|
1423
1584
|
// Navigation (Next.js Link + constants)
|
|
1424
1585
|
import Link from 'next/link';
|