refactored grid with flex, displayed footer tabs, diplay results, toggle results display

This commit is contained in:
2019-09-22 18:23:40 +02:00
parent c9e7a335c1
commit 63f3c6409f
9 changed files with 350 additions and 45 deletions
+146 -12
View File
@@ -1,7 +1,7 @@
@import './base/reset';
@import './base/variables';
@import './base/colors';
@import './base/grid';
@import './base/grid-flex';
@import './base/layout';
@import './base/fonts';
@@ -10,6 +10,9 @@ body{
color: #1a1a1a;
}
#root{
}
header[role="banner"]{
div.wrapper{
display: grid;
@@ -53,14 +56,67 @@ section[role="main-content"]{
}
footer[role="tools"]{
#history{
// color: #1a1a1a;
background-color: $or;
padding:1.2em $side-padding;
}
#results{
// color: #1a1a1a;
background-color: $gris;
max-height: 50vh;
padding:1.2em $side-padding;
section.col-1{
.results-count{
font-size: 0.756em;
}
}
.results-list{
overflow-x: hidden;
.wrapper{
height:100%;
overflow-y: auto;
width:calc(100% + 1em);
padding-right: 1em;
>ul{
padding:0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
}
li.result{
flex-basis: percentage(2/$default_sum);
height: 5.3em;
overflow: hidden;
margin-bottom: 1em;
padding-right: 0.7em;
box-sizing: border-box;
}
article.result.item{
header{
h1{
font-size: 0.882em;
font-weight: normal;
margin:0 0 0.5em 0;
}
}
.extract{
p{
font-size: 0.882em;
margin:0;
}
code{
background-color: lighten(desaturate($rouge,20%), 20%);
}
}
}
}
}
#footer-bottom{
padding:0 $side-padding;
background-color: $bleuroi;
&>*{
// disable grid gap
padding-right: 0;
}
#footer-tabs{
ul{
padding:0; margin:0;
@@ -68,21 +124,25 @@ footer[role="tools"]{
flex-direction: column;
li{
flex: 1 1 auto;
box-sizing: border-box;
padding:0.3em;
margin:0;
line-height: 0.6em;
height:2em;
&.history{
.wrapper{
box-sizing: border-box;
line-height: 0.6em;
height:2em;
width: calc(100% + $side-padding);
margin-left:-$side-padding;
padding:0.3em 0.5em 0.3em $side-padding;
}
&.history .wrapper{
background-color: $or;
}
&.results{
&.results .wrapper{
background-color: $gris;
}
span{
font-size: 0.693em;
font-weight: 400;
text-transform: uppercase;
cursor: pointer;
}
}
}
@@ -90,8 +150,38 @@ footer[role="tools"]{
#search{
color: #fff;
background-color: $bleuroi;
label[for="keys"]{
display: none;
form{
padding: 0.7em;
label[for="keys"]{
display: none;
}
input[type="text"]{
padding:0.3em;
font-size: 0.756em;
line-height: 1;
height:1em;
border:none;
border-radius: 2px;
}
// input[type="submit"]{
// #submit-search{
// border:none;
//
// }
// }
span.mdi{
display: inline-block;
font-size: 1.2em;
line-height:1.1;
vertical-align:middle;
width:1.2em; height:1.2em;
border-radius: 0.6em;
background-color: #fff;
color: $bleuroi;
text-align: center;
font-weight: 700;
cursor: pointer;
}
}
}
}
@@ -100,5 +190,49 @@ footer[role="tools"]{
font-size: 0.756em;
font-weight: 400;
text-transform: uppercase;
padding:0;
}
}
// ___
// |_ _|__ ___ _ _ ___
// | |/ _/ _ \ ' \(_-<
// |___\__\___/_||_/__/
span.mdi-close{
cursor: pointer;
}
@keyframes spin {
from {
transform:rotate(0deg);
}
to {
transform:rotate(360deg);
}
}
span.mdi-loading{
animation-name: spin;
animation-duration: 2000ms;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
// _ _ _ _
// | |_ _ _ __ _ _ _ __(_) |_(_)___ _ _ ___
// | _| '_/ _` | ' \(_-< | _| / _ \ ' \(_-<
// \__|_| \__,_|_||_/__/_|\__|_\___/_||_/__/
.fade-roll-enter-active{
transition: all .3s ease-in-out;
}
.fade-roll-leave-active{
transition: all .8s ease;
}
.fade-roll-enter, .fade-roll-leave-to{
opacity:0;
// height:1px;
}
+86
View File
@@ -0,0 +1,86 @@
// http://www.thesassway.com/intermediate/simple-grid-mixins
@mixin row() {
display:flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: stretch;
// &:after{
// content:"";
// clear:both;
// display: block;
// }
}
.row{
@include row;
}
.row-rl{
@include row;
}
%col-reset {
box-sizing: border-box;
}
@mixin col($col, $offset: 0, $sum: $default_sum, $gap: $default_gap, $align: top) {
@extend %col-reset;
padding-left: $gap*$offset;
@if $col == $default_sum {
// if last col, then no gap
padding-right: 0;
}@else{
padding-right: $gap;
}
&:last-child{padding-right: 0;}
// no offset with flex ??
// margin-left: percentage(($col/$sum)*$offset);
// col width
flex-basis: percentage($col/$sum);
}
@for $c from 1 through $default_sum {
.col-#{$c} {
@include col($c);
}
// small
.small-col-#{$c} {
@media only screen and (max-width: $small-bp) {
@include col($c);
}
}
// medium
.med-col-#{$c} {
@media only screen and (min-width: $small-bp+1) and (max-width: $med-bp) {
@include col($c);
}
}
// large
.large-col-#{$c} {
@media only screen and (min-width: $med-bp+1) {
@include col($c);
}
}
}
@for $c from 1 through $default_sum - 1 {
@for $o from 1 through $default_sum - $c {
.col-#{$c}-offset-#{$o} {
@include col($c, $o);
}
}
}
// TODO: replace with align-self:flex-start or flex-end
// .col.float-right{
// float: right;
// padding-right: 0;
// padding-left: $default_gap;
// }
+4 -2
View File
@@ -1,3 +1,5 @@
$side-padding:3em;
body, html{
position: relative;
width: 100%;
@@ -24,12 +26,12 @@ body{
header[role="banner"]{
flex: 0 0 auto;
@extend %layout-element;
padding:1em 1em 0 1em;
padding:1em $side-padding 0 $side-padding;
}
section[role="main-content"]{
flex:1 1 auto;
@extend %layout-element;
padding:0 1em 0 1em;
padding:0 $side-padding 0 $side-padding;
overflow-y: auto;
overflow-x: hidden;
}
+2 -2
View File
@@ -1,8 +1,8 @@
$base_font_size:16px;
// grid
$default_gap: 0;
$default_sum: 12;
$default_gap: 1em;
$default_sum: 12; // total number of columns
$small-bp:768px;
$med-bp:1080px;
+7 -2
View File
@@ -16,7 +16,7 @@
</section>
<footer role="tools">
<History />
<Results />
<Results v-if="resultsOpened" />
<div id="footer-bottom" class="row">
<FooterTabs />
<Search />
@@ -31,7 +31,7 @@ import History from './components/nav/History'
import Results from './components/nav/Results'
import Search from './components/nav/Search'
import FooterTabs from './components/nav/FooterTabs'
// import { mapState, mapActions } from 'vuex'
import { mapState } from 'vuex'
export default {
metaInfo: {
@@ -46,6 +46,11 @@ export default {
Results,
Search,
FooterTabs
},
computed: {
...mapState({
resultsOpened: state => state.Search.opened
})
}
}
</script>
+30 -5
View File
@@ -2,21 +2,46 @@
<div id="footer-tabs" class="col-1">
<ul>
<li class="history">
<span>Historique de consultation</span>
<div class="wrapper">
<span>Historique de consultation</span>
</div>
</li>
<li class="results">
<span>Resultas</span>
<div class="wrapper">
<span
v-if="resultsItems.length && !resultsOpened"
title="Ouvrir les resultats"
@click.prevent="openResults"
@keydown.enter.prevent="openResults"
>
Resultas
</span>
</div>
</li>
</ul>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'FooterTabs',
data: () => ({
})
computed: {
resultsOpened: {
get () { return this.$store.state.Search.opened },
set (value) { this.$store.commit('Search/setOpened', value) }
},
...mapState({
resultsItems: state => state.Search.results
})
},
methods: {
openResults () {
this.resultsOpened = true
}
}
}
</script>
+38 -14
View File
@@ -1,16 +1,33 @@
<template>
<div id="results">
<h2>Resultats</h2>
<h3 v-if="keys">{{ keys }}</h3>
<div class="results-list">
<ul v-if="results.length">
<li v-for="result in results" :key="result.uuid">
<ResultItem :result="result" />
</li>
</ul>
<transition name="fade-roll">
<div
v-if="opened"
id="results"
class="row"
>
<section class="col-1">
<h2>Resultats</h2>
<span class="results-count">{{ results.length }} resultat(s)</span>
</section>
<section class="col-10 results-list">
<div class="wrapper">
<ul v-if="results.length">
<li v-for="result in results" :key="result.uuid" class="result">
<ResultItem :result="result" />
</li>
</ul>
</div>
</section>
<section class="col-1 tools">
<span
class="mdi mdi-close"
title="close"
@click.prevent="close"
@keydown.enter.prevent="close"
/>
</section>
</div>
</div>
</transition>
</template>
<script>
@@ -23,14 +40,21 @@ export default {
components: {
ResultItem
},
data: () => ({
}),
computed: {
opened: {
get () { return this.$store.state.Search.opened },
set (value) { this.$store.commit('Search/setOpened', value) }
},
...mapState({
keys: state => state.Search.keys,
results: state => state.Search.results
})
},
methods: {
close () {
console.log('clicked on close results')
this.opened = false
}
}
}
</script>
+24 -7
View File
@@ -1,28 +1,42 @@
<template>
<div id="search" class="col-11">
<form class="" action="index.html" method="post">
<label htmlFor="keys">Search</label>
<form class="search-form">
<label for="keys">Search</label>
<input
id="keys"
v-model="keys"
type="text"
placeholder="search"
@keydown.enter.prevent="submit"
>
<input
id="search"
<span
v-if="!isloading"
class="mdi mdi-magnify"
title="rechercher"
@click.prevent="submit"
@keydown.enter.prevent="submit"
/>
<span
v-else
class="mdi mdi-loading"
title="chargement"
/>
<!-- <input
id="submit-search"
type="submit"
name="search"
value="Search"
class="mdi mdi-magnify"
@click.prevent="submit"
@keyup.enter="submit"
>
> -->
</form>
</div>
</template>
<script>
import { mapActions } from 'vuex'
import { mapActions, mapState } from 'vuex'
export default {
name: 'Search',
@@ -33,7 +47,10 @@ export default {
keys: {
get () { return this.$store.state.Search.keys },
set (value) { this.$store.commit('Search/setKeys', value) }
}
},
...mapState({
isloading: state => state.Search.isloading
})
},
methods: {
...mapActions({
+13 -1
View File
@@ -7,7 +7,9 @@ export default {
// initial state
state: {
keys: '',
results: []
results: [],
isloading: false,
opened: false
},
// getters
@@ -20,6 +22,12 @@ export default {
},
setResults (state, content) {
state.results = content
},
setIsloading (state, isloading) {
state.isloading = isloading
},
setOpened (state, opened) {
state.opened = opened
}
},
@@ -27,6 +35,7 @@ export default {
actions: {
getResults ({ dispatch, commit, state }) {
console.log('getResults', state.keys)
commit('setIsloading', true)
let params = {
search: state.keys
}
@@ -35,10 +44,13 @@ export default {
return REST.get(`/search?` + q)
.then(({ data }) => {
console.log('search REST: data', data)
commit('setIsloading', false)
commit('setOpened', true)
commit('setResults', data.content)
})
.catch((error) => {
console.warn('Issue with search', error)
commit('setIsloading', false)
Promise.reject(error)
})
}