or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

accessibility-limits.mdcore-component.mdindex.mdplatform-features.mdprogrammatic-control.mdstep-indicators.md

programmatic-control.mddocs/

0

# Programmatic Control

1

2

Reference-based methods for programmatic value updates and control, allowing external manipulation of slider values without user interaction.

3

4

## Capabilities

5

6

### Slider Reference Interface

7

8

Interface for programmatically controlling slider values through React refs.

9

10

```typescript { .api }

11

interface SliderRef {

12

/**

13

* Programmatically update the slider value

14

* @param value - New value to set (must be within min/max range)

15

*/

16

updateValue(value: number): void;

17

}

18

19

type SliderReferenceType =

20

| (React.MutableRefObject<SliderRef> & React.LegacyRef<Slider>)

21

| undefined;

22

23

interface SliderRefProps {

24

/**

25

* Reference object for programmatic control

26

*/

27

ref?: SliderReferenceType;

28

}

29

```

30

31

**Usage Examples:**

32

33

```typescript

34

import React, { useRef, useState } from 'react';

35

import { View, Text, Button } from 'react-native';

36

import Slider from '@react-native-community/slider';

37

import type { SliderRef } from '@react-native-community/slider';

38

39

// Basic programmatic control

40

function ProgrammaticSlider() {

41

const sliderRef = useRef<SliderRef>(null);

42

const [currentValue, setCurrentValue] = useState(50);

43

44

const setToMinimum = () => {

45

sliderRef.current?.updateValue(0);

46

};

47

48

const setToMaximum = () => {

49

sliderRef.current?.updateValue(100);

50

};

51

52

const setToMiddle = () => {

53

sliderRef.current?.updateValue(50);

54

};

55

56

return (

57

<View>

58

<Text>Current Value: {currentValue}</Text>

59

60

<Slider

61

ref={sliderRef}

62

style={{width: 300, height: 40}}

63

minimumValue={0}

64

maximumValue={100}

65

value={currentValue}

66

onValueChange={setCurrentValue}

67

/>

68

69

<View style={{flexDirection: 'row', gap: 10}}>

70

<Button title="Min (0)" onPress={setToMinimum} />

71

<Button title="Mid (50)" onPress={setToMiddle} />

72

<Button title="Max (100)" onPress={setToMaximum} />

73

</View>

74

</View>

75

);

76

}

77

78

// Animated value updates

79

function AnimatedSlider() {

80

const sliderRef = useRef<SliderRef>(null);

81

const [currentValue, setCurrentValue] = useState(0);

82

const [isAnimating, setIsAnimating] = useState(false);

83

84

const animateToValue = (targetValue: number) => {

85

if (isAnimating) return;

86

87

setIsAnimating(true);

88

const startValue = currentValue;

89

const difference = targetValue - startValue;

90

const duration = 1000; // 1 second

91

const steps = 60; // 60 FPS

92

const stepValue = difference / steps;

93

94

let currentStep = 0;

95

const interval = setInterval(() => {

96

currentStep++;

97

const newValue = startValue + (stepValue * currentStep);

98

99

sliderRef.current?.updateValue(newValue);

100

101

if (currentStep >= steps) {

102

clearInterval(interval);

103

setIsAnimating(false);

104

sliderRef.current?.updateValue(targetValue); // Ensure exact final value

105

}

106

}, duration / steps);

107

};

108

109

return (

110

<View>

111

<Text>Animated Value: {currentValue.toFixed(1)}</Text>

112

113

<Slider

114

ref={sliderRef}

115

style={{width: 300, height: 40}}

116

minimumValue={0}

117

maximumValue={100}

118

value={currentValue}

119

onValueChange={setCurrentValue}

120

disabled={isAnimating}

121

/>

122

123

<View style={{flexDirection: 'row', gap: 10}}>

124

<Button

125

title="Animate to 25"

126

onPress={() => animateToValue(25)}

127

disabled={isAnimating}

128

/>

129

<Button

130

title="Animate to 75"

131

onPress={() => animateToValue(75)}

132

disabled={isAnimating}

133

/>

134

</View>

135

</View>

136

);

137

}

138

```

139

140

### External Control Patterns

