feat: create the multiple banner/theme homepage

This commit is contained in:
Adrien Marquès 2022-08-31 15:19:07 +02:00
parent 8d542aa85f
commit 24baa3c5c4
Signed by: xdrm-brackets
GPG Key ID: D75243CA236D825E
11 changed files with 403 additions and 430 deletions

View File

@ -1,22 +1,19 @@
<template> <template>
<div id="app"> <div id="app">
<Banner/> <Home/>
<Skills/> <Skills/>
<Experiences/>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue } from 'vue-property-decorator'; import { Component, Vue } from 'vue-property-decorator';
import Banner from './components/Banner.vue'; import Home from './components/Home.vue';
import Skills from './components/Skills.vue'; import Skills from './components/Skills.vue';
import Experiences from './components/Experiences.vue';
@Component({ @Component({
components: { components: {
Banner, Home,
Skills, Skills,
Experiences,
}, },
}) })
export default class App extends Vue { export default class App extends Vue {
@ -39,6 +36,6 @@ export default class App extends Vue {
overflow: hidden; overflow: hidden;
background: #1a1a1a; background: #fff;
} }
</style> </style>

5
src/assets/tick.svg Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="4.2333mm" height="4.2333mm" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg">
<path id="a" d="m2.1173 0c-1.1611 0-2.1173 0.95625-2.1173 2.1173 0 1.1611 0.95626 2.116 2.1173 2.116s2.116-0.95493 2.116-2.116c0-1.1611-0.95493-2.1173-2.116-2.1173zm-6.4e-4 0.67548a1.4418 1.4418 0 0 1 0.0445 6.38e-4 1.4418 1.4418 0 0 1 0.0445 0.0019 1.4418 1.4418 0 0 1 0.0442 0.0034 1.4418 1.4418 0 0 1 0.0442 5e-3 1.4418 1.4418 0 0 1 0.0442 0.0062 1.4418 1.4418 0 0 1 0.0438 0.0072 1.4418 1.4418 0 0 1 0.0435 9e-3 1.4418 1.4418 0 0 1 0.0432 0.01024 1.4418 1.4418 0 0 1 0.0429 0.01152 1.4418 1.4418 0 0 1 0.0426 0.0128 1.4418 1.4418 0 0 1 0.0421 0.01408 1.4418 1.4418 0 0 1 0.0418 0.0152 1.4418 1.4418 0 0 1 0.0411 0.0168 1.4418 1.4418 0 0 1 0.0405 0.01779 1.4418 1.4418 0 0 1 0.0402 0.01944 1.4418 1.4418 0 0 1 0.0392 0.02042 1.4418 1.4418 0 0 1 0.0389 0.02141 1.4418 1.4418 0 0 1 0.0382 0.02272 1.4418 1.4418 0 0 1 0.0373 0.02403 1.4418 1.4418 0 0 1 0.037 0.02504 1.4418 1.4418 0 0 1 0.0355 0.02635 1.4418 1.4418 0 0 1 0.0352 0.02733 1.4418 1.4418 0 0 1 0.0339 0.02832 1.4418 1.4418 0 0 1 0.0336 0.02931 1.4418 1.4418 0 0 1 0.0323 0.03062 1.4418 1.4418 0 0 1 0.0314 0.03128 1.4418 1.4418 0 0 1 0.0302 0.03227 1.4418 1.4418 0 0 1 0.0296 0.03326 1.4418 1.4418 0 0 1 0.0283 0.03426 1.4418 1.4418 0 0 1 0.0274 0.03491 1.4418 1.4418 0 0 1 0.0261 0.0359 1.4418 1.4418 0 0 1 0.0254 0.03656 1.4418 1.4418 0 0 1 0.0237 0.03755 1.4418 1.4418 0 0 1 0.0227 0.03821 1.4418 1.4418 0 0 1 0.0218 0.03853 1.4418 1.4418 0 0 1 0.0203 0.03952 1.4418 1.4418 0 0 1 0.0192 0.04018 1.4418 1.4418 0 0 1 0.0181 0.04051 1.4418 1.4418 0 0 1 0.0165 0.04117 1.4418 1.4418 0 0 1 0.016 0.0415 1.4418 1.4418 0 0 1 0.0144 0.04216 1.4418 1.4418 0 0 1 0.0128 0.04248 1.4418 1.4418 0 0 1 0.0112 0.04315 1.4418 1.4418 0 0 1 0.01 0.04315 1.4418 1.4418 0 0 1 8e-3 0.04347 1.4418 1.4418 0 0 1 8e-3 0.04381 1.4418 1.4418 0 0 1 6e-3 0.04381 1.4418 1.4418 0 0 1 5e-3 0.04446 1.4418 1.4418 0 0 1 3e-3 0.04413 1.4418 1.4418 0 0 1 2e-3 0.04446 1.4418 1.4418 0 0 1 6.4e-4 0.04413 1.4418 1.4418 0 0 1-6e-3 0.13306 1.4418 1.4418 0 0 1-0.0184 0.13206 1.4418 1.4418 0 0 1-0.0304 0.12942 1.4418 1.4418 0 0 1-0.0426 0.12646 1.4418 1.4418 0 0 1-0.0536 0.12186 1.4418 1.4418 0 0 1-0.065 0.11626 1.4418 1.4418 0 0 1-0.075 0.11 1.4418 1.4418 0 0 1-0.0853 0.10243 1.4418 1.4418 0 0 1-0.0939 0.09419 1.4418 1.4418 0 0 1-0.10272 0.08498 1.4418 1.4418 0 0 1-0.1096 0.07509 1.4418 1.4418 0 0 1-0.11632 0.06488 1.4418 1.4418 0 0 1-0.12176 0.05402 1.4418 1.4418 0 0 1-0.1264 0.04216 1.4418 1.4418 0 0 1-0.12944 0.03062 1.4418 1.4418 0 0 1-0.132 0.01845 1.4418 1.4418 0 0 1-0.13312 0.0059 1.4418 1.4418 0 0 1-0.13312-0.0059 1.4418 1.4418 0 0 1-0.13168-0.01845 1.4418 1.4418 0 0 1-0.12976-0.03062 1.4418 1.4418 0 0 1-0.12608-0.04216 1.4418 1.4418 0 0 1-0.12192-0.05402 1.4418 1.4418 0 0 1-0.11632-0.06488 1.4418 1.4418 0 0 1-0.10992-0.07509 1.4418 1.4418 0 0 1-0.1024-0.08498 1.4418 1.4418 0 0 1-0.0942-0.09419 1.4418 1.4418 0 0 1-0.085-0.10243 1.4418 1.4418 0 0 1-0.0754-0.11 1.4418 1.4418 0 0 1-0.0648-0.11626 1.4418 1.4418 0 0 1-0.0536-0.12186 1.4418 1.4418 0 0 1-0.0422-0.12646 1.4418 1.4418 0 0 1-0.0307-0.12942 1.4418 1.4418 0 0 1-0.0184-0.13206 1.4418 1.4418 0 0 1-6e-3 -0.13306 1.4418 1.4418 0 0 1 6e-3 -0.13272 1.4418 1.4418 0 0 1 0.0184-0.13206 1.4418 1.4418 0 0 1 0.0307-0.12976 1.4418 1.4418 0 0 1 0.0422-0.12614 1.4418 1.4418 0 0 1 0.0536-0.12186 1.4418 1.4418 0 0 1 0.0648-0.11626 1.4418 1.4418 0 0 1 0.0754-0.11 1.4418 1.4418 0 0 1 0.085-0.10243 1.4418 1.4418 0 0 1 0.0942-0.09419 1.4418 1.4418 0 0 1 0.1024-0.08498 1.4418 1.4418 0 0 1 0.10992-0.07542 1.4418 1.4418 0 0 1 0.11632-0.06454 1.4418 1.4418 0 0 1 0.12192-0.05402 1.4418 1.4418 0 0 1 0.12608-0.04216 1.4418 1.4418 0 0 1 0.12976-0.03063 1.4418 1.4418 0 0 1 0.13168-0.01845 1.4418 1.4418 0 0 1 0.13312-0.0059z" color="#000000" fill="#f8f8f8" stroke-linecap="round" stroke-width=".63731" style="paint-order:stroke fill markers"/>
<circle id="b" cx="2.1167" cy="2.1171" r=".73799" fill="#f8f8f8" style="paint-order:stroke fill markers"/>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg width="420mm" height="20.822mm" version="1.1" viewBox="0 0 420 20.822" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <svg width="420mm" height="20.822mm" version="1.1" viewBox="0 0 420 20.822" xmlns="http://www.w3.org/2000/svg">
<defs> <defs>
<linearGradient id="a" x1="787.57" x2="787.57" y1="4.8222" y2="78.695" gradientUnits="userSpaceOnUse"> <linearGradient id="a" x1="787.57" x2="787.57" y1="4.8222" y2="78.695" gradientUnits="userSpaceOnUse">
<stop stop-color="#1a1a1a" stop-opacity=".97647" offset="0"/> <stop stop-color="#fff" stop-opacity=".97647" offset="0"/>
<stop stop-color="#1a1a1a" stop-opacity=".89804" offset=".59203"/> <stop stop-color="#fff" stop-opacity=".89804" offset=".59203"/>
<stop stop-color="#1a1a1a" offset="1"/> <stop stop-color="#fff" offset="1"/>
</linearGradient> </linearGradient>
</defs> </defs>
<g transform="translate(-.83328 -158.95)"> <g transform="translate(-.83328 -158.95)">

Before

Width:  |  Height:  |  Size: 921 B

After

Width:  |  Height:  |  Size: 869 B

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg width="420mm" height="20.822mm" version="1.1" viewBox="0 0 420 20.822" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <svg width="420mm" height="20.822mm" version="1.1" viewBox="0 0 420 20.822" xmlns="http://www.w3.org/2000/svg">
<defs> <defs>
<linearGradient id="a" x1="775" x2="775" y1="78.695" y2="-.00018898" gradientUnits="userSpaceOnUse"> <linearGradient id="a" x1="775" x2="775" y1="78.695" y2="-.00018898" gradientUnits="userSpaceOnUse">
<stop stop-color="#1a1a1a" stop-opacity=".25098" offset="0"/> <stop stop-color="#fff" stop-opacity=".25098" offset="0"/>
<stop stop-color="#1a1a1a" stop-opacity=".14902" offset=".22879"/> <stop stop-color="#fff" stop-opacity=".14902" offset=".22879"/>
<stop stop-color="#1a1a1a" stop-opacity=".05098" offset="1"/> <stop stop-color="#fff" stop-opacity=".05098" offset="1"/>
</linearGradient> </linearGradient>
</defs> </defs>
<g transform="translate(-.83328 -158.95)"> <g transform="translate(-.83328 -158.95)">

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1019 B

View File

@ -1,310 +0,0 @@
<template>
<div id='banner'>
<div class='wave'></div>
<div class='wave w2'></div>
<div class='border-card'></div>
<div class='content'>
<h3>Hello, I'm</h3>
<h1 class='name'>
{{ model.firstname.toUpperCase() }}
{{ model.lastname.toUpperCase() }}
</h1>
<h2 class='headline'>{{ model.headline.toUpperCase() }}</h2>
<form class='themes'>
<input type='radio' name='theme' id='bw' checked/>
<label for='bw'>
<div class='spacer'>
<div class='tick'></div>
</div>
</label>
<input type='radio' name='theme' id='gooey'/>
<label for='gooey'>
<div class='spacer'>
<div class='tick'></div>
</div>
</label>
<input type='radio' name='theme' id='flat'/>
<label for='flat'>
<div class='spacer'>
<div class='tick'></div>
</div>
</label>
<input type='radio' name='theme' id='glass'/>
<label for='glass'>
<div class='spacer'>
<div class='tick'></div>
</div>
</label>
</form>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import BannerModel from '../model/banner';
@Component({})
export default class Banner extends Vue {
private model: any = BannerModel;
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
@import '../global.scss';
$banner-size: 100vh;
$wave-height: 6.3rem;
$bg-color: #f8f8f8;
$themes-spacing: 2rem;
// horizontal spacing between theme chips
$theme-chip-spacing: 1rem;
// full size of a theme chip
$theme-chip-size: 1.8rem;
// empty space inside the chip (relative to the chip size)
$theme-chip-void: 1.2rem;
// size of the inner (checked) circle (relative to the chip void)
$theme-chip-inner: .6rem;
// MEDIA QUERIES
// optimize vertical space
$mq-vert: 590px;
#banner {
flex: #{$banner-size * 0.999} 0 0;
display: flex;
position: relative;
top: 0;
left: 0;
width: 100%;
flex-flow: row wrap;
justify-content: flex-start;
align-items: center;
color: #3d3d3d;
font-size: 1rem;
font-family: 'Source Sans Pro';
font-weight: 400;
white-space: nowrap;
background: $bg-color;
}
@keyframes wave-x {
from{ background-position-x: 1px; }
to{ background-position-x: 100vw; }
}
.wave {
display: block;
position: absolute;
top: calc( #{$banner-size} - #{$wave-height} );
left: 0;
width: 100vw;
height: $wave-height;
background-image: url('../assets/wave.invert.1.svg');
background-repeat: repeat-x;
background-position-y: 101%;
background-size: auto 100%;
animation: 18s ease-in-out wave-x infinite alternate;
&.w2{
background-image: url('../assets/wave.invert.2.svg');
animation: 20s ease-in-out wave-x infinite alternate-reverse;
}
}
.border-card {
display: block;
position: absolute;
top: -20vw;
left: 70vw;
width: 60vw;
height: 60vw;
background: #1a1a1a;
border-radius: 3rem;
transform: rotate(35deg);
}
.content {
flex: auto 0 1;
display: flex;
position: relative;
flex-flow: column nowrap;
margin: 0 10rem;
margin-bottom: $wave-height;
h1 {
font-size: 4em;
font-weight: 700;
}
h2 {
font-size: 2.2em;
font-weight: 400;
}
h3 {
font-size: 2em;
font-weight: 400;
}
.name {
display: inline-block;
}
}
.themes {
display: flex;
position: relative;
flex-flow: row wrap;
justify-content: flex-start;
align-items: center;
margin-top: 1em;
input[type=radio]{
display: none;
}
& > label {
display: flex;
position: relative;
width: $theme-chip-size;
height: $theme-chip-size;
justify-content: center;
align-items: center;
margin: 0 #{$theme-chip-spacing};
background: transparent;
border-radius: 50% / 50%;
cursor: pointer;
transition: transform .2s ease-in;
// hide the center to make a ring
.spacer {
display: flex;
position: relative;
width: $theme-chip-void;
height: $theme-chip-void;
justify-content: center;
align-items: center;
background: $bg-color;
border-radius: 50% / 50%;
}
.tick {
opacity: 0;
display: block;
position: relative;
width: $theme-chip-inner;
height: $theme-chip-inner;
background: transparent;
border-radius: 50% / 50%;
transition: opacity .1s ease-in-out;
}
}
label:nth-child(2) { margin-left: 0; }
label:last-child { margin-right: 0; }
input:checked + label .tick {
opacity: 1;
}
input#bw + label {
background: #3d3d3d;
.tick{
background: #3d3d3d;
}
}
input#gooey + label {
background: linear-gradient(#7936dc, #bd8eff);
.tick{
background: linear-gradient(#7936dc, #bd8eff);
}
}
input#flat + label {
background: #3d3d3d;
.tick{
background: #3d3d3d;
}
}
input#glass + label {
background: #3d3d3d;
.tick{
background: #3d3d3d;
}
}
}
// not enough vertical space
@media screen and (max-height: 615px){
#banner {
align-items: flex-start;
.content {
margin-top: 2rem;
}
}
}
// not enough horizontal space
@media screen and (max-width: 740px){
#banner {
font-size: 2vw;
align-items: center;
justify-content: center;
.content {
margin: 0 2rem;
}
}
}
// not enough vertical space
@media screen and (max-height: 615px){
#banner {
font-size: 1vw;
}
}
// border-card overlaps with the text
@media screen and (max-width: 1010px){
.border-card {
left: 80vw;
}
}
</style>

