or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

animation-and-transitions.mdevent-management.mdfocus-and-accessibility.mdid-and-refs.mdindex.mdlinks-and-navigation.mdmiscellaneous-utilities.mdplatform-detection.mdprops-and-events.mdscrolling-and-layout.mdshadow-dom-support.mdstate-and-effects.mdvirtual-events-and-input.md

links-and-navigation.mddocs/

0

# Links & Navigation

1

2

Client-side routing integration, synthetic link handling, and programmatic navigation utilities for React applications.

3

4

## Capabilities

5

6

### Router Integration

7

8

Components and hooks for integrating with client-side routing systems.

9

10

```typescript { .api }

11

/**

12

* Provides client-side navigation context to nested components

13

* @param props - Router configuration

14

* @returns JSX element providing router context

15

*/

16

function RouterProvider(props: {

17

navigate: (path: string) => void;

18

useHref?: (href: string) => string;

19

children: ReactNode;

20

}): JSX.Element;

21

22

/**

23

* Accesses router context for navigation

24

* @returns Router object with navigation methods

25

*/

26

function useRouter(): Router;

27

28

interface Router {

29

/** Whether native browser navigation should be used */

30

isNative: boolean;

31

/** Open link with modifier key handling */

32

open: (target: HTMLAnchorElement, modifiers: Modifiers, setOpening?: boolean) => void;

33

/** Transform href for routing system */

34

useHref?: (href: string) => string;

35

}

36

```

37

38

**Usage Examples:**

39

40

```typescript

41

import { RouterProvider, useRouter } from "@react-aria/utils";

42

43

// App-level router setup

44

function App() {

45

const navigate = (path: string) => {

46

// Your router's navigation function

47

history.push(path);

48

};

49

50

const useHref = (href: string) => {

51

// Transform href for your routing system

52

return `/app${href}`;

53

};

54

55

return (

56

<RouterProvider navigate={navigate} useHref={useHref}>

57

<MainContent />

58

</RouterProvider>

59

);

60

}

61

62

// Using router in components

63

function NavigationComponent() {

64

const router = useRouter();

65

66

const handleLinkClick = (href: string, modifiers: Modifiers) => {

67

if (router.isNative) {

68

// Use browser navigation

69

window.location.href = href;

70

} else {

71

// Use client-side navigation

72

router.open(document.createElement('a'), modifiers);

73

}

74

};

75

76

return <div>Navigation component</div>;

77

}

78

```

79

80

### Link Opening

81

82

Functions for programmatically opening links with modifier key support.

83

84

```typescript { .api }

85

/**

86

* Programmatically opens links with modifier key support

87

* @param target - Anchor element to open

88

* @param modifiers - Object with modifier key states

89

* @param setOpening - Whether to set opening flag for popup blockers

90

*/

91

function openLink(

92

target: HTMLAnchorElement,

93

modifiers: Modifiers,

94

setOpening?: boolean

95

): void;

96

97

/**

98

* Determines if link should use client-side navigation

99

* @param link - Anchor element to check

100

* @param modifiers - Modifier key states

101

* @returns Boolean indicating if router should handle navigation

102

*/

103

function shouldClientNavigate(

104

link: HTMLAnchorElement,

105

modifiers: Modifiers

106

): boolean;

107

108

/**

109

* Handles link clicks with modifier key support

110

* @param target - Anchor element clicked

111

* @param modifiers - Modifier key states from event

112

*/

113

function handleLinkClick(

114

target: HTMLAnchorElement,

115

modifiers: Modifiers

116

): void;

117

118

interface Modifiers {

119

metaKey: boolean;

120

ctrlKey: boolean;

121

altKey: boolean;

122

shiftKey: boolean;

123

}

124

```

125

126

**Usage Examples:**

127

128