141

142

Common patterns for controlling sliders from external sources like APIs, timers, or other components.

143

144

**Usage Examples:**

145

146

```typescript

147

import React, { useRef, useState, useEffect } from 'react';

148

import { View, Text, Button } from 'react-native';

149

import Slider from '@react-native-community/slider';

150

151

// Timer-controlled slider

152

function TimerControlledSlider() {

153

const sliderRef = useRef<SliderRef>(null);

154

const [progress, setProgress] = useState(0);

155

const [isRunning, setIsRunning] = useState(false);

156

157

useEffect(() => {

158

if (!isRunning) return;

159

160

const interval = setInterval(() => {

161

setProgress(prev => {

162

const newValue = prev + 1;

163

if (newValue >= 100) {

164

setIsRunning(false);

165

return 100;

166

}

167

sliderRef.current?.updateValue(newValue);

168

return newValue;

169

});

170

}, 100); // Update every 100ms

171

172

return () => clearInterval(interval);

173

}, [isRunning]);

174

175

const startTimer = () => {

176

setIsRunning(true);

177

};

178

179

const stopTimer = () => {

180

setIsRunning(false);

181

};

182

183

const resetTimer = () => {

184

setIsRunning(false);

185

setProgress(0);

186

sliderRef.current?.updateValue(0);

187

};

188

189

return (

190

<View>

191

<Text>Progress: {progress}%</Text>

192

193

<Slider

194

ref={sliderRef}

195

style={{width: 300, height: 40}}

196

minimumValue={0}

197

maximumValue={100}

198

value={progress}

199

onValueChange={setProgress}

200

disabled={isRunning}

201

/>

202

203

<View style={{flexDirection: 'row', gap: 10}}>

204

<Button title="Start" onPress={startTimer} disabled={isRunning} />

205

<Button title="Stop" onPress={stopTimer} disabled={!isRunning} />

206

<Button title="Reset" onPress={resetTimer} />

207

</View>

208

</View>

209

);

210

}

211

212

// Network-controlled slider

213

function NetworkControlledSlider() {

214

const sliderRef = useRef<SliderRef>(null);

215

const [volume, setVolume] = useState(50);

216

const [isLoading, setIsLoading] = useState(false);

217

218

// Simulate API call to update volume

219

const syncWithServer = async (newVolume: number) => {

220

setIsLoading(true);

221

try {

222

// Simulate API call

223

await new Promise(resolve => setTimeout(resolve, 500));

224

225

// Update slider with server response

226

sliderRef.current?.updateValue(newVolume);

227

setVolume(newVolume);

228

} catch (error) {

229

console.error('Failed to sync with server:', error);

230

} finally {

231

setIsLoading(false);

232

}

233

};

234

235

// Simulate receiving updates from server

236

const simulateServerUpdate = () => {

237

const randomVolume = Math.floor(Math.random() * 100);

238

syncWithServer(randomVolume);

239

};

240

241

return (

242

<View>

243

<Text>Volume: {volume}% {isLoading && '(Syncing...)'}</Text>

244

245

<Slider

246

ref={sliderRef}

247

style={{width: 300, height: 40}}

248

minimumValue={0}

249

maximumValue={100}

250

value={volume}

251

onValueChange={(value) => {

252

setVolume(value);

253

// Could trigger debounced API call here

254

}}

255

disabled={isLoading}

256

/>

257

258

<Button

259

title="Simulate Server Update"

260

onPress={simulateServerUpdate}

261

disabled={isLoading}

262

/>

263

</View>

264

);

265

}

266

```

267

268

### Multi-Slider Coordination

269

270

Coordinating multiple sliders programmatically for complex UI scenarios.

271

272

**Usage Examples:**

273

274

