Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 6 additions & 15 deletions components/LoadingIndicator.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
<template>
<svg
class="h-4 w-4 animate-spin"
viewBox="3 3 18 18"
role="presentation"
>
<path
class="fill-primary"
d="M12 5C8.13401 5 5 8.13401 5 12C5 15.866 8.13401 19 12 19C15.866 19 19 15.866 19 12C19 8.13401 15.866 5 12 5ZM3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12Z"
/>
<path
class="fill-white"
d="M16.9497 7.05015C14.2161 4.31648 9.78392 4.31648 7.05025 7.05015C6.65973 7.44067 6.02656 7.44067 5.63604 7.05015C5.24551 6.65962 5.24551 6.02646 5.63604 5.63593C9.15076 2.12121 14.8492 2.12121 18.364 5.63593C18.7545 6.02646 18.7545 6.65962 18.364 7.05015C17.9734 7.44067 17.3403 7.44067 16.9497 7.05015Z"
/>
</svg>
</template>
<Spinner size="sm" v-bind="$attrs" />
</template>

<script setup lang="ts">
import { Spinner } from "@libretexts/davis-vue";
</script>
54 changes: 17 additions & 37 deletions components/ThemedButton.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
<template>
<button v-bind="$attrs" :class="variantClasses" :aria-busy="$props.loading"
:disabled="$props.disabled || $props.loading">
<template v-if="!$props.loading">
<div class="flex items-center justify-center">
<component :is="TablerIconsVue[$props.icon]" class="w-5 h-5 mr-3" v-if="$props.icon" />
<slot />
</div>
</template>
<template v-else>
<LoadingIndicator />
<span class="ml-2">{{ $t("common.loading") }}...</span>
</template>
</button>
<Button
v-bind="$attrs"
:variant="davisVariant"
:size="props.small ? 'sm' : 'md'"
:loading="props.loading"
:disabled="props.disabled"
:full-width="!props.small"
>
<component :is="TablerIconsVue[props.icon]" class="w-5 h-5 mr-2" v-if="props.icon && !props.loading" />
<slot />
</Button>
</template>

<script setup lang="ts">
import { computed } from "vue";
import LoadingIndicator from "@components/LoadingIndicator.vue";
import { Button } from "@libretexts/davis-vue";
import * as TablerIconsVue from "@tabler/icons-vue";

const props = withDefaults(
Expand All @@ -35,34 +33,16 @@ const props = withDefaults(
}
);

const variantClasses = computed(() => {
const baseClasses =
"flex items-center justify-center rounded-md text-white font-medium hover:shadow";

const sizeClasses = props.small ? "w-40 h-6 text-sm pb-0.5" : "w-full h-10";

//If the button is disabled, we don't want to apply any of the other classes
if (props.disabled) {
return `${baseClasses} ${sizeClasses} bg-gray-400 cursor-default`;
}

let variantClasses = "";
const davisVariant = computed(() => {
switch (props.variant) {
case "save":
variantClasses = "bg-save hover:bg-green-600";
break;
return "primary";
case "outlined":
variantClasses =
"bg-transparent border border-primary text-sky-700 text-primary";
break;
return "outline";
case "danger":
variantClasses = "bg-red-500 hover:bg-red-600";
break;
return "destructive";
default:
variantClasses = "bg-primary hover:bg-sky-700";
break;
return "primary";
}

return `${baseClasses} ${sizeClasses} ${variantClasses}`;
});
</script>
116 changes: 44 additions & 72 deletions components/ThemedInput.vue
Original file line number Diff line number Diff line change
@@ -1,77 +1,49 @@
<template>
<div
:class="type === 'checkbox' ? 'flex flex-row items-start' : 'flex flex-col'"
<Checkbox
v-if="type === 'checkbox'"
v-bind="$attrs"
>
<label
v-if="label && type !== 'checkbox'"
:for="id"
:class="`block text-sm font-medium ${instructions ? 'mb-1' : 'mb-2'}`"
>
{{ label }}<span
v-if="required"
class="text-red-500"
>*</span>
</label>
<p
v-if="instructions && type !== 'checkbox'"
class="text-xs mb-2 text-slate-500 italic"
>
{{ instructions }}
</p>
<input
:id="id"
:checked="type === 'checkbox' ? (modelValue as boolean) : undefined"
:value="type !== 'checkbox' ? (modelValue as string) : undefined"
:type="type"
:required="required"
:aria-required="required"
@input="
type === 'checkbox'
? $emit('update:modelValue', ($event.target as HTMLInputElement).checked)
: $emit('update:modelValue', ($event.target as HTMLInputElement).value)
"
:placeholder="placeholder"
:class="[
type === 'checkbox'
? 'h-4 w-4 mt-0.5 mr-2 cursor-pointer flex-shrink-0'
: 'border block h-10 w-full rounded-md px-2 placeholder:text-slate-400',
]"
>
<label
v-if="label && type === 'checkbox'"
:for="id"
class="text-sm font-normal cursor-pointer flex-1"
>
{{ label }}<span
v-if="required"
class="text-red-500"
>*</span>
</label>
</div>
:id="id"
:name="id"
:label="label"
:model-value="(modelValue as boolean)"
:required="required"
@update:model-value="$emit('update:modelValue', $event)"
/>
<Input
v-else
v-bind="$attrs"
:name="id"
:label="label"
:placeholder="placeholder"
:helper-text="instructions"
:model-value="(modelValue as string)"
:type="type"
:required="required"
@update:model-value="$emit('update:modelValue', $event)"
/>
</template>

<script lang="ts" setup>
import { defineProps } from 'vue';
defineEmits(['update:modelValue']);
withDefaults(
defineProps<{
id: string;
label?: string;
placeholder?: string;
instructions?: string;
modelValue?: string | boolean;
type?: string;
required?: boolean;
}>(),
{
id: '',
label: '',
placeholder: '',
instructions: '',
modelValue: '',
type: 'text',
required: false,
},
);
</script>
import { Input, Checkbox } from '@libretexts/davis-vue';
defineEmits(['update:modelValue']);
withDefaults(
defineProps<{
id: string;
label?: string;
placeholder?: string;
instructions?: string;
modelValue?: string | boolean;
type?: string;
required?: boolean;
}>(),
{
id: '',
label: '',
placeholder: '',
instructions: '',
modelValue: '',
type: 'text',
required: false,
},
);
</script>
29 changes: 9 additions & 20 deletions components/ThemedModal.vue
Original file line number Diff line number Diff line change
@@ -1,33 +1,22 @@
<template>
<dialog
class="bg-white shadow-md rounded-md p-8 z-50"
ref="dialogRef"
@click="closeFromEvent"
>
<Dialog :open="isOpen" @close="isOpen = false">
<slot />
</dialog>
</Dialog>
</template>

<script setup lang="ts">
import { ref, defineExpose } from "vue";
const dialogRef = ref<HTMLDialogElement | null>(null);
import { ref } from "vue";
import { Dialog } from "@libretexts/davis-vue";

const isOpen = ref(false);

const show = () => {
dialogRef.value?.showModal();
isOpen.value = true;
};

const close = () => {
dialogRef.value?.close();
};

const closeFromEvent = (e: MouseEvent) => {
if (e.currentTarget === e.target) {
close();
}
isOpen.value = false;
};

defineExpose({
show,
close,
});
defineExpose({ show, close });
</script>
Loading