Skip to content

Commit

Permalink
Ran ui:fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Blackshadow8910 committed Jan 10, 2025
1 parent 4315dad commit ca33267
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 160 deletions.
17 changes: 12 additions & 5 deletions frontend/components/Base/Modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
<input :id="modalId" v-model="modal" type="checkbox" class="modal-toggle" />
<div class="modal modal-bottom overflow-visible sm:modal-middle">
<div ref="modalBox" class="modal-box relative overflow-visible">
<button v-if="props.showCloseButton" :for="modalId" class="btn btn-circle btn-sm absolute right-2 top-2" @click="close">✕</button>
<button
v-if="props.showCloseButton"
:for="modalId"
class="btn btn-circle btn-sm absolute right-2 top-2"
@click="close"
>
</button>

<h3 class="text-lg font-bold">
<slot name="title"></slot>
Expand Down Expand Up @@ -33,9 +40,9 @@
showCloseButton: {
type: Boolean,
default: true,
}
},
});
const modalBox = ref();
function escClose(e: KeyboardEvent) {
Expand All @@ -45,8 +52,8 @@
}
onClickOutside(modalBox, () => {
close()
})
close();
});
function close() {
if (props.readonly) {
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/Form/Multiselect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<div
tabindex="0"
style="display: inline"
class="dropdown-content menu bg-base-100 z-[9999] mb-1 w-full rounded border border-gray-400 shadow"
class="dropdown-content menu z-[9999] mb-1 w-full rounded border border-gray-400 bg-base-100 shadow"
>
<div class="m-2">
<input v-model="search" placeholder="Search…" class="input input-bordered input-sm w-full" />
Expand Down
185 changes: 92 additions & 93 deletions frontend/components/global/QuickMenu/Input.vue
Original file line number Diff line number Diff line change
@@ -1,109 +1,108 @@
<template>
<Combobox v-model="selectedAction">
<ComboboxInput ref="inputBox" @input="inputValue = $event.target.value" class="input input-bordered w-full"></ComboboxInput>
<ComboboxOptions
class="card dropdown-content absolute w-full rounded-lg border border-base-300 bg-base-100"
>
<ComboboxOption v-for="(action, idx) in filteredActions"
:key="idx"
:value="action"
as="template"
v-slot="{ active }"
>
<button
class="flex transition-colors w-full text-left rounded-lg px-3 py-1.5"
:class="{ 'bg-primary text-primary-content': active }"
>
{{ action.text }}
<Combobox v-model="selectedAction">
<ComboboxInput
ref="inputBox"
class="input input-bordered w-full"
@input="inputValue = $event.target.value"
></ComboboxInput>
<ComboboxOptions class="card dropdown-content absolute w-full rounded-lg border border-base-300 bg-base-100">
<ComboboxOption
v-for="(action, idx) in filteredActions"
:key="idx"
v-slot="{ active }"
:value="action"
as="template"
>
<button
class="flex w-full rounded-lg px-3 py-1.5 text-left transition-colors"
:class="{ 'bg-primary text-primary-content': active }"
>
{{ action.text }}

<kbd v-if="action.shortcut"
class="ml-auto text-center px-2 border border-base-300 rounded-md"
:class="{ 'border-primary-content': active }"
>
{{action.shortcut}}
</kbd>
</button>
</ComboboxOption>
<div v-if="filteredActions.length == 0"
class="transition-colors w-full text-left rounded-lg p-3 hover:bg-base-300">
No actions found.
</div>
</ComboboxOptions>
<ComboboxButton ref="inputBoxButton"></ComboboxButton>
</Combobox>
<kbd
v-if="action.shortcut"
class="ml-auto rounded-md border border-base-300 px-2 text-center"
:class="{ 'border-primary-content': active }"
>
{{ action.shortcut }}
</kbd>
</button>
</ComboboxOption>
<div
v-if="filteredActions.length == 0"
class="w-full rounded-lg p-3 text-left transition-colors hover:bg-base-300"
>
No actions found.
</div>
</ComboboxOptions>
<ComboboxButton ref="inputBoxButton"></ComboboxButton>
</Combobox>
</template>

<script setup lang="ts">
import {
Combobox,
ComboboxInput,
ComboboxOptions,
ComboboxOption,
ComboboxButton
} from '@headlessui/vue';
import { Combobox, ComboboxInput, ComboboxOptions, ComboboxOption, ComboboxButton } from "@headlessui/vue";
type ExposedProps = {
focused: boolean,
revealActions: () => void,
}
type ExposedProps = {
focused: boolean;
revealActions: () => void;
};
type QuickMenuAction = {
text: string;
action: () => void;
// A character that invokes this action instantly if pressed
shortcut?: string;
};
const props = defineProps({
modelValue: {
type: Object as PropType<QuickMenuAction>,
required: false,
default: undefined,
},
actions: {
type: Array as PropType<QuickMenuAction[]>,
required: true,
},
});
type QuickMenuAction = {
text: string,
action: () => void,
// A character that invokes this action instantly if pressed
shortcut?: string,
};
const selectedAction = useVModel(props, "modelValue");
const props = defineProps({
modelValue: {
type: Object as PropType<QuickMenuAction>,
required: false,
},
actions: {
type: Array as PropType<QuickMenuAction[]>,
required: true,
},
})
const inputValue = ref("");
const inputBox = ref();
const inputBoxButton = ref();
const { focused: inputBoxFocused } = useFocus(inputBox);
const selectedAction = useVModel(props, "modelValue");
const emit = defineEmits(["update:modelValue", "quickSelect"]);
const inputValue = ref("");
const inputBox = ref();
const inputBoxButton = ref();
const { focused: inputBoxFocused } = useFocus(inputBox);
const revealActions = () => {
unrefElement(inputBoxButton).click();
};
const emit = defineEmits(["update:modelValue", "quickSelect"])
watch(inputBoxFocused, () => {
if (inputBoxFocused.value) revealActions();
else inputValue.value = "";
});
const revealActions = () => {
unrefElement(inputBoxButton).click();
watch(inputValue, (val, oldVal) => {
if (!oldVal) {
const action = props.actions?.find(v => v.shortcut === val);
if (action) {
emit("quickSelect", action);
}
}
watch(inputBoxFocused, () => {
if (inputBoxFocused.value)
revealActions();
else
inputValue.value = "";
})
});
watch(inputValue, (val, oldVal) => {
if (!oldVal) {
let action = props.actions?.find(v => v.shortcut == val);
if (action) {
emit("quickSelect", action)
}
}
})
const filteredActions = computed(() => {
return (props.actions || []).filter(action => {
return (
action.text.toLowerCase().includes(inputValue.value.toLowerCase()) ||
action.shortcut?.includes(inputValue.value.toLowerCase())
)
})
})
const filteredActions = computed(() => {
return (props.actions || []).filter(action => {
return (
action.text.toLowerCase().includes(inputValue.value.toLowerCase()) ||
action.shortcut?.includes(inputValue.value.toLowerCase())
);
});
});
defineExpose({ focused: inputBoxFocused, revealActions })
defineExpose({ focused: inputBoxFocused, revealActions });
export type { QuickMenuAction, ExposedProps as QuickMenuInput }
</script>
export type { QuickMenuAction, ExposedProps };
</script>
115 changes: 60 additions & 55 deletions frontend/components/global/QuickMenu/Modal.vue
Original file line number Diff line number Diff line change
@@ -1,65 +1,70 @@
<template>
<BaseModal v-model="modal" :show-close-button="false">
<div class="relative">
<QuickMenuInput ref="inputBox" v-model="selectedAction" :actions="props.actions || []" @quickSelect="invokeAction"></QuickMenuInput>
<ul v-if=false class="menu rounded-box w-full">
<li v-for="(action, idx) in (actions || [])" :key="idx">
<button
@click="invokeAction(action)"
class="transition-colors w-full text-left rounded-btn p-3 hover:bg-neutral hover:text-white">
<b v-if="action.shortcut">{{action.shortcut}}.</b>

{{ action.text }}
</button>
</li>
</ul>
<span class="text-base-300">Use number keys to quick select.</span>
</div>
</BaseModal>
<BaseModal v-model="modal" :show-close-button="false">
<div class="relative">
<QuickMenuInput
ref="inputBox"
v-model="selectedAction"
:actions="props.actions || []"
@quick-select="invokeAction"
></QuickMenuInput>
<ul v-if="false" class="menu rounded-box w-full">
<li v-for="(action, idx) in actions || []" :key="idx">
<button
class="rounded-btn w-full p-3 text-left transition-colors hover:bg-neutral hover:text-white"
@click="invokeAction(action)"
>
<b v-if="action.shortcut">{{ action.shortcut }}.</b>

{{ action.text }}
</button>
</li>
</ul>
<span class="text-base-300">Use number keys to quick select.</span>
</div>
</BaseModal>
</template>

<script setup lang="ts">
import type { QuickMenuAction, QuickMenuInput } from "./Input.vue"
const props = defineProps({
modelValue: {
type: Boolean,
required: true,
},
actions: {
type: Array as PropType<QuickMenuAction[]>,
required: false,
},
});
import type { ExposedProps as QuickMenuInputData, QuickMenuAction } from "./Input.vue";
const props = defineProps({
modelValue: {
type: Boolean,
required: true,
},
actions: {
type: Array as PropType<QuickMenuAction[]>,
required: false,
default: () => [],
},
});
const modal = useVModel(props, "modelValue");
const selectedAction = ref<QuickMenuAction>();
const inputBox = ref<QuickMenuInputData>({ focused: false, revealActions: () => {} });
const modal = useVModel(props, "modelValue");
const selectedAction = ref<QuickMenuAction>();
const inputBox = ref<QuickMenuInput>({ focused: false, revealActions: () => {} });
const onModalOpen = useTimeoutFn(() => {
inputBox.value.focused = true;
}, 50).start
const onModalOpen = useTimeoutFn(() => {
inputBox.value.focused = true;
}, 50).start;
const onModalClose = () => {
selectedAction.value = undefined
inputBox.value.focused = false
}
const onModalClose = () => {
selectedAction.value = undefined;
inputBox.value.focused = false;
};
watch(modal, () => (modal.value ? onModalOpen : onModalClose)())
watch(modal, () => (modal.value ? onModalOpen : onModalClose)());
onStartTyping(() => {
inputBox.value.focused = true;
});
onStartTyping(() => {
inputBox.value.focused = true
})
function invokeAction(action: QuickMenuAction) {
modal.value = false;
useTimeoutFn(action.action, 100).start();
}
function invokeAction(action: QuickMenuAction) {
modal.value = false;
useTimeoutFn(action.action, 100).start();
}
watch(selectedAction, (action) => {
if (action)
invokeAction(action)
})
</script>
watch(selectedAction, action => {
if (action) invokeAction(action);
});
</script>
Loading

0 comments on commit ca33267

Please sign in to comment.