Skip to content

Add on this page navigation #416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
60eeb6c
feat: add OnThisPageTracker component
Jul 26, 2022
fe4200f
feat: add a sticky right sidenav to docs
Jul 28, 2022
80f64c9
refactor: add styling to the OnThisPageTracker and fix issues with bu…
Aug 3, 2022
8945cdc
refactor: make sure sections without a title are not tracked for OnTh…
Aug 3, 2022
50ac4cc
refactor: add a smart OnThisPageStickyContainer.vue component
Aug 4, 2022
058aa23
fix: spacing issue
Aug 21, 2022
30b3226
chore: add tests and cleanup old code
Aug 21, 2022
4917162
fix: optionally enable OnThisPageNav
Aug 22, 2022
d0e300a
fix: import path
Aug 22, 2022
2909e7c
fix: extra spacing
Aug 22, 2022
d6dc8a1
refactor: make sure OnThisPageStickyContainer is visible for more vie…
Aug 24, 2022
e79c79e
refactor: remove extra nested logic as it will not be used
Aug 24, 2022
04f58b0
refactor: use pre-defined font-weights
Aug 24, 2022
78f05b9
fix: prevent jump on scroll, when at the bottom of the page
Aug 26, 2022
24173b5
fix: remove bolding
Aug 31, 2022
8074389
Apply suggestions from code review
dobromir-hristov Sep 9, 2022
caebb3c
refactor: set the section's anchor as current
Sep 9, 2022
3dc8979
Merge branch 'dhristov/r97715869-add-on-this-page-navigation' of http…
Sep 9, 2022
7a05c87
refactor: remove `on-this-page` font style for `body-reduced-tight`
Sep 9, 2022
79555cb
refactor: OnThisPageNav scoped slot
Sep 9, 2022
b06756a
Merge branch 'main' into dhristov/r97715869-add-on-this-page-navigation
Sep 16, 2022
3e15a92
refactor: use mixin focusAndScroll method
Sep 16, 2022
5760958
Apply suggestions from code review
dobromir-hristov Sep 19, 2022
1d2929b
refactor: copy date
Sep 19, 2022
20fd172
Merge branch 'dhristov/r97715869-add-on-this-page-navigation' of http…
Sep 19, 2022
177efa5
refactor: exit early the `onScroll` function
Sep 19, 2022
63aa095
refactor: register OnThisPage Sections inside the `LinkableHeading` c…
Sep 19, 2022
415dac2
Merge branch 'main' into dhristov/r97715869-add-on-this-page-navigation
Sep 19, 2022
0b576c7
refactor: cleanup unused state
Sep 20, 2022
85effce
chore: remove unused components
Sep 20, 2022
05fc0f9
Merge branch 'main' into dhristov/r97715869-add-on-this-page-navigation
Sep 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions src/components/ContentNode/LinkableHeading.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

<template>
<component
:id="anchor"
:is="`h${level}`"
:id="anchor"
:is="`h${level}`"
>
<router-link
v-if="anchor && !isTargetIDE"
Expand All @@ -21,7 +21,7 @@
@click="handleFocusAndScroll(anchor)"
>
<slot />
<LinkIcon class="icon" aria-hidden="true"/>
<LinkIcon class="icon" aria-hidden="true" />
</router-link>
<template v-else>
<slot />
Expand Down Expand Up @@ -49,17 +49,39 @@ export default {
default: () => 2,
validator: v => v >= 1 && v <= 6,
},
registerOnThisPage: {
type: Boolean,
default: true,
},
},
computed: {
shouldRegisterOnThisPage({ registerOnThisPage, level, anchor }) {
return registerOnThisPage && level < 4 && anchor;
},
},
inject: {
isTargetIDE: {
default: () => false,
},
store: {
default: () => ({ addOnThisPageSection: () => {} }),
},
},
mounted() {
if (this.shouldRegisterOnThisPage) {
this.store.addOnThisPageSection({
anchor: this.anchor,
title: this.$el.textContent.trim(),
level: this.level,
});
}
},
};
</script>

<style scoped lang="scss">
@import 'docc-render/styles/_core.scss';

$icon-margin: 7px;

