feat(ui): add label prop and slot to textarea component

This commit is contained in:
upsiflu 2024-12-29 18:31:18 +01:00
parent 9e3f2cfb57
commit b2ba7e1e6a
3 changed files with 73 additions and 29 deletions

View File

@ -4,8 +4,9 @@ import { useTextareaAutosize, computedWithControl, useManualRefHistory, watchDeb
import Button from './Button.vue' import Button from './Button.vue'
import Markdown from './Markdown.vue' import Markdown from './Markdown.vue'
import Layout from '~/components/ui/Layout.vue'
const { max=Infinity, placeholder='' } = defineProps<{ max?:number,placeholder?:string }>() const { max=Infinity, placeholder='', ...restProps } = defineProps<{ max?:number,placeholder?:string, label?:string }>()
const model = defineModel<string>({ default: '' }) const model = defineModel<string>({ default: '' })
@ -177,6 +178,15 @@ const focus = () => textarea.value.focus()
</script> </script>
<template> <template>
<Layout stack no-gap label
class="funkwhale textarea-label"
>
<span v-if="$slots['label']" class="label">
<slot name="label" />
</span>
<span v-if="restProps.label" class="label">
{{ restProps.label }}
</span>
<div :class="{ 'has-preview': preview }" class="funkwhale textarea" @mousedown.prevent="focus" @mouseup.prevent="focus"> <div :class="{ 'has-preview': preview }" class="funkwhale textarea" @mousedown.prevent="focus" @mouseup.prevent="focus">
<Markdown :md="model" class="preview" /> <Markdown :md="model" class="preview" />
<textarea ref="textarea" @click="updateLineNumber" @mousedown.stop @mouseup.stop @keydown.left="updateLineNumber" <textarea ref="textarea" @click="updateLineNumber" @mousedown.stop @mouseup.stop @keydown.left="updateLineNumber"
@ -209,6 +219,7 @@ const focus = () => textarea.value.focus()
<span v-if="max !== Infinity && typeof max === 'number'" class="letter-count">{{ max - model.length }}</span> <span v-if="max !== Infinity && typeof max === 'number'" class="letter-count">{{ max - model.length }}</span>
</div> </div>
</div> </div>
</Layout>
</template> </template>
<style lang="scss"> <style lang="scss">

View File

@ -1,4 +1,12 @@
.funkwhale { .funkwhale {
&.textarea-label {
display: block;
> .label {
padding-bottom: 4px;
font-size:14px;
font-weight:600;
}
}
&.textarea { &.textarea {
background-color: var(--fw-bg-color); background-color: var(--fw-bg-color);
box-shadow: inset 0 0 0 4px var(--fw-border-color); box-shadow: inset 0 0 0 4px var(--fw-border-color);

View File

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import Textarea from '~/components/ui/Textarea.vue' import Textarea from '~/components/ui/Textarea.vue'
import { ref } from 'vue' import { ref } from 'vue'
const text1 = ref('# Funk\nwhale') const text1 = ref('# Funk\nwhale')
@ -27,12 +28,12 @@ Create a textarea and attach its input to a value using a `v-model` directive.
```vue-html{2} ```vue-html{2}
<Textarea <Textarea
v-model="text" v-model="text" label="My Area"
/> />
``` ```
<ClientOnly> <ClientOnly>
<Textarea v-model="text1" /> <Textarea v-model="text1" label="My Area"/>
</ClientOnly> </ClientOnly>
## Textarea max length ## Textarea max length
@ -64,3 +65,27 @@ Add a placeholder to a textarea to guide users on what they should enter by pass
<ClientOnly> <ClientOnly>
<Textarea v-model="text3" placeholder="Describe this track here…" /> <Textarea v-model="text3" placeholder="Describe this track here…" />
</ClientOnly> </ClientOnly>
## Label slot
```vue-html{2-4}
<Textarea>
<template #label>
About my music
</template>
</Textarea>
```
<Textarea>
<template #label>
About my music <span style="color:red; float:right;">*required</span>
</template>
</Textarea>
If you just have a string, we have a convenience prop, so instead you can write:
```vue-html
<Textarea label="About my music" />
```
<Textarea label="About my music" />