142
src/components/Banner1.vue Normal file
View File

@ -0,0 +1,142 @@
<template>
<div id='banner1'>
<div class='border-card'></div>
<div class='content'>
<h3>Hello, I'm</h3>
<h1 class='name'>
{{ model.firstname.toUpperCase() }}
{{ model.lastname.toUpperCase() }}
</h1>
<h2 class='headline'>{{ model.headline.toUpperCase() }}</h2>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import BannerModel from '../model/banner';
@Component({})
export default class Banner1 extends Vue {
private model: any = BannerModel;
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
@import '../global.scss';
$banner-size: 100vh;
$bg-color: #ededed;
// MEDIA QUERIES
// optimize vertical space
$mq-vert: 590px;
#banner1 {
flex: #{$banner-size * 0.999} 0 0;
display: flex;
position: relative;
top: 0;
left: 0;
width: 100%;
height: 100%;
flex-flow: row wrap;
justify-content: flex-start;
align-items: center;
color: #3d3d3d;
font-size: 1rem;
font-family: 'Source Sans Pro';
font-weight: 400;
white-space: nowrap;
background: $bg-color;
}
.border-card {
display: block;
position: absolute;
top: -20vw;
left: 70vw;
width: 60vw;
height: 60vw;
background: linear-gradient(45deg, #1a1a1a, #292929);
border-radius: 3rem;
transform: rotate(35deg);
}
.content {
flex: auto 0 1;
display: flex;
position: relative;
flex-flow: column nowrap;
margin: 0 10rem;
margin-bottom: 6rem;
h1 {
font-size: 4em;
font-weight: 700;
}
h2 {
font-size: 2.2em;
font-weight: 400;
}
h3 {
font-size: 2em;
font-weight: 400;
}
.name {
display: inline-block;
}
}
// not enough vertical space
@media screen and (max-height: 615px){
#banner1 {
align-items: flex-start;
.content {
margin-top: 2rem;
}
}
}
// not enough horizontal space
@media screen and (max-width: 740px){
#banner1 {
font-size: 2vw;
align-items: center;
justify-content: center;
.content {
margin: 0 2rem;
}
}
}
// not enough vertical space
@media screen and (max-height: 615px){
#banner1 {
font-size: 1vw;
}
}
// border-card overlaps with the text
@media screen and (max-width: 1010px){
.border-card {
left: 80vw;
}
}
</style>

