Skip to content

Commit b6da958

Browse files
author
Dobromir Hristov
authored
Add on this page navigation (#416)
closes rdar://97715869
1 parent 110f26a commit b6da958

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+803
-806
lines changed

src/components/ContentNode/LinkableHeading.vue

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
<template>
1212
<component
13-
:id="anchor"
14-
:is="`h${level}`"
13+
:id="anchor"
14+
:is="`h${level}`"
1515
>
1616
<router-link
1717
v-if="anchor && !isTargetIDE"
@@ -21,7 +21,7 @@
2121
@click="handleFocusAndScroll(anchor)"
2222
>
2323
<slot />
24-
<LinkIcon class="icon" aria-hidden="true"/>
24+
<LinkIcon class="icon" aria-hidden="true" />
2525
</router-link>
2626
<template v-else>
2727
<slot />
@@ -49,17 +49,39 @@ export default {
4949
default: () => 2,
5050
validator: v => v >= 1 && v <= 6,
5151
},
52+
registerOnThisPage: {
53+
type: Boolean,
54+
default: true,
55+
},
56+
},
57+
computed: {
58+
shouldRegisterOnThisPage({ registerOnThisPage, level, anchor }) {
59+
return registerOnThisPage && level < 4 && anchor;
60+
},
5261
},
5362
inject: {
5463
isTargetIDE: {
5564
default: () => false,
5665
},
66+
store: {
67+
default: () => ({ addOnThisPageSection: () => {} }),
68+
},
69+
},
70+
mounted() {
71+
if (this.shouldRegisterOnThisPage) {
72+
this.store.addOnThisPageSection({
73+
anchor: this.anchor,
74+
title: this.$el.textContent.trim(),
75+
level: this.level,
76+
});
77+
}
5778
},
5879
};
5980
</script>
6081

