aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/c-input-text/c-input-text.vue42
-rw-r--r--src/ui/c-modal/c-modal.demo.vue15
-rw-r--r--src/ui/c-modal/c-modal.theme.ts11
-rw-r--r--src/ui/c-modal/c-modal.vue74
-rw-r--r--src/ui/theme/themes.ts2
5 files changed, 139 insertions, 5 deletions
diff --git a/src/ui/c-input-text/c-input-text.vue b/src/ui/c-input-text/c-input-text.vue
index 513834d..b89d1e4 100644
--- a/src/ui/c-input-text/c-input-text.vue
+++ b/src/ui/c-input-text/c-input-text.vue
@@ -29,6 +29,7 @@ const props = withDefaults(
multiline?: boolean
rows?: number | string
autosize?: boolean
+ autofocus?: boolean
}>(),
{
value: '',
@@ -54,13 +55,14 @@ const props = withDefaults(
multiline: false,
rows: 3,
autosize: false,
+ autofocus: false,
},
);
const emit = defineEmits(['update:value']);
const value = useVModel(props, 'value', emit);
const showPassword = ref(false);
-const { id, placeholder, label, validationRules, labelPosition, labelWidth, labelAlign, autosize, readonly, disabled, clearable, type, multiline, rows, rawText } = toRefs(props);
+const { id, placeholder, label, validationRules, labelPosition, labelWidth, labelAlign, autosize, readonly, disabled, clearable, type, multiline, rows, rawText, autofocus } = toRefs(props);
const validation
= props.validation
@@ -74,12 +76,9 @@ const theme = useTheme();
const appTheme = useAppTheme();
const textareaRef = ref<HTMLTextAreaElement>();
+const inputRef = ref<HTMLInputElement>();
const inputWrapperRef = ref<HTMLElement>();
-defineExpose({
- inputWrapperRef,
-});
-
watch(
value,
() => {
@@ -107,6 +106,38 @@ const htmlInputType = computed(() => {
return 'text';
});
+
+function focus() {
+ if (textareaRef.value) {
+ textareaRef.value.focus();
+ }
+
+ if (inputRef.value) {
+ inputRef.value.focus();
+ }
+}
+
+function blur() {
+ if (textareaRef.value) {
+ textareaRef.value.blur?.();
+ }
+
+ if (inputRef.value) {
+ inputRef.value.blur?.();
+ }
+}
+
+onMounted(() => {
+ if (autofocus.value) {
+ focus();
+ }
+});
+
+defineExpose({
+ inputWrapperRef,
+ focus,
+ blur,
+});
</script>
<template>
@@ -140,6 +171,7 @@ const htmlInputType = computed(() => {
<input
v-else
:id="id"
+ ref="inputRef"
v-model="value"
:type="htmlInputType"
class="input"
diff --git a/src/ui/c-modal/c-modal.demo.vue b/src/ui/c-modal/c-modal.demo.vue
new file mode 100644
index 0000000..c4349f6
--- /dev/null
+++ b/src/ui/c-modal/c-modal.demo.vue
@@ -0,0 +1,15 @@
+<script lang="ts" setup>
+const modal1 = ref();
+</script>
+
+<template>
+ <div>
+ <c-button @click="() => modal1?.open()">
+ Open Modal
+ </c-button>
+
+ <c-modal ref="modal1">
+ Content
+ </c-modal>
+ </div>
+</template>
diff --git a/src/ui/c-modal/c-modal.theme.ts b/src/ui/c-modal/c-modal.theme.ts
new file mode 100644
index 0000000..0681417
--- /dev/null
+++ b/src/ui/c-modal/c-modal.theme.ts
@@ -0,0 +1,11 @@
+import { defineThemes } from '../theme/theme.models';
+import { appThemes } from '../theme/themes';
+
+export const { useTheme } = defineThemes({
+ dark: {
+ background: appThemes.dark.background,
+ },
+ light: {
+ background: appThemes.light.background,
+ },
+});
diff --git a/src/ui/c-modal/c-modal.vue b/src/ui/c-modal/c-modal.vue
new file mode 100644
index 0000000..af92f01
--- /dev/null
+++ b/src/ui/c-modal/c-modal.vue
@@ -0,0 +1,74 @@
+<script setup lang="ts">
+import { useTheme } from './c-modal.theme';
+
+const props = withDefaults(defineProps<{ open?: boolean; centered?: boolean }>(), {
+ open: false,
+ centered: true,
+});
+const emit = defineEmits(['update:open']);
+const isOpen = useVModel(props, 'open', emit, { passive: true });
+
+const { centered } = toRefs(props);
+
+function close() {
+ isOpen.value = false;
+}
+
+function open() {
+ isOpen.value = true;
+}
+
+function toggle() {
+ isOpen.value = !isOpen.value;
+}
+
+defineExpose({
+ close,
+ open,
+ toggle,
+ isOpen,
+});
+
+defineOptions({
+ inheritAttrs: false,
+});
+
+const theme = useTheme();
+const modal = ref();
+
+onClickOutside(modal, () => {
+ if (isOpen.value) {
+ close();
+ }
+});
+</script>
+
+<template>
+ <transition>
+ <div v-if="isOpen" class="c-modal--overlay" fixed left-0 top-0 z-10 h-full w-full flex justify-center px-2 :class="{ 'items-center': centered }">
+ <div ref="modal" class="c-modal--container" v-bind="$attrs" max-w-xl w-full flex-grow rounded-md pa-24px>
+ <slot />
+ </div>
+ </div>
+ </transition>
+</template>
+
+<style scoped lang="less">
+.c-modal--overlay {
+ background-color: rgba(0, 0, 0, 0.5);
+}
+
+.c-modal--container {
+ background-color: v-bind('theme.background');
+}
+
+.v-enter-active,
+.v-leave-active {
+ transition: opacity 0.3s ease-in-out;
+}
+
+.v-enter-from,
+.v-leave-to {
+ opacity: 0;
+}
+</style>
diff --git a/src/ui/theme/themes.ts b/src/ui/theme/themes.ts
index 81d7ddf..2c330b0 100644
--- a/src/ui/theme/themes.ts
+++ b/src/ui/theme/themes.ts
@@ -2,6 +2,7 @@ import { defineThemes } from './theme.models';
export const { themes: appThemes, useTheme: useAppTheme } = defineThemes({
light: {
+ background: '#ffffff',
text: {
baseColor: '#333639',
mutedColor: '#767c82',
@@ -37,6 +38,7 @@ export const { themes: appThemes, useTheme: useAppTheme } = defineThemes({
},
},
dark: {
+ background: '#1e1e1e',
text: {
baseColor: '#ffffffd1',
mutedColor: '#ffffff80',