diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/c-input-text/c-input-text.vue | 42 | ||||
-rw-r--r-- | src/ui/c-modal/c-modal.demo.vue | 15 | ||||
-rw-r--r-- | src/ui/c-modal/c-modal.theme.ts | 11 | ||||
-rw-r--r-- | src/ui/c-modal/c-modal.vue | 74 | ||||
-rw-r--r-- | src/ui/theme/themes.ts | 2 |
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', |