mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-08 22:50:27 +00:00
## Summary Replace PrimeVue `FloatLabel` + `Textarea` in `WidgetTextarea` with a CSS-only IFTA label and a new shadcn-vue Textarea component, fixing the label-obscures-content bug. <img width="965" height="754" alt="image" src="https://github.com/user-attachments/assets/cab98527-834c-496d-a0ef-942fb21fd862" /> ## Changes - **What**: Add `src/components/ui/textarea/Textarea.vue` — thin wrapper around native `<textarea>` with `cn()` class merging and `defineModel`. Rewrite `WidgetTextarea.vue` to use a plain `<div>` wrapper with an absolutely-positioned label and the new Textarea, replacing PrimeVue's `FloatLabel variant="in"`. Add Storybook stories (Default, Disabled, WithLabel). Update tests to remove PrimeVue plugin setup. ## Review Focus - The label uses `absolute left-3 top-1.5 z-10 text-xxs` positioning — verify it clears textarea content with `pt-5` padding - `filteredProps` forwards widget options to a native textarea via `v-bind="restAttrs"` — unknown attrs are silently ignored by the browser Supersedes #8536 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9076-fix-replace-PrimeVue-FloatLabel-in-WidgetTextarea-with-CSS-only-IFTA-label-30f6d73d3650816fabe5ee30de0c793e) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com>
55 lines
1.3 KiB
TypeScript
55 lines
1.3 KiB
TypeScript
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
import { ref } from 'vue'
|
|
|
|
import Textarea from './Textarea.vue'
|
|
|
|
const meta: Meta<typeof Textarea> = {
|
|
title: 'UI/Textarea',
|
|
component: Textarea,
|
|
tags: ['autodocs']
|
|
}
|
|
|
|
export default meta
|
|
type Story = StoryObj<typeof Textarea>
|
|
|
|
export const Default: Story = {
|
|
render: () => ({
|
|
components: { Textarea },
|
|
setup() {
|
|
const value = ref('Hello world')
|
|
return { value }
|
|
},
|
|
template:
|
|
'<Textarea v-model="value" placeholder="Type something..." class="max-w-sm" />'
|
|
})
|
|
}
|
|
|
|
export const Disabled: Story = {
|
|
render: () => ({
|
|
components: { Textarea },
|
|
template:
|
|
'<Textarea model-value="Disabled textarea" disabled class="max-w-sm" />'
|
|
})
|
|
}
|
|
|
|
export const WithLabel: Story = {
|
|
render: () => ({
|
|
components: { Textarea },
|
|
setup() {
|
|
const value = ref('Content that sits below the label')
|
|
return { value }
|
|
},
|
|
template: `
|
|
<div class="relative max-w-sm rounded-lg bg-component-node-widget-background">
|
|
<label class="pointer-events-none absolute left-3 top-1.5 text-xxs text-muted-foreground z-10">
|
|
Prompt
|
|
</label>
|
|
<Textarea
|
|
v-model="value"
|
|
class="size-full resize-none border-none bg-transparent pt-5 text-xs"
|
|
/>
|
|
</div>
|
|
`
|
|
})
|
|
}
|