chrysopedia/frontend/src/components/CategoryIcons.tsx
jlightner 4b0914b12b fix: restore complete project tree from ub01 canonical state
Auto-mode commit 7aa33cd accidentally deleted 78 files (14,814 lines) during M005
execution. Subsequent commits rebuilt some frontend files but backend/, alembic/,
tests/, whisper/, docker configs, and prompts were never restored in this repo.

This commit restores the full project tree by syncing from ub01's working directory,
which has all M001-M007 features running in production containers.

Restored: backend/ (config, models, routers, database, redis, search_service, worker),
alembic/ (6 migrations), docker/ (Dockerfiles, nginx, compose), prompts/ (4 stages),
tests/, whisper/, README.md, .env.example, chrysopedia-spec.md
2026-03-31 02:10:41 +00:00

124 lines
4.1 KiB
XML

/**
* Purpose-built SVG icons for topic categories and navigation.
* Monoline stroke style — no fills, currentColor inheritance,
* designed to feel like audio tool UI, not clip art.
*/
const S = { width: "1.2em", height: "1.2em", verticalAlign: "-0.15em" } as const;
const P = { fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" as const, strokeLinejoin: "round" as const };
/** Routing nodes — signal flow / DAW session */
export function IconWorkflow() {
return (
<svg viewBox="0 0 24 24" style={S}>
<circle {...P} cx="4" cy="12" r="2" />
<circle {...P} cx="20" cy="6" r="2" />
<circle {...P} cx="20" cy="18" r="2" />
<path {...P} d="M6 12 h4 q4 0 4-4 l0-2" />
<path {...P} d="M6 12 h4 q4 0 4 4 l0 2" />
</svg>
);
}
/** Interval / two notes on a staff fragment */
export function IconMusicTheory() {
return (
<svg viewBox="0 0 24 24" style={S}>
<line {...P} x1="3" y1="8" x2="21" y2="8" strokeOpacity={0.3} />
<line {...P} x1="3" y1="12" x2="21" y2="12" strokeOpacity={0.3} />
<line {...P} x1="3" y1="16" x2="21" y2="16" strokeOpacity={0.3} />
<ellipse {...P} cx="8" cy="14" rx="2.5" ry="2" transform="rotate(-15 8 14)" strokeWidth={1.8} />
<line {...P} x1="10.3" y1="13" x2="10.3" y2="4" strokeWidth={1.8} />
<ellipse {...P} cx="16" cy="10" rx="2.5" ry="2" transform="rotate(-15 16 10)" strokeWidth={1.8} />
<line {...P} x1="18.3" y1="9" x2="18.3" y2="4" strokeWidth={1.8} />
</svg>
);
}
/** Speaker cone with two radiation arcs */
export function IconSoundDesign() {
return (
<svg viewBox="0 0 24 24" style={S}>
<polygon {...P} points="3,9 3,15 6,15 11,19 11,5 6,9" />
<path {...P} d="M14 9.5 a4 4 0 0 1 0 5" />
<path {...P} d="M16.5 7 a7.5 7.5 0 0 1 0 10" />
</svg>
);
}
/** Oscillator waveshapes — sine morphing to saw */
export function IconSynthesis() {
return (
<svg viewBox="0 0 24 24" style={S}>
<path {...P} d="M2 12 Q5 4, 8 12 Q11 20, 14 12 L17 5 V19 L20 12 H22" />
</svg>
);
}
/** Timeline blocks — arrangement regions at staggered positions */
export function IconArrangement() {
return (
<svg viewBox="0 0 24 24" style={S}>
<rect {...P} x="2" y="5" width="8" height="3" rx="1" />
<rect {...P} x="6" y="10.5" width="12" height="3" rx="1" />
<rect {...P} x="10" y="16" width="6" height="3" rx="1" />
</svg>
);
}
/** Dual faders at different levels */
export function IconMixing() {
return (
<svg viewBox="0 0 24 24" style={S}>
<line {...P} x1="7" y1="4" x2="7" y2="20" />
<rect {...P} x="4.5" y="8" width="5" height="4" rx="1" />
<line {...P} x1="17" y1="4" x2="17" y2="20" />
<rect {...P} x="14.5" y="13" width="5" height="4" rx="1" />
</svg>
);
}
/** Peak meter hitting ceiling — limiter bar at top */
export function IconMastering() {
return (
<svg viewBox="0 0 24 24" style={S}>
<line {...P} x1="2" y1="4" x2="22" y2="4" strokeOpacity={0.5} strokeDasharray="2 2" />
<rect {...P} x="4" y="10" width="3" height="10" rx="0.5" />
<rect {...P} x="10" y="6" width="3" height="14" rx="0.5" />
<rect {...P} x="16" y="4" width="3" height="16" rx="0.5" />
</svg>
);
}
/** Grid of categorized items */
export function IconTopics() {
return (
<svg viewBox="0 0 24 24" style={S}>
<rect {...P} x="3" y="3" width="7" height="7" rx="1.5" />
<rect {...P} x="14" y="3" width="7" height="7" rx="1.5" />
<rect {...P} x="3" y="14" width="7" height="7" rx="1.5" />
<rect {...P} x="14" y="14" width="7" height="7" rx="1.5" />
</svg>
);
}
/** Person silhouette — minimal */
export function IconCreators() {
return (
<svg viewBox="0 0 24 24" style={S}>
<circle {...P} cx="12" cy="8" r="4" />
<path {...P} d="M4 21 v-1 a7 7 0 0 1 16 0 v1" />
</svg>
);
}
/** Map from category name → component */
export const CATEGORY_ICON: Record<string, () => JSX.Element> = {
"Workflow": IconWorkflow,
"Music Theory": IconMusicTheory,
"Sound Design": IconSoundDesign,
"Synthesis": IconSynthesis,
"Arrangement": IconArrangement,
"Mixing": IconMixing,
"Mastering": IconMastering,
};