Base components updated.

This commit is contained in:
Jesse Malotaux 2025-04-11 13:55:55 +02:00
parent e2dbf13060
commit 8dd567fce2
4 changed files with 125 additions and 46 deletions

View file

@ -1,20 +1,51 @@
<template> <template>
<div class="accordion"> <div class="accordion">
<header> <header @click="toggleAccordion(!accordionOpen)">
<slot name="title" /> <h4>{{ title }}</h4>
<ButtonComp variant="ghost" size="sm" class="!px-1">
<IconChevronDown v-if="!accordionOpen" />
<IconChevronUp v-else />
</ButtonComp>
</header> </header>
<section :class="`accordion__content ${open ? 'open' : ''}`"> <section :class="`accordion__wrapper ${accordionOpen ? 'open' : ''}`">
<div> <div class="accordion__content">
<slot name="content" /> <slot />
</div> </div>
</section> </section>
</div> </div>
</template> </template>
<script setup> <script setup>
defineProps({ import { onMounted, ref } from 'vue'
import ButtonComp from './ButtonComp.vue'
import { IconChevronDown, IconChevronUp } from '@tabler/icons-vue'
const emit = defineEmits(['onOpen', 'onClose', 'onToggle'])
defineExpose({ toggleAccordion })
const props = defineProps({
title: String,
open: Boolean, open: Boolean,
}) })
const accordionOpen = ref(false)
onMounted(() => {
if (props.open) toggleAccordion(props.open)
})
function toggleAccordion(open = false) {
if (open) {
accordionOpen.value = true
emit('onOpen')
} else {
accordionOpen.value = false
emit('onClose')
}
emit('onToggle')
}
</script> </script>
<style scoped> <style scoped>
@ -23,16 +54,39 @@ defineProps({
.accordion { .accordion {
@apply grid; @apply grid;
.accordion__content { header {
@apply grid
grid-cols-[1fr_auto]
px-4 py-2;
}
.accordion__wrapper {
@apply grid @apply grid
grid-rows-[0fr] grid-rows-[0fr]
overflow-hidden border-y
border-b-white/60
border-t-transparent
duration-300 duration-300
ease-in-out; ease-in-out;
div { .accordion__content {
@apply grid @apply grid
grid-rows-[0fr]; grid-rows-[0fr]
overflow-hidden
opacity-0
transition-opacity
delay-0;
}
&.open {
@apply grid-rows-[1fr]
border-t-white/20;
.accordion__content {
@apply grid-rows-[1fr]
opacity-100
delay-200;
}
} }
} }
} }

View file

@ -1,10 +1,15 @@
<template> <template>
<div :class="`alert alert__${type}`"> <div
<IconInfoCircle v-if="type === 'info'" /> :class="`alert alert__${variant} ${pageWide ? 'page-wide' : ''}`"
<IconCheck v-if="type === 'success'" /> @click="href ? router.push(href) : null"
<IconExclamationCircle v-if="type === 'warning'" /> >
<IconAlertTriangle v-if="type === 'error'" /> <IconInfoCircle v-if="variant === 'info'" />
<slot /> <IconCheck v-if="variant === 'success'" />
<IconExclamationCircle v-if="variant === 'warning'" />
<IconAlertTriangle v-if="variant === 'error'" />
<div class="alert__content">
<slot />
</div>
</div> </div>
</template> </template>
@ -15,10 +20,15 @@ import {
IconExclamationCircle, IconExclamationCircle,
IconInfoCircle, IconInfoCircle,
} from '@tabler/icons-vue' } from '@tabler/icons-vue'
import { useRouter } from 'vue-router'
defineProps({ defineProps({
type: String, // info, success, warning, error variant: String, // info, success, warning, error
pageWide: Boolean,
href: String,
}) })
const router = useRouter()
</script> </script>
<style scoped> <style scoped>
@ -51,5 +61,19 @@ defineProps({
&.alert__error { &.alert__error {
@apply text-rose-400 bg-rose-400/10; @apply text-rose-400 bg-rose-400/10;
} }
&.page-wide {
@apply fixed
bottom-0 left-0
w-full;
}
&[href] {
@apply cursor-pointer;
}
.alert__content {
@apply grid gap-2;
}
} }
</style> </style>

View file

@ -1,8 +1,8 @@
<template> <template>
<template v-if="href"> <template v-if="href">
<a :href="href" :class="classString"> <RouterLink :to="href" :class="classString">
<slot /> <slot />
</a> </RouterLink>
</template> </template>
<template v-else> <template v-else>
<button :class="classString"> <button :class="classString">
@ -64,12 +64,22 @@ button,
@apply size-5 transition-[stroke] duration-400 ease-in-out; @apply size-5 transition-[stroke] duration-400 ease-in-out;
} }
&.btn__sm svg { &.btn__sm {
@apply size-4; @apply px-3 py-1
text-sm;
svg {
@apply size-4;
}
} }
&.btn__lg svg { &.btn__lg {
@apply size-6; @apply px-6 py-3
text-lg;
svg {
@apply size-6;
}
} }
&:hover { &:hover {

View file

@ -1,12 +1,8 @@
<template> <template>
<nav id="main-menu"> <nav id="main-menu">
<button <button id="menu-toggle" :class="menuOpen ? 'open' : ''" @click="menuOpen = !menuOpen">
id="menu-toggle"
:class="menuOpen ? 'open' : ''"
@click="menuOpen = !menuOpen"
>
<img <img
class="logo p-1" class="p-1 logo"
:class="{ 'opacity-0': menuOpen }" :class="{ 'opacity-0': menuOpen }"
src="@/assets/img/Macrame-Logo-gradient.svg" src="@/assets/img/Macrame-Logo-gradient.svg"
aria-hidden="true" aria-hidden="true"
@ -15,36 +11,30 @@
</button> </button>
<ul :class="menuOpen ? 'open' : ''"> <ul :class="menuOpen ? 'open' : ''">
<li> <li>
<RouterLink @click="menuOpen = false" to="/"> <RouterLink @click="menuOpen = false" to="/"> <IconHome />Dashboard </RouterLink>
<IconHome />Dashboard
</RouterLink>
</li> </li>
<li> <li>
<RouterLink @click="menuOpen = false" to="/panels"> <RouterLink @click="menuOpen = false" to="/panels"> <IconLayoutGrid />Panels </RouterLink>
<IconLayoutGrid />Panels
</RouterLink>
</li> </li>
<li> <li v-if="isLocal()">
<RouterLink @click="menuOpen = false" to="/macros"> <RouterLink @click="menuOpen = false" to="/macros"> <IconKeyboard />Macros </RouterLink>
<IconKeyboard />Macros
</RouterLink>
</li> </li>
<li> <li>
<RouterLink @click="menuOpen = false" to="/devices"> <RouterLink @click="menuOpen = false" to="/devices">
<IconDevices />Device <IconDevices />{{ isLocal() ? 'Devices' : 'Server' }}
</RouterLink> </RouterLink>
</li> </li>
<li> <!-- <li>
<RouterLink @click="menuOpen = false" to="/settings"> <RouterLink @click="menuOpen = false" to="/settings">
<IconSettings />Settings <IconSettings />Settings
</RouterLink> </RouterLink>
</li> </li> -->
</ul> </ul>
</nav> </nav>
</template> </template>
<script setup> <script setup>
import { RouterLink } from "vue-router"; import { RouterLink } from 'vue-router'
import { import {
IconDevices, IconDevices,
IconHome, IconHome,
@ -52,10 +42,11 @@ import {
IconLayoutGrid, IconLayoutGrid,
IconSettings, IconSettings,
IconX, IconX,
} from "@tabler/icons-vue"; } from '@tabler/icons-vue'
import { ref } from "vue"; import { ref } from 'vue'
import { isLocal } from '@/services/ApiService'
const menuOpen = ref(false); const menuOpen = ref(false)
</script> </script>
<style> <style>