mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 12:14:41 +01:00
feat(Textarea): new component (#62)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
@@ -27,6 +27,7 @@ const components = [
|
||||
'slideover',
|
||||
'switch',
|
||||
'tabs',
|
||||
'textarea',
|
||||
'tooltip'
|
||||
]
|
||||
|
||||
|
||||
34
playground/pages/textarea.vue
Normal file
34
playground/pages/textarea.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<script setup lang="ts">
|
||||
import textarea from '#build/ui/textarea'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<div class="flex gap-4">
|
||||
<UTextarea />
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
<UTextarea placeholder="Search..." autofocus />
|
||||
<UTextarea placeholder="Search..." color="gray" />
|
||||
<UTextarea placeholder="Search..." color="primary" />
|
||||
<UTextarea placeholder="Search..." disabled />
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<UTextarea
|
||||
v-for="size in Object.keys(textarea.variants.size)"
|
||||
:key="size"
|
||||
placeholder="Search..."
|
||||
:size="(size as any)"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
<UTextarea autofocus />
|
||||
<UTextarea autofocus :autofocus-delay="500" />
|
||||
<UTextarea autoresize />
|
||||
<UTextarea autoresize :maxrows="5" :rows="1" />
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
<UTextarea variant="none" placeholder="You can't see me" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
175
src/runtime/components/Textarea.vue
Normal file
175
src/runtime/components/Textarea.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<script lang="ts">
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/textarea'
|
||||
import { looseToNumber } from '#ui/utils'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { textarea: Partial<typeof theme> } }
|
||||
|
||||
const textarea = tv({ extend: tv(theme), ...(appConfig.ui?.textarea || {}) })
|
||||
|
||||
type TextareaVariants = VariantProps<typeof textarea>
|
||||
|
||||
export interface TextareaProps {
|
||||
id?: string
|
||||
name?: string
|
||||
placeholder?: string
|
||||
color?: TextareaVariants['color']
|
||||
variant?: TextareaVariants['variant']
|
||||
size?: TextareaVariants['size']
|
||||
required?: boolean
|
||||
autofocus?: boolean
|
||||
autofocusDelay?: number
|
||||
disabled?: boolean
|
||||
class?: any
|
||||
rows?: number
|
||||
maxrows?: number
|
||||
autoresize?: boolean
|
||||
ui?: Partial<typeof textarea.slots>
|
||||
}
|
||||
export interface TextareaEmits {
|
||||
(e: 'blur', event: FocusEvent): void
|
||||
}
|
||||
|
||||
export interface TextareaSlots {
|
||||
default(): any
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted, nextTick, watch } from 'vue'
|
||||
import { useFormField } from '#ui/composables/useFormField'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
|
||||
const props = withDefaults(defineProps<TextareaProps>(), {
|
||||
rows: 3,
|
||||
maxrows: 0,
|
||||
autofocusDelay: 100
|
||||
})
|
||||
|
||||
const emit = defineEmits<TextareaEmits>()
|
||||
defineSlots<TextareaSlots>()
|
||||
|
||||
const [modelValue, modelModifiers] = defineModel<string | number>()
|
||||
|
||||
const { emitFormBlur, emitFormInput, size, color, inputId, name, disabled } = useFormField<TextareaProps>(props)
|
||||
|
||||
const ui = computed(() => tv({ extend: textarea, slots: props.ui })({
|
||||
color: color.value,
|
||||
variant: props.variant,
|
||||
size: size?.value
|
||||
}))
|
||||
|
||||
|
||||
const inputRef = ref<HTMLTextAreaElement | null>(null)
|
||||
|
||||
function autoFocus () {
|
||||
if (props.autofocus) {
|
||||
inputRef.value?.focus()
|
||||
}
|
||||
}
|
||||
|
||||
// Custom function to handle the v-model properties
|
||||
function updateInput (value: string) {
|
||||
if (modelModifiers.trim) {
|
||||
value = value.trim()
|
||||
}
|
||||
|
||||
if (modelModifiers.number) {
|
||||
value = looseToNumber(value)
|
||||
}
|
||||
|
||||
modelValue.value = value
|
||||
emitFormInput()
|
||||
}
|
||||
|
||||
function onInput (event: Event) {
|
||||
autoResize()
|
||||
|
||||
if (!modelModifiers.lazy) {
|
||||
updateInput((event.target as HTMLInputElement).value)
|
||||
}
|
||||
}
|
||||
|
||||
function onChange (event: Event) {
|
||||
const value = (event.target as HTMLInputElement).value
|
||||
|
||||
if (modelModifiers.lazy) {
|
||||
updateInput(value)
|
||||
}
|
||||
|
||||
// Update trimmed textarea so that it has same behavior as native textarea https://github.com/vuejs/core/blob/5ea8a8a4fab4e19a71e123e4d27d051f5e927172/packages/runtime-dom/src/directives/vModel.ts#L63
|
||||
if (modelModifiers.trim) {
|
||||
(event.target as HTMLInputElement).value = value.trim()
|
||||
}
|
||||
}
|
||||
|
||||
function onBlur (event: FocusEvent) {
|
||||
emitFormBlur()
|
||||
emit('blur', event)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
autoFocus()
|
||||
}, props.autofocusDelay)
|
||||
})
|
||||
|
||||
const autoResize = () => {
|
||||
if (props.autoresize) {
|
||||
|
||||
if (!inputRef.value) {
|
||||
return
|
||||
}
|
||||
|
||||
inputRef.value.rows = props.rows
|
||||
|
||||
const styles = window.getComputedStyle(inputRef.value)
|
||||
const paddingTop = parseInt(styles.paddingTop)
|
||||
const paddingBottom = parseInt(styles.paddingBottom)
|
||||
const padding = paddingTop + paddingBottom
|
||||
const lineHeight = parseInt(styles.lineHeight)
|
||||
const { scrollHeight } = inputRef.value
|
||||
const newRows = (scrollHeight - padding) / lineHeight
|
||||
|
||||
if (newRows > props.rows) {
|
||||
inputRef.value.rows = props.maxrows ? Math.min(newRows, props.maxrows) : newRows
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
watch(() => modelValue, () => {
|
||||
nextTick(autoResize)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
autoResize()
|
||||
}, 100)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="ui.root({ class: props.class })">
|
||||
<textarea
|
||||
:id="inputId"
|
||||
ref="inputRef"
|
||||
:value="modelValue"
|
||||
:name="name"
|
||||
:rows="rows"
|
||||
:placeholder="placeholder"
|
||||
:class="ui.base()"
|
||||
:disabled="disabled"
|
||||
:required="required"
|
||||
v-bind="$attrs"
|
||||
@input="onInput"
|
||||
@blur="onBlur"
|
||||
@change="onChange"
|
||||
/>
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
@@ -20,3 +20,4 @@ export { default as slideover } from './slideover'
|
||||
export { default as switch } from './switch'
|
||||
export { default as tabs } from './tabs'
|
||||
export { default as tooltip } from './tooltip'
|
||||
export { default as textarea } from './textarea'
|
||||
|
||||
63
src/theme/textarea.ts
Normal file
63
src/theme/textarea.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
export default (config: { colors: string[] }) => ({
|
||||
slots: {
|
||||
root: 'relative',
|
||||
base: 'relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500'
|
||||
},
|
||||
|
||||
variants: {
|
||||
size: {
|
||||
'2xs': {
|
||||
base: 'text-xs gap-x-1 px-2 py-1'
|
||||
},
|
||||
xs: {
|
||||
base: 'text-sm gap-x-1.5 px-2.5 py-1.5'
|
||||
},
|
||||
sm: {
|
||||
base: 'text-sm gap-x-1.5 px-2.5 py-1.5'
|
||||
},
|
||||
md: {
|
||||
base: 'text-sm gap-x-1.5 px-3 py-2'
|
||||
},
|
||||
lg: {
|
||||
base: 'text-sm gap-x-2.5 px-3.5 py-2.5'
|
||||
},
|
||||
xl: {
|
||||
base: 'text-base gap-x-2.5 px-3.5 py-2.5'
|
||||
}
|
||||
},
|
||||
|
||||
variant: {
|
||||
outline: '',
|
||||
none: 'bg-transparent focus:ring-0 focus:shadow-none'
|
||||
},
|
||||
|
||||
color: {
|
||||
...Object.fromEntries(config.colors.map((color: string) => [color, ''])),
|
||||
white: '',
|
||||
gray: ''
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
compoundVariants: [
|
||||
...config.colors.map((color: string) => ({
|
||||
color,
|
||||
variant: 'outline',
|
||||
class: `shadow-sm bg-transparent text-gray-900 dark:text-white ring ring-inset ring-${color}-500 dark:ring-${color}-400 focus:ring-2 focus:ring-${color}-500 dark:focus:ring-${color}-400`
|
||||
})), {
|
||||
color: 'white',
|
||||
variant: 'outline',
|
||||
class: 'shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400'
|
||||
}, {
|
||||
color: 'gray',
|
||||
variant: 'outline',
|
||||
class: 'shadow-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400'
|
||||
}
|
||||
],
|
||||
|
||||
defaultVariants: {
|
||||
size: 'sm',
|
||||
color: 'white',
|
||||
variant: 'outline'
|
||||
}
|
||||
})
|
||||
60
test/components/Textarea.spec.ts
Normal file
60
test/components/Textarea.spec.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { describe, it, expect, test } from 'vitest'
|
||||
import Textarea, { type TextareaProps } from '../../src/runtime/components/Textarea.vue'
|
||||
import ComponentRender from '../component-render'
|
||||
import { mount } from '@vue/test-utils'
|
||||
|
||||
describe('Textarea', () => {
|
||||
it.each([
|
||||
['basic case', {}],
|
||||
['with id', { props: { id: 'exampleId' } }],
|
||||
['with name', { props: { name: 'exampleName' } }],
|
||||
['with placeholder', { props: { placeholder: 'examplePlaceholder' } }],
|
||||
['with required', { props: { required: true } }],
|
||||
['with disabled', { props: { disabled: true } }],
|
||||
['with rows', { props: { rows: 5 } }],
|
||||
['with size', { props: { size: 'sm' } }],
|
||||
['with color', { props: { color: 'blue' } }],
|
||||
['with size 2xs', { props: { size: '2xs' as const } }],
|
||||
['with size xs', { props: { size: 'xs' as const } }],
|
||||
['with size sm', { props: { size: 'sm' as const } }],
|
||||
['with size md', { props: { size: 'md' as const } }],
|
||||
['with size lg', { props: { size: 'lg' as const } }],
|
||||
['with size xl', { props: { size: 'xl' as const } }],
|
||||
['with variant', { variant: 'outline' }],
|
||||
['with default slot', { slots: { default: () => 'Default slot' } }]
|
||||
// @ts-ignore
|
||||
])('renders %s correctly', async (nameOrHtml: string, options: { props: TextareaProps, slots?: any }) => {
|
||||
const html = await ComponentRender(nameOrHtml, options, Textarea)
|
||||
expect(html).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it.each([
|
||||
['with .trim modifier', { props: { modelModifiers: { trim: true } } }, { input: 'input ', expected: 'input' } ],
|
||||
['with .number modifier', { props: { modelModifiers: { number: true } } }, { input: '42', expected: 42 } ],
|
||||
['with .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' } ]
|
||||
])('%s works', async (_nameOrHtml: string, options: { props?: any, slots?: any }, spec: { input: any, expected: any }) => {
|
||||
const wrapper = await mount(Textarea, {
|
||||
...options
|
||||
})
|
||||
|
||||
const input = wrapper.find('textarea')
|
||||
await input.setValue(spec.input)
|
||||
|
||||
expect(wrapper.emitted()).toMatchObject({ 'update:modelValue': [[spec.expected]] })
|
||||
})
|
||||
|
||||
test('with .lazy modifier updates on change only', async () => {
|
||||
const wrapper = mount(Textarea, {
|
||||
props: {
|
||||
modelModifiers: { lazy: true }
|
||||
}
|
||||
})
|
||||
|
||||
const input = wrapper.find('textarea')
|
||||
await input.trigger('update')
|
||||
expect(wrapper.emitted()).toMatchObject({ })
|
||||
|
||||
await input.trigger('change')
|
||||
expect(wrapper.emitted()).toMatchObject({ 'update:modelValue': [['']] })
|
||||
})
|
||||
})
|
||||
35
test/components/__snapshots__/Textarea.spec.ts.snap
Normal file
35
test/components/__snapshots__/Textarea.spec.ts.snap
Normal file
@@ -0,0 +1,35 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Textarea > renders basic case correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with color correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-transparent text-gray-900 dark:text-white ring ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with default slot correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea>Default slot</div>"`;
|
||||
|
||||
exports[`Textarea > renders with disabled correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400" disabled=""></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with id correctly 1`] = `"<div class="relative"><textarea id="exampleId" rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with name correctly 1`] = `"<div class="relative"><textarea name="exampleName" rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with placeholder correctly 1`] = `"<div class="relative"><textarea rows="3" placeholder="examplePlaceholder" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with required correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400" required=""></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with rows correctly 1`] = `"<div class="relative"><textarea rows="5" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with size 2xs correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-xs gap-x-1 px-2 py-1 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with size correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with size lg correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-2.5 px-3.5 py-2.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with size md correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-3 py-2 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with size sm correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with size xl correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-base gap-x-2.5 px-3.5 py-2.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with size xs correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
|
||||
exports[`Textarea > renders with variant correctly 1`] = `"<div class="relative"><textarea rows="3" class="relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-sm gap-x-1.5 px-2.5 py-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400"></textarea></div>"`;
|
||||
Reference in New Issue
Block a user