mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-05-20 14:44:51 +02:00
feat(ui): Redesign bottom-right map control cluster
- Increase touch targets from 36px to 44px (meets accessibility guidelines) - Wrap Locate and Layers buttons in unified .map-controls-br container - Layer popover now opens LEFT of buttons (avoids collision with Locate) - Add hover and active states with theme-aware styling - Proper spacing for scale control below the cluster - Increased icon sizes from 18px to 20px - Mobile-responsive with proper max-height on layer popover Layout: [Locate] 44x44 [Layers] 44x44 ────────────── Scale: 0.5 mi Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
9d3b972d81
commit
67779dbbf7
4 changed files with 84 additions and 31 deletions
|
|
@ -96,8 +96,12 @@ export default function App() {
|
||||||
<Panel onManeuverClick={handleManeuverClick} />
|
<Panel onManeuverClick={handleManeuverClick} />
|
||||||
|
|
||||||
<ContactModal />
|
<ContactModal />
|
||||||
<LayerControl mapRef={mapViewRef} />
|
|
||||||
|
{/* Bottom-right map controls */}
|
||||||
|
<div className="map-controls-br">
|
||||||
<LocateButton mapRef={mapViewRef} />
|
<LocateButton mapRef={mapViewRef} />
|
||||||
|
<LayerControl mapRef={mapViewRef} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ export default function LayerControl({ mapRef }) {
|
||||||
title="Map layers"
|
title="Map layers"
|
||||||
aria-label="Toggle map layers"
|
aria-label="Toggle map layers"
|
||||||
>
|
>
|
||||||
<Layers size={18} />
|
<Layers size={20} />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{open && (
|
{open && (
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export default function LocateButton({ mapRef }) {
|
||||||
title="My location"
|
title="My location"
|
||||||
aria-label="Center map on my location"
|
aria-label="Center map on my location"
|
||||||
>
|
>
|
||||||
<Locate size={18} />
|
<Locate size={20} />
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
105
src/index.css
105
src/index.css
|
|
@ -236,42 +236,80 @@ body {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ═══ LAYER CONTROL ═══ */
|
/* ═══ BOTTOM-RIGHT MAP CONTROLS ═══ */
|
||||||
.layer-control {
|
.map-controls-br {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 32px;
|
bottom: 40px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layer-control-btn {
|
.map-control-btn {
|
||||||
width: 36px;
|
width: 44px;
|
||||||
height: 36px;
|
height: 44px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: var(--bg-raised);
|
background: var(--bg-raised);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
transition: color 0.1s, border-color 0.1s;
|
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-control-btn:hover {
|
||||||
|
color: var(--text-primary);
|
||||||
|
border-color: var(--accent);
|
||||||
|
background: var(--bg-overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-control-btn:active {
|
||||||
|
background: var(--bg-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══ LAYER CONTROL ═══ */
|
||||||
|
.layer-control {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-control-btn {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: var(--bg-raised);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 10px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layer-control-btn:hover {
|
.layer-control-btn:hover {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
border-color: var(--accent);
|
border-color: var(--accent);
|
||||||
|
background: var(--bg-overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-control-btn:active {
|
||||||
|
background: var(--bg-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.layer-control-popover {
|
.layer-control-popover {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 44px;
|
bottom: 0;
|
||||||
right: 0;
|
right: 52px;
|
||||||
min-width: 160px;
|
min-width: 180px;
|
||||||
background: var(--bg-raised);
|
background: var(--bg-raised);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
box-shadow: var(--shadow-lg);
|
box-shadow: var(--shadow-lg);
|
||||||
}
|
}
|
||||||
|
|
@ -367,27 +405,28 @@ body {
|
||||||
|
|
||||||
/* ═══ LOCATE BUTTON ═══ */
|
/* ═══ LOCATE BUTTON ═══ */
|
||||||
.locate-btn {
|
.locate-btn {
|
||||||
position: absolute;
|
width: 44px;
|
||||||
bottom: 80px;
|
height: 44px;
|
||||||
right: 10px;
|
|
||||||
z-index: 10;
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: var(--bg-raised);
|
background: var(--bg-raised);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
transition: color 0.1s, border-color 0.1s;
|
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.locate-btn:hover {
|
.locate-btn:hover {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
border-color: var(--accent);
|
border-color: var(--accent);
|
||||||
|
background: var(--bg-overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
.locate-btn:active {
|
||||||
|
background: var(--bg-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ═══ STOP REMOVE BUTTON (touch-friendly) ═══ */
|
/* ═══ STOP REMOVE BUTTON (touch-friendly) ═══ */
|
||||||
|
|
@ -406,16 +445,15 @@ body {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layer-control {
|
.map-controls-br {
|
||||||
bottom: auto;
|
bottom: 24px;
|
||||||
top: 120px;
|
right: 8px;
|
||||||
right: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.locate-btn {
|
.layer-control-popover {
|
||||||
bottom: auto;
|
right: 52px;
|
||||||
top: 166px;
|
max-height: 60vh;
|
||||||
right: 10px;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stop-remove-btn {
|
.stop-remove-btn {
|
||||||
|
|
@ -501,3 +539,14 @@ body {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
text-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
|
text-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ═══ MAPLIBRE CONTROL POSITIONING ═══ */
|
||||||
|
.maplibregl-ctrl-bottom-right {
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maplibregl-ctrl-bottom-right .maplibregl-ctrl-scale {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue