From 41d5da964fb6f1a77c7dfca56906d2d76df8465a Mon Sep 17 00:00:00 2001 From: Pierre-Jean CHANCELLIER <paidge_cs@hotmail.com> Date: Wed, 15 Dec 2021 16:07:31 +0100 Subject: [PATCH] add theme selector --- assets/css/style.scss | 26 +------ components/btn/Theme.vue | 97 ++++++++++++++++++++++++++ components/navigation/Bar.vue | 38 ++++++++-- components/navigation/Breadcrumb.vue | 13 ++-- components/navigation/menu/Sidebar.vue | 4 +- layouts/default.vue | 43 +++++++++++- nuxt.config.js | 5 +- pages/appolo.vue | 2 +- pages/chartjs.vue | 5 +- pages/explore.vue | 2 +- pages/index.vue | 2 +- pages/test.vue | 48 +++++++++++++ 12 files changed, 240 insertions(+), 45 deletions(-) create mode 100644 components/btn/Theme.vue create mode 100644 pages/test.vue diff --git a/assets/css/style.scss b/assets/css/style.scss index 20aefe5..b402489 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -1,29 +1,7 @@ $link-hover-decoration: none; $text-muted: #a6a4b0; +$enable-responsive-font-sizes: true; $font-family-base: Montserrat, Helvetica, Arial, serif; @import 'font'; -@import 'bootstrap'; - -:root { - --menu-size: 320px; -} - -.content { - @extend .container-fluid; -} - -.table.striped tbody { - tr { - opacity: .9; - cursor: pointer; - - &:nth-child(2n+1) { - opacity: .7; - } - - &:hover { - opacity: 1; - } - } -} \ No newline at end of file +@import 'bootstrap'; \ No newline at end of file diff --git a/components/btn/Theme.vue b/components/btn/Theme.vue new file mode 100644 index 0000000..cb98626 --- /dev/null +++ b/components/btn/Theme.vue @@ -0,0 +1,97 @@ +<template> + <div> + <input @change="toggleTheme" id="checkbox" type="checkbox" class="switch-checkbox" /> + <label for="checkbox" class="switch-label"> + <span>🌙</span> + <span>☀ï¸</span> + <div class="switch-toggle" :class="{ 'switch-toggle-checked': userTheme === 'dark-theme' }"></div> + </label> + </div> +</template> + +<script> +export default { + mounted() { + const initUserTheme = this.getMediaPreference(); + this.setTheme(initUserTheme); + }, + + data() { + return { + userTheme: "light-theme", + }; + }, + + methods: { + toggleTheme() { + const activeTheme = localStorage.getItem("user-theme"); + if (activeTheme === "light-theme") { + this.setTheme("dark-theme"); + } else { + this.setTheme("light-theme"); + } + }, + + setTheme(theme) { + localStorage.setItem("user-theme", theme); + this.userTheme = theme; + document.documentElement.className = theme; + }, + + getMediaPreference() { + const hasDarkPreference = window.matchMedia( + "(prefers-color-scheme: dark)" + ).matches; + if (hasDarkPreference) { + return "dark-theme"; + } else { + return "light-theme"; + } + }, + }, +}; +</script> + +<!-- Add "scoped" attribute to limit CSS to this component only --> +<style scoped> +*, ::before, ::after { + box-sizing: initial; +} +.switch-checkbox { + display: none; +} + +.switch-label { + align-items: center; + background: var(--text-primary-color); + border: calc(var(--element-size) * 0.025) solid var(--accent-color); + border-radius: var(--element-size); + cursor: pointer; + display: flex; + font-size: calc(var(--element-size) * 0.3); + height: calc(var(--element-size) * 0.35); + position: relative; + padding: calc(var(--element-size) * 0.1); + transition: background 0.5s ease; + justify-content: space-between; + width: var(--element-size); + z-index: 1; + margin-bottom: 0; +} + +.switch-toggle { + position: absolute; + background-color: var(--background-color-primary); + border-radius: 50%; + top: calc(var(--element-size) * 0.07); + left: calc(var(--element-size) * 0.07); + height: calc(var(--element-size) * 0.4); + width: calc(var(--element-size) * 0.4); + transform: translateX(0); + transition: transform 0.3s ease, background-color 0.5s ease; +} + +.switch-toggle-checked { + transform: translateX(calc(var(--element-size) * 0.6)) !important; +} +</style> diff --git a/components/navigation/Bar.vue b/components/navigation/Bar.vue index 6f9f89f..6fb9982 100644 --- a/components/navigation/Bar.vue +++ b/components/navigation/Bar.vue @@ -1,8 +1,8 @@ <template> <header> <div class="position-relative"> - <button class="toggle btn border-secondary position-absolute p-1 m-3" @click="toggleMenu"><span></span></button> - <NavigationBreadcrumb :breadcrumb="breadcrumb" class="ml-5 py-3 px-4" /> + <button class="toggle btn border-secondary position-absolute p-1 m-1 ml-3" @click="toggleMenu"><span></span></button> + <NavigationBreadcrumb :breadcrumb="breadcrumb" class="breadcrumb p-1" /> </div> <NavigationMenuSidebar @toggleMenu="toggleMenu" :menus="menus" /> <div class="bg_overlay" @click="toggleMenu"></div> @@ -28,11 +28,32 @@ $bg-menu: #fff; $btn-width: 50px; $line-color: #000; +nav.breadcrumb { + margin: .5rem .5rem .5rem 5rem; + justify-content: space-between; + align-items: center; + + a {color: var(--text-primary-color)} + + .breadcrumb-item { + &.active { + color: var(--text-primary-color); + opacity: .7; + } + + & + .breadcrumb-item::before {color: var(--text-primary-color)} + } + + &, .breadcrumb { + background-color: var(--background-color-secondary); + } +} + %hamburger-line { display: block; height: 4px; width: .8 * $btn-width; - background: var(--color); + background: var(--text-primary-color); content: ""; position: absolute; transition-property: transform; @@ -40,7 +61,6 @@ $line-color: #000; } .toggle { - --color: #{$line-color}; height: $btn-width; width: $btn-width; line-height: $btn-width; @@ -83,7 +103,7 @@ $line-color: #000; .menu { width: var(--menu-size); - background: $bg-menu; + background: var(--background-color-primary); position: fixed; top: 0; z-index: 1200; @@ -95,7 +115,15 @@ $line-color: #000; transition: left .5s ease-in-out; left: -400px; + h1 {color: var(--text-primary-color);} + .list-group-item { + background-color: var(--background-color-primary); + + &-action { + color: var(--text-primary-color); + } + &.nuxt-link-active { z-index: 2; color: #fff; diff --git a/components/navigation/Breadcrumb.vue b/components/navigation/Breadcrumb.vue index 4338751..e5d6383 100644 --- a/components/navigation/Breadcrumb.vue +++ b/components/navigation/Breadcrumb.vue @@ -1,11 +1,12 @@ <template> <nav aria-label="breadcrumb"> - <ol class="breadcrumb m-0"> - <li class="breadcrumb-item" :class="{ 'active': item.active }" :aria-current="item.active ? 'page' : null" v-for="item in breadcrumb" :key="item.text"> - <NuxtLink :to="item.to" v-if="item.to">{{ item.text }}</NuxtLink> - <span v-else>{{ item.text }}</span> - </li> - </ol> + <ol class="breadcrumb m-0"> + <li class="breadcrumb-item" :class="{ 'active': item.active }" :aria-current="item.active ? 'page' : null" v-for="item in breadcrumb" :key="item.text"> + <NuxtLink :to="item.to" v-if="item.to">{{ item.text }}</NuxtLink> + <span v-else>{{ item.text }}</span> + </li> + </ol> + <BtnTheme /> </nav> </template> diff --git a/components/navigation/menu/Sidebar.vue b/components/navigation/menu/Sidebar.vue index 2114ce6..d76a2ae 100644 --- a/components/navigation/menu/Sidebar.vue +++ b/components/navigation/menu/Sidebar.vue @@ -1,12 +1,12 @@ <template> <aside class="menu shadow"> <div class="nav_header border-bottom pb-3 mb-5"> - <nuxt-link to="/" class="text-dark"><h1 class="h2 d-flex"><img src="@/assets/img/logo.png" alt="Accueil" class="logo"> Wotwizard</h1></nuxt-link> + <nuxt-link to="/"><h1 class="h2 d-flex"><img src="@/assets/img/logo.png" alt="Accueil" class="logo"> Wotwizard</h1></nuxt-link> <button type="button" class="close position-absolute d-xl-none" aria-label="Close" @click="toggleMenu"> <span aria-hidden="true">×</span> </button> </div> - <nav class="navbar-light"> + <nav> <NavigationMenuGroup v-for="menu in menus" :key="menu.title" :menu="menu"/> </nav> </aside> diff --git a/layouts/default.vue b/layouts/default.vue index ae8a265..37ec8bd 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -16,7 +16,8 @@ export default { items : [ {path: '/explore',title: 'Explorer la toile de confiance'}, {path: '/appolo',title: 'Appolo'}, - {path: '/chartjs',title: 'ChartJS'} + {path: '/chartjs',title: 'ChartJS'}, + {path: '/test',title: 'Test'} ]}, { title: 'Un menu', @@ -36,7 +37,47 @@ export default { </script> <style lang="scss"> +/* Define styles for the default root window element */ +:root { + --text-primary-color: var(--dark); + --text-secondary-color: var(--white); + --accent-color: var(--light); + --background-color-primary: var(--white); + --background-color-secondary: #e9ecef; + --element-size: 4rem; + --menu-size: 320px; +} + +/* Define styles for the root window with dark - mode preference */ +:root.dark-theme { + --text-primary-color: var(--white); + --text-secondary-color: var(--dark); + --accent-color: var(--dark); + --background-color-primary: var(--dark); + --background-color-secondary: hsl(210, 16%, 60%); +} + +body { + background-color: var(--background-color-primary); + color: var(--text-primary-color); +} + .app { transition: margin .5s ease-in-out; } + +.table.striped tbody { + tr { + opacity: .9; + cursor: pointer; + + &:nth-child(2n+1) { + opacity: .7; + } + + &:hover { + opacity: 1; + } + } +} </style> \ No newline at end of file diff --git a/nuxt.config.js b/nuxt.config.js index bf1608d..1c3d5d5 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -34,12 +34,13 @@ export default { // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules buildModules: [ + // https://go.nuxtjs.dev/pwa + '@nuxtjs/pwa', ], // Modules: https://go.nuxtjs.dev/config-modules modules: [ - // https://go.nuxtjs.dev/pwa - '@nuxtjs/pwa', + // https://github.com/nuxt-community/apollo-module '@nuxtjs/apollo', ], diff --git a/pages/appolo.vue b/pages/appolo.vue index eed3c80..1f879b0 100644 --- a/pages/appolo.vue +++ b/pages/appolo.vue @@ -1,5 +1,5 @@ <template> -<main class="content"> +<main class="container-fluid"> <h2 class="display-2 text-center mb-5">Test Appolo</h2> <div class="row"> <div class="col-6 m-auto text-center"> diff --git a/pages/chartjs.vue b/pages/chartjs.vue index 71b19a8..222ccb0 100644 --- a/pages/chartjs.vue +++ b/pages/chartjs.vue @@ -1,5 +1,5 @@ <template> - <div class="demo"> + <main class="container-fluid demo"> <p class="text-center">Pour activer/désactiver des types de graphiques, il faut éditer le fichier <code>/plugins/chart.js</code></p> <select class="form-control" id="exampleFormControlSelect1" v-model="activeType"> <option v-for="type in types" :key="type">{{type}}</option> @@ -8,10 +8,11 @@ <component :is="type+'-chart'" :chart-data="datacollection" :options="chartOptions" v-if="activeType==type" /> </div> <button @click="fillData()" class="btn btn-primary">Randomize</button> - </div> + </main> </template> <script> +// Import to access to chartTypes import chartJS from "~/plugins/chart.js" export default { diff --git a/pages/explore.vue b/pages/explore.vue index 8a38b76..b6651fe 100644 --- a/pages/explore.vue +++ b/pages/explore.vue @@ -1,5 +1,5 @@ <template> -<main class="content"> +<main class="container-fluid"> <h2 class="display-2 text-center mb-5">Explorer avec fetch</h2> <div class="row"> <div class="col-6 m-auto"> diff --git a/pages/index.vue b/pages/index.vue index b69cbbb..541c0bc 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -1,5 +1,5 @@ <template> -<main class="content"> +<main class="container-fluid"> <h2 class="display-2 text-center mb-5">Page d'accueil</h2> <div class="row"> <div class="col-6 m-auto text-center"> diff --git a/pages/test.vue b/pages/test.vue new file mode 100644 index 0000000..4071e11 --- /dev/null +++ b/pages/test.vue @@ -0,0 +1,48 @@ +<template> + <main class="container-fluid"> + <h1>Hello Nuxters! 👋</h1> + <p> + This page is rendered on the <strong>{{ rendering }}</strong> + </p> + <p v-if="rendering === 'server'"> + First load or hard refresh is done on server side. + </p> + <p v-if="rendering === 'client'">Navigation is done on client side.</p> + <ul> + <li>Refresh the page for server side rendering.</li> + <li>Click the links to see client side rendering.</li> + </ul> + <NuxtLink to="/">Home Page</NuxtLink> + </main> +</template> + +<script> +export default { + data() { + // Variables locales + return { + // Fil d'ariane + breadcrumb: [ + { + text: 'Accueil', + to: "/" + }, + { + text: 'Test', + active: true + } + ], + hello: '' + } + }, + asyncData() { + return { + rendering: process.server ? 'server' : 'client' + } + }, + mounted () { + // Mise à jour du fil d'ariane au chargement + $nuxt.$emit('changeRoute',this.breadcrumb) + } +} +</script> -- GitLab