mirror of https://github.com/FreeTubeApp/FreeTube
Implement dynamic scroll-based underlining of active section
This commit is contained in:
parent
f4d8648607
commit
8135ff2dd0
|
@ -2,11 +2,10 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 0;
|
gap: 2px;
|
||||||
gap: 5px;
|
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
inline-size: fit-content;
|
inline-size: 250px;
|
||||||
max-inline-size: 250px;
|
padding-inline-start: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
@ -26,9 +25,29 @@
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settingsMenuTitleContent {
|
||||||
|
inline-size: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settingsMenuTitleAndIcon {
|
||||||
|
/* needed to have underline poke out */
|
||||||
|
margin-inline-start: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settingsMenuTitleUnderline {
|
||||||
|
/* have underline poke out */
|
||||||
|
inline-size: calc(100% + 3px);
|
||||||
|
|
||||||
|
/* prevent "active" border from visibly pushing the content up */
|
||||||
|
border-block-end: 3px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.settingsMenuTitle.active {
|
.settingsMenuTitle.active {
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
border-block-end: 3px solid var(--primary-text-color);
|
}
|
||||||
|
|
||||||
|
.settingsMenuTitle.active .settingsMenuTitleUnderline {
|
||||||
|
border-block-end: 3px solid var(--primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.settingsMenuTitleIcon {
|
.settingsMenuTitleIcon {
|
||||||
|
|
|
@ -7,15 +7,21 @@
|
||||||
</h2>
|
</h2>
|
||||||
<a
|
<a
|
||||||
v-for="(settingsSection) in settingsSections"
|
v-for="(settingsSection) in settingsSections"
|
||||||
:key="settingsSection.type + 'link'"
|
:id="settingsSection.type + '-link'"
|
||||||
|
:key="settingsSection.type + '-link'"
|
||||||
:href="'#' + settingsSection.type"
|
:href="'#' + settingsSection.type"
|
||||||
class="settingsMenuTitle"
|
class="settingsMenuTitle"
|
||||||
>
|
>
|
||||||
|
<div class="settingsMenuTitleContent">
|
||||||
|
<div class="settingsMenuTitleAndIcon">
|
||||||
<font-awesome-icon
|
<font-awesome-icon
|
||||||
:icon="['fas', settingsSection.icon]"
|
:icon="['fas', settingsSection.icon]"
|
||||||
class="settingsMenuTitleIcon"
|
class="settingsMenuTitleIcon"
|
||||||
/>
|
/>
|
||||||
{{ getTitleForSection(settingsSection) }}
|
{{ getTitleForSection(settingsSection) }}
|
||||||
|
</div>
|
||||||
|
<div class="settingsMenuTitleUnderline" />
|
||||||
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</menu>
|
</menu>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -7,25 +7,42 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
max-inline-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settingsSections {
|
.settingsSections {
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.switchRow {
|
.settingsSections:last-child {
|
||||||
display: flex;
|
margin-block-end: calc(76vh - 150px)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .settingsSections {
|
.switchRow {
|
||||||
|
display: flex;
|
||||||
} */
|
margin-inline-end: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.settingsToggle {
|
.settingsToggle {
|
||||||
padding-block: 0;
|
padding-block: 0;
|
||||||
margin-block: 10px 5px;
|
margin-block: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
/* enables anchor link clicks to land right at the section headings */
|
||||||
|
scroll-margin-top: 24vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section + .section {
|
.section + .section {
|
||||||
padding-block-start: 20px;
|
padding-block-start: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (width <= 950px) {
|
||||||
|
ft-settings-menu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settingsContent {
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -45,10 +45,6 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
locale: function() {
|
|
||||||
return this.$i18n.locale.replace('_', '-')
|
|
||||||
},
|
|
||||||
|
|
||||||
settingsPassword: function () {
|
settingsPassword: function () {
|
||||||
return this.$store.getters.getSettingsPassword
|
return this.$store.getters.getSettingsPassword
|
||||||
},
|
},
|
||||||
|
@ -170,15 +166,39 @@ export default defineComponent({
|
||||||
return settingsSections
|
return settingsSections
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
locale: 'scrollToGeneralSettings'
|
||||||
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
if (this.settingsPassword === '') {
|
if (this.settingsPassword === '') {
|
||||||
this.unlocked = true
|
this.unlocked = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted: function () {
|
||||||
|
document.addEventListener('scroll', this.scrollCurrentSection)
|
||||||
|
},
|
||||||
|
beforeDestroy: function () {
|
||||||
|
document.removeEventListener('scroll', this.scrollCurrentSection)
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
scrollToSection(section) {
|
scrollToGeneralSettings() {
|
||||||
const sectionElement = this.$refs[section]
|
document.getElementById('general-settings')?.scrollIntoView()
|
||||||
sectionElement?.scrollIntoView()
|
},
|
||||||
|
|
||||||
|
scrollCurrentSection: function() {
|
||||||
|
const scrollY = window.scrollY + innerHeight / 4
|
||||||
|
this.settingsSectionComponents.forEach((section) => {
|
||||||
|
const sectionElement = document.getElementById(section.type)
|
||||||
|
const sectionHeight = sectionElement.offsetHeight
|
||||||
|
const sectionTop = sectionElement.offsetTop
|
||||||
|
|
||||||
|
const menuElement = document.getElementById(`${section.type}-link`)
|
||||||
|
if (scrollY > sectionTop && scrollY <= sectionTop + sectionHeight) {
|
||||||
|
menuElement.classList.add('active')
|
||||||
|
} else {
|
||||||
|
menuElement.classList.remove('active')
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
...mapActions([
|
...mapActions([
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
<div class="settingsSections">
|
<div class="settingsSections">
|
||||||
<template
|
<template
|
||||||
v-for="(settingsComponent) in settingsSectionComponents"
|
v-for="(settingsComponent) in settingsSectionComponents"
|
||||||
|
ref=""
|
||||||
>
|
>
|
||||||
<component
|
<component
|
||||||
:is="settingsComponent.type"
|
:is="settingsComponent.type"
|
||||||
:id="settingsComponent.type"
|
:id="settingsComponent.type"
|
||||||
:ref="settingsComponent.type"
|
:key="settingsComponent.type + '-component'"
|
||||||
:key="settingsComponent.type + 'component'"
|
|
||||||
class="section"
|
class="section"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue