Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70a4db94c1 | ||
|
|
83722aeb7c | ||
|
|
2709d4c164 | ||
|
|
549553c05b | ||
|
|
ac3b69f864 | ||
|
|
a62ff5b064 | ||
|
|
53a9ed015a |
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
|
.claude/
|
||||||
.superpowers/
|
.superpowers/
|
||||||
.worktrees/
|
.worktrees/
|
||||||
test-results/
|
test-results/
|
||||||
|
|||||||
101
AGENTS.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<!-- gitnexus:start -->
|
||||||
|
# GitNexus — Code Intelligence
|
||||||
|
|
||||||
|
This project is indexed by GitNexus as **design-system** (1479 symbols, 2371 relationships, 24 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||||
|
|
||||||
|
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
|
||||||
|
|
||||||
|
## Always Do
|
||||||
|
|
||||||
|
- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `gitnexus_impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
|
||||||
|
- **MUST run `gitnexus_detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows.
|
||||||
|
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
|
||||||
|
- When exploring unfamiliar code, use `gitnexus_query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
|
||||||
|
- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `gitnexus_context({name: "symbolName"})`.
|
||||||
|
|
||||||
|
## When Debugging
|
||||||
|
|
||||||
|
1. `gitnexus_query({query: "<error or symptom>"})` — find execution flows related to the issue
|
||||||
|
2. `gitnexus_context({name: "<suspect function>"})` — see all callers, callees, and process participation
|
||||||
|
3. `READ gitnexus://repo/design-system/process/{processName}` — trace the full execution flow step by step
|
||||||
|
4. For regressions: `gitnexus_detect_changes({scope: "compare", base_ref: "main"})` — see what your branch changed
|
||||||
|
|
||||||
|
## When Refactoring
|
||||||
|
|
||||||
|
- **Renaming**: MUST use `gitnexus_rename({symbol_name: "old", new_name: "new", dry_run: true})` first. Review the preview — graph edits are safe, text_search edits need manual review. Then run with `dry_run: false`.
|
||||||
|
- **Extracting/Splitting**: MUST run `gitnexus_context({name: "target"})` to see all incoming/outgoing refs, then `gitnexus_impact({target: "target", direction: "upstream"})` to find all external callers before moving code.
|
||||||
|
- After any refactor: run `gitnexus_detect_changes({scope: "all"})` to verify only expected files changed.
|
||||||
|
|
||||||
|
## Never Do
|
||||||
|
|
||||||
|
- NEVER edit a function, class, or method without first running `gitnexus_impact` on it.
|
||||||
|
- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
|
||||||
|
- NEVER rename symbols with find-and-replace — use `gitnexus_rename` which understands the call graph.
|
||||||
|
- NEVER commit changes without running `gitnexus_detect_changes()` to check affected scope.
|
||||||
|
|
||||||
|
## Tools Quick Reference
|
||||||
|
|
||||||
|
| Tool | When to use | Command |
|
||||||
|
|------|-------------|---------|
|
||||||
|
| `query` | Find code by concept | `gitnexus_query({query: "auth validation"})` |
|
||||||
|
| `context` | 360-degree view of one symbol | `gitnexus_context({name: "validateUser"})` |
|
||||||
|
| `impact` | Blast radius before editing | `gitnexus_impact({target: "X", direction: "upstream"})` |
|
||||||
|
| `detect_changes` | Pre-commit scope check | `gitnexus_detect_changes({scope: "staged"})` |
|
||||||
|
| `rename` | Safe multi-file rename | `gitnexus_rename({symbol_name: "old", new_name: "new", dry_run: true})` |
|
||||||
|
| `cypher` | Custom graph queries | `gitnexus_cypher({query: "MATCH ..."})` |
|
||||||
|
|
||||||
|
## Impact Risk Levels
|
||||||
|
|
||||||
|
| Depth | Meaning | Action |
|
||||||
|
|-------|---------|--------|
|
||||||
|
| d=1 | WILL BREAK — direct callers/importers | MUST update these |
|
||||||
|
| d=2 | LIKELY AFFECTED — indirect deps | Should test |
|
||||||
|
| d=3 | MAY NEED TESTING — transitive | Test if critical path |
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
| Resource | Use for |
|
||||||
|
|----------|---------|
|
||||||
|
| `gitnexus://repo/design-system/context` | Codebase overview, check index freshness |
|
||||||
|
| `gitnexus://repo/design-system/clusters` | All functional areas |
|
||||||
|
| `gitnexus://repo/design-system/processes` | All execution flows |
|
||||||
|
| `gitnexus://repo/design-system/process/{name}` | Step-by-step execution trace |
|
||||||
|
|
||||||
|
## Self-Check Before Finishing
|
||||||
|
|
||||||
|
Before completing any code modification task, verify:
|
||||||
|
1. `gitnexus_impact` was run for all modified symbols
|
||||||
|
2. No HIGH/CRITICAL risk warnings were ignored
|
||||||
|
3. `gitnexus_detect_changes()` confirms changes match expected scope
|
||||||
|
4. All d=1 (WILL BREAK) dependents were updated
|
||||||
|
|
||||||
|
## Keeping the Index Fresh
|
||||||
|
|
||||||
|
After committing code changes, the GitNexus index becomes stale. Re-run analyze to update it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx gitnexus analyze
|
||||||
|
```
|
||||||
|
|
||||||
|
If the index previously included embeddings, preserve them by adding `--embeddings`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx gitnexus analyze --embeddings
|
||||||
|
```
|
||||||
|
|
||||||
|
To check whether embeddings exist, inspect `.gitnexus/meta.json` — the `stats.embeddings` field shows the count (0 means no embeddings). **Running analyze without `--embeddings` will delete any previously generated embeddings.**
|
||||||
|
|
||||||
|
> Claude Code users: A PostToolUse hook handles this automatically after `git commit` and `git merge`.
|
||||||
|
|
||||||
|
## CLI
|
||||||
|
|
||||||
|
| Task | Read this skill file |
|
||||||
|
|------|---------------------|
|
||||||
|
| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
|
||||||
|
| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
|
||||||
|
| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
|
||||||
|
| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
|
||||||
|
| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
|
||||||
|
| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
|
||||||
|
|
||||||
|
<!-- gitnexus:end -->
|
||||||
@@ -132,7 +132,7 @@ import camelSvg from '@cameleer/design-system/assets/camel-logo.svg' // simp
|
|||||||
<!-- gitnexus:start -->
|
<!-- gitnexus:start -->
|
||||||
# GitNexus — Code Intelligence
|
# GitNexus — Code Intelligence
|
||||||
|
|
||||||
This project is indexed by GitNexus as **design-system** (1461 symbols, 2336 relationships, 23 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
This project is indexed by GitNexus as **design-system** (1479 symbols, 2371 relationships, 24 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||||
|
|
||||||
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
|
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 941 B After Width: | Height: | Size: 941 B |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 342 KiB After Width: | Height: | Size: 342 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@cameleer/design-system",
|
"name": "@cameleer/design-system",
|
||||||
"version": "0.1.47",
|
"version": "0.1.52",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.es.js",
|
"main": "./dist/index.es.js",
|
||||||
"module": "./dist/index.es.js",
|
"module": "./dist/index.es.js",
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ interface BreadcrumbItem {
|
|||||||
interface BreadcrumbProps {
|
interface BreadcrumbProps {
|
||||||
items: BreadcrumbItem[]
|
items: BreadcrumbItem[]
|
||||||
className?: string
|
className?: string
|
||||||
|
onNavigate?: (href: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Breadcrumb({ items, className }: BreadcrumbProps) {
|
export function Breadcrumb({ items, className, onNavigate }: BreadcrumbProps) {
|
||||||
return (
|
return (
|
||||||
<nav aria-label="Breadcrumb" className={className}>
|
<nav aria-label="Breadcrumb" className={className}>
|
||||||
<ol className={styles.list}>
|
<ol className={styles.list}>
|
||||||
@@ -22,7 +23,11 @@ export function Breadcrumb({ items, className }: BreadcrumbProps) {
|
|||||||
{isLast ? (
|
{isLast ? (
|
||||||
<span className={styles.active}>{item.label}</span>
|
<span className={styles.active}>{item.label}</span>
|
||||||
) : item.href ? (
|
) : item.href ? (
|
||||||
<a href={item.href} className={styles.link}>
|
<a
|
||||||
|
href={item.href}
|
||||||
|
className={styles.link}
|
||||||
|
onClick={onNavigate ? (e) => { e.preventDefault(); onNavigate(item.href!) } : undefined}
|
||||||
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -61,6 +61,38 @@
|
|||||||
background: color-mix(in srgb, var(--text-faint) 8%, transparent);
|
background: color-mix(in srgb, var(--text-faint) 8%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sourceBadge {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: 9px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
padding: 1px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: nowrap;
|
||||||
|
min-width: 48px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceContainer {
|
||||||
|
color: var(--text-muted);
|
||||||
|
background: color-mix(in srgb, var(--text-muted) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceApp {
|
||||||
|
color: var(--running);
|
||||||
|
background: color-mix(in srgb, var(--running) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceAgent {
|
||||||
|
color: var(--warning);
|
||||||
|
background: color-mix(in srgb, var(--warning) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sourceDefault {
|
||||||
|
color: var(--text-muted);
|
||||||
|
background: color-mix(in srgb, var(--text-muted) 8%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-family: var(--font-mono);
|
font-family: var(--font-mono);
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { render, screen } from '@testing-library/react'
|
|||||||
import { LogViewer, type LogEntry } from './LogViewer'
|
import { LogViewer, type LogEntry } from './LogViewer'
|
||||||
|
|
||||||
const entries: LogEntry[] = [
|
const entries: LogEntry[] = [
|
||||||
{ timestamp: '2024-01-15T10:30:00Z', level: 'info', message: 'Server started' },
|
{ timestamp: '2024-01-15T10:30:00Z', level: 'info', message: 'Server started', source: 'app' },
|
||||||
{ timestamp: '2024-01-15T10:30:05Z', level: 'warn', message: 'High memory usage' },
|
{ timestamp: '2024-01-15T10:30:05Z', level: 'warn', message: 'High memory usage', source: 'container' },
|
||||||
{ timestamp: '2024-01-15T10:30:10Z', level: 'error', message: 'Connection failed' },
|
{ timestamp: '2024-01-15T10:30:10Z', level: 'error', message: 'Connection failed', source: 'agent' },
|
||||||
{ timestamp: '2024-01-15T10:30:15Z', level: 'debug', message: 'Query executed in 3ms' },
|
{ timestamp: '2024-01-15T10:30:15Z', level: 'debug', message: 'Query executed in 3ms' },
|
||||||
{ timestamp: '2024-01-15T10:30:20Z', level: 'trace', message: 'Entering handleRequest()' },
|
{ timestamp: '2024-01-15T10:30:20Z', level: 'trace', message: 'Entering handleRequest()' },
|
||||||
]
|
]
|
||||||
@@ -52,6 +52,23 @@ describe('LogViewer', () => {
|
|||||||
expect(el.classList.contains('custom-class')).toBe(true)
|
expect(el.classList.contains('custom-class')).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('renders source badges when source is provided', () => {
|
||||||
|
render(<LogViewer entries={entries} />)
|
||||||
|
expect(screen.getByText('app')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('container')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('agent')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('omits source badge when source is not provided', () => {
|
||||||
|
const noSourceEntries: LogEntry[] = [
|
||||||
|
{ timestamp: '2024-01-15T10:30:00Z', level: 'info', message: 'No source here' },
|
||||||
|
]
|
||||||
|
render(<LogViewer entries={noSourceEntries} />)
|
||||||
|
expect(screen.getByText('No source here')).toBeInTheDocument()
|
||||||
|
expect(screen.queryByText('app')).not.toBeInTheDocument()
|
||||||
|
expect(screen.queryByText('container')).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
it('has role="log" for accessibility', () => {
|
it('has role="log" for accessibility', () => {
|
||||||
render(<LogViewer entries={entries} />)
|
render(<LogViewer entries={entries} />)
|
||||||
expect(screen.getByRole('log')).toBeInTheDocument()
|
expect(screen.getByRole('log')).toBeInTheDocument()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export interface LogEntry {
|
|||||||
timestamp: string
|
timestamp: string
|
||||||
level: 'info' | 'warn' | 'error' | 'debug' | 'trace'
|
level: 'info' | 'warn' | 'error' | 'debug' | 'trace'
|
||||||
message: string
|
message: string
|
||||||
|
source?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LogViewerProps {
|
export interface LogViewerProps {
|
||||||
@@ -21,6 +22,12 @@ const LEVEL_CLASS: Record<LogEntry['level'], string> = {
|
|||||||
trace: styles.levelTrace,
|
trace: styles.levelTrace,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SOURCE_CLASS: Record<string, string> = {
|
||||||
|
container: styles.sourceContainer,
|
||||||
|
app: styles.sourceApp,
|
||||||
|
agent: styles.sourceAgent,
|
||||||
|
}
|
||||||
|
|
||||||
function formatTime(iso: string): string {
|
function formatTime(iso: string): string {
|
||||||
try {
|
try {
|
||||||
return new Date(iso).toLocaleTimeString('en-GB', {
|
return new Date(iso).toLocaleTimeString('en-GB', {
|
||||||
@@ -67,6 +74,11 @@ export function LogViewer({ entries, maxHeight = 400, className }: LogViewerProp
|
|||||||
<span className={[styles.levelBadge, LEVEL_CLASS[entry.level]].join(' ')}>
|
<span className={[styles.levelBadge, LEVEL_CLASS[entry.level]].join(' ')}>
|
||||||
{entry.level.toUpperCase()}
|
{entry.level.toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
|
{entry.source && (
|
||||||
|
<span className={[styles.sourceBadge, SOURCE_CLASS[entry.source] ?? styles.sourceDefault].join(' ')}>
|
||||||
|
{entry.source}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
<span className={styles.message}>{entry.message}</span>
|
<span className={styles.message}>{entry.message}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ export function ThemedChart({
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show ~5-6 ticks max to avoid label overlap
|
||||||
|
const maxTicks = 6
|
||||||
|
const tickInterval = data.length > maxTicks
|
||||||
|
? Math.ceil(data.length / maxTicks) - 1
|
||||||
|
: 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className} style={{ width: '100%', height }}>
|
<div className={className} style={{ width: '100%', height }}>
|
||||||
<ResponsiveContainer width="100%" height="100%">
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
@@ -46,6 +52,8 @@ export function ThemedChart({
|
|||||||
type={xType}
|
type={xType}
|
||||||
{...rechartsTheme.xAxis}
|
{...rechartsTheme.xAxis}
|
||||||
tickFormatter={xTickFormatter}
|
tickFormatter={xTickFormatter}
|
||||||
|
interval={tickInterval}
|
||||||
|
minTickGap={40}
|
||||||
/>
|
/>
|
||||||
<YAxis
|
<YAxis
|
||||||
{...rechartsTheme.yAxis}
|
{...rechartsTheme.yAxis}
|
||||||
|
|||||||
@@ -53,6 +53,12 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebarCollapsed .collapseToggle {
|
||||||
|
top: 52px;
|
||||||
|
right: 50%;
|
||||||
|
transform: translateX(50%);
|
||||||
|
}
|
||||||
|
|
||||||
.logoImg {
|
.logoImg {
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ interface TopBarProps {
|
|||||||
user?: { name: string }
|
user?: { name: string }
|
||||||
userMenuItems?: import('../../composites/Dropdown/Dropdown').DropdownItem[]
|
userMenuItems?: import('../../composites/Dropdown/Dropdown').DropdownItem[]
|
||||||
onLogout?: () => void
|
onLogout?: () => void
|
||||||
|
onNavigate?: (href: string) => void
|
||||||
className?: string
|
className?: string
|
||||||
children?: ReactNode
|
children?: ReactNode
|
||||||
}
|
}
|
||||||
@@ -24,6 +25,7 @@ export function TopBar({
|
|||||||
user,
|
user,
|
||||||
userMenuItems,
|
userMenuItems,
|
||||||
onLogout,
|
onLogout,
|
||||||
|
onNavigate,
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
}: TopBarProps) {
|
}: TopBarProps) {
|
||||||
@@ -33,7 +35,7 @@ export function TopBar({
|
|||||||
return (
|
return (
|
||||||
<header className={`${styles.topbar} ${className ?? ''}`}>
|
<header className={`${styles.topbar} ${className ?? ''}`}>
|
||||||
{/* Left: Breadcrumb */}
|
{/* Left: Breadcrumb */}
|
||||||
<Breadcrumb items={breadcrumbOverride ?? breadcrumb} className={styles.breadcrumb} />
|
<Breadcrumb items={breadcrumbOverride ?? breadcrumb} className={styles.breadcrumb} onNavigate={onNavigate} />
|
||||||
|
|
||||||
{/* Center: consumer-provided controls */}
|
{/* Center: consumer-provided controls */}
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import styles from './BrandAssetsSection.module.css'
|
import styles from './BrandAssetsSection.module.css'
|
||||||
import camelLogoSvg from '../../../assets/camel-logo.svg'
|
import camelLogoSvg from '../../../assets/camel-logo.svg'
|
||||||
import cameleer3Logo from '../../../assets/cameleer3-logo.png'
|
import cameleerLogo from '../../../assets/cameleer-logo.png'
|
||||||
import cameleer3LogoSvg from '../../../assets/cameleer3-logo.svg'
|
import cameleerLogoSvg from '../../../assets/cameleer-logo.svg'
|
||||||
|
|
||||||
const LOGO_SIZES = [16, 32, 48, 180, 192, 512] as const
|
const LOGO_SIZES = [16, 32, 48, 180, 192, 512] as const
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ export function BrandAssetsSection() {
|
|||||||
<h2 className={styles.sectionTitle}>Brand Assets</h2>
|
<h2 className={styles.sectionTitle}>Brand Assets</h2>
|
||||||
|
|
||||||
<div className={styles.componentCard}>
|
<div className={styles.componentCard}>
|
||||||
<h3 className={styles.componentTitle}>Cameleer3 Logo (PNG)</h3>
|
<h3 className={styles.componentTitle}>Cameleer Logo (PNG)</h3>
|
||||||
<p className={styles.componentDesc}>
|
<p className={styles.componentDesc}>
|
||||||
Full-resolution logo and pre-generated size variants for favicons, PWA icons, and social images.
|
Full-resolution logo and pre-generated size variants for favicons, PWA icons, and social images.
|
||||||
Shipped as static assets via <code>@cameleer/design-system/assets/*</code> export.
|
Shipped as static assets via <code>@cameleer/design-system/assets/*</code> export.
|
||||||
@@ -22,27 +22,27 @@ export function BrandAssetsSection() {
|
|||||||
<div key={size} className={styles.logoItem}>
|
<div key={size} className={styles.logoItem}>
|
||||||
<div className={styles.logoPreview}>
|
<div className={styles.logoPreview}>
|
||||||
<img
|
<img
|
||||||
src={cameleer3Logo}
|
src={cameleerLogo}
|
||||||
alt={`Logo ${size}×${size}`}
|
alt={`Logo ${size}×${size}`}
|
||||||
width={Math.min(size, 96)}
|
width={Math.min(size, 96)}
|
||||||
height={Math.min(size, 96)}
|
height={Math.min(size, 96)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className={styles.logoLabel}>{size}×{size}</span>
|
<span className={styles.logoLabel}>{size}×{size}</span>
|
||||||
<code className={styles.logoExport}>assets/cameleer3-{size}.png</code>
|
<code className={styles.logoExport}>assets/cameleer-{size}.png</code>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div className={styles.logoItem}>
|
<div className={styles.logoItem}>
|
||||||
<div className={styles.logoPreview}>
|
<div className={styles.logoPreview}>
|
||||||
<img
|
<img
|
||||||
src={cameleer3Logo}
|
src={cameleerLogo}
|
||||||
alt="Full resolution logo"
|
alt="Full resolution logo"
|
||||||
width={96}
|
width={96}
|
||||||
height={96}
|
height={96}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className={styles.logoLabel}>Original</span>
|
<span className={styles.logoLabel}>Original</span>
|
||||||
<code className={styles.logoExport}>assets/cameleer3-logo.png</code>
|
<code className={styles.logoExport}>assets/cameleer-logo.png</code>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -57,10 +57,10 @@ export function BrandAssetsSection() {
|
|||||||
<div className={styles.logoGrid}>
|
<div className={styles.logoGrid}>
|
||||||
<div className={styles.logoItem}>
|
<div className={styles.logoItem}>
|
||||||
<div className={styles.logoPreview}>
|
<div className={styles.logoPreview}>
|
||||||
<img src={cameleer3LogoSvg} alt="Cameleer3 SVG logo" width={96} height={96} />
|
<img src={cameleerLogoSvg} alt="Cameleer SVG logo" width={96} height={96} />
|
||||||
</div>
|
</div>
|
||||||
<span className={styles.logoLabel}>Cameleer3 SVG</span>
|
<span className={styles.logoLabel}>Cameleer SVG</span>
|
||||||
<code className={styles.logoExport}>assets/cameleer3-logo.svg</code>
|
<code className={styles.logoExport}>assets/cameleer-logo.svg</code>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.logoItem}>
|
<div className={styles.logoItem}>
|
||||||
<div className={styles.logoPreview}>
|
<div className={styles.logoPreview}>
|
||||||
|
|||||||