responsive menus

This commit is contained in:
bkfox
2023-11-29 15:41:15 +01:00
parent f5ce00795e
commit 8202a9324c
17 changed files with 639 additions and 336 deletions

View File

@ -59,41 +59,6 @@ $screen-wide: 1380px;
//-- helpers/modifiers
.is-fullwidth { width: 100%; }
.is-fullheight { height: 100%; }
.is-fixed-bottom {
position: fixed;
bottom: 0;
margin-bottom: 0px;
border-radius: 0;
}
.is-borderless { border: none; }
.has-text-nowrap {
white-space: nowrap;
}
.has-background-transparent {
background-color: transparent;
}
.is-opacity-light {
opacity: 0.7;
&:hover {
opacity: 1;
}
}
.float-right { float: right }
.float-left { float: left }
.overflow-hidden { overflow: hidden }
.overflow-hidden.is-fullwidth { max-width: 100%; }
*[draggable="true"] {
cursor: move;
}
//-- forms
input.half-field:not(:active):not(:hover) {
border: none;
@ -102,21 +67,6 @@ input.half-field:not(:active):not(:hover) {
}
//-- animations
@keyframes blink {
from { opacity: 1; }
to { opacity: 0.4; }
}
.blink {
animation: 1s ease-in-out 2s infinite alternate blink;
}
.loading {
animation: 1s ease-in-out 3s infinite alternate blink;
}
//-- navbar
.navbar.has-shadow, .navbar.is-fixed-bottom.has-shadow {
box-shadow: 0em 0em 1em rgba(0,0,0,0.1);
@ -178,6 +128,9 @@ a.navbar-item.is-active {
--highlight-color-2-alpha: rgb(0, 0, 254, 0.7);
--highlight-color-2-grey: rgba(50, 200, 200, 1);
--nav-primary-height: 4rem;
--nav-secondary-height: 3rem;
--header-height: 30rem;
--heading-height: 30rem;
@ -245,30 +198,65 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
// ---- helpers
*[draggable="true"] {
cursor: move;
}
//-- animations
@keyframes blink {
from { opacity: 1; }
to { opacity: 0.4; }
}
.blink { animation: 1s ease-in-out 3s infinite alternate blink; }
.loading { animation: 1s ease-in-out 1s infinite alternate blink; }
// -- layout
.d-inline { display: inline; }
.d-block { display: block; }
.d-inline-block { display: inline-block; }
.p-relative { position: relative }
.p-absolute { position: absolute }
.p-fixed { position: fixed }
.p-sticky { position: sticky }
.p-static { position: static }
.align-left { text-align: left; justify-content: left; }
.align-right { text-align: right; justify-content: right; }
.height-full { height: 100%; }
.d-inline { display: inline !important; }
.d-block { display: block !important; }
.d-inline-block { display: inline-block !important; }
.flex-push-right { margin-left: auto; }
.flex-grow-0 { flex-grow: 0 !important; }
.float-right { float: right }
.float-left { float: left }
.is-fullwidth { width: 100%; }
.is-fullheight { height: 100%; }
.is-fixed-bottom {
position: fixed;
bottom: 0;
margin-bottom: 0px;
border-radius: 0;
}
.is-borderless { border: none; }
.overflow-hidden { overflow: hidden }
.overflow-hidden.is-fullwidth { max-width: 100%; }
.p-relative { position: relative !important }
.p-absolute { position: absolute !important }
.p-fixed { position: fixed !important }
.p-sticky { position: sticky !important }
.p-static { position: static !important }
.height-full { height: 100%; }
.ws-nowrap { white-space: nowrap; }
.no-border { border: 0px !important; }
// -- colors
.highlight-color { color: var(--highlight-color); }
.highlight-color-2 { color: var(--highlight-color-2); }
.bg-transparent { background-color: transparent; }
.is-success {
background-color: $green !important;
border-color: $green-dark !important;
@ -288,6 +276,19 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
}
.schedules {
margin-top: calc(0rem - $mp-3) !important;
padding-top: 0;
}
.schedule {
.day {
font-weight: $weight-bold;
margin-right: $mp-3;
}
}
// -- buttons, forms
.button, a.button, button.button, .nav-urls a {
display: inline-block;
@ -302,8 +303,10 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
.icon {
vertical-align: middle;
&:first-child { margin-right: $mp-3; }
&:last-child { margin-left: $mp-3 }
&:not(:only-child) {
&:first-child { margin-right: $mp-3; }
&:last-child { margin-left: $mp-3 }
}
}
@ -341,8 +344,9 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
}
.button-group {
.button-group, .nav {
.button {
border-radius: 0px;
background-color: transparent;
border-top: 0px;
border-bottom: 0px;
@ -384,6 +388,9 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
}
.label, .textarea, .input, .select {
font-size: $text-size-medium;
}
// -- headings
.title {
@ -424,6 +431,8 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
display: none;
}
.burger { display: none; }
.nav-item {
padding: $mp-3;
flex-grow: 1;
@ -433,31 +442,45 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
font-family: var(--heading-font-family);
text-transform: uppercase;
a, .button {
display: block;
width: 100%;
}
&.active {
background-color: var(--highlight-color-2);
color: var(--highlight-color);
}
}
&.primary {
.nav-brand {
display: inline-block;
margin-right: $mp-3;
padding: $mp-3;
.nav-menu {
display: flex;
flex-grow: 1;
background-color: var(--highlight-color);
}
img {
width: 12rem !important;
}
}
&.primary {
height: var(--nav-primary-height);
.nav-menu {
display: flex;
flex-grow: 1;
}
.nav-brand {
display: inline-block;
padding: $mp-3;
flex-grow: 0;
flex-shrink: 1;
img {
height: 100%;
}
}
.nav-item {
font-size: $text-size-2;
font-weight: $weight-bold;
white-space: nowrap;
}
}
@ -470,6 +493,64 @@ h1, h2, h3, h4, h5, h6, .heading, .title, .subtitle {
}
}
@media screen and (max-width: $screen-normal) {
.page {
margin-top: var(--nav-primary-height);
}
.navs {
z-index: 100000;
position: fixed;
display: flex;
left: 0;
right: 0;
top: 0;
.nav:first-child {
flex-grow: 1;
}
.nav + .nav {
flew-grow: 0 !important;
}
}
.nav {
justify-content: space-between;
.burger {
display: unset;
margin-left: auto;
}
.nav-menu {
display: block;
position: absolute;
left: 0;
top: 100%;
width: 100%;
box-shadow: 0em 0.5em 0.5em rgba(0,0,0,0.05);
.nav-item {
display: block;
font-size: $text-size-medium;
font-weight: $weight-normal;
&:hover {
background-color: var(--highlight-color-2-alpha);
color: var(--highlight-color);
}
}
}
.nav-menu:not(.active) {
display: none !important
}
}
}
nav li {
list-style: none;
@ -792,6 +873,11 @@ nav li {
}
@media screen and (max-width: $screen-normal) {
.container.header {
margin-right: 0 !important;
margin-left: 0 !important;
}
.page .container {
margin-left: $mp-4;
margin-right: $mp-4;
@ -953,7 +1039,7 @@ nav li {
border-top: 1px $grey-light solid;
background: var(--player-bar-bg);
box-shadow: 0em 1.5em 2.5em rgba(0, 0, 0, 0.6);
box-shadow: 0em -0.5em 0.5em rgba(0, 0, 0, 0.05);
> * { height: 100%; }

View File

@ -0,0 +1,75 @@
<template>
<button :title="ariaLabel"
:aria-label="ariaLabel || label" :aria-description="ariaDescription"
@click="toggle" :class="buttonClass">
<slot name="default" :active="active">
<span class="icon">
<i :class="icon"></i>
</span>
<label v-if="label">{{ label }}</label>
</slot>
</button>
</template>
<script>
export default {
props: {
initialActive: {type: Boolean, default: null},
el: {type: String, default: ""},
label: {type: String, default: ""},
icon: {type: String, default: "fa fa-bars"},
ariaLabel: {type: String, default: ""},
ariaDescription: {type: String, default: ""},
activeClass: {type: String, default:"active"},
/// switch toggle of all items of this group.
group: {type: String, default: ""},
},
data() {
return {
active: this.initialActive,
}
},
computed: {
groupClass() {
return this.group && "a-switch-" + this.group || ''
},
buttonClass() {
return [
this.active && 'active' || '',
this.groupClass
]
}
},
methods: {
toggle() {
this.set(!this.active)
},
set(active) {
const el = document.querySelector(this.el)
if(active)
el.classList.add(this.activeClass)
else
el.classList.remove(this.activeClass)
this.active = active
if(active)
this.resetGroup()
},
resetGroup() {
const els = document.querySelectorAll("." + this.groupClass)
for(var el of els)
if(el != this.$el)
el.__vnode.ctx.ctx.set(false)
},
},
mounted() {
if(this.initialActive !== null)
this.set(this.initialActive)
},
}
</script>

View File

@ -9,6 +9,7 @@ import APlaylist from './APlaylist.vue'
import APlaylistEditor from './APlaylistEditor.vue'
import AProgress from './AProgress.vue'
import ASoundItem from './ASoundItem.vue'
import ASwitch from './ASwitch.vue'
import AStatistics from './AStatistics.vue'
import AStreamer from './AStreamer.vue'
@ -17,7 +18,7 @@ import AStreamer from './AStreamer.vue'
*/
export const base = {
AAutocomplete, ACarousel, ADropdown, AEpisode, AList, APage, APlayer, APlaylist,
AProgress, ASoundItem,
AProgress, ASoundItem, ASwitch
}
export default base