```typescript

275

import React, { useRef, useState } from 'react';

276

import { View, Text, Button } from 'react-native';

277

import Slider from '@react-native-community/slider';

278

279

// RGB Color picker with coordinated sliders

280

function RGBColorPicker() {

281

const redSliderRef = useRef<SliderRef>(null);

282

const greenSliderRef = useRef<SliderRef>(null);

283

const blueSliderRef = useRef<SliderRef>(null);

284

285

const [red, setRed] = useState(128);

286

const [green, setGreen] = useState(128);

287

const [blue, setBlue] = useState(128);

288

289

const setPresetColor = (r: number, g: number, b: number) => {

290

redSliderRef.current?.updateValue(r);

291

greenSliderRef.current?.updateValue(g);

292

blueSliderRef.current?.updateValue(b);

293

setRed(r);

294

setGreen(g);

295

setBlue(b);

296

};

297

298

const rgbColor = `rgb(${red}, ${green}, ${blue})`;

299

300

return (

301

<View>

302

<View style={{

303

width: 100,

304

height: 100,

305

backgroundColor: rgbColor,

306

marginBottom: 20,

307

borderRadius: 8,

308

}} />

309

310

<Text>RGB: ({red}, {green}, {blue})</Text>

311

312

<View style={{marginVertical: 10}}>

313

<Text>Red: {red}</Text>

314

<Slider

315

ref={redSliderRef}

316

style={{width: 300, height: 40}}

317

minimumValue={0}

318

maximumValue={255}

319

step={1}

320

value={red}

321

onValueChange={setRed}

322

minimumTrackTintColor="#ff0000"

323

/>

324

</View>

325

326

<View style={{marginVertical: 10}}>

327

<Text>Green: {green}</Text>

328

<Slider

329

ref={greenSliderRef}

330

style={{width: 300, height: 40}}

331

minimumValue={0}

332

maximumValue={255}

333

step={1}

334

value={green}

335

onValueChange={setGreen}

336

minimumTrackTintColor="#00ff00"

337

/>

338

</View>

339

340

<View style={{marginVertical: 10}}>

341

<Text>Blue: {blue}</Text>

342

<Slider

343

ref={blueSliderRef}

344

style={{width: 300, height: 40}}

345

minimumValue={0}

346

maximumValue={255}

347

step={1}

348

value={blue}

349

onValueChange={setBlue}

350

minimumTrackTintColor="#0000ff"

351

/>

352

</View>

353

354

<View style={{flexDirection: 'row', gap: 10, marginTop: 20}}>

355

<Button title="Red" onPress={() => setPresetColor(255, 0, 0)} />

356

<Button title="Green" onPress={() => setPresetColor(0, 255, 0)} />

357

<Button title="Blue" onPress={() => setPresetColor(0, 0, 255)} />

358

<Button title="Black" onPress={() => setPresetColor(0, 0, 0)} />

359

<Button title="White" onPress={() => setPresetColor(255, 255, 255)} />

360

</View>

361

</View>

362

);

363

}

364

365

// Master-slave slider relationship

366

function MasterSlaveSliders() {

367

const masterRef = useRef<SliderRef>(null);

368

const slave1Ref = useRef<SliderRef>(null);

369

const slave2Ref = useRef<SliderRef>(null);

370

371

const [masterValue, setMasterValue] = useState(50);

372

const [slave1Value, setSlave1Value] = useState(25);

373

const [slave2Value, setSlave2Value] = useState(75);

374

375

// When master changes, update slaves proportionally

376

const handleMasterChange = (value: number) => {

377

setMasterValue(value);

378

379

// Update slaves to maintain proportion

380

const slave1Proportion = value * 0.5; // 50% of master

381

const slave2Proportion = Math.min(100, value * 1.5); // 150% of master (clamped)

382

383

slave1Ref.current?.updateValue(slave1Proportion);

384

slave2Ref.current?.updateValue(slave2Proportion);

385

setSlave1Value(slave1Proportion);

386

setSlave2Value(slave2Proportion);

387

};

388

389

return (

390

<View>

391

<Text>Master Control System</Text>

392

393

<View style={{marginVertical: 10}}>

394

<Text>Master: {masterValue.toFixed(1)}</Text>

395

<Slider

396

ref={masterRef}

397

style={{width: 300, height: 40}}

398

minimumValue={0}

399

maximumValue={100}

400

value={masterValue}

401

onValueChange={handleMasterChange}

402

minimumTrackTintColor="#ff6b6b"

403

/>

404

</View>

405

406

<View style={{marginVertical: 10}}>

407

<Text>Slave 1 (50% of Master): {slave1Value.toFixed(1)}</Text>

408

<Slider

409

ref={slave1Ref}

410

style={{width: 300, height: 40}}

411

minimumValue={0}

412

maximumValue={100}

413

value={slave1Value}

414

onValueChange={setSlave1Value}

415

disabled={true} // Controlled by master

416

minimumTrackTintColor="#4ecdc4"

417

/>

418

</View>

419

420

<View style={{marginVertical: 10}}>

421

<Text>Slave 2 (150% of Master): {slave2Value.toFixed(1)}</Text>

422

<Slider

423

ref={slave2Ref}

424

style={{width: 300, height: 40}}

425

minimumValue={0}

426

maximumValue={100}

427

value={slave2Value}

428

onValueChange={setSlave2Value}

429

disabled={true} // Controlled by master

430

minimumTrackTintColor="#45b7d1"

431

/>

432

</View>

433

</View>

434

);

435

}

436

```

