Skip to content

Commit ee24eea

Browse files
committed
style(icons): 🎨 replace inline SVGs with Lucide React icons
Switch from hand-drawn inline SVG icons to Lucide React library for consistent, polished iconography across the entire app: - ThemeToggle: Sun/Moon icons - FileUpload: Map icon (was broken globe SVG), ArrowRight - Controls: Play/Pause icons - ExportPanel, SceneEditor, Toast, GoogleGuide: X close icons - page.tsx: Plus icon for New button - JourneyCreator: Check icon for Done button - GoogleGuide: ExternalLink icon, Circle bullet dots - Update E2E test to find Play button by role instead of polygon element
1 parent 9d2d304 commit ee24eea

12 files changed

Lines changed: 38 additions & 53 deletions

e2e/travelback.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ test.describe('Travelback App', () => {
6060
test('playback controls work after importing track', async ({ page }) => {
6161
await uploadGpx(page)
6262

63-
// Find play button (it has a play icon SVG polygon)
64-
const playBtn = page.locator('button').filter({ has: page.locator('polygon') }).first()
63+
// Find play button by its aria-label/title
64+
const playBtn = page.getByRole('button', { name: 'Play' })
6565
await expect(playBtn).toBeVisible({ timeout: 10_000 })
6666

6767
// Click play - use force:true to bypass Next.js dev overlay intercepting pointer events

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
},
1111
"dependencies": {
1212
"@tmcw/togeojson": "^7.1.2",
13+
"lucide-react": "^0.575.0",
1314
"maplibre-gl": "^5.18.0",
1415
"mediabunny": "^1.34.4",
1516
"next": "16.1.6",

src/app/page.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Toast, { useToast } from '@/components/Toast'
1414
import ErrorBoundary from '@/components/ErrorBoundary'
1515
import ElevationProfile from '@/components/ElevationProfile'
1616
import ThemeToggle from '@/components/ThemeToggle'
17+
import { Plus } from 'lucide-react'
1718
import { MAP_STYLES } from '@/types'
1819
import { generateDefaultScenes } from '@/lib/camera'
1920
import { exportVideo, downloadVideo } from '@/lib/videoEncoder'
@@ -316,9 +317,7 @@ export default function Home() {
316317
className="gi px-3 py-2 text-sm font-medium cursor-pointer"
317318
style={{ color: 'var(--t1)', boxShadow: '0 0 0 1px rgba(var(--gl),.35), 0 4px 12px rgba(0,0,0,.1)' }}
318319
>
319-
<svg className="w-3.5 h-3.5 inline -mt-px" fill="none" stroke="currentColor" strokeWidth={2.5} viewBox="0 0 24 24">
320-
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
321-
</svg>{' '}New
320+
<Plus size={14} strokeWidth={2.5} className="inline -mt-px" />{' '}New
322321
</button>
323322
<button
324323
onClick={() => setShowSceneEditor(s => !s)}

src/components/Controls.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client'
22

33
import { useCallback } from 'react'
4+
import { Play, Pause } from 'lucide-react'
45
import type { Track } from '@/types'
56
import { formatDistance, formatDuration, totalDistance } from '@/lib/interpolate'
67

@@ -78,14 +79,9 @@ export default function Controls({
7879
style={{ background: 'rgba(var(--gl),.85)', color: '#fff' }}
7980
>
8081
{isPlaying ? (
81-
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
82-
<rect x="6" y="4" width="4" height="16" />
83-
<rect x="14" y="4" width="4" height="16" />
84-
</svg>
82+
<Pause size={16} fill="currentColor" />
8583
) : (
86-
<svg className="w-4 h-4 ml-0.5" fill="currentColor" viewBox="0 0 24 24">
87-
<polygon points="5,3 19,12 5,21" />
88-
</svg>
84+
<Play size={16} fill="currentColor" className="ml-0.5" />
8985
)}
9086
</button>
9187

src/components/ExportPanel.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client'
22

33
import { useState, useCallback, useEffect } from 'react'
4+
import { X } from 'lucide-react'
45
import type { VideoCodec, ExportConfig, ResolutionPreset } from '@/types'
56
import { CODEC_LABELS, RESOLUTION_PRESETS } from '@/types'
67
import { isCodecSupported } from '@/lib/videoEncoder'
@@ -66,9 +67,7 @@ export default function ExportPanel({
6667
{!isExporting && (
6768
<button onClick={onClose}
6869
className="cursor-pointer" style={{ color: 'var(--t4)' }}>
69-
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
70-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
71-
</svg>
70+
<X size={20} strokeWidth={2} />
7271
</button>
7372
)}
7473
</div>

src/components/FileUpload.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client'
22

33
import { useCallback, useState, useRef } from 'react'
4+
import { Map, ArrowRight } from 'lucide-react'
45
import type { Track } from '@/types'
56
import { parseTrackFile } from '@/lib/parser'
67

@@ -90,11 +91,7 @@ export default function FileUpload({ onTrackLoaded, hasTrack, onShowGoogleGuide
9091
<div className="inline-block w-10 h-10 border-4 rounded-full animate-spin"
9192
style={{ borderColor: 'rgb(var(--gl))', borderTopColor: 'transparent' }} />
9293
) : (
93-
<svg className="w-12 h-12" fill="none" stroke="currentColor" strokeWidth={1.5} viewBox="0 0 24 24"
94-
style={{ color: 'rgb(var(--gl))' }}>
95-
<path strokeLinecap="round" strokeLinejoin="round"
96-
d="M9 6.75V15m6-6v8.25m.503-11.307c.955.06 1.897.164 2.825.31A48.36 48.36 0 0112 3.75a48.36 48.36 0 01-6.328.563c.928-.146 1.87-.25 2.825-.31M9 6.75a48.6 48.6 0 016 0m-6 0a48.2 48.2 0 00-4.764.544M15 6.75a48.2 48.2 0 014.764.544m-14.528 0A48.1 48.1 0 003 8.25c0 2.291.61 4.441 1.676 6.293m.652-7.505A48.1 48.1 0 0112 6a48.1 48.1 0 016.672.788m0 0c1.065 1.852 1.676 4.002 1.676 6.293m0 0c-1.446 2.518-3.87 4.36-6.762 5.086M3 14.543c1.446 2.518 3.87 4.36 6.762 5.086m0 0a48.7 48.7 0 004.476 0" />
97-
</svg>
94+
<Map size={48} strokeWidth={1.5} style={{ color: 'rgb(var(--gl))' }} />
9895
)}
9996
</div>
10097
<h2 className="text-2xl font-bold mb-2" style={{ color: 'var(--t1)' }}>
@@ -126,9 +123,7 @@ export default function FileUpload({ onTrackLoaded, hasTrack, onShowGoogleGuide
126123
<button onClick={onShowGoogleGuide} className="underline text-sm inline-flex items-center gap-1"
127124
style={{ color: 'rgb(var(--gl))' }}>
128125
How to export Google Location History
129-
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24">
130-
<path strokeLinecap="round" strokeLinejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
131-
</svg>
126+
<ArrowRight size={14} strokeWidth={2} />
132127
</button>
133128
</div>
134129
)}

src/components/GoogleGuide.tsx

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use client'
22

3+
import { X, ExternalLink, Circle } from 'lucide-react'
4+
35
interface GoogleGuideProps {
46
isOpen: boolean
57
onClose: () => void
@@ -75,10 +77,7 @@ export default function GoogleGuide({ isOpen, onClose }: GoogleGuideProps) {
7577
style={{ color: 'var(--t4)' }}
7678
aria-label="Close"
7779
>
78-
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
79-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
80-
d="M6 18L18 6M6 6l12 12" />
81-
</svg>
80+
<X size={20} strokeWidth={2} />
8281
</button>
8382
</div>
8483

@@ -115,10 +114,7 @@ export default function GoogleGuide({ isOpen, onClose }: GoogleGuideProps) {
115114
className="vitro-btn-primary inline-flex items-center gap-1.5 mt-3 px-4 py-2 text-sm font-medium"
116115
>
117116
{step.action.label}
118-
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
119-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
120-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
121-
</svg>
117+
<ExternalLink size={14} strokeWidth={2} />
122118
</a>
123119
)}
124120
</div>
@@ -134,9 +130,7 @@ export default function GoogleGuide({ isOpen, onClose }: GoogleGuideProps) {
134130
<ul className="space-y-1">
135131
{tips.map((tip, i) => (
136132
<li key={i} className="text-sm flex gap-2" style={{ color: 'var(--t3)' }}>
137-
<svg className="w-1.5 h-1.5 flex-shrink-0 mt-1.5" fill="currentColor" viewBox="0 0 8 8">
138-
<circle cx="4" cy="4" r="4" />
139-
</svg>
133+
<Circle size={6} fill="currentColor" strokeWidth={0} className="flex-shrink-0 mt-1.5" />
140134
<span>{tip}</span>
141135
</li>
142136
))}

src/components/JourneyCreator.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client'
22

33
import { useEffect, useRef, useCallback, useState } from 'react'
4+
import { Check } from 'lucide-react'
45
import maplibregl from 'maplibre-gl'
56
import type { Track, TrackPoint } from '@/types'
67
import type { MapViewHandle } from '@/components/MapView'
@@ -352,9 +353,7 @@ export default function JourneyCreator({ isActive, onComplete, onCancel, mapRef
352353
style={{ background: '#f97316' }}
353354
>
354355
Done
355-
<svg className="w-3.5 h-3.5 inline -mt-px ml-1" fill="none" stroke="currentColor" strokeWidth={2.5} viewBox="0 0 24 24">
356-
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 12.75l6 6 9-13.5" />
357-
</svg>
356+
<Check size={14} strokeWidth={2.5} className="inline -mt-px ml-1" />
358357
</button>
359358
</div>
360359
</div>

src/components/SceneEditor.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client'
22

33
import { useCallback, useMemo, useState, useEffect, useRef } from 'react'
4+
import { X } from 'lucide-react'
45
import type { Scene, CameraMode } from '@/types'
56
import { CAMERA_MODE_LABELS, DEFAULT_CAMERA_PARAMS } from '@/types'
67
import { generateDefaultScenes, generateSimpleFlyover, generateBirdeyeFlyover, generateDynamicScenes } from '@/lib/camera'
@@ -103,9 +104,7 @@ export default function SceneEditor({ scenes, onChange, onClose, transitionDurat
103104
</button>
104105
<button onClick={onClose}
105106
className="cursor-pointer" style={{ color: 'var(--t4)' }}>
106-
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
107-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
108-
</svg>
107+
<X size={16} strokeWidth={2} />
109108
</button>
110109
</div>
111110
</div>
@@ -189,9 +188,7 @@ export default function SceneEditor({ scenes, onChange, onClose, transitionDurat
189188
onBlur={e => e.target.style.borderBottomColor = 'transparent'} />
190189
<button onClick={() => removeScene(scene.id)}
191190
className="text-xs cursor-pointer flex items-center justify-center" style={{ color: 'var(--t4)' }}>
192-
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24">
193-
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
194-
</svg>
191+
<X size={14} strokeWidth={2} />
195192
</button>
196193
</div>
197194

0 commit comments

Comments
 (0)