|
<script setup lang="ts"> |
|
import { RiArrowRightLine } from '@remixicon/vue'; |
|
import { useI18n } from 'vue-i18n'; |
|
type Emits = { |
|
(e: 'search', val: string): void, |
|
} |
|
|
|
type Props = { |
|
loading: boolean |
|
autofocus: boolean |
|
limit?: number |
|
} |
|
|
|
const { t } = useI18n(); |
|
|
|
const props = withDefaults(defineProps<Props>(), { |
|
limit: 520 |
|
}); |
|
|
|
const emits = defineEmits<Emits>(); |
|
|
|
const query = defineModel<string>(); |
|
|
|
const onSearch = () => { |
|
if (!query.value?.trim()) return; |
|
emits('search', query.value.trim()); |
|
}; |
|
</script> |
|
|
|
<template> |
|
<div id="searchbar" class="flex flex-row rounded-3xl bg-zinc-100 p-2 transition-all dark:bg-zinc-800"> |
|
<div class="grow overflow-hidden rounded-3xl border border-zinc-100 dark:border-zinc-300 dark:bg-zinc-600"> |
|
<t-input |
|
v-model="query" |
|
:disabled="props.loading" |
|
:autofocus="autofocus" |
|
:maxlength="limit" |
|
:placeholder="t('tips.search')" |
|
size="large" |
|
clearable |
|
@enter="onSearch" |
|
> |
|
<template #suffix> |
|
<t-button :disabled="loading" shape="round" variant="base" @click="onSearch"> |
|
<template #icon><RiArrowRightLine /></template> |
|
</t-button> |
|
</template> |
|
</t-input> |
|
</div> |
|
<div class="grow-0"> |
|
<slot /> |
|
</div> |
|
</div> |
|
</template> |
|
|
|
|
|
<style scoped> |
|
#searchbar { |
|
--td-radius-default: 24px; |
|
} |
|
</style> |
|
|