437

438

### Error Handling and Validation

439

440

Proper error handling when using programmatic control.

441

442

**Usage Examples:**

443

444

```typescript

445

import React, { useRef, useState } from 'react';

446

import { View, Text, Button, Alert } from 'react-native';

447

import Slider from '@react-native-community/slider';

448

449

function ValidatedSlider() {

450

const sliderRef = useRef<SliderRef>(null);

451

const [value, setValue] = useState(50);

452

const [inputValue, setInputValue] = useState('50');

453

454

const updateSliderSafely = (newValue: number) => {

455

try {

456

// Validate the value is within bounds

457

const minValue = 0;

458

const maxValue = 100;

459

460

if (isNaN(newValue)) {

461

throw new Error('Value must be a number');

462

}

463

464

if (newValue < minValue || newValue > maxValue) {

465

throw new Error(`Value must be between ${minValue} and ${maxValue}`);

466

}

467

468

// Update the slider

469

sliderRef.current?.updateValue(newValue);

470

setValue(newValue);

471

setInputValue(newValue.toString());

472

473

} catch (error) {

474

Alert.alert('Invalid Value', error.message);

475

// Revert input to current valid value

476

setInputValue(value.toString());

477

}

478

};

479

480

const handleTextInput = (text: string) => {

481

setInputValue(text);

482

const numericValue = parseFloat(text);

483

if (!isNaN(numericValue)) {

484

updateSliderSafely(numericValue);

485

}

486

};

487

488

return (

489

<View>

490

<Text>Current Value: {value}</Text>

491

492

<Slider

493

ref={sliderRef}

494

style={{width: 300, height: 40}}

495

minimumValue={0}

496

maximumValue={100}

497

value={value}

498

onValueChange={setValue}

499

/>

500

501

<TextInput

502

style={{

503

borderWidth: 1,

504

borderColor: '#ccc',

505

padding: 8,

506

marginVertical: 10,

507

width: 100,

508

}}

509

value={inputValue}

510

onChangeText={handleTextInput}

511

keyboardType="numeric"

512

placeholder="Enter value"

513

/>

514

515

<View style={{flexDirection: 'row', gap: 10}}>

516

<Button title="Set to 25" onPress={() => updateSliderSafely(25)} />

517

<Button title="Set to 75" onPress={() => updateSliderSafely(75)} />

518

<Button title="Invalid (-10)" onPress={() => updateSliderSafely(-10)} />

519

</View>

520

</View>

521

);

522

}

523

```

524

525

## Types

526

527

### Reference Type Definitions

528

529

```typescript { .api }

530

import type { React } from 'react';

531

532

interface SliderRef {

533

updateValue(value: number): void;

534

}

535

536

type SliderReferenceType =

537

| (React.MutableRefObject<SliderRef> & React.LegacyRef<Slider>)

538

| undefined;

539

540

interface SliderRefProps {

541

ref?: SliderReferenceType;

542

}

543

```

544

545

### Hook Integration Types

546

547

```typescript { .api }

548

// For use with useRef hook

549

type SliderRefHook = React.MutableRefObject<SliderRef | null>;

550

551

// For use with forwardRef pattern

552

type ForwardedSliderRef = React.ForwardedRef<SliderRef>;

553

```