View File

@ -1,87 +0,0 @@
<template>
<div id='experiences'>
<div class='experience' v-for='(experience, si) of experiences' :key='si'>
<h2>{{ experience.title.toUpperCase() }}</h2>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import ExperiencesModel from '../model/experiences';
@Component
export default class Experiences extends Vue {
private experiences = ExperiencesModel;
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
@import '../global';
$timeline-width: .25rem;
$timeline-dot-size: 1rem;
$timeline-spacing: 1rem;
#experiences {
flex: auto 0 1;
display: flex;
position: relative;
margin: 0 5%;
margin-top: 3em;
flex-flow: row wrap;
justify-content: space-between;
align-items: flex-start;
// timeline
&:before {
content: '';
position: absolute;
display: block;
width: $timeline-width;
height: 100%;
border-radius: #{$timeline-width} / #{$timeline-width};
background: #07142d;
}
.experience {
display: inline-block;
position: relative;
width: 100%;
margin-left: $timeline-spacing;
border: 1px solid red;
h2 {
font-size: 1.3em;
font-weight: normal;
&:before {
content: '';
position: absolute;
display: block;
top: calc( 1em - #{$timeline-dot-size});
left: calc( #{-$timeline-spacing} - #{$timeline-dot-size} / 2 + #{$timeline-width} / 5 );
width: $timeline-dot-size;
height: $timeline-dot-size;
border-radius: 50% / 50%;
border: 2px solid white;
background: #07142d;
}
}
}
}
</style>

222
src/components/Home.vue Normal file
View File

@ -0,0 +1,222 @@
<template>
<div id='home'>
<div class='wave'></div>
<div class='wave w2'></div>
<div id='banner-container'>
<Banner1 v-if='theme == `black_white`' />
<Banner2 v-if='theme == `blue`' />
<Banner2 v-if='theme == `orange`' />
</div>
<form class='themes' @change="onThemeSelected" ref='theme_form'>
<h2>THEMES</h2>
<template v-for='t in themes'>
<input :key='`${t.name}-input`' type='radio' name='theme' :id='t.name' :value='t.name' :checked='t.default'/>
<label :key='`${t.name}-label`' :for='t.name'>
<svg width="16" height="16" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id='blue-gradient'>
<stop offset='0' style='stop-color: var(--color0); stop-opacity: 1'/>
<stop offset='1' style='stop-color: var(--color1); stop-opacity: 1'/>
</linearGradient>
<linearGradient id='orange-gradient'>
<stop offset='0' style='stop-color: var(--color0); stop-opacity: 1'/>
<stop offset='1' style='stop-color: var(--color1); stop-opacity: 1'/>
</linearGradient>
<linearGradient id='green-gradient'>
<stop offset='0' style='stop-color: var(--color0); stop-opacity: 1'/>
<stop offset='1' style='stop-color: var(--color1); stop-opacity: 1'/>
</linearGradient>
</defs>
<g transform="translate(-157.14 -77.615)">
<g transform="matrix(0 -.11388 -.11388 0 185.25 96.78)" stroke="#1a1a1a" stroke-width="11.855">
<path d="m168.29 228.24c0 10.195-8.3886 18.587-18.585 18.587s-18.59-8.3921-18.59-18.587c0-10.195 8.3931-18.587 18.59-18.587s18.585 8.3921 18.585 18.587zm-5.9273 0c0-6.9441-5.7129-12.661-12.658-12.661s-12.662 5.7168-12.662 12.661c0 6.9441 5.7175 12.661 12.662 12.661s12.658-5.7168 12.658-12.661z" color="#000000" fill="#1a1a1a" stroke="none" style="paint-order:stroke fill markers"/>
<circle cx="149.71" cy="228.24" r="6.4803" fill="#1a1a1a" stroke="none" style="paint-order:stroke fill markers"/>
</g>
</g>
</svg>
</label>
</template>
</form>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { Themes, Theme } from '@/model/themes';
import Banner1 from '@/components/Banner1.vue';
@Component({
components: {
Banner1,
},
})
export default class Home extends Vue {
private themes: Theme[] = Themes;
private theme: string = Themes[0].name;
private onThemeSelected() {
const fd = new FormData(this.$refs.theme_form as HTMLFormElement);
console.log(fd);
this.theme = fd.get('theme') as string;
console.log(this.theme);
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
$width: 100vw;
$height: 100vh;
$wave-height: 6.3rem;
// horizontal spacing between theme chips
$theme-chip-spacing: 1rem;
// full size of a theme chip
$theme-chip-size: 1.8rem;
// empty space inside the chip (relative to the chip size)
$theme-chip-void: 1.2rem;
// size of the inner (checked) circle (relative to the chip void)
$theme-chip-inner: .6rem;
#home {
position: relative;
top: 0;
left: 0;
width: $width;
height: $height;
background: #ededed;
}
@keyframes wave-x {
from{ background-position-x: 1px; }
to{ background-position-x: 100vw; }
}
.wave {
display: block;
position: absolute;
top: calc( #{$height*1.001} - #{$wave-height} );
left: 0;
width: 100vw;
height: $wave-height;
background-image: url('../assets/wave.invert.1.svg');
background-repeat: repeat-x;
background-position-y: 101%;
background-size: auto 100%;
animation: 18s ease-in-out wave-x infinite alternate;
&.w2{
background-image: url('../assets/wave.invert.2.svg');
animation: 20s ease-in-out wave-x infinite alternate-reverse;
}
z-index: 900;
}
.themes {
display: flex;
position: relative;
top: calc( #{$height} - #{$wave-height} );
width: $width;
flex-flow: row wrap;
justify-content: center;
align-items: center;
transform: translateY(-100%);
input[type=radio]{
display: none;
}
h2 {
flex: 100%;
text-align: center;
margin-bottom: 1rem;
}
& > label {
display: flex;
position: relative;
width: $theme-chip-size;
height: $theme-chip-size;
justify-content: center;
align-items: center;
margin: 0 #{$theme-chip-spacing};
cursor: pointer;
transition: transform .2s ease-in;
svg {
width: 100%;
height: 100%;
}
svg circle {
opacity: 0;
transition: opacity .1s ease-in-out;
}
}
label:nth-child(2) { margin-left: 0; }
label:last-child { margin-right: 0; }
input:checked + label svg circle {
opacity: 1;
}
// define our custom svg gradients
#blue-gradient {
--color0: #3d4ba3;
--color1: #5768f8;
}
#orange-gradient {
--color0: #fcb67b;
--color1: #c54556;
}
#green-gradient {
--color0: #00d89f;
--color1: #00a2d8;
}
input[value='black_white'] + label {
circle, path{ fill: #1a1a1a; }
}
input[value='blue'] + label {
circle, path{ fill: url(#blue-gradient); }
}
input[value='forest'] + label {
circle, path{ fill: url(#orange-gradient); }
}
input[value='glass'] + label {
circle, path{ fill: url(#green-gradient); }
}
z-index: 1000;
}
#banner-container {
position: absolute;
top: 0;
left: 0;
width: $width;
height: $height;
}
</style>

View File

@ -13,8 +13,8 @@
<div class='stack'> <div class='stack'>
<template v-for='(skill,i) of skillset.skills'> <template v-for='(skill,i) of skillset.skills'>
<a class='label' :key='i' :href='skill.link' v-html='skill.label'></a> <a class='label' :key='`${i}-link`' :href='skill.link' v-html='skill.label'></a>
<span class='level' :key='i'> <span class='level' :key='`${i}-span`'>
<span :style='{ width: (skill.level*100)+"%" }'></span> <span :style='{ width: (skill.level*100)+"%" }'></span>
</span> </span>
</template> </template>

View File

@ -1,16 +0,0 @@
export default [
{
title: 'LogAuth',
link: `https://git.xdrm.io/logauth`,
when: [ '2014', '2018' ],
description: `Système de régulation évolutif pour système embarqués avec plateforme de gestion`,
tags: [ `php`, `js`, `python`, `raspberry`, `rest`, `electronics`, `systemd`, `linux` ],
},
{
title: 'LogAuth 2',
link: `https://git.xdrm.io/logauth`,
when: [ '2015', '2018' ],
description: `Système de régulation évolutif pour système embarqués avec plateforme de gestion`,
tags: [ `php`, `js`, `python`, `raspberry`, `rest`, `electronics`, `systemd`, `linux` ],
},
];

20
src/model/themes.ts Normal file
View File

@ -0,0 +1,20 @@
export interface Theme {
name: string;
default: boolean;
}
export const Themes: Theme[] = [
{
name: 'black_white',
default: true,
}, {
name: 'blue',
default: false,
}, {
name: 'forest',
default: false,
}, {
name: 'glass',
default: false,
},
];