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>
<div class="accordion">
<header>
<slot name="title" />
<header @click="toggleAccordion(!accordionOpen)">
<h4>{{ title }}</h4>
<ButtonComp variant="ghost" size="sm" class="!px-1">
<IconChevronDown v-if="!accordionOpen" />
<IconChevronUp v-else />
</ButtonComp>
</header>
<section :class="`accordion__content ${open ? 'open' : ''}`">
<div>
<slot name="content" />
<section :class="`accordion__wrapper ${accordionOpen ? 'open' : ''}`">
<div class="accordion__content">
<slot />
</div>
</section>
</div>
</template>
<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,
})
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>
<style scoped>
@ -23,16 +54,39 @@ defineProps({
.accordion {
@apply grid;
.accordion__content {
header {
@apply grid
grid-cols-[1fr_auto]
px-4 py-2;
}
.accordion__wrapper {
@apply grid
grid-rows-[0fr]
overflow-hidden
border-y
border-b-white/60
border-t-transparent
duration-300
ease-in-out;
div {
.accordion__content {
@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>
<div :class="`alert alert__${type}`">
<IconInfoCircle v-if="type === 'info'" />
<IconCheck v-if="type === 'success'" />
<IconExclamationCircle v-if="type === 'warning'" />
<IconAlertTriangle v-if="type === 'error'" />
<slot />
<div
:class="`alert alert__${variant} ${pageWide ? 'page-wide' : ''}`"
@click="href ? router.push(href) : null"
>
<IconInfoCircle v-if="variant === 'info'" />
<IconCheck v-if="variant === 'success'" />
<IconExclamationCircle v-if="variant === 'warning'" />
<IconAlertTriangle v-if="variant === 'error'" />
<div class="alert__content">
<slot />
</div>
</div>
</template>
@ -15,10 +20,15 @@ import {
IconExclamationCircle,
IconInfoCircle,
} from '@tabler/icons-vue'
import { useRouter } from 'vue-router'
defineProps({
type: String, // info, success, warning, error
variant: String, // info, success, warning, error
pageWide: Boolean,
href: String,
})
const router = useRouter()
</script>
<style scoped>
@ -51,5 +61,19 @@ defineProps({
&.alert__error {
@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>

View file

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

View file

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