Skip to content

Commit 81a2ae6

Browse files
committed
add sublists for vertical ToC
1 parent 0c76590 commit 81a2ae6

File tree

8 files changed

+530
-273
lines changed

8 files changed

+530
-273
lines changed

public/00000000-0000-0000-0000-000000000000/00000000-0000-0000-0000-000000000000_fr.json

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,88 @@
329329
]
330330
}
331331
],
332+
"tableOfContents": [
333+
{
334+
"title": "Apercu",
335+
"slideIndex": 0,
336+
"sublist": [
337+
{
338+
"title": "Gisements de sables bitumineux",
339+
"slideIndex": 1
340+
}
341+
]
342+
},
343+
{
344+
"title": "Extraction de sables bitumineux",
345+
"slideIndex": 2,
346+
"sublist": [
347+
{
348+
"title": "Extraction des sables bitumineux (2)",
349+
"slideIndex": 3
350+
},
351+
{
352+
"title": "Où sont situées les installations?",
353+
"slideIndex": 4
354+
}
355+
]
356+
},
357+
{
358+
"title": "Substances de l'INRP déclarées par les installations d’exploitation minière de sables bitumineux",
359+
"slideIndex": 5,
360+
"sublist": [
361+
{
362+
"title": "Substances de l'INRP déclarées par les installations d’exploitation minière de sables bitumineux MAP",
363+
"slideIndex": 6
364+
},
365+
{
366+
"title": "Rejets de principaux contaminants atmosphériques de mines de sables bitumineux",
367+
"slideIndex": 7
368+
},
369+
{
370+
"title": "Résidus miniers déclarés par les installations d’exploitation minière à ciel ouvert des sables bitumineux",
371+
"slideIndex": 8
372+
},
373+
{
374+
"title": "Résidus miniers déclarés à l’INRP par les installations d’exploitation minière à ciel ouvert de sables bitumineux",
375+
"slideIndex": 9
376+
},
377+
{
378+
"title": "Résidus miniers déclarés à l’INRP par les installations d’exploitation minière à ciel ouvert de sables bitumineux MAP",
379+
"slideIndex": 10
380+
}
381+
]
382+
},
383+
{
384+
"title": "Tendances dans les résidus miniers déclarés par les installations d’exploitation minière à ciel ouvert",
385+
"slideIndex": 11
386+
},
387+
{
388+
"title": "Installations in situ",
389+
"slideIndex": 12,
390+
"sublist": [
391+
{
392+
"title": "Rejets à l’air déclarés par les installations in situ",
393+
"slideIndex": 13
394+
},
395+
{
396+
"title": "Tendances entourant les substances déclarées à l’INRP par les installations in situ",
397+
"slideIndex": 14
398+
},
399+
{
400+
"title": "Rejets à l’air déclarés à l’INRP par les installations in situ",
401+
"slideIndex": 15
402+
},
403+
{
404+
"title": "Gestion des répercussions sur l’environnement",
405+
"slideIndex": 16
406+
}
407+
]
408+
},
409+
{
410+
"title": "Finale",
411+
"slideIndex": 17
412+
}
413+
],
332414
"contextLink": "https://www.canada.ca/en/environment-climate-change/services/national-pollutant-release-inventory/tools-resources-data/exploredata.html",
333415
"contextLabel": "Explore National Pollutant Release Inventory data",
334416
"lang": "en",
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<template>
2+
<div :class="{ flex: parentItem }">
3+
<!-- using router-link causes a page refresh which breaks plugin -->
4+
<a
5+
class="flex items-center px-2 py-1 mx-1 cursor-pointer"
6+
:class="{ 'flex-grow pb-2 min-w-0': parentItem, 'pb-2': parentItem && !verticalToc }"
7+
@click="scrollToChapter(getSlideId(tocItem.slideIndex))"
8+
v-tippy="{
9+
delay: '200',
10+
placement: 'right',
11+
content: getTitle(tocItem),
12+
animateFill: true,
13+
animation: 'chapter-menu'
14+
}"
15+
v-if="plugin"
16+
>
17+
<svg
18+
class="flex-shrink-0"
19+
width="24"
20+
height="24"
21+
viewBox="0 0 24 24"
22+
xmlns="http://www.w3.org/2000/svg"
23+
fill="#fff"
24+
stroke="#878787"
25+
v-if="verticalToc"
26+
>
27+
<path
28+
d="m19.325 16.229c-2.4415 1.4096-4.8829 2.8191-7.3244 4.2286-2.4415-1.4096-4.883-2.8192-7.3245-4.2288-3.55e-5 -2.8191-7.1e-5 -5.6383-1.066e-4 -8.4574 2.4415-1.4096 4.8829-2.8191 7.3244-4.2286 2.4415 1.4096 4.883 2.8192 7.3245 4.2288 3.7e-5 2.8191 7.4e-5 5.6383 1.1e-4 8.4574z"
29+
stroke-width=".93974"
30+
/>
31+
</svg>
32+
<span
33+
class="flex-1 overflow-hidden leading-normal overflow-ellipsis whitespace-nowrap"
34+
:class="{ 'ml-4': verticalToc && parentItem, 'pl-8': verticalToc && !parentItem }"
35+
>{{ getTitle(tocItem) }}</span
36+
>
37+
</a>
38+
39+
<router-link
40+
:to="{ hash: `#${getSlideId(tocItem.slideIndex)}` }"
41+
class="flex items-center px-2 py-1 mx-1"
42+
:class="{ 'flex-grow min-w-0': parentItem, 'pb-2': parentItem && !verticalToc }"
43+
target
44+
v-tippy="{
45+
delay: '200',
46+
placement: 'right',
47+
content: getTitle(tocItem),
48+
animateFill: true,
49+
animation: 'chapter-menu'
50+
}"
51+
v-else
52+
>
53+
<svg
54+
class="flex-shrink-0"
55+
width="24"
56+
height="24"
57+
viewBox="0 0 24 24"
58+
xmlns="http://www.w3.org/2000/svg"
59+
fill="#fff"
60+
stroke="#878787"
61+
v-if="verticalToc"
62+
>
63+
<path
64+
d="m19.325 16.229c-2.4415 1.4096-4.8829 2.8191-7.3244 4.2286-2.4415-1.4096-4.883-2.8192-7.3245-4.2288-3.55e-5 -2.8191-7.1e-5 -5.6383-1.066e-4 -8.4574 2.4415-1.4096 4.8829-2.8191 7.3244-4.2286 2.4415 1.4096 4.883 2.8192 7.3245 4.2288 3.7e-5 2.8191 7.4e-5 5.6383 1.1e-4 8.4574z"
65+
stroke-width=".93974"
66+
/>
67+
</svg>
68+
<span
69+
class="flex-1 overflow-hidden leading-normal overflow-ellipsis whitespace-nowrap"
70+
:class="{ 'ml-4': verticalToc && parentItem, 'pl-8': verticalToc && !parentItem }"
71+
>{{ getTitle(tocItem) }}</span
72+
>
73+
</router-link>
74+
75+
<slot></slot>
76+
</div>
77+
</template>
78+
79+
<script setup lang="ts">
80+
import type { PropType } from 'vue';
81+
import { MenuItem, Slide } from '@storylines/definitions';
82+
83+
import { useI18n } from 'vue-i18n';
84+
const { t } = useI18n();
85+
86+
const props = defineProps({
87+
tocItem: {
88+
type: Object as PropType<MenuItem>,
89+
required: true
90+
},
91+
slides: {
92+
type: Array as PropType<Array<Slide>>,
93+
required: true
94+
},
95+
parentItem: {
96+
type: Boolean,
97+
required: false,
98+
default: true
99+
},
100+
verticalToc: {
101+
type: Boolean,
102+
required: false,
103+
default: true
104+
},
105+
mobile: {
106+
type: Boolean,
107+
required: false,
108+
default: false
109+
},
110+
plugin: {
111+
type: Boolean,
112+
required: true
113+
},
114+
returnTop: {
115+
type: Boolean,
116+
required: false,
117+
default: false
118+
}
119+
});
120+
121+
const scrollToChapter = (id: string): void => {
122+
const el = document.getElementById(id);
123+
if (el) {
124+
el.scrollIntoView({ behavior: 'smooth' });
125+
}
126+
};
127+
128+
const getTitle = (slide: Slide | MenuItem): string => {
129+
return slide.title !== '' ? slide.title : t('chapters.untitled');
130+
};
131+
132+
const getSlideId = (slideIdx: number): string => {
133+
const slide = props.slides.find((slide, idx) => idx === slideIdx);
134+
return slide ? `${slideIdx}-${slide.title.toLowerCase().replaceAll(' ', '-')}` : '';
135+
};
136+
</script>
137+
138+
<style lang="scss" scoped></style>

0 commit comments

Comments
 (0)