Skip to content

Commit d34e098

Browse files
committed
Sync TOC with visible headings
1 parent 51e56e1 commit d34e098

File tree

3 files changed

+63
-12
lines changed

3 files changed

+63
-12
lines changed

docusaurus.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default {
99
favicon: 'img/favicon.ico',
1010
organizationName: 'react-navigation',
1111
projectName: 'react-navigation.github.io',
12-
scripts: ['/js/snack-helpers.js'],
12+
scripts: ['/js/snack-helpers.js', '/js/toc-fixes.js'],
1313
themeConfig: {
1414
prism: {
1515
theme: require('prism-react-renderer').themes.github,

static/js/toc-fixes.js

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Docusaurus shows items in hidden tabs in the TOC.
3+
* It's confusing since it doesn't represent the actual page.
4+
* And clicking on those items doesn't do anything.
5+
* This scripts syncs the TOCs with visible headings.
6+
*/
7+
const sync = () => {
8+
const headings = document.querySelectorAll('article :is(h2, h3)');
9+
10+
// Get all visible headings
11+
const titles = Array.from(headings)
12+
.filter((el) => el.offsetParent)
13+
.map((el) => trim(el.textContent));
14+
15+
const toc = document.querySelectorAll('.table-of-contents li > a');
16+
17+
// Hide TOC items that don't have a corresponding heading
18+
toc.forEach((el) => {
19+
if (!titles.includes(trim(el.textContent))) {
20+
el.parentElement.style.display = 'none';
21+
} else {
22+
el.parentElement.style.display = 'block';
23+
}
24+
});
25+
};
26+
27+
if (window.navigation) {
28+
document.addEventListener('DOMContentLoaded', () => {
29+
// For the first page load, wait till page is loaded
30+
const observer = new MutationObserver(() => {
31+
const article = document.querySelector('article');
32+
33+
if (article) {
34+
observer.disconnect();
35+
sync();
36+
37+
// Listen to navigation events to detect tab query param change
38+
window.navigation.addEventListener('navigate', (event) => {
39+
requestAnimationFrame(sync);
40+
});
41+
}
42+
});
43+
44+
observer.observe(document.documentElement, {
45+
childList: true,
46+
subtree: true,
47+
});
48+
});
49+
}
50+
51+
const trim = (str) => str.trim().replace(/[\u200B-\u200D\uFEFF]/g, '');

versioned_docs/version-7.x/typescript.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ Now, when using `StaticParamList<typeof RootStack>`, it will include the screens
135135

136136
When using the dynamic API, it is necessary to specify the types for each screen as well as the nesting structure as it cannot be inferred from the code.
137137

138-
### Typechecking the navigator
138+
## Typechecking the navigator
139139

140140
To typecheck our route name and params, the first thing we need to do is to create an object type with mappings for route names to the params of the route. For example, say we have a route called `Profile` in our root navigator which should have a param `userId`:
141141

@@ -187,7 +187,7 @@ The type containing the mapping must be a type alias (e.g. `type RootStackParamL
187187

188188
:::
189189

190-
### Type checking screens
190+
## Type checking screens
191191

192192
To typecheck our screens, we need to annotate the `navigation` and the `route` props received by a screen. The navigator packages in React Navigation export generic types to define types for both the `navigation` and `route` props from the corresponding navigator.
193193

@@ -274,9 +274,9 @@ type ProfileScreenRouteProp = RouteProp<RootStackParamList, 'Profile'>;
274274

275275
We recommend creating a separate file: `types.tsx` - where you keep the types and import from there in your component files instead of repeating them in each file.
276276

277-
### Nesting navigators
277+
## Nesting navigators
278278

279-
#### Type checking screens and params in nested navigator
279+
### Type checking screens and params in nested navigator
280280

281281
You can [navigate to a screen in a nested navigator](nesting-navigators.md#navigating-to-a-screen-in-a-nested-navigator) by passing `screen` and `params` properties for the nested screen:
282282

@@ -298,7 +298,7 @@ type TabParamList = {
298298
};
299299
```
300300

301-
#### Combining navigation props
301+
### Combining navigation props
302302

303303
When you nest navigators, the navigation prop of the screen is a combination of multiple navigation props. For example, if we have a tab inside a stack, the `navigation` prop will have both `jumpTo` (from the tab navigator) and `push` (from the stack navigator). To make it easier to combine types from multiple navigators, you can use the `CompositeScreenProps` type:
304304

@@ -340,7 +340,7 @@ type ProfileScreenNavigationProp = CompositeNavigationProp<
340340
>;
341341
```
342342

343-
### Annotating `useNavigation`
343+
## Annotating `useNavigation`
344344

345345
:::danger
346346

@@ -355,7 +355,7 @@ To annotate the `navigation` object that we get from `useNavigation`, we can use
355355
const navigation = useNavigation<ProfileScreenNavigationProp>();
356356
```
357357

358-
### Annotating `useRoute`
358+
## Annotating `useRoute`
359359

360360
:::danger
361361

@@ -370,7 +370,7 @@ To annotate the `route` object that we get from `useRoute`, we can use a type pa
370370
const route = useRoute<ProfileScreenRouteProp>();
371371
```
372372

373-
### Annotating `options` and `screenOptions`
373+
## Annotating `options` and `screenOptions`
374374

375375
When you pass the `options` to a `Screen` or `screenOptions` prop to a `Navigator` component, they are already type-checked and you don't need to do anything special. However, sometimes you might want to extract the options to a separate object, and you might want to annotate it.
376376

@@ -401,7 +401,7 @@ const options = ({ route }: StackOptionsArgs): StackNavigationOptions => {
401401
};
402402
```
403403

404-
### Annotating `ref` on `NavigationContainer`
404+
## Annotating `ref` on `NavigationContainer`
405405

406406
If you use the `createNavigationContainerRef()` method to create the ref, you can annotate it to type-check navigation actions:
407407

@@ -447,7 +447,7 @@ const navigationRef =
447447
React.createRef<NavigationContainerRef<RootStackParamList>>();
448448
```
449449

450-
### Specifying default types for `useNavigation`, `Link`, `ref` etc
450+
## Specifying default types for `useNavigation`, `Link`, `ref` etc
451451

452452
Instead of manually annotating these APIs, you can specify a global type for your root navigator which will be used as the default type.
453453

@@ -465,7 +465,7 @@ The `RootParamList` interface lets React Navigation know about the params accept
465465

466466
Specifying this type is important if you heavily use `useNavigation`, `Link` etc. in your app since it'll ensure type-safety. It will also make sure that you have correct nesting on the `linking` prop.
467467

468-
### Organizing types
468+
## Organizing types
469469

470470
When writing types for React Navigation, there are a couple of things we recommend to keep things organized.
471471

0 commit comments

Comments
 (0)