style(stage-ui,stage-tamagotchi): improved style
This commit is contained in:
@@ -4,17 +4,17 @@ import { Select } from '@proj-airi/ui'
|
||||
const props = defineProps<{
|
||||
label: string
|
||||
description?: string
|
||||
options: { label: string, value: string | number }[]
|
||||
options?: { label: string, value: string | number }[]
|
||||
placeholder?: string
|
||||
disabled?: boolean
|
||||
}>()
|
||||
|
||||
const modelValue = defineModel<string>({ required: true })
|
||||
const modelValue = defineModel<string>({ required: false })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label flex="~ col gap-4">
|
||||
<div flex="~ row col" justify-center gap-2>
|
||||
<div flex="~ row" items-center gap-2>
|
||||
<div flex="1">
|
||||
<div class="flex items-center gap-1 text-sm font-medium">
|
||||
{{ props.label }}
|
||||
@@ -23,13 +23,15 @@ const modelValue = defineModel<string>({ required: true })
|
||||
{{ props.description }}
|
||||
</div>
|
||||
</div>
|
||||
<Select
|
||||
v-model="modelValue"
|
||||
:options="props.options"
|
||||
:placeholder="props.placeholder"
|
||||
:disabled="props.disabled"
|
||||
:title="label"
|
||||
/>
|
||||
<slot>
|
||||
<Select
|
||||
v-model="modelValue"
|
||||
:options="props.options"
|
||||
:placeholder="props.placeholder"
|
||||
:disabled="props.disabled"
|
||||
:title="label"
|
||||
/>
|
||||
</slot>
|
||||
</div>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { inject } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
value: string | number
|
||||
label?: string
|
||||
active?: boolean
|
||||
}>()
|
||||
|
||||
const selectOption = inject('selectOption') as (value: string | number) => void
|
||||
const hide = inject('hide') as () => void
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-bind="{ ...$attrs, class: null, style: null }"
|
||||
class="cursor-pointer rounded px-2 py-1.5 text-sm text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
||||
:class="{ 'bg-neutral-100 dark:bg-neutral-800': props.active }"
|
||||
@click="() => {
|
||||
selectOption(props.value)
|
||||
hide()
|
||||
}"
|
||||
>
|
||||
<slot>
|
||||
{{ props.label }}
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,24 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Dropdown as VDropdown } from 'floating-vue'
|
||||
import { computed } from 'vue'
|
||||
import { provide, ref } from 'vue'
|
||||
|
||||
import UIOption from './Option.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
options: { label: string, value: string | number }[]
|
||||
options?: { label: string, value: string | number }[]
|
||||
placeholder?: string
|
||||
disabled?: boolean
|
||||
title?: string
|
||||
}>()
|
||||
|
||||
const modelValue = defineModel<string | number>({ required: true })
|
||||
|
||||
const selectedLabel = computed(() => {
|
||||
const selected = props.options.find(opt => opt.value === modelValue.value)
|
||||
return selected ? selected.label : props.placeholder
|
||||
})
|
||||
const show = ref(false)
|
||||
const modelValue = defineModel<string | number>({ required: false })
|
||||
|
||||
function selectOption(value: string | number) {
|
||||
modelValue.value = value
|
||||
}
|
||||
|
||||
function handleHide() {
|
||||
show.value = false
|
||||
}
|
||||
|
||||
provide('selectOption', selectOption)
|
||||
provide('hide', handleHide)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -31,27 +36,24 @@ function selectOption(value: string | number) {
|
||||
:class="{ 'pointer-events-none': props.disabled }"
|
||||
>
|
||||
<div class="flex-1 truncate">
|
||||
<slot :label="selectedLabel">
|
||||
{{ selectedLabel }}
|
||||
</slot>
|
||||
<slot :value="modelValue" />
|
||||
</div>
|
||||
<div i-solar:alt-arrow-down-bold-duotone class="h-3.5 w-3.5 text-neutral-500 dark:text-neutral-400" />
|
||||
<div i-solar:alt-arrow-down-linear class="h-3.5 w-3.5 text-neutral-500 dark:text-neutral-400" />
|
||||
</div>
|
||||
|
||||
<template #popper="{ hide }">
|
||||
<div class="min-w-[160px] flex flex-col gap-0.5 border border-neutral-200 rounded-lg bg-white p-1 shadow-lg dark:border-neutral-800 dark:bg-neutral-900">
|
||||
<div
|
||||
v-for="option of props.options"
|
||||
v-bind="{ ...$attrs, class: null, style: null }"
|
||||
:key="option.value"
|
||||
class="cursor-pointer rounded px-2 py-1.5 text-sm text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
||||
:class="{
|
||||
'bg-neutral-100 dark:bg-neutral-800': modelValue === option.value,
|
||||
}"
|
||||
@click="selectOption(option.value); hide()"
|
||||
>
|
||||
{{ option.label }}
|
||||
</div>
|
||||
<slot name="options" :hide="hide">
|
||||
<template v-if="props.options && props.options.length">
|
||||
<UIOption
|
||||
v-for="option of props.options"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
:label="option.label"
|
||||
:active="modelValue === option.value"
|
||||
/>
|
||||
</template>
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
</VDropdown>
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { default as Option } from './Option.vue'
|
||||
export { default as Select } from './Select.vue'
|
||||
|
||||
Reference in New Issue
Block a user