mirror of
https://github.com/FreeTubeApp/FreeTube
synced 2024-11-10 21:00:29 +01:00
Implement dynamic scroll-based underlining of active section
This commit is contained in:
parent
f4d8648607
commit
8135ff2dd0
@ -2,11 +2,10 @@
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
gap: 5px;
|
||||
gap: 2px;
|
||||
font-size: 22px;
|
||||
inline-size: fit-content;
|
||||
max-inline-size: 250px;
|
||||
inline-size: 250px;
|
||||
padding-inline-start: 10px;
|
||||
}
|
||||
|
||||
.header {
|
||||
@ -26,9 +25,29 @@
|
||||
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 {
|
||||
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 {
|
||||
|
@ -7,15 +7,21 @@
|
||||
</h2>
|
||||
<a
|
||||
v-for="(settingsSection) in settingsSections"
|
||||
:key="settingsSection.type + 'link'"
|
||||
:id="settingsSection.type + '-link'"
|
||||
:key="settingsSection.type + '-link'"
|
||||
:href="'#' + settingsSection.type"
|
||||
class="settingsMenuTitle"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="['fas', settingsSection.icon]"
|
||||
class="settingsMenuTitleIcon"
|
||||
/>
|
||||
{{ getTitleForSection(settingsSection) }}
|
||||
<div class="settingsMenuTitleContent">
|
||||
<div class="settingsMenuTitleAndIcon">
|
||||
<font-awesome-icon
|
||||
:icon="['fas', settingsSection.icon]"
|
||||
class="settingsMenuTitleIcon"
|
||||
/>
|
||||
{{ getTitleForSection(settingsSection) }}
|
||||
</div>
|
||||
<div class="settingsMenuTitleUnderline" />
|
||||
</div>
|
||||
</a>
|
||||
</menu>
|
||||
</template>
|
||||
|
@ -7,25 +7,42 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
max-inline-size: 80%;
|
||||
}
|
||||
|
||||
.settingsSections {
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.switchRow {
|
||||
display: flex;
|
||||
.settingsSections:last-child {
|
||||
margin-block-end: calc(76vh - 150px)
|
||||
}
|
||||
|
||||
/* .settingsSections {
|
||||
|
||||
} */
|
||||
.switchRow {
|
||||
display: flex;
|
||||
margin-inline-end: auto;
|
||||
}
|
||||
|
||||
.settingsToggle {
|
||||
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 {
|
||||
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: {
|
||||
locale: function() {
|
||||
return this.$i18n.locale.replace('_', '-')
|
||||
},
|
||||
|
||||
settingsPassword: function () {
|
||||
return this.$store.getters.getSettingsPassword
|
||||
},
|
||||
@ -170,15 +166,39 @@ export default defineComponent({
|
||||
return settingsSections
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
locale: 'scrollToGeneralSettings'
|
||||
},
|
||||
created: function () {
|
||||
if (this.settingsPassword === '') {
|
||||
this.unlocked = true
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
document.addEventListener('scroll', this.scrollCurrentSection)
|
||||
},
|
||||
beforeDestroy: function () {
|
||||
document.removeEventListener('scroll', this.scrollCurrentSection)
|
||||
},
|
||||
methods: {
|
||||
scrollToSection(section) {
|
||||
const sectionElement = this.$refs[section]
|
||||
sectionElement?.scrollIntoView()
|
||||
scrollToGeneralSettings() {
|
||||
document.getElementById('general-settings')?.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([
|
||||
|
@ -5,29 +5,29 @@
|
||||
:settings-sections="settingsSectionComponents"
|
||||
/>
|
||||
<div class="settingsContent">
|
||||
<div class="switchRow">
|
||||
<ft-toggle-switch
|
||||
class="settingsToggle"
|
||||
:label="$t('Settings.Sort Settings Sections (A-Z)')"
|
||||
:default-value="settingsSectionSortEnabled"
|
||||
:compact="false"
|
||||
@change="updateSettingsSectionSortEnabled"
|
||||
/>
|
||||
</div>
|
||||
<div class="settingsSections">
|
||||
<template
|
||||
v-for="(settingsComponent) in settingsSectionComponents"
|
||||
>
|
||||
<component
|
||||
:is="settingsComponent.type"
|
||||
:id="settingsComponent.type"
|
||||
:ref="settingsComponent.type"
|
||||
:key="settingsComponent.type + 'component'"
|
||||
class="section"
|
||||
<div class="switchRow">
|
||||
<ft-toggle-switch
|
||||
class="settingsToggle"
|
||||
:label="$t('Settings.Sort Settings Sections (A-Z)')"
|
||||
:default-value="settingsSectionSortEnabled"
|
||||
:compact="false"
|
||||
@change="updateSettingsSectionSortEnabled"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
<div class="settingsSections">
|
||||
<template
|
||||
v-for="(settingsComponent) in settingsSectionComponents"
|
||||
ref=""
|
||||
>
|
||||
<component
|
||||
:is="settingsComponent.type"
|
||||
:id="settingsComponent.type"
|
||||
:key="settingsComponent.type + '-component'"
|
||||
class="section"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<password-dialog
|
||||
v-else
|
||||
|
Loading…
Reference in New Issue
Block a user