feat(lite/component): New multicolor modal (#6394)
This commit is contained in:
parent
5218d6df1a
commit
4b3728e8d8
@ -14,46 +14,44 @@
|
|||||||
</UiActionButton>
|
</UiActionButton>
|
||||||
</UiFilterGroup>
|
</UiFilterGroup>
|
||||||
|
|
||||||
<UiModal v-if="isOpen">
|
<UiModal v-if="isOpen" :icon="faFilter" @submit.prevent="handleSubmit">
|
||||||
<form @submit.prevent="handleSubmit">
|
<div class="rows">
|
||||||
<div class="rows">
|
<CollectionFilterRow
|
||||||
<CollectionFilterRow
|
v-for="(newFilter, index) in newFilters"
|
||||||
v-for="(newFilter, index) in newFilters"
|
:key="newFilter.id"
|
||||||
:key="newFilter.id"
|
v-model="newFilters[index]"
|
||||||
v-model="newFilters[index]"
|
:available-filters="availableFilters"
|
||||||
:available-filters="availableFilters"
|
@remove="removeNewFilter"
|
||||||
@remove="removeNewFilter"
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="newFilters.some((filter) => filter.isAdvanced)"
|
v-if="newFilters.some((filter) => filter.isAdvanced)"
|
||||||
class="available-properties"
|
class="available-properties"
|
||||||
>
|
>
|
||||||
{{ $t("available-properties-for-advanced-filter") }}
|
{{ $t("available-properties-for-advanced-filter") }}
|
||||||
<div class="properties">
|
<div class="properties">
|
||||||
<UiBadge
|
<UiBadge
|
||||||
v-for="(filter, property) in availableFilters"
|
v-for="(filter, property) in availableFilters"
|
||||||
:key="property"
|
:key="property"
|
||||||
:icon="getFilterIcon(filter)"
|
:icon="getFilterIcon(filter)"
|
||||||
>
|
>
|
||||||
{{ property }}
|
{{ property }}
|
||||||
</UiBadge>
|
</UiBadge>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<UiButtonGroup>
|
<template #buttons>
|
||||||
<UiButton color="secondary" @click="addNewFilter">
|
<UiButton transparent @click="addNewFilter">
|
||||||
{{ $t("add-or") }}
|
{{ $t("add-or") }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
<UiButton :disabled="!isFilterValid" type="submit">
|
<UiButton :disabled="!isFilterValid" type="submit">
|
||||||
{{ $t(editedFilter ? "update" : "add") }}
|
{{ $t(editedFilter ? "update" : "add") }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
<UiButton color="secondary" @click="handleCancel">
|
<UiButton outlined @click="handleCancel">
|
||||||
{{ $t("cancel") }}
|
{{ $t("cancel") }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</UiButtonGroup>
|
</template>
|
||||||
</form>
|
|
||||||
</UiModal>
|
</UiModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -61,12 +59,11 @@
|
|||||||
import { Or, parse } from "complex-matcher";
|
import { Or, parse } from "complex-matcher";
|
||||||
import { computed, ref } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import type { Filters, NewFilter } from "@/types/filter";
|
import type { Filters, NewFilter } from "@/types/filter";
|
||||||
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
import { faFilter, faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||||
import CollectionFilterRow from "@/components/CollectionFilterRow.vue";
|
import CollectionFilterRow from "@/components/CollectionFilterRow.vue";
|
||||||
import UiActionButton from "@/components/ui/UiActionButton.vue";
|
import UiActionButton from "@/components/ui/UiActionButton.vue";
|
||||||
import UiBadge from "@/components/ui/UiBadge.vue";
|
import UiBadge from "@/components/ui/UiBadge.vue";
|
||||||
import UiButton from "@/components/ui/UiButton.vue";
|
import UiButton from "@/components/ui/UiButton.vue";
|
||||||
import UiButtonGroup from "@/components/ui/UiButtonGroup.vue";
|
|
||||||
import UiFilter from "@/components/ui/UiFilter.vue";
|
import UiFilter from "@/components/ui/UiFilter.vue";
|
||||||
import UiFilterGroup from "@/components/ui/UiFilterGroup.vue";
|
import UiFilterGroup from "@/components/ui/UiFilterGroup.vue";
|
||||||
import UiModal from "@/components/ui/UiModal.vue";
|
import UiModal from "@/components/ui/UiModal.vue";
|
||||||
|
@ -17,35 +17,33 @@
|
|||||||
</UiActionButton>
|
</UiActionButton>
|
||||||
</UiFilterGroup>
|
</UiFilterGroup>
|
||||||
|
|
||||||
<UiModal v-if="isOpen">
|
<UiModal v-if="isOpen" @submit.prevent="handleSubmit" :icon="faSort">
|
||||||
<form @submit.prevent="handleSubmit">
|
<div class="form-widgets">
|
||||||
<div class="form-widgets">
|
<FormWidget :label="$t('sort-by')">
|
||||||
<FormWidget :label="$t('sort-by')">
|
<select v-model="newSortProperty">
|
||||||
<select v-model="newSortProperty">
|
<option v-if="!newSortProperty"></option>
|
||||||
<option v-if="!newSortProperty"></option>
|
<option
|
||||||
<option
|
v-for="(sort, property) in availableSorts"
|
||||||
v-for="(sort, property) in availableSorts"
|
:key="property"
|
||||||
:key="property"
|
:value="property"
|
||||||
:value="property"
|
>
|
||||||
>
|
{{ sort.label ?? property }}
|
||||||
{{ sort.label ?? property }}
|
</option>
|
||||||
</option>
|
</select>
|
||||||
</select>
|
</FormWidget>
|
||||||
</FormWidget>
|
<FormWidget>
|
||||||
<FormWidget>
|
<select v-model="newSortIsAscending">
|
||||||
<select v-model="newSortIsAscending">
|
<option :value="true">{{ $t("ascending") }}</option>
|
||||||
<option :value="true">{{ $t("ascending") }}</option>
|
<option :value="false">{{ $t("descending") }}</option>
|
||||||
<option :value="false">{{ $t("descending") }}</option>
|
</select>
|
||||||
</select>
|
</FormWidget>
|
||||||
</FormWidget>
|
</div>
|
||||||
</div>
|
<template #buttons>
|
||||||
<UiButtonGroup>
|
<UiButton type="submit">{{ $t("add") }}</UiButton>
|
||||||
<UiButton type="submit">{{ $t("add") }}</UiButton>
|
<UiButton outlined @click="handleCancel">
|
||||||
<UiButton color="secondary" @click="handleCancel">
|
|
||||||
{{ $t("cancel") }}
|
{{ $t("cancel") }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</UiButtonGroup>
|
</template>
|
||||||
</form>
|
|
||||||
</UiModal>
|
</UiModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -56,11 +54,11 @@ import {
|
|||||||
faCaretDown,
|
faCaretDown,
|
||||||
faCaretUp,
|
faCaretUp,
|
||||||
faPlus,
|
faPlus,
|
||||||
|
faSort,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import FormWidget from "@/components/FormWidget.vue";
|
import FormWidget from "@/components/FormWidget.vue";
|
||||||
import UiButton from "@/components/ui/UiButton.vue";
|
import UiButton from "@/components/ui/UiButton.vue";
|
||||||
import UiActionButton from "@/components/ui/UiActionButton.vue";
|
import UiActionButton from "@/components/ui/UiActionButton.vue";
|
||||||
import UiButtonGroup from "@/components/ui/UiButtonGroup.vue";
|
|
||||||
import UiFilter from "@/components/ui/UiFilter.vue";
|
import UiFilter from "@/components/ui/UiFilter.vue";
|
||||||
import UiFilterGroup from "@/components/ui/UiFilterGroup.vue";
|
import UiFilterGroup from "@/components/ui/UiFilterGroup.vue";
|
||||||
import UiModal from "@/components/ui/UiModal.vue";
|
import UiModal from "@/components/ui/UiModal.vue";
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
<style lang="postcss" scoped>
|
<style lang="postcss" scoped>
|
||||||
.ui-filter-group {
|
.ui-filter-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background-color: var(--background-color-primary);
|
background-color: var(--background-color-primary);
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
@ -1,38 +1,151 @@
|
|||||||
<template>
|
<template>
|
||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
<div class="ui-modal">
|
<form
|
||||||
<div class="content">
|
:class="className"
|
||||||
<slot />
|
class="ui-modal"
|
||||||
|
v-bind="$attrs"
|
||||||
|
@click.self="emit('close')"
|
||||||
|
>
|
||||||
|
<div class="container">
|
||||||
|
<span v-if="onClose" class="close-icon" @click="emit('close')">
|
||||||
|
<FontAwesomeIcon :icon="faXmark" />
|
||||||
|
</span>
|
||||||
|
<div v-if="icon || $slots.icon" class="modal-icon">
|
||||||
|
<slot name="icon">
|
||||||
|
<FontAwesomeIcon :icon="icon" />
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<UiTitle v-if="$slots.title" type="h4">
|
||||||
|
<slot name="title" />
|
||||||
|
</UiTitle>
|
||||||
|
<div v-if="$slots.subtitle" class="subtitle">
|
||||||
|
<slot name="subtitle" />
|
||||||
|
</div>
|
||||||
|
<div v-if="$slots.default" class="content">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
<UiButtonGroup :color="color">
|
||||||
|
<slot name="buttons" />
|
||||||
|
</UiButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup></script>
|
<script lang="ts" setup>
|
||||||
|
import { computed } from "vue";
|
||||||
|
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
|
||||||
|
import { faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { useMagicKeys, whenever } from "@vueuse/core";
|
||||||
|
import UiButtonGroup from "@/components/ui/UiButtonGroup.vue";
|
||||||
|
import UiTitle from "@/components/ui/UiTitle.vue";
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
icon?: IconDefinition;
|
||||||
|
color?: "info" | "warning" | "error" | "success";
|
||||||
|
onClose?: () => void;
|
||||||
|
}>(),
|
||||||
|
{ color: "info" }
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(event: "close"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { escape } = useMagicKeys();
|
||||||
|
whenever(escape, () => emit("close"));
|
||||||
|
|
||||||
|
const className = computed(() => {
|
||||||
|
return [`color-${props.color}`, { "has-icon": props.icon !== undefined }];
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="postcss" scoped>
|
<style lang="postcss" scoped>
|
||||||
.ui-modal {
|
.ui-modal {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
|
||||||
background-color: #00000080;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
background-color: #00000080;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.color-success {
|
||||||
background-color: var(--background-color-primary);
|
--modal-color: var(--color-green-infra-base);
|
||||||
|
--modal-background-color: var(--background-color-green-infra);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-info {
|
||||||
|
--modal-color: var(--color-extra-blue-base);
|
||||||
|
--modal-background-color: var(--background-color-extra-blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-warning {
|
||||||
|
--modal-color: var(--color-orange-world-base);
|
||||||
|
--modal-background-color: var(--background-color-orange-world);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-error {
|
||||||
|
--modal-color: var(--color-red-vates-base);
|
||||||
|
--modal-background-color: var(--background-color-red-vates);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
min-width: 40rem;
|
min-width: 40rem;
|
||||||
padding: 2rem;
|
padding: 4.2rem;
|
||||||
|
text-align: center;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
|
background-color: var(--modal-background-color);
|
||||||
box-shadow: var(--shadow-400);
|
box-shadow: var(--shadow-400);
|
||||||
}
|
}
|
||||||
|
|
||||||
:slotted(.ui-button-group) {
|
.close-icon {
|
||||||
justify-content: center;
|
font-size: 2rem;
|
||||||
margin-top: 1rem;
|
position: absolute;
|
||||||
|
top: 1.5rem;
|
||||||
|
right: 2rem;
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--modal-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container :slotted(.accent) {
|
||||||
|
color: var(--modal-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-icon {
|
||||||
|
font-size: 4.8rem;
|
||||||
|
margin: 2rem 0;
|
||||||
|
color: var(--modal-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-title {
|
||||||
|
margin-top: 4rem;
|
||||||
|
|
||||||
|
.has-icon & {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
font-weight: 400;
|
||||||
|
color: var(--color-blue-scale-200);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-button-group {
|
||||||
|
margin-top: 4rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
||||||
export default function useModal() {
|
export default function useModal<T>() {
|
||||||
const $payload = ref();
|
const $payload = ref<T>();
|
||||||
const $isOpen = ref(false);
|
const $isOpen = ref(false);
|
||||||
|
|
||||||
const open = (payload?: any) => {
|
const open = (payload?: T) => {
|
||||||
$isOpen.value = true;
|
$isOpen.value = true;
|
||||||
$payload.value = payload;
|
$payload.value = payload;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user