```typescript

129

import { openLink, shouldClientNavigate, handleLinkClick } from "@react-aria/utils";

130

131

function SmartLink({ href, children, onClick, ...props }) {

132

const linkRef = useRef<HTMLAnchorElement>(null);

133

134

const handleClick = (e: MouseEvent) => {

135

if (!linkRef.current) return;

136

137

const modifiers = {

138

metaKey: e.metaKey,

139

ctrlKey: e.ctrlKey,

140

altKey: e.altKey,

141

shiftKey: e.shiftKey

142

};

143

144

// Check if we should use client-side navigation

145

if (shouldClientNavigate(linkRef.current, modifiers)) {

146

e.preventDefault();

147

handleLinkClick(linkRef.current, modifiers);

148

} else {

149

// Let browser handle navigation

150

openLink(linkRef.current, modifiers, true);

151

}

152

153

onClick?.(e);

154

};

155

156

return (

157

<a

158

ref={linkRef}

159

href={href}

160

onClick={handleClick}

161

{...props}

162

>

163

{children}

164

</a>

165

);

166

}

167

168

// Link with programmatic opening

169

function ProgrammaticLink({ href, openInNewTab = false }) {

170

const linkRef = useRef<HTMLAnchorElement>(null);

171

172

const handleButtonClick = () => {

173

if (!linkRef.current) return;

174

175

const modifiers = {

176

metaKey: openInNewTab,

177

ctrlKey: openInNewTab,

178

altKey: false,

179

shiftKey: false

180

};

181

182

openLink(linkRef.current, modifiers, true);

183

};

184

185

return (

186

<div>

187

<a ref={linkRef} href={href} style={{ display: 'none' }} />

188

<button onClick={handleButtonClick}>

189

Open Link {openInNewTab ? '(New Tab)' : ''}

190

</button>

191

</div>

192

);

193

}

194

```

195

196

### Synthetic Links

197

198

Utilities for creating non-anchor elements that behave like links.

199

200

```typescript { .api }

201

/**

202

* Creates data attributes for synthetic links

203

* @param props - Link DOM properties

204

* @returns Object with data-* attributes for non-anchor elements

205

*/

206

function getSyntheticLinkProps(props: LinkDOMProps): DOMAttributes<HTMLElement>;

207

208

/**

209

* Hook that creates data attributes for synthetic links

210

* @param props - Link DOM properties

211

* @returns Object with data-* attributes for non-anchor elements

212

*/

213

function useSyntheticLinkProps(props: LinkDOMProps): DOMAttributes<HTMLElement>;

214

215

/**

216

* Hook that processes link props with router context

217

* @param props - Optional link properties

218

* @returns Link props with router-processed href

219

*/

220

function useLinkProps(props?: LinkDOMProps): LinkDOMProps;

221

222

interface LinkDOMProps extends DOMProps {

223

href?: string;

224

target?: string;

225

rel?: string;

226

download?: boolean | string;

227

ping?: string;

228

referrerPolicy?: string;

229

}

230

```

231

232

**Usage Examples:**

233

234

```typescript

235

import { useSyntheticLinkProps, useLinkProps, getSyntheticLinkProps } from "@react-aria/utils";

236

237

// Button that acts like a link

238

function LinkButton({ href, children, ...props }) {

239

const linkProps = useLinkProps({ href, ...props });

240

const syntheticProps = useSyntheticLinkProps(linkProps);

241

242

return (

243

<button

244

{...syntheticProps}

245

onClick={(e) => {

246

// Handle click as link

247

const link = document.createElement('a');

248

link.href = href;

249

handleLinkClick(link, {

250

metaKey: e.metaKey,

251

ctrlKey: e.ctrlKey,

252

altKey: e.altKey,

253

shiftKey: e.shiftKey

254

});

255

}}

256

>

257

{children}

258

</button>

259

);

260

}

261

262

// Card component that's entirely clickable

263

function ClickableCard({ href, title, description }) {

264

const syntheticProps = getSyntheticLinkProps({ href });

265

266

return (

267

<div

268

{...syntheticProps}

269

className="card clickable"

270

role="link"

271

tabIndex={0}

272

onClick={(e) => {

273

const link = document.createElement('a');

274

link.href = href;

275

openLink(link, {

276

metaKey: e.metaKey,

277

ctrlKey: e.ctrlKey,

278

altKey: e.altKey,

279

shiftKey: e.shiftKey

280

});

281

}}

282

onKeyDown={(e) => {

283

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

284

e.preventDefault();

285

const link = document.createElement('a');

286

link.href = href;

287

openLink(link, { metaKey: false, ctrlKey: false, altKey: false, shiftKey: false });

288

}

289

}}

290

>

291

<h3>{title}</h3>

292

<p>{description}</p>

293

</div>

294

);

295

}

296

297

// Router-aware link component

298

function RouterLink({ href, children, ...props }) {

299

const linkProps = useLinkProps({ href, ...props });

300

const router = useRouter();

301

302

return (

303

<a

304

{...linkProps}

305

onClick={(e) => {

306

const modifiers = {

307

metaKey: e.metaKey,

308

ctrlKey: e.ctrlKey,

309

altKey: e.altKey,

310

shiftKey: e.shiftKey

311

};

312

313

if (shouldClientNavigate(e.currentTarget, modifiers)) {

314

e.preventDefault();

315

if (router.isNative) {

316

window.location.href = href;

317

} else {

318

// Use router navigation

319

router.open(e.currentTarget, modifiers);

320

}

321

}

322

}}

323

>

324

{children}

325

</a>

326

);

327

}

328

```