.header-anchor {
Expand Down
113 changes: 69 additions & 44 deletions src/components/DocumentationTopic.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,49 +46,56 @@
:platforms="platforms" :technologies="technologies"
/>
</DocumentationHero>
<div v-if="showContainer" class="container">
<div class="description" :class="{ 'after-enhanced-hero': enhanceBackground }">
<RequirementMetadata
v-if="isRequirement"
:defaultImplementationsCount="defaultImplementationsCount"
<div class="doc-content-wrapper">
<div class="doc-content">
<div v-if="showContainer" class="container">
<div class="description" :class="{ 'after-enhanced-hero': enhanceBackground }">
<RequirementMetadata
v-if="isRequirement"
:defaultImplementationsCount="defaultImplementationsCount"
/>
<Aside v-if="deprecationSummary && deprecationSummary.length" kind="deprecated">
<ContentNode :content="deprecationSummary" />
</Aside>
<Aside
v-if="downloadNotAvailableSummary && downloadNotAvailableSummary.length"
kind="note"
>
<ContentNode :content="downloadNotAvailableSummary" />
</Aside>
</div>
<PrimaryContent
v-if="primaryContentSections && primaryContentSections.length"
:class="{ 'with-border': !enhanceBackground }"
:conformance="conformance"
:source="remoteSource"
:sections="primaryContentSections"
/>
</div>
<Topics
v-if="topicSections"
:sections="topicSections"
:isSymbolDeprecated="isSymbolDeprecated"
:isSymbolBeta="isSymbolBeta"
/>
<DefaultImplementations
v-if="defaultImplementationsSections"
:sections="defaultImplementationsSections"
:isSymbolDeprecated="isSymbolDeprecated"
:isSymbolBeta="isSymbolBeta"
/>
<Relationships v-if="relationshipsSections" :sections="relationshipsSections" />
<!-- NOTE: see also may contain information about other apis, so we cannot
pass deprecation and beta information -->
<SeeAlso
v-if="seeAlsoSections"
:sections="seeAlsoSections"
/>
<Aside v-if="deprecationSummary && deprecationSummary.length" kind="deprecated">
<ContentNode :content="deprecationSummary" />
</Aside>
<Aside
v-if="downloadNotAvailableSummary && downloadNotAvailableSummary.length"
kind="note"
>
<ContentNode :content="downloadNotAvailableSummary" />
</Aside>
</div>
<PrimaryContent
v-if="primaryContentSections && primaryContentSections.length"
:class="{ 'with-border': !enhanceBackground }"
:conformance="conformance"
:source="remoteSource"
:sections="primaryContentSections"
/>
<OnThisPageStickyContainer v-if="enableOnThisPageNav">
<OnThisPageNav />
</OnThisPageStickyContainer>
</div>
<Topics
v-if="topicSections"
:sections="topicSections"
:isSymbolDeprecated="isSymbolDeprecated"
:isSymbolBeta="isSymbolBeta"
/>
<DefaultImplementations
v-if="defaultImplementationsSections"
:sections="defaultImplementationsSections"
:isSymbolDeprecated="isSymbolDeprecated"
:isSymbolBeta="isSymbolBeta"
/>
<Relationships v-if="relationshipsSections" :sections="relationshipsSections" />
<!-- NOTE: see also may contain information about other apis, so we cannot
pass deprecation and beta information -->
<SeeAlso
v-if="seeAlsoSections"
:sections="seeAlsoSections"
/>
<BetaLegalText v-if="!isTargetIDE && hasBetaContent" />
</main>
<div aria-live="polite" class="visuallyhidden">
Expand All @@ -106,6 +113,7 @@ import BetaLegalText from 'theme/components/DocumentationTopic/BetaLegalText.vue
import LanguageSwitcher from 'theme/components/DocumentationTopic/Summary/LanguageSwitcher.vue';
import DocumentationHero from 'docc-render/components/DocumentationTopic/DocumentationHero.vue';
import WordBreak from 'docc-render/components/WordBreak.vue';
import OnThisPageNav from 'theme/components/OnThisPageNav.vue';
import Abstract from './DocumentationTopic/Description/Abstract.vue';
import ContentNode from './DocumentationTopic/ContentNode.vue';
import CallToActionButton from './CallToActionButton.vue';
Expand All @@ -117,6 +125,7 @@ import Availability from './DocumentationTopic/Summary/Availability.vue';
import SeeAlso from './DocumentationTopic/SeeAlso.vue';
import Title from './DocumentationTopic/Title.vue';
import Topics from './DocumentationTopic/Topics.vue';
import OnThisPageStickyContainer from './DocumentationTopic/OnThisPageStickyContainer.vue';

export default {
name: 'DocumentationTopic',
Expand All @@ -131,12 +140,14 @@ export default {
default() {
return {
reset() {},
state: { onThisPageSections: [] },
state: {},
};
},
},
},
components: {
OnThisPageStickyContainer,
OnThisPageNav,
DocumentationHero,
Abstract,
Aside,
Expand Down Expand Up @@ -275,6 +286,10 @@ export default {
type: Array,
required: false,
},
enableOnThisPageNav: {
type: Boolean,
default: false,
},
},
provide() {
// NOTE: this is not reactive: if this.references change, the provided value
Expand All @@ -299,9 +314,6 @@ export default {
0,
);
},
onThisPageSections() {
return this.topicState.onThisPageSections;
},
hasAvailability: ({ platforms, technologies }) => (
(platforms || []).length || (technologies || []).length
),
Expand Down Expand Up @@ -463,4 +475,17 @@ export default {
}
}
}

