or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

controls.mddraggable.mdgeojson.mdindex.mdmap.mdmarkers-overlays.mdproviders.md

controls.mddocs/

0

# Map Controls

1

2

UI controls for map interaction including zoom buttons and other control elements. Controls are positioned overlays that provide user interface elements for map interaction without interfering with map events.

3

4

## Capabilities

5

6

### ZoomControl Component

7

8

Zoom in/out button controls with customizable styling and positioning.

9

10

```typescript { .api }

11

/**

12

* Zoom in/out button controls for map interaction

13

* @param props - Zoom control configuration and styling

14

* @returns JSX.Element representing the zoom controls

15

*/

16

function ZoomControl(props: ZoomProps): JSX.Element;

17

18

interface ZoomProps extends PigeonProps {

19

style?: React.CSSProperties;

20

buttonStyle?: React.CSSProperties;

21

}

22

```

23

24

**Usage Examples:**

25

26

```tsx

27

import React from "react";

28

import { Map, ZoomControl } from "pigeon-maps";

29

30

// Basic zoom controls

31

function MapWithZoomControls() {

32

return (

33

<Map height={400} center={[50.879, 4.6997]} zoom={11}>

34

<ZoomControl />

35

</Map>

36

);

37

}

38

39

// Styled zoom controls

40

function StyledZoomControls() {

41

return (

42

<Map height={400} center={[50.879, 4.6997]} zoom={11}>

43

<ZoomControl

44

style={{

45

position: 'absolute',

46

top: 20,

47

right: 20,

48

left: 'auto' // Override default left positioning

49

}}

50

buttonStyle={{

51

backgroundColor: '#007bff',

52

color: 'white',

53

border: 'none',

54

borderRadius: '4px',

55

fontSize: '18px'

56

}}

57

/>

58

</Map>

59

);

60

}

61

```

62

63

### Custom Positioned Controls

64

65

```tsx

66

function CustomPositionedControls() {

67

return (

68

<Map height={400} center={[50.879, 4.6997]} zoom={11}>

69

{/* Top-right zoom controls */}

70

<ZoomControl

71

style={{

72

position: 'absolute',

73

top: 10,

74

right: 10,

75

left: 'auto'

76

}}

77

/>

78

79

{/* Custom control overlay */}

80

<div style={{

81

position: 'absolute',

82

bottom: 10,

83

left: 10,

84

background: 'white',

85

padding: '8px',

86

borderRadius: '4px',

87

boxShadow: '0 2px 4px rgba(0,0,0,0.2)'

88

}}>

89

Custom Control

90

</div>

91

</Map>

92

);

93

}

94

```

95

96

## Zoom Control Features

97

98

### Button Functionality

99

100

The zoom control provides two buttons:

101

- **Zoom In (+)**: Increases zoom level by 1, respecting `maxZoom` limit

102

- **Zoom Out (–)**: Decreases zoom level by 1, respecting `minZoom` limit

103

104

### Automatic Integration

105

106

Zoom controls automatically:

107

- Access current map state (zoom level, bounds)

108

- Respect map zoom limits (`minZoom`, `maxZoom`)

109

- Use map's zoom animation settings

110

- Call the map's `setCenterZoom` function

111

112

### Default Styling

113

114

```typescript { .api }

115

// Default container style

116

const commonStyle: React.CSSProperties = {

117

position: 'absolute',

118

top: 10,

119

left: 10,

120

};

121

122

// Default button style

123

const commonButtonStyle: React.CSSProperties = {

124

width: 28,

125

height: 28,

126

borderRadius: 2,

127

boxShadow: '0 1px 4px -1px rgba(0,0,0,.3)',

128

background: 'white',

129

lineHeight: '26px',

130

fontSize: '20px',

131

fontWeight: 700,

132

color: '#666',

133

marginBottom: 1,

134

cursor: 'pointer',

135

border: 'none',

136

display: 'block',

137

outline: 'none',

138

};

139

```

140

141

## CSS Classes

142

143

### Default Classes

144

145

```typescript { .api }

146

// Container classes

147

className="pigeon-zoom-buttons pigeon-drag-block"

148

149

// Button classes

150

className="pigeon-zoom-in" // Zoom in button

151

className="pigeon-zoom-out" // Zoom out button

152

```

153

154

The `pigeon-drag-block` class prevents map interactions when clicking on controls.

155

156

### Custom Styling Examples

157

158

```css

159

/* Custom zoom control styling */

160

.pigeon-zoom-buttons {

161

background: rgba(255, 255, 255, 0.9);

162

border-radius: 8px;

163

padding: 4px;

164

}

165

166

.pigeon-zoom-in,

167

.pigeon-zoom-out {

168

background: linear-gradient(to bottom, #f8f8f8, #e8e8e8);

169

border: 1px solid #ccc;

170

transition: all 0.2s;

171

}

172

173

.pigeon-zoom-in:hover,

174

.pigeon-zoom-out:hover {

175

background: linear-gradient(to bottom, #fff, #f0f0f0);

176

border-color: #999;

177

}

178

179

.pigeon-zoom-in:active,

180

.pigeon-zoom-out:active {

181

background: linear-gradient(to bottom, #e8e8e8, #f8f8f8);

182

box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);

183

}

184

```

185

186

## Custom Controls

187

188

### Creating Custom Controls

189

190