329

330

### Advanced Navigation Patterns

331

332

Complex navigation scenarios with conditional routing and state management:

333

334

```typescript

335

import {

336

useRouter,

337

shouldClientNavigate,

338

useLinkProps,

339

useSyntheticLinkProps

340

} from "@react-aria/utils";

341

342

function AdvancedNavigation() {

343

const router = useRouter();

344

const [isNavigating, setIsNavigating] = useState(false);

345

346

const handleNavigation = useCallback(async (href: string, modifiers: Modifiers) => {

347

const link = document.createElement('a');

348

link.href = href;

349

350

if (shouldClientNavigate(link, modifiers)) {

351

setIsNavigating(true);

352

353

try {

354

// Perform client-side navigation with loading state

355

await router.navigate(href);

356

} finally {

357

setIsNavigating(false);

358

}

359

} else {

360

// Use browser navigation

361

openLink(link, modifiers, true);

362

}

363

}, [router]);

364

365

return (

366

<nav>

367

<NavigationItem

368

href="/dashboard"

369

onClick={handleNavigation}

370

isLoading={isNavigating}

371

>

372

Dashboard

373

</NavigationItem>

374

</nav>

375

);

376

}

377

378

// Context menu with link actions

379

function ContextMenu({ href, onClose }) {

380

const menuActions = [

381

{

382

label: 'Open',

383

action: () => {

384

const link = document.createElement('a');

385

link.href = href;

386

openLink(link, { metaKey: false, ctrlKey: false, altKey: false, shiftKey: false });

387

onClose();

388

}

389

},

390

{

391

label: 'Open in New Tab',

392

action: () => {

393

const link = document.createElement('a');

394

link.href = href;

395

openLink(link, { metaKey: true, ctrlKey: false, altKey: false, shiftKey: false });

396

onClose();

397

}

398

},

399

{

400

label: 'Copy Link',

401

action: () => {

402

navigator.clipboard.writeText(href);

403

onClose();

404

}

405

}

406

];

407

408

return (

409

<ul role="menu">

410

{menuActions.map(action => (

411

<li key={action.label}>

412

<button onClick={action.action}>

413

{action.label}

414

</button>

415

</li>

416

))}

417

</ul>

418

);

419

}

420

```

421

422

## Types

423

424

```typescript { .api }

425

interface DOMProps {

426

id?: string;

427

}

428

429

interface LinkDOMProps extends DOMProps {

430

href?: string;

431

target?: string;

432

rel?: string;

433

download?: boolean | string;

434

ping?: string;

435

referrerPolicy?: string;

436

}

437

438

interface Modifiers {

439

metaKey: boolean;

440

ctrlKey: boolean;

441

altKey: boolean;

442

shiftKey: boolean;

443

}

444

445

interface Router {

446

isNative: boolean;

447

open: (target: HTMLAnchorElement, modifiers: Modifiers, setOpening?: boolean) => void;

448

useHref?: (href: string) => string;

449

}

450

```