7 Commits

Author SHA1 Message Date
syoul 9f3752b621 chore: merge dev → main v1.4.0
ci/woodpecker/push/woodpecker Pipeline was successful
- feat: bouton ℹ flottant isolé sous ☰ (mobile) / top-left (desktop)
- fix: supprimer label 'Vitesse' + bouton ✕ AnimationPlayer
- fix: couleur émetteurs rouge #e53935 (meilleur contraste vs or)
- fix: InfoPanel — dégradés or→rouge / or→vert documentés
- docs: features-roadmap.md (14 features planifiées)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 13:31:49 +01:00
syoul 6fc1705f6d chore: bump version to 1.4.0
ci/woodpecker/push/woodpecker Pipeline was successful
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 13:31:36 +01:00
syoul 15807c7bcb fix: InfoPanel — couleur émetteurs rouge (dégradé or→rouge) + description dégradés
ci/woodpecker/push/woodpecker Pipeline was successful
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 13:27:16 +01:00
syoul bac113e51b fix: couleur émetteurs #e53935 (rouge) au lieu de #ff6d00 (orange)
ci/woodpecker/push/woodpecker Pipeline was successful
Meilleur contraste avec la couleur neutre or #d4a843.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 13:22:45 +01:00
syoul 6d01c8d29e fix: supprimer bouton ✕ de l'AnimationPlayer (fermeture via ▶ Animer)
ci/woodpecker/push/woodpecker Pipeline was successful
Économise une ligne sur mobile. onClose retiré de l'interface et du JSX.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 13:19:52 +01:00
syoul 46b11710cc fix: supprimer label 'Vitesse' dans AnimationPlayer (gain de place mobile)
ci/woodpecker/push/woodpecker Pipeline was successful
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 13:15:41 +01:00
syoul 78ede01d11 feat: déplacer bouton ℹ hors du PeriodSelector → bouton flottant isolé
ci/woodpecker/push/woodpecker Pipeline was successful
- Sous ☰ sur mobile (top-16 left-4), top-4 left-4 sur desktop
- PeriodSelector : suppression prop onInfo + bouton ℹ intégré

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 13:12:24 +01:00
6 changed files with 15 additions and 29 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "g1flux",
"private": true,
"version": "1.3.2",
"version": "1.4.0",
"type": "module",
"scripts": {
"dev": "vite",
+9 -2
View File
@@ -131,6 +131,15 @@ export default function App() {
</button>
)}
{/* Bouton info — sous ☰ sur mobile, top-left sur desktop */}
<button
onClick={() => setInfoOpen(true)}
className={`absolute ${isMobile ? 'top-16' : 'top-4'} left-4 z-[1001] w-10 h-10 bg-[#0a0b0f]/90 backdrop-blur-sm border border-[#2e2f3a] rounded-xl flex items-center justify-center text-[#6b7280] hover:text-[#d4a843] transition-colors text-base`}
aria-label="Aide"
>
</button>
{/* Period selector — floating over map */}
<div className={`absolute top-4 z-[1000] ${isMobile ? 'left-16 right-4' : 'left-1/2 -translate-x-1/2'}`}>
<PeriodSelector
@@ -143,7 +152,6 @@ export default function App() {
geoPercent={visibleStats && visibleStats.transactionCount > 0
? Math.round((visibleStats.geoCount / visibleStats.transactionCount) * 100)
: null}
onInfo={() => setInfoOpen(true)}
/>
</div>
@@ -184,7 +192,6 @@ export default function App() {
onPlay={animation.play}
onPause={animation.pause}
onSpeedChange={animation.setSpeed}
onClose={animation.deactivate}
/>
)}
-11
View File
@@ -9,7 +9,6 @@ interface AnimationPlayerProps {
onPlay: () => void;
onPause: () => void;
onSpeedChange: (s: 1 | 2 | 4) => void;
onClose: () => void;
}
export function AnimationPlayer({
@@ -21,7 +20,6 @@ export function AnimationPlayer({
onPlay,
onPause,
onSpeedChange,
onClose,
}: AnimationPlayerProps) {
const frame = frames[currentIndex];
@@ -78,7 +76,6 @@ export function AnimationPlayer({
{/* Speed selector */}
<div className="flex items-center gap-1">
<span className="text-[#4b5563] text-xs mr-1">Vitesse</span>
{([1, 2, 4] as const).map((s) => (
<button
key={s}
@@ -94,14 +91,6 @@ export function AnimationPlayer({
))}
</div>
{/* Close */}
<button
onClick={onClose}
className="text-[#4b5563] hover:text-white transition-colors px-2 py-1 text-sm ml-2"
title="Quitter l'animation"
>
</button>
</div>
</div>
</div>
+1 -1
View File
@@ -17,7 +17,7 @@ function lerpColor(hex1: string, hex2: string, t: number): string {
}
const COLOR_NEUTRAL = '#d4a843'; // or Ğ1
const COLOR_NEG = '#ff6d00'; // orange vif
const COLOR_NEG = '#e53935'; // rouge vif
const COLOR_POS = '#00c853'; // vert vif
const NEUTRAL_THRESHOLD = 0.05; // ±5 % → couleur neutre
const CLUSTER_RADIUS = 38; // pixels — distance max pour regrouper deux villes
+2 -2
View File
@@ -54,8 +54,8 @@ export function InfoPanel({ onClose }: InfoPanelProps) {
</Feature>
<Feature icon="●" name="Couleur des nœuds">
<span className="text-green-400">Vert</span> = receveur net (reçoit plus que ce qu'il émet) ·{' '}
<span className="text-[#d4a843]">Or</span> = équilibré ·{' '}
<span className="text-orange-400">Orange</span> = émetteur net.
<span className="text-[#d4a843]">Or</span> = équilibré (dégradé or vert selon l'excédent reçu) ·{' '}
<span className="text-[#e53935]">Rouge</span> = émetteur net (dégradé or rouge selon l'excédent émis).
</Feature>
<Feature icon="↗" name="Clic sur un nœud">
Affiche la liste des villes du cluster avec leur balance individuelle,
+1 -11
View File
@@ -8,7 +8,6 @@ interface PeriodSelectorProps {
viewMode: 'heatmap' | 'flow';
onViewModeChange: (mode: 'heatmap' | 'flow') => void;
geoPercent?: number | null;
onInfo: () => void;
}
const PERIODS = [
@@ -19,7 +18,7 @@ const PERIODS = [
const PRESET_DAYS = new Set([1, 7, 30]);
export function PeriodSelector({ value, onChange, animationActive, onAnimate, viewMode, onViewModeChange, geoPercent, onInfo }: PeriodSelectorProps) {
export function PeriodSelector({ value, onChange, animationActive, onAnimate, viewMode, onViewModeChange, geoPercent }: PeriodSelectorProps) {
const [customOpen, setCustomOpen] = useState(false);
const [inputVal, setInputVal] = useState('');
const inputRef = useRef<HTMLInputElement>(null);
@@ -132,15 +131,6 @@ export function PeriodSelector({ value, onChange, animationActive, onAnimate, vi
</span>
)}
<div className="w-px mx-1 bg-[#2e2f3a] self-stretch" />
<button
onClick={onInfo}
className="px-2 py-1.5 rounded-md text-sm text-[#6b7280] hover:text-[#d4a843] hover:bg-[#1a1b23] transition-all duration-200 cursor-pointer leading-none"
aria-label="Aide"
>
</button>
</div>
);
}