```tsx

191

import React from "react";

192

import { Map } from "pigeon-maps";

193

194

function CustomMapControls() {

195

const [mapRef, setMapRef] = useState(null);

196

197

// Custom zoom to specific location

198

const zoomToLocation = (center, zoom) => {

199

if (mapRef && mapRef.setCenterZoom) {

200

mapRef.setCenterZoom(center, zoom);

201

}

202

};

203

204

return (

205

<Map

206

height={400}

207

center={[50.879, 4.6997]}

208

zoom={11}

209

ref={setMapRef}

210

>

211

{/* Custom location buttons */}

212

<div style={{

213

position: 'absolute',

214

top: 10,

215

right: 10,

216

display: 'flex',

217

flexDirection: 'column',

218

gap: '4px'

219

}}>

220

<button

221

className="pigeon-drag-block"

222

style={{

223

padding: '8px 12px',

224

background: 'white',

225

border: '1px solid #ccc',

226

borderRadius: '4px',

227

cursor: 'pointer'

228

}}

229

onClick={() => zoomToLocation([50.879, 4.6997], 15)}

230

>

231

Brussels

232

</button>

233

<button

234

className="pigeon-drag-block"

235

style={{

236

padding: '8px 12px',

237

background: 'white',

238

border: '1px solid #ccc',

239

borderRadius: '4px',

240

cursor: 'pointer'

241

}}

242

onClick={() => zoomToLocation([48.8566, 2.3522], 12)}

243

>

244

Paris

245

</button>

246

</div>

247

</Map>

248

);

249

}

250

```

251

252

### Control with Map State

253

254

```tsx

255

function StatefulControls() {

256

const [zoom, setZoom] = useState(11);

257

const [center, setCenter] = useState([50.879, 4.6997]);

258

259

return (

260

<Map

261

height={400}

262

center={center}

263

zoom={zoom}

264

onBoundsChanged={({ center, zoom }) => {

265

setCenter(center);

266

setZoom(zoom);

267

}}

268

>

269

{/* Display current state */}

270

<div style={{

271

position: 'absolute',

272

top: 10,

273

left: 10,

274

background: 'rgba(255, 255, 255, 0.9)',

275

padding: '8px',

276

borderRadius: '4px',

277

fontSize: '12px',

278

fontFamily: 'monospace'

279

}}>

280

<div>Zoom: {zoom.toFixed(2)}</div>

281

<div>Lat: {center[0].toFixed(4)}</div>

282

<div>Lng: {center[1].toFixed(4)}</div>

283

</div>

284

285

<ZoomControl />

286

</Map>

287

);

288

}

289

```

290

291

### Toggle Controls

292

293

```tsx

294

function ToggleControls() {

295

const [showSatellite, setShowSatellite] = useState(false);

296

const [showTraffic, setShowTraffic] = useState(false);

297

298

return (

299

<Map height={400} center={[50.879, 4.6997]} zoom={11}>

300

{/* Toggle control panel */}

301

<div style={{

302

position: 'absolute',

303

bottom: 10,

304

left: 10,

305

background: 'white',

306

padding: '12px',

307

borderRadius: '4px',

308

boxShadow: '0 2px 8px rgba(0,0,0,0.1)'

309

}}>

310

<label style={{ display: 'block', marginBottom: '8px' }}>

311

<input

312

type="checkbox"

313

checked={showSatellite}

314

onChange={(e) => setShowSatellite(e.target.checked)}

315

style={{ marginRight: '8px' }}

316

/>

317

Satellite View

318

</label>

319

<label style={{ display: 'block' }}>

320

<input

321

type="checkbox"

322

checked={showTraffic}

323

onChange={(e) => setShowTraffic(e.target.checked)}

324

style={{ marginRight: '8px' }}

325

/>

326

Traffic Layer

327

</label>

328

</div>

329

330

<ZoomControl />

331

</Map>

332

);

333

}

334

```

335

336

## Accessibility

337

338

### Keyboard Support

339

340

```tsx

341

function AccessibleControls() {

342

const handleKeyDown = (event, action) => {

343

if (event.key === 'Enter' || event.key === ' ') {

344

event.preventDefault();

345

action();

346

}

347

};

348

349

return (

350

<Map height={400} center={[50.879, 4.6997]} zoom={11}>

351

<div style={{

352

position: 'absolute',

353

top: 10,

354

right: 10,

355

display: 'flex',

356

flexDirection: 'column'

357

}}>

358

<button

359

className="pigeon-drag-block"

360

aria-label="Zoom in"

361

tabIndex={0}

362

onKeyDown={(e) => handleKeyDown(e, () => console.log('zoom in'))}

363

style={{

364

width: 32,

365

height: 32,

366

fontSize: '18px',

367

marginBottom: 2

368

}}

369

>

370

+

371

</button>

372

<button

373

className="pigeon-drag-block"

374

aria-label="Zoom out"

375

tabIndex={0}

376

onKeyDown={(e) => handleKeyDown(e, () => console.log('zoom out'))}

377

style={{

378

width: 32,

379

height: 32,

380

fontSize: '18px'

381

}}

382

>

383

384

</button>

385

</div>

386

</Map>

387

);

388

}

389

```

390

391

## Performance Considerations

392

393

- Controls are lightweight DOM elements with minimal re-rendering

394

- Use `pigeon-drag-block` class to prevent event conflicts with map

395

- Position controls absolutely to avoid affecting map layout

396

- Consider control visibility at different screen sizes

397

- Group related controls to minimize DOM complexity