Frontend: Fixing major issues with the sidebar when on large screens. Optimised the code to use less scrollY.

This commit is contained in:
Yohan Boujon 2024-01-30 22:48:10 +01:00
parent 06188f1faa
commit e9563e6a5d
2 changed files with 178 additions and 153 deletions

View file

@ -9,14 +9,12 @@
.sidebar { .sidebar {
position: absolute; position: absolute;
width: 15rem; width: 15rem;
height: 75rem;
background-color: var(--color-special);
transition: all 0s ease 0s; transition: all 0s ease 0s;
margin-left: 1rem;
} }
.fake-sidebar { .fake-sidebar {
width: 100%; width: 20rem;
flex-basis: 20rem;
box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px; box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px;
background-color: var(--color-special); background-color: var(--color-special);
} }

View file

@ -1,162 +1,189 @@
<script> <script>
import SvgIcon from "@jamescoyle/svelte-icon"; import SvgIcon from "@jamescoyle/svelte-icon";
import { processData } from "$lib/js/processdata.js"; import { processData } from "$lib/js/processdata.js";
import { formatDate } from "$lib/js/date.js"; import { formatDate } from "$lib/js/date.js";
import "$lib/css/base.css"; import "$lib/css/base.css";
import "$lib/css/cv.css"; import "$lib/css/cv.css";
// Sidebar // Sidebar
import SidebarComponent from "$lib/components/sidebar-component.svelte"; import SidebarComponent from "$lib/components/sidebar-component.svelte";
import { import {
mdiAccount, mdiAccount,
mdiCogs, mdiCogs,
mdiEmailOutline, mdiEmailOutline,
mdiPhone, mdiPhone,
mdiStar, mdiStar,
mdiXml, mdiXml,
mdiApplication, mdiApplication,
mdiEarth, mdiEarth,
mdiHeart mdiHeart,
} from "@mdi/js"; } from "@mdi/js";
// Main // Main
import Section from "$lib/components/section.svelte"; import Section from "$lib/components/section.svelte";
import SubSection from "$lib/components/subsection.svelte"; import SubSection from "$lib/components/subsection.svelte";
import Education from "$lib/components/education.svelte"; import Education from "$lib/components/education.svelte";
import Experience from "$lib/components/experience.svelte"; import Experience from "$lib/components/experience.svelte";
import Projects from "$lib/components/projects.svelte" import Projects from "$lib/components/projects.svelte";
import SlideShow from "$lib/components/slideshow.svelte"; import SlideShow from "$lib/components/slideshow.svelte";
import Pill from "$lib/components/pill.svelte" import Pill from "$lib/components/pill.svelte";
import FlagComponent from "$lib/components/flag-component.svelte" import FlagComponent from "$lib/components/flag-component.svelte";
import ProjectsPopup from "$lib/components/projects-popup.svelte" import ProjectsPopup from "$lib/components/projects-popup.svelte";
import { mdiSchool, mdiBriefcase, mdiWrench, mdiPencil } from "@mdi/js"; import { mdiSchool, mdiBriefcase, mdiWrench, mdiPencil } from "@mdi/js";
import { onMount } from "svelte"; import { onMount } from "svelte";
export let data; export let data;
const cv = data.status == 0 ? processData(data) : undefined; const cv = data.status == 0 ? processData(data) : undefined;
const birth_year = const birth_year =
data.status == 0 ? formatDate(cv.info.birth_year) : undefined; data.status == 0 ? formatDate(cv.info.birth_year) : undefined;
// Sidebar sticky // Sidebar sticky
let sidebar; let sidebar;
let footer; let containerCv;
let moving_position = 0; let footer;
$: scrollY = 0; $: scrollY = 0;
$: innerHeight = 0; $: innerHeight = 0;
onMount(() => { onMount(() => {
sidebarScrollingHandler(); sidebarScrollingHandler();
}); });
function sidebarScrollingHandler() { function sidebarScrollingHandler() {
let isBottom = (scrollY+innerHeight >= footer.offsetTop); let isBottom = scrollY + innerHeight >= footer.offsetTop;
// Testing if sidebar is outside of scrolling scope let isMoved = scrollY + innerHeight >= sidebar.offsetHeight;
if(scrollY+innerHeight >= sidebar.offsetHeight && !isBottom) { let littleScreen = innerHeight < sidebar.offsetHeight;
sidebar.style.position = 'fixed'; console.log(littleScreen);
sidebar.style.top = `-${sidebar.offsetHeight-innerHeight}px`; // Only having the sticky sidebar if the size of the screen is too 'little'
moving_position = scrollY;
}
else if(isBottom) {
sidebar.style.position = 'absolute';
sidebar.style.top = `${moving_position-(sidebar.offsetHeight-innerHeight)}px`;
}
else {
sidebar.style.position = 'absolute';
sidebar.style.top = '';
}
}
// Mobile check // Testing if sidebar is outside of scrolling scope
$: innerWidth = 0; if (isMoved && !isBottom) {
function mobileCheck() { sidebar.style.position = "fixed";
//console.log(innerWidth); sidebar.style.top = littleScreen
} ? `${innerHeight - sidebar.offsetHeight}px`
: "0px";
}
// Checking if at the bottom, calculating the diff. between the cv and the sidebar heights
else if (isBottom && littleScreen) {
sidebar.style.position = "absolute";
sidebar.style.top = `${
containerCv.offsetHeight - sidebar.offsetHeight
}px`;
}
// Only putting absolute if on little screen
else if (littleScreen) {
sidebar.style.position = "absolute";
sidebar.style.top = "";
}
}
// Mobile check
$: innerWidth = 0;
function mobileCheck() {
//console.log(innerWidth);
}
</script> </script>
<svelte:window bind:scrollY bind:innerHeight bind:innerWidth on:scroll={sidebarScrollingHandler} on:resize={mobileCheck} /> <svelte:window
bind:scrollY
bind:innerHeight
bind:innerWidth
on:scroll={sidebarScrollingHandler}
on:resize={mobileCheck}
/>
{#if data.status == 0} {#if data.status == 0}
<ProjectsPopup tags={cv.tags} /> <ProjectsPopup tags={cv.tags} />
<div class="container-cv"> <div class="container-cv" bind:this={containerCv}>
<!-- SIDEBAR DIV (LEFT) --> <!-- SIDEBAR DIV (LEFT) -->
<div class="sidebar" bind:this={sidebar}> <div class="sidebar" bind:this={sidebar}>
<div class="profile-picture-container"> <div class="profile-picture-container">
<img <img
class="profile-picture" class="profile-picture"
src={cv.info.profile_pic} src={cv.info.profile_pic}
alt={cv.info.full_name} alt={cv.info.full_name}
/> />
</div> </div>
<SidebarComponent icon={mdiAccount} description={birth_year} /> <SidebarComponent icon={mdiAccount} description={birth_year} />
<SidebarComponent <SidebarComponent icon={mdiEmailOutline} description={cv.info.email} />
icon={mdiEmailOutline} {#if cv.info.phone_number != null}
description={cv.info.email} <SidebarComponent icon={mdiPhone} description={cv.info.phone_number} />
/> {/if}
{#if cv.info.phone_number != null} <SidebarComponent
<SidebarComponent icon={mdiStar}
icon={mdiPhone} title="Interests"
description={cv.info.phone_number} description={cv.info.interests}
/> />
{/if} <SidebarComponent
<SidebarComponent icon={mdiCogs}
icon={mdiStar} title="Soft-Skills"
title="Interests" description={cv.info.softskills}
description={cv.info.interests} />
/> </div>
<SidebarComponent <div class="fake-sidebar" />
icon={mdiCogs} <!-- MAIN DIV (RIGHT) -->
title="Soft-Skills" <div class="main">
description={cv.info.softskills} <h1 class="name">{cv.info.full_name}</h1>
/> <h2 class="name">Apprentice Engineer Automatic/Electronic</h2>
</div> <Section icon={mdiSchool} title="Education" />
<div class="fake-sidebar" /> <SlideShow
<!-- MAIN DIV (RIGHT) --> data={cv.education}
<div class="main"> type={Education}
<h1 class="name">{cv.info.full_name}</h1> timeline="true"
<h2 class="name">Apprentice Engineer Automatic/Electronic</h2> reverse="true"
<Section icon={mdiSchool} title="Education" /> />
<SlideShow <Section icon={mdiBriefcase} title="Experience" />
data={cv.education} <SlideShow
type={Education} data={cv.experiences}
timeline="true" type={Experience}
reverse="true" timeline="true"
/> reverse="true"
<Section icon={mdiBriefcase} title="Experience" /> />
<SlideShow <Section icon={mdiWrench} title="Projects" />
data={cv.experiences} <SlideShow data={cv.skills.project} type={Projects} />
type={Experience} <Section icon={mdiPencil} title="Skills" />
timeline="true" <SubSection icon={mdiXml} title="Programming Languages" />
reverse="true" <div class="subsection">
/> {#each cv.skills.programming_languages as pilldata, index (index)}
<Section icon={mdiWrench} title="Projects" /> <Pill
<SlideShow name={pilldata.lang}
data={cv.skills.project} type_icon={pilldata.type_icon}
type={Projects} icon={pilldata.icon}
/> color={pilldata.color}
<Section icon={mdiPencil} title="Skills" /> show_tooltip={true}
<SubSection icon={mdiXml} title="Programming Languages"/> tooltip_data={cv.project_programming[index]}
<div class="subsection"> />
{#each cv.skills.programming_languages as pilldata, index (index)} {/each}
<Pill name={pilldata.lang} type_icon={pilldata.type_icon} icon={pilldata.icon} color={pilldata.color} show_tooltip={true} tooltip_data={cv.project_programming[index]}/> </div>
{/each} <SubSection icon={mdiApplication} title="Software" />
</div> <div class="subsection">
<SubSection icon={mdiApplication} title="Software"/> {#each cv.skills.softwares as pilldata, index (index)}
<div class="subsection"> <Pill
{#each cv.skills.softwares as pilldata, index (index)} name={pilldata.software}
<Pill name={pilldata.software} type_icon={pilldata.type_icon} icon={pilldata.icon} color={pilldata.color} show_tooltip={true} tooltip_data={cv.project_software[index]}/> type_icon={pilldata.type_icon}
{/each} icon={pilldata.icon}
</div> color={pilldata.color}
<SubSection icon={mdiEarth} title="Languages"/> show_tooltip={true}
<div class="subsection flag-container end"> tooltip_data={cv.project_software[index]}
{#each cv.skills.languages as langdata} />
<FlagComponent lang={langdata.lang} level={langdata.level} icon={langdata.icon_alpha}/> {/each}
{/each} </div>
</div> <SubSection icon={mdiEarth} title="Languages" />
</div> <div class="subsection flag-container end">
</div> {#each cv.skills.languages as langdata}
<div class="footer" bind:this={footer}> <FlagComponent
<p>Made with <SvgIcon size="20" path={mdiHeart} type="mdi"/> using Svelte</p> lang={langdata.lang}
<p>All rights reserved, Yohan Boujon • {new Date().getFullYear()}</p> level={langdata.level}
</div> icon={langdata.icon_alpha}
/>
{/each}
</div>
</div>
</div>
<div class="footer" bind:this={footer}>
<p>
Made with <SvgIcon size="20" path={mdiHeart} type="mdi" /> using Svelte
</p>
<p>All rights reserved, Yohan Boujon • {new Date().getFullYear()}</p>
</div>
{:else} {:else}
<h1 class="h1 text-center">Oops, could not load database :/</h1> <h1 class="h1 text-center">Oops, could not load database :/</h1>
{/if} {/if}