6182
<style scoped lang="scss">
6283
@import 'docc-render/styles/_core.scss';
84+
6385
$icon-margin: 7px;
6486
6587
.header-anchor {

src/components/DocumentationTopic.vue

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -46,49 +46,56 @@
4646
:platforms="platforms" :technologies="technologies"
4747
/>
4848
</DocumentationHero>
49-
<div v-if="showContainer" class="container">
50-
<div class="description" :class="{ 'after-enhanced-hero': enhanceBackground }">
51-
<RequirementMetadata
52-
v-if="isRequirement"
53-
:defaultImplementationsCount="defaultImplementationsCount"
49+
<div class="doc-content-wrapper">
50+
<div class="doc-content">
51+
<div v-if="showContainer" class="container">
52+
<div class="description" :class="{ 'after-enhanced-hero': enhanceBackground }">
53+
<RequirementMetadata
54+
v-if="isRequirement"
55+
:defaultImplementationsCount="defaultImplementationsCount"
56+
/>
57+
<Aside v-if="deprecationSummary && deprecationSummary.length" kind="deprecated">
58+
<ContentNode :content="deprecationSummary" />
59+
</Aside>
60+
<Aside
61+
v-if="downloadNotAvailableSummary && downloadNotAvailableSummary.length"
62+
kind="note"
63+
>
64+
<ContentNode :content="downloadNotAvailableSummary" />
65+
</Aside>
66+
</div>
67+
<PrimaryContent
68+
v-if="primaryContentSections && primaryContentSections.length"
69+
:class="{ 'with-border': !enhanceBackground }"
70+
:conformance="conformance"
71+
:source="remoteSource"
72+
:sections="primaryContentSections"
73+
/>
74+
</div>
75+
<Topics
76+
v-if="topicSections"
77+
:sections="topicSections"
78+
:isSymbolDeprecated="isSymbolDeprecated"
79+
:isSymbolBeta="isSymbolBeta"
80+
/>
81+
<DefaultImplementations
82+
v-if="defaultImplementationsSections"
83+
:sections="defaultImplementationsSections"
84+
:isSymbolDeprecated="isSymbolDeprecated"
85+
:isSymbolBeta="isSymbolBeta"
86+
/>
87+
<Relationships v-if="relationshipsSections" :sections="relationshipsSections" />
88+
<!-- NOTE: see also may contain information about other apis, so we cannot
89+
pass deprecation and beta information -->
90+
<SeeAlso
91+
v-if="seeAlsoSections"
92+
:sections="seeAlsoSections"
5493
/>
55-
<Aside v-if="deprecationSummary && deprecationSummary.length" kind="deprecated">
56-
<ContentNode :content="deprecationSummary" />
57-
</Aside>
58-
<Aside
59-
v-if="downloadNotAvailableSummary && downloadNotAvailableSummary.length"
60-
kind="note"
61-
>
62-
<ContentNode :content="downloadNotAvailableSummary" />
63-
</Aside>
6494
</div>
65-
<PrimaryContent
66-
v-if="primaryContentSections && primaryContentSections.length"
67-
:class="{ 'with-border': !enhanceBackground }"
68-
:conformance="conformance"
69-
:source="remoteSource"
70-
:sections="primaryContentSections"
71-
/>
95+
<OnThisPageStickyContainer v-if="enableOnThisPageNav">
96+
<OnThisPageNav />
97+
</OnThisPageStickyContainer>
7298
</div>
73-
<Topics
74-
v-if="topicSections"
75-
:sections="topicSections"
76-
:isSymbolDeprecated="isSymbolDeprecated"
77-
:isSymbolBeta="isSymbolBeta"
78-
/>
79-
<DefaultImplementations
80-
v-if="defaultImplementationsSections"
81-
:sections="defaultImplementationsSections"
82-
:isSymbolDeprecated="isSymbolDeprecated"
83-
:isSymbolBeta="isSymbolBeta"
84-
/>
85-
<Relationships v-if="relationshipsSections" :sections="relationshipsSections" />
86-
<!-- NOTE: see also may contain information about other apis, so we cannot
87-
pass deprecation and beta information -->
88-
<SeeAlso
89-
v-if="seeAlsoSections"
90-
:sections="seeAlsoSections"
91-
/>
9299
<BetaLegalText v-if="!isTargetIDE && hasBetaContent" />
93100
</main>
94101
<div aria-live="polite" class="visuallyhidden">
@@ -106,6 +113,7 @@ import BetaLegalText from 'theme/components/DocumentationTopic/BetaLegalText.vue
106113
import LanguageSwitcher from 'theme/components/DocumentationTopic/Summary/LanguageSwitcher.vue';
107114
import DocumentationHero from 'docc-render/components/DocumentationTopic/DocumentationHero.vue';
108115
import WordBreak from 'docc-render/components/WordBreak.vue';
116+
import OnThisPageNav from 'theme/components/OnThisPageNav.vue';
109117
import Abstract from './DocumentationTopic/Description/Abstract.vue';
110118
import ContentNode from './DocumentationTopic/ContentNode.vue';
111119
import CallToActionButton from './CallToActionButton.vue';
@@ -117,6 +125,7 @@ import Availability from './DocumentationTopic/Summary/Availability.vue';
117125
import SeeAlso from './DocumentationTopic/SeeAlso.vue';
118126
import Title from './DocumentationTopic/Title.vue';
119127
import Topics from './DocumentationTopic/Topics.vue';
128+
import OnThisPageStickyContainer from './DocumentationTopic/OnThisPageStickyContainer.vue';
120129
121130
export default {
122131
name: 'DocumentationTopic',
@@ -131,12 +140,14 @@ export default {
131140
default() {
132141
return {
133142
reset() {},
134-
state: { onThisPageSections: [] },
143+
state: {},
135144
};
136145
},
137146
},
138147
},
139148
components: {
149+
OnThisPageStickyContainer,
150+
OnThisPageNav,
140151
DocumentationHero,
141152
Abstract,
142153
Aside,
@@ -275,6 +286,10 @@ export default {
275286
type: Array,
276287
required: false,
277288
},
289+
enableOnThisPageNav: {
290+
type: Boolean,
291+
default: false,
292+
},
278293
},
279294
provide() {
280295
// NOTE: this is not reactive: if this.references change, the provided value
@@ -299,9 +314,6 @@ export default {
299314
0,
300315
);
301316
},
302-
onThisPageSections() {
303-
return this.topicState.onThisPageSections;
304-
},
305317
hasAvailability: ({ platforms, technologies }) => (
306318
(platforms || []).length || (technologies || []).length
307319
),
@@ -463,4 +475,17 @@ export default {
463475
}
464476
}
465477
}
478+
479+
.doc-content-wrapper {
480+
display: flex;
481+
482+
.sidebar-hidden & {
483+
justify-content: center;
484+
}
485+
486+
.doc-content {
487+
min-width: 0;
488+
width: 100%;
489+
}
490+
}
466491
</style>

src/components/DocumentationTopic/ContentTable.vue

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,20 @@
99
-->
1010

