Base components added and updated.

This commit is contained in:
Jesse Malotaux 2025-03-10 12:50:19 +01:00
parent b6f7694a0e
commit f4a4bc5c4a
4 changed files with 293 additions and 4 deletions

View file

@ -25,6 +25,7 @@ const classString = computed(() => {
'bg-sky-500/80 hover:bg-sky-400 text-white border-sky-400': props.variant === 'primary',
'bg-white/80 hover:bg-white text-slate-900 border-white': props.variant === 'secondary',
'bg-red-700/80 hover:bg-red-700 text-white border-red-800': props.variant === 'danger',
'bg-slate-700/80 hover:bg-slate-700 text-white border-slate-600': props.variant === 'dark',
'bg-lime-500/80 hover:bg-lime-500 text-white border-lime-600': props.variant === 'success',
'button__subtle bg-transparent hover:bg-white/10 text-white border-transparent':
props.variant === 'subtle',
@ -38,10 +39,6 @@ const classString = computed(() => {
.filter((key) => classes[key])
.join(' ')
})
onMounted(() => {
console.log(classString)
})
</script>
<style>

View file

@ -0,0 +1,76 @@
<template>
<div class="context-menu">
<div class="context-menu__trigger" @click="menuOpen = !menuOpen">
<slot name="trigger" />
</div>
<div :class="`context-menu__content ${menuOpen ? 'open' : ''}`">
<slot name="content" />
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const props = defineProps({
open: Boolean,
})
const menuOpen = ref(false)
onMounted(() => {
menuOpen.value = props.open
})
</script>
<style>
@reference "@/assets/main.css";
.context-menu {
@apply relative;
.context-menu__content {
@apply absolute
top-full
-translate-y-full
opacity-0
pointer-events-none
mt-2
min-w-full
grid
border
border-white/50
bg-slate-100/60
backdrop-blur-3xl
text-slate-800
rounded-md
z-50
transition-all;
&.open {
@apply translate-y-0
opacity-100
pointer-events-auto;
}
}
}
ul {
@apply text-slate-800
divide-y
divide-slate-300;
li {
@apply flex
gap-2
items-center
p-2
hover:bg-black/10
cursor-pointer;
svg {
@apply size-5;
}
}
}
</style>

View file

@ -0,0 +1,107 @@
<template>
<div class="dialog-container">
<div class="trigger" @click="toggleDialog(true)">
<slot name="trigger" />
</div>
<dialog ref="dialog">
<ButtonComp
class="dialog__close p-0"
variant="ghost"
size="sm"
tabindex="-1"
@click="toggleDialog(false)"
>
<IconX />
</ButtonComp>
<slot name="content" />
</dialog>
</div>
</template>
<script setup>
import ButtonComp from './ButtonComp.vue'
import { IconX } from '@tabler/icons-vue'
import { onMounted, onUpdated, ref } from 'vue'
const dialog = ref(null)
const openDialog = ref()
const emit = defineEmits(['onOpen', 'onClose', 'onToggle'])
const props = defineProps({
open: Boolean,
})
onMounted(() => {
if (props.open === true) toggleDialog(props.open)
})
onUpdated(() => {
if (props.open === true) toggleDialog(props.open)
})
const toggleDialog = (openToggle) => {
if (openToggle) {
dialog.value.showModal()
emit('onOpen')
} else {
dialog.value.close()
emit('onClose')
}
openDialog.value = openToggle
emit('onToggle')
}
onMounted(() => {
openDialog.value = props.open
if (dialog.value.innerHTML.includes('form')) {
dialog.value.querySelector('form').addEventListener('submit', () => {
toggleDialog()
})
}
})
</script>
<style scoped>
@reference "@/assets/main.css";
.dialog-container {
@apply relative;
dialog {
@apply fixed
top-1/2 left-1/2
-translate-x-1/2 -translate-y-1/2
p-4
bg-slate-800
border
border-slate-600
rounded-lg
shadow-md
shadow-black
z-50
pointer-events-none;
&[open] {
@apply pointer-events-auto;
}
&::backdrop {
@apply bg-black/50 backdrop-blur-xs transition;
}
.dialog__close {
@apply absolute
top-2 right-2
p-0
text-white;
svg {
@apply size-5;
}
}
}
}
</style>

View file

@ -0,0 +1,109 @@
<template>
<div class="macro-input">
<div class="macro-input__output" ref="macroOutput"></div>
<input class="macro-input__input" type="text" ref="macroInput" @keydown.prevent="keyDown" />
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
const macroOutput = ref(null)
const macroInput = ref(null)
onMounted(() => {
macroInput.value.focus()
})
const keyDown = (e) => {
console.log(e)
const modKeys = {
Control: 'Ctrl',
Shift: 'Shift',
Alt: 'Alt',
Meta: 'Win',
}
const specialKeys = {
PageUp: 'PgUp',
PageDown: 'PgDn',
ScrollLock: 'Scr Lk',
}
let key = e.key
if (e.shiftKey) {
key = e.key.toLowerCase()
}
const newKeyEl = document.createElement('kbd')
if (e.code === 'Space') {
newKeyEl.innerHTML = 'Space'
} else if (e.location === 1 && Object.keys(modKeys).includes(key)) {
newKeyEl.innerHTML = '<sup>left</sup> ' + (modKeys[key] || key)
} else if (e.location === 2 && Object.keys(modKeys).includes(key)) {
newKeyEl.innerHTML = '<sup>right</sup> ' + (modKeys[key] || key)
} else if (e.location === 3) {
newKeyEl.innerHTML = '<sup>num</sup> ' + (modKeys[key] || key)
} else if (Object.keys(specialKeys).includes(key)) {
newKeyEl.innerHTML = specialKeys[key] || key
} else {
newKeyEl.innerHTML = key
}
macroOutput.value.appendChild(newKeyEl)
}
</script>
<style>
@reference "@/assets/main.css";
.macro-input {
@apply relative
w-full
h-96
my-4
rounded-lg
bg-slate-900/50
border
border-white/10
overflow-auto;
.macro-input__input,
.macro-input__output {
@apply absolute
inset-0
size-full;
}
.macro-input__output {
@apply flex
flex-wrap
items-start
gap-2
p-4
h-fit;
}
kbd {
@apply flex
items-center
gap-2
px-4 py-1
h-9
bg-white/10
font-sans
font-bold
text-lg
uppercase
rounded-md
border;
sup {
@apply text-xs font-light -ml-1.5 mt-1;
}
}
}
</style>