.doc-content-wrapper {
display: flex;

.sidebar-hidden & {
justify-content: center;
}

.doc-content {
min-width: 0;
width: 100%;
}
}
</style>
11 changes: 3 additions & 8 deletions src/components/DocumentationTopic/ContentTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,20 @@
-->

<template>
<OnThisPageSection
class="contenttable alt-light"
:anchor="anchor"
:title="title"
>
<section class="contenttable alt-light">
<div class="container">
<LinkableHeading class="title" :anchor="anchor">{{ title }}</LinkableHeading>
<slot />
</div>
</OnThisPageSection>
</section>
</template>

<script>
import LinkableHeading from 'docc-render/components/ContentNode/LinkableHeading.vue';
import OnThisPageSection from './OnThisPageSection.vue';

export default {
name: 'ContentTable',
components: { OnThisPageSection, LinkableHeading },
components: { LinkableHeading },
props: {
anchor: {
type: String,
Expand Down
1 change: 1 addition & 0 deletions src/components/DocumentationTopic/ContentTableSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
:level="3"
class="title"
:anchor="anchorComputed"
:register-on-this-page="false"
>{{ title }}</LinkableHeading>
</slot>
</div>
Expand Down
44 changes: 0 additions & 44 deletions src/components/DocumentationTopic/OnThisPageSection.vue

This file was deleted.

60 changes: 60 additions & 0 deletions src/components/DocumentationTopic/OnThisPageStickyContainer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!--
This source file is part of the Swift.org open source project

Copyright (c) 2022 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
-->
<template>
<div class="OnThisPageStickyContainer" :class="{ hidden: isHidden }">
<slot />
</div>
</template>

<script>
// 660px content + (170px aside + 22px padding-right)*2 + 28px*2 gutter
export const ON_THIS_PAGE_CONTENT_BREAKPOINT = 1110;
// 1080 content + (170px aside + 22px padding-right)
export const ON_THIS_PAGE_CONTENT_BREAKPOINT_BIG = 1272;

export default {
name: 'OnThisPageStickyContainer',
inject: ['store'],
computed: {
isHidden: ({ store }) => {
let compareTo = ON_THIS_PAGE_CONTENT_BREAKPOINT;
// when the window is above 1500, the content max-width grows
if (window.outerWidth >= 1500) {
compareTo = ON_THIS_PAGE_CONTENT_BREAKPOINT_BIG;
}
return store.state.contentWidth < compareTo;
},
},
};
</script>

<style scoped lang='scss'>
@import 'docc-render/styles/_core.scss';

.OnThisPageStickyContainer {
$aside-width: rem(170px);
margin-top: $contenttable-spacing-single-side;
position: sticky;
top: $nav-height + rem(10px);
align-self: flex-start;
flex: 0 0 auto;
width: $aside-width;
margin-left: -($aside-width + $nav-padding);
padding-right: $nav-padding;

@include breakpoint(small) {
display: none;
}

&.hidden {
display: none;
}
}
</style>
6 changes: 3 additions & 3 deletions src/components/DocumentationTopic/PrimaryContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
<script>
import PossibleValues from 'docc-render/components/DocumentationTopic/PrimaryContent/PossibleValues.vue';
import RestEndpoint from 'docc-render/components/DocumentationTopic/PrimaryContent/RestEndpoint.vue';
import ContentNode from 'docc-render/components/DocumentationTopic/ContentNode.vue';
import Declaration from './PrimaryContent/Declaration.vue';
import PropertyListKeyDetails from './PrimaryContent/PropertyListKeyDetails.vue';
import GenericContent from './PrimaryContent/GenericContent.vue';
import Parameters from './PrimaryContent/Parameters.vue';
import PropertyTable from './PrimaryContent/PropertyTable.vue';
import RestBody from './PrimaryContent/RestBody.vue';
Expand All @@ -50,7 +50,7 @@ export default {
name: 'PrimaryContent',
components: {
Declaration,
GenericContent,
ContentNode,
Parameters,
PropertyListKeyDetails,
PropertyTable,
Expand Down Expand Up @@ -90,7 +90,7 @@ export default {
methods: {
componentFor(section) {
return {
[SectionKind.content]: GenericContent,
[SectionKind.content]: ContentNode,
[SectionKind.declarations]: Declaration,
[SectionKind.details]: PropertyListKeyDetails,
[SectionKind.parameters]: Parameters,
Expand Down
Loading