1111
<template>
12-
<OnThisPageSection
13-
class="contenttable alt-light"
14-
:anchor="anchor"
15-
:title="title"
16-
>
12+
<section class="contenttable alt-light">
1713
<div class="container">
1814
<LinkableHeading class="title" :anchor="anchor">{{ title }}</LinkableHeading>
1915
<slot />
2016
</div>
21-
</OnThisPageSection>
17+
</section>
2218
</template>
2319

2420
<script>
2521
import LinkableHeading from 'docc-render/components/ContentNode/LinkableHeading.vue';
26-
import OnThisPageSection from './OnThisPageSection.vue';
2722
2823
export default {
2924
name: 'ContentTable',
30-
components: { OnThisPageSection, LinkableHeading },
25+
components: { LinkableHeading },
3126
props: {
3227
anchor: {
3328
type: String,

src/components/DocumentationTopic/ContentTableSection.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
:level="3"
1717
class="title"
1818
:anchor="anchorComputed"
19+
:register-on-this-page="false"
1920
>{{ title }}</LinkableHeading>
2021
</slot>
2122
</div>

src/components/DocumentationTopic/OnThisPageSection.vue

Lines changed: 0 additions & 44 deletions
This file was deleted.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!--
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2022 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See https://swift.org/LICENSE.txt for license information
8+
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
-->
10+
<template>
11+
<div class="OnThisPageStickyContainer" :class="{ hidden: isHidden }">
12+
<slot />
13+
</div>
14+
</template>
15+
16+
<script>
17+
// 660px content + (170px aside + 22px padding-right)*2 + 28px*2 gutter
18+
export const ON_THIS_PAGE_CONTENT_BREAKPOINT = 1110;
19+
// 1080 content + (170px aside + 22px padding-right)
20+
export const ON_THIS_PAGE_CONTENT_BREAKPOINT_BIG = 1272;
21+
22+
export default {
23+
name: 'OnThisPageStickyContainer',
24+
inject: ['store'],
25+
computed: {
26+
isHidden: ({ store }) => {
27+
let compareTo = ON_THIS_PAGE_CONTENT_BREAKPOINT;
28+
// when the window is above 1500, the content max-width grows
29+
if (window.outerWidth >= 1500) {
30+
compareTo = ON_THIS_PAGE_CONTENT_BREAKPOINT_BIG;
31+
}
32+
return store.state.contentWidth < compareTo;
33+
},
34+
},
35+
};
36+
</script>
37+
38+
<style scoped lang='scss'>
39+
@import 'docc-render/styles/_core.scss';
40+
41+
.OnThisPageStickyContainer {
42+
$aside-width: rem(170px);
43+
margin-top: $contenttable-spacing-single-side;
44+
position: sticky;
45+
top: $nav-height + rem(10px);
46+
align-self: flex-start;
47+
flex: 0 0 auto;
48+
width: $aside-width;
49+
margin-left: -($aside-width + $nav-padding);
50+
padding-right: $nav-padding;
51+
52+
@include breakpoint(small) {
53+
display: none;
54+
}
55+
56+
&.hidden {
57+
display: none;
58+
}
59+
}
60+
</style>

src/components/DocumentationTopic/PrimaryContent.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
<script>
2323
import PossibleValues from 'docc-render/components/DocumentationTopic/PrimaryContent/PossibleValues.vue';
2424
import RestEndpoint from 'docc-render/components/DocumentationTopic/PrimaryContent/RestEndpoint.vue';
25+
import ContentNode from 'docc-render/components/DocumentationTopic/ContentNode.vue';
2526
import Declaration from './PrimaryContent/Declaration.vue';
2627
import PropertyListKeyDetails from './PrimaryContent/PropertyListKeyDetails.vue';
27-
import GenericContent from './PrimaryContent/GenericContent.vue';
2828
import Parameters from './PrimaryContent/Parameters.vue';
2929
import PropertyTable from './PrimaryContent/PropertyTable.vue';
3030
import RestBody from './PrimaryContent/RestBody.vue';
@@ -50,7 +50,7 @@ export default {
5050
name: 'PrimaryContent',
5151
components: {
5252
Declaration,
53-
GenericContent,
53+
ContentNode,
5454
Parameters,
5555
PropertyListKeyDetails,
5656
PropertyTable,
@@ -90,7 +90,7 @@ export default {
9090
methods: {
9191
componentFor(section) {
9292
return {
93-
[SectionKind.content]: GenericContent,
93+
[SectionKind.content]: ContentNode,
9494
[SectionKind.declarations]: Declaration,
9595
[SectionKind.details]: PropertyListKeyDetails,
9696
[SectionKind.parameters]: Parameters,

0 commit comments

Comments
 (0)