feat: add textarea component

Signed-off-by: Ryan Wang <i@ryanc.cc>
pull/581/head
Ryan Wang 3 years ago
parent 28ea197230
commit 55f23cb961

@ -0,0 +1,73 @@
<script lang="ts" setup>
defineProps({
modelValue: {
type: String,
},
disabled: {
type: Boolean,
default: false,
},
placeholder: {
type: String,
},
rows: {
type: Number,
default: 3,
},
});
const emit = defineEmits(["update:modelValue"]);
function handleInput(e: Event) {
const { value } = e.target as HTMLInputElement;
emit("update:modelValue", value);
}
</script>
<template>
<div class="textarea-wrapper">
<textarea
:placeholder="placeholder"
:value="modelValue"
@input="handleInput"
:disabled="disabled"
:rows="rows"
>
</textarea>
</div>
</template>
<style lang="scss">
.textarea-wrapper {
@apply box-border;
@apply relative;
@apply w-full;
@apply inline-flex;
textarea {
@apply outline-0;
@apply bg-white;
@apply antialiased;
@apply w-full;
@apply text-black;
@apply block;
@apply transition-all;
@apply appearance-none;
@apply p-3;
@apply text-sm;
border: 1px solid #ced4da;
border-radius: 4px;
&:active {
border-color: #4ccba0;
}
&:focus {
border-color: #4ccba0;
}
&:disabled {
@apply opacity-50;
@apply cursor-not-allowed;
}
}
}
</style>

@ -0,0 +1,70 @@
import { describe, expect, it, vi } from "vitest";
import { VTextarea } from "../index";
import { mount } from "@vue/test-utils";
describe("Textarea", () => {
it("should render", function () {
expect(VTextarea).toBeDefined();
expect(mount(VTextarea).html()).toMatchSnapshot();
});
it("should work with placeholder prop", async function () {
const textarea = mount(VTextarea);
expect(
textarea.find("textarea").attributes()["placeholder"]
).toBeUndefined();
// set placeholder prop
const placeholderText = "Please enter your text";
await textarea.setProps({ placeholder: placeholderText });
expect(textarea.find("textarea").attributes()["placeholder"]).toBe(
placeholderText
);
});
it("should work with disabled prop", async function () {
const textarea = mount(VTextarea);
expect(textarea.find("textarea").attributes()["disabled"]).toBeUndefined();
// set disabled prop
await textarea.setProps({ disabled: true });
expect(textarea.find("textarea").attributes()["disabled"]).toBeDefined();
});
it("should work with rows prop", function () {
const textarea = mount(VTextarea, {
propsData: {
rows: 5,
},
});
expect(textarea.find("textarea").attributes()["rows"]).toBe("5");
});
it("should work with v-model", async function () {
const wrapper = mount({
data() {
return {
value: "my name is ryanwang",
};
},
template: `
<v-textarea v-model="value" />
`,
components: { VTextarea },
});
expect(wrapper.find("textarea").element.value).toBe("my name is ryanwang");
// change value
await wrapper.setData({
value: "my name is ryanwang, my website is https://ryanc.cc",
});
expect(wrapper.find("textarea").element.value).toBe(
"my name is ryanwang, my website is https://ryanc.cc"
);
// change modelValue by textarea element value
await wrapper.find("textarea").setValue("my name is ryanwang");
expect(wrapper.vm.$data.value).toBe("my name is ryanwang");
});
});

@ -0,0 +1,6 @@
// Vitest Snapshot v1
exports[`Textarea > should render 1`] = `
"<div class=\\"textarea-wrapper\\"><textarea rows=\\"3\\">
</textarea></div>"
`;

@ -0,0 +1 @@
export { default as VTextarea } from "./Textarea.vue";

@ -77,6 +77,19 @@
<VInput v-model="inputValue" disabled />
</div>
</section>
<section class="box border-2 rounded p-2 mb-3">
<h1 class="text-xl font-bold mb-2">Textarea</h1>
<div class="mb-3">
<VTextarea
v-model="inputValue"
placeholder="Please input your description"
/>
</div>
<h2 class="mb-1">Disabled:</h2>
<div class="mb-3">
<VTextarea v-model="inputValue" disabled :rows="4" />
</div>
</section>
<section class="box border-2 rounded p-2">
<h1 class="text-xl font-bold mb-2">Select</h1>
<h2 class="mb-1">Size:</h2>
@ -113,6 +126,7 @@ import { FilledLayout } from "../layouts";
import { VButton } from "@/components/base/button";
import { VInput } from "@/components/base/input";
import { VSelect, VOption } from "@/components/base/select";
import { VTextarea } from "@/components/base/textarea";
import { ref } from "vue";
const inputValue = ref();

Loading…
Cancel
Save