From 69b6aada5ce9d04b347da5b786a0a6100ff67efa Mon Sep 17 00:00:00 2001 From: anlyyao Date: Thu, 24 Nov 2022 20:01:38 +0800 Subject: [PATCH 1/2] feat(Textarea): enrich attributes --- src/textarea/README.md | 34 ++++-- .../__test__/__snapshots__/demo.test.js.snap | 32 +++++- .../__test__/__snapshots__/index.test.js.snap | 9 +- src/textarea/__test__/demo.test.js | 2 +- src/textarea/__test__/index.test.js | 10 +- src/textarea/_example/autosize/index.wxml | 2 +- src/textarea/_example/custom/index.js | 1 + src/textarea/_example/custom/index.json | 6 + src/textarea/_example/custom/index.wxml | 4 + src/textarea/_example/custom/index.wxss | 12 ++ src/textarea/_example/disabled/index.wxml | 2 +- src/textarea/_example/maxcharacter/index.wxml | 2 +- src/textarea/_example/maxlength/index.wxml | 2 +- src/textarea/_example/textarea.json | 5 +- src/textarea/_example/textarea.wxml | 15 ++- src/textarea/props.ts | 27 ++++- src/textarea/textarea.less | 105 +++++++++++------- src/textarea/textarea.ts | 7 +- src/textarea/textarea.wxml | 16 ++- src/textarea/type.ts | 33 +++++- 20 files changed, 241 insertions(+), 85 deletions(-) create mode 100644 src/textarea/_example/custom/index.js create mode 100644 src/textarea/_example/custom/index.json create mode 100644 src/textarea/_example/custom/index.wxml create mode 100644 src/textarea/_example/custom/index.wxss diff --git a/src/textarea/README.md b/src/textarea/README.md index 4b89d6546..b560cae3e 100644 --- a/src/textarea/README.md +++ b/src/textarea/README.md @@ -18,32 +18,40 @@ isComponent: true ## 代码演示 -### 基础多行文本框 +### 类型 - +基础多行文本框 {{ base }} -### 带标题多行文本框 +带标题多行文本框 {{ label }} -### 自动增高多行文本框 +自动增高多行文本框 {{ autoSize }} -### 禁用多行文本框 -{{ disabled }} - -### 设置最大字符个数 +设置最大字符个数 {{ maxlength }} -### 设置最大字符个数,一个汉字表示两个字符 +设置最大字符个数,一个汉字表示两个字符 {{ maxcharacter }} +### 状态 + +禁用多行文本框 + +{{ disabled }} + +### 自定义样式 + +标签外置输入框 + +{{ custom }} ## 提示 - 如果需要在页面中调整 `textarea` 中 `placeholder` 样式,请使用名称为`t-textarea__placeholder`的Class选择器,直接覆盖组件内部样式(注意权重)。 @@ -61,14 +69,18 @@ confirm-type | String | done | 设置键盘右下角按钮的文字,仅在 typ cursor-spacing | Number | 0 | 指定光标与键盘的距离。取textarea距离底部的距离和cursor-spacing指定的距离的最小值作为光标与键盘的距离 | N custom-style `v0.25.0` | String | - | 自定义组件样式 | N disabled | Boolean | false | 是否禁用文本框 | N -external-classes | Array | - | 组件类名,分别用于表示组件外层元素、输入框、占位符、标签名等元素类名。`['t-class', 't-class-textarea', 't-class-label']` | N +external-classes | Array | - | 组件类名,分别用于表示组件外层元素、输入框、占位符、标签名等元素类名。`['t-class', 't-class-textarea', 't-class-label, 't-class-indicator]` | N focus | Boolean | false | 自动聚焦 | N label | String / Slot | - | 左侧文本 | N maxcharacter | Number | - | 用户最多可以输入的字符个数,一个中文汉字表示两个字符长度 | N -maxlength | Number | - | 用户最多可以输入的字符个数 | N +maxlength | Number | -1 | 用户最多可以输入的字符个数。默认为 -1,不限制输入长度 | N +indicator | Boolean | false | 显示文本计数器,如 0/140。当 `maxlength < 0 && maxcharacter < 0` 成立时, indicator无效 | N placeholder | String | undefined | 占位符 | N +placeholderStyle | String | '' | 指定 placeholder 的样式,目前仅支持 color ,font-size和font-weight | N value | String | - | 文本框值 | N default-value | String | undefined | 文本框值。非受控属性 | N +fixed | Boolean | false | 如果 textarea 是在一个 `position:fixed` 的区域,需要显示指定属性 fixed 为 true | N +bordered | Boolean | false | 是否显示外边框 | N ### Textarea Events diff --git a/src/textarea/__test__/__snapshots__/demo.test.js.snap b/src/textarea/__test__/__snapshots__/demo.test.js.snap index cf51c90f8..f01e5909e 100644 --- a/src/textarea/__test__/__snapshots__/demo.test.js.snap +++ b/src/textarea/__test__/__snapshots__/demo.test.js.snap @@ -4,7 +4,6 @@ exports[`Textarea Textarea autosize demo works fine 1`] = ` @@ -18,11 +17,30 @@ exports[`Textarea Textarea base demo works fine 1`] = ` `; +exports[`Textarea Textarea custom demo works fine 1`] = ` + + + + 标签文字 + + + + +`; + exports[`Textarea Textarea disabled demo works fine 1`] = ` @@ -41,8 +59,9 @@ exports[`Textarea Textarea label demo works fine 1`] = ` exports[`Textarea Textarea maxcharacter demo works fine 1`] = ` @@ -51,8 +70,9 @@ exports[`Textarea Textarea maxcharacter demo works fine 1`] = ` exports[`Textarea Textarea maxlength demo works fine 1`] = ` diff --git a/src/textarea/__test__/__snapshots__/index.test.js.snap b/src/textarea/__test__/__snapshots__/index.test.js.snap index 9b6eec826..8f4d56322 100644 --- a/src/textarea/__test__/__snapshots__/index.test.js.snap +++ b/src/textarea/__test__/__snapshots__/index.test.js.snap @@ -5,11 +5,11 @@ exports[`textarea slots : label 1`] = ` class="base" > { mapper.forEach((demoName) => { diff --git a/src/textarea/__test__/index.test.js b/src/textarea/__test__/index.test.js index e53257f49..a126aee98 100644 --- a/src/textarea/__test__/index.test.js +++ b/src/textarea/__test__/index.test.js @@ -24,7 +24,7 @@ describe('textarea', () => { comp.attach(document.createElement('parent-wrapper')); const component = comp.querySelector('.base'); - const $label = comp.querySelector('.base >>> .t-textarea__name'); + const $label = comp.querySelector('.base >>> .t-textarea__label'); expect($label).toBeDefined(); expect($label.dom.textContent).toBe(component.instance.data.label); }); @@ -55,7 +55,7 @@ describe('textarea', () => { const component = comp.querySelector('.base'); expect(component.instance.data.count).toBe(7); - const $textarea = comp.querySelector('.base >>> .t-textarea__wrapper-textarea'); + const $textarea = comp.querySelector('.base >>> .t-textarea__wrapper-inner'); $textarea.dispatchEvent('input', { detail: { value: 'tdesign123' } }); await simulate.sleep(0); @@ -92,7 +92,7 @@ describe('textarea', () => { const component = comp.querySelector('.base'); expect(component).toMatchSnapshot(); - const $label = comp.querySelector('.base >>> .t-textarea__name'); + const $label = comp.querySelector('.base >>> .t-textarea__label'); expect($label.dom.textContent).toBe('标签文字'); // }); @@ -125,7 +125,7 @@ describe('textarea', () => { const component = comp.querySelector('.base'); expect(component.instance.data.count).toBe(7); - const $textarea = comp.querySelector('.base >>> .t-textarea__wrapper-textarea'); + const $textarea = comp.querySelector('.base >>> .t-textarea__wrapper-inner'); $textarea.dispatchEvent('linechange', { detail: { @@ -171,7 +171,7 @@ describe('textarea', () => { const component = comp.querySelector('.base'); expect(component.instance.data.count).toBe(7); - const $textarea = comp.querySelector('.base >>> .t-textarea__wrapper-textarea'); + const $textarea = comp.querySelector('.base >>> .t-textarea__wrapper-inner'); $textarea.dispatchEvent('focus'); await simulate.sleep(); diff --git a/src/textarea/_example/autosize/index.wxml b/src/textarea/_example/autosize/index.wxml index 22f164d7f..6ea287e52 100644 --- a/src/textarea/_example/autosize/index.wxml +++ b/src/textarea/_example/autosize/index.wxml @@ -1 +1 @@ - + diff --git a/src/textarea/_example/custom/index.js b/src/textarea/_example/custom/index.js new file mode 100644 index 000000000..b79c5124b --- /dev/null +++ b/src/textarea/_example/custom/index.js @@ -0,0 +1 @@ +Component({}); diff --git a/src/textarea/_example/custom/index.json b/src/textarea/_example/custom/index.json new file mode 100644 index 000000000..8969b7947 --- /dev/null +++ b/src/textarea/_example/custom/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "t-textarea": "tdesign-miniprogram/textarea/textarea" + } +} diff --git a/src/textarea/_example/custom/index.wxml b/src/textarea/_example/custom/index.wxml new file mode 100644 index 000000000..dc557a286 --- /dev/null +++ b/src/textarea/_example/custom/index.wxml @@ -0,0 +1,4 @@ + + 标签文字 + + diff --git a/src/textarea/_example/custom/index.wxss b/src/textarea/_example/custom/index.wxss new file mode 100644 index 000000000..0c337eedc --- /dev/null +++ b/src/textarea/_example/custom/index.wxss @@ -0,0 +1,12 @@ +.demo-textarea { + padding: 32rpx; + background-color: #fff; +} + +.demo-textarea--label { + display: block; + color: rgba(0, 0, 0, 0.9); + font-size: 24rpx; + line-height: 40rpx; + padding-bottom: 16rpx; +} diff --git a/src/textarea/_example/disabled/index.wxml b/src/textarea/_example/disabled/index.wxml index f3532a185..9c28d07b7 100644 --- a/src/textarea/_example/disabled/index.wxml +++ b/src/textarea/_example/disabled/index.wxml @@ -1 +1 @@ - + diff --git a/src/textarea/_example/maxcharacter/index.wxml b/src/textarea/_example/maxcharacter/index.wxml index 8a79c8508..d5479d4df 100644 --- a/src/textarea/_example/maxcharacter/index.wxml +++ b/src/textarea/_example/maxcharacter/index.wxml @@ -1 +1 @@ - + diff --git a/src/textarea/_example/maxlength/index.wxml b/src/textarea/_example/maxlength/index.wxml index 5624d4650..1a04b36df 100644 --- a/src/textarea/_example/maxlength/index.wxml +++ b/src/textarea/_example/maxlength/index.wxml @@ -1 +1 @@ - + diff --git a/src/textarea/_example/textarea.json b/src/textarea/_example/textarea.json index ddc119763..dc8de2927 100644 --- a/src/textarea/_example/textarea.json +++ b/src/textarea/_example/textarea.json @@ -2,10 +2,11 @@ "navigationBarTitleText": "Textarea 多行输入框", "usingComponents": { "base": "./base", - "labelDemo": "./label", + "label": "./label", "autosize": "./autosize", "disabled": "./disabled", "maxcharacter": "./maxcharacter", - "maxlength": "./maxlength" + "maxlength": "./maxlength", + "custom": "./custom" } } diff --git a/src/textarea/_example/textarea.wxml b/src/textarea/_example/textarea.wxml index fd0a52509..9ec1616f4 100644 --- a/src/textarea/_example/textarea.wxml +++ b/src/textarea/_example/textarea.wxml @@ -5,18 +5,21 @@ - + - - - - + - + + + + + + + diff --git a/src/textarea/props.ts b/src/textarea/props.ts index 7c1beb0f7..8f85cd1d8 100644 --- a/src/textarea/props.ts +++ b/src/textarea/props.ts @@ -59,19 +59,30 @@ const props: TdTextareaProps = { label: { type: String, }, + /** 如果 textarea 是在一个 `position:fixed` 的区域,需要显示指定属性 fixed 为 true */ + fixed: { + type: Boolean, + value: false, + }, /** 用户最多可以输入的字符个数,一个中文汉字表示两个字符长度 */ maxcharacter: { type: Number, }, - /** 用户最多可以输入的字符个数 */ + /** 用户最多可以输入的字符个数。默认为 -1,不限制输入长度 */ maxlength: { type: Number, + value: -1, }, - /** 占位符 */ + /** 指定 placeholder 的样式,目前仅支持 color ,font-size和font-weight */ placeholder: { type: String, value: undefined, }, + /** 占位符样式 */ + placeholderStyle: { + type: String, + value: '', + }, /** 文本框值 */ value: { type: String, @@ -82,6 +93,18 @@ const props: TdTextareaProps = { type: String, value: '', }, + /** 是否显示外边框 */ + bordered: { + type: Boolean, + value: false, + }, + /** + * 显示文本计数器,如 0/140。当 `maxlength < 0 && maxcharacter < 0` 成立时, indicator无效 + */ + indicator: { + type: Boolean, + value: false, + }, }; export default props; diff --git a/src/textarea/textarea.less b/src/textarea/textarea.less index cc46071ef..f1b5e0c59 100644 --- a/src/textarea/textarea.less +++ b/src/textarea/textarea.less @@ -1,44 +1,62 @@ @import '../common/style/index.less'; -@textarea-background-color: @bg-color-block; -@textarea-text-color: @text-level-1-color; -@textarea-placeholder-text-color: @text-level-4-color; -@textarea-disabled-text-color: @text-level-1-color; -@textarea-placeholder-text-color: @text-level-3-color; -@textarea-font-size: 32rpx; -@textarea-line-height: 48rpx; -@textarea-count-font-size: 24rpx; -@textarea-vertical-padding: 24rpx; -@textarea-horizontal-padding: 32rpx; +@textarea-height: 72px; // 指定文本框高度 +@textarea-vertical-padding: 32rpx; // 文本框垂直方向间距 +@textarea-horizontal-padding: 32rpx; // 文本框水平方向间距 +@textarea-text-line-height: 48rpx; // 输入框文本行高 +@textarea-label-line-height: 44px; // 标签文本行高 +@textarea-label-padding-bottom: @spacer; +@textarea-indicator-text-line-height: 40rpx; // 计数器文本行高 +@textarea-indicator-text-padding-top: @spacer; // 计数器文本顶部间距 +@textarea-indicator-text-align: right; // 计数器文本对齐方式 +@textarea-border-width: 2rpx; // 文本框边框大小 + +// 文本框背景颜色 +@textarea-background-color: var(--td-textarea-background-color, @bg-color-block); +// 占位符文本大小 +@textarea-placeholder-font-size: var(--td-textarea-placeholder-font-size, @font-size-m); +// 占位符文本颜色 +@textarea-placeholder-color: var(--td-textarea-placeholder-color, @font-gray-3); +// 输入框文本大小 +@textarea-text-font-size: var(--td-textarea-text-font-size, @font-size-m); +// 输入框文本颜色 +@textarea-text-color: var(--td-textarea-text-color, @font-gray-1); +// 标签文本大小 +@textarea-label-font-size: var(--td-textarea-label-font-size, @font-size-base); +// 标签文本颜色 +@textarea-label-color: var(--td-textarea-label-color, @font-gray-1); +// 计数器文本大小 +@textarea-indicator-text-font-size: var(--td-textarea-indicator-text-font-size, @spacer-1); +// 计数器文本颜色 +@textarea-indicator-text-color: var(--td-textarea-indicator-text-color, @font-gray-3); +// 文本框圆角大小 +@textarea-border-radius: var(--td-textarea-border-radius, 12rpx); +// 文本框边框颜色 +@textarea-border-color: var(--td-textarea-border-color, rgba(220, 220, 220, 1)); +// 文本框禁用状态时的输入文本颜色 +@textarea-disabled-text-color: var(--td-textarea-disabled-text-color, @font-gray-4); .@{prefix}-textarea { - position: relative; - background-color: #fff; + padding: @textarea-vertical-padding @textarea-horizontal-padding; + background-color: @textarea-background-color; - &__name:not(:empty) { - position: relative; - padding: @textarea-vertical-padding @textarea-horizontal-padding; - font-size: @textarea-font-size; - color: @textarea-text-color; + &__label:not(:empty) { + font-size: @textarea-label-font-size; + color: @textarea-label-color; + line-height: @textarea-label-line-height; + padding-bottom: @textarea-label-padding-bottom; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; - - &::after { - .hairline-bottom(); - left: @textarea-horizontal-padding; - } } &__wrapper { - padding: @textarea-vertical-padding @textarea-horizontal-padding; - font-size: @textarea-font-size; - color: @textarea-text-color; + width: 100%; - &-textarea { - display: block; + &-inner { box-sizing: border-box; - width: 100%; + width: inherit; + height: @textarea-height; min-width: 0; margin: 0; padding: 0; @@ -46,20 +64,31 @@ background-color: transparent; border: 0; resize: none; - font-size: @textarea-font-size; - line-height: @textarea-line-height; + font-size: @textarea-text-font-size; + color: @textarea-text-font-size; + line-height: @textarea-text-line-height; } } - &__placeholder, - &__count { - color: @textarea-placeholder-text-color; - font-size: @textarea-font-size; - line-height: @textarea-line-height; + &__placeholder { + color: @textarea-placeholder-color; + font-size: @textarea-placeholder-font-size; + } + + &__indicator:not(:empty) { + color: @textarea-indicator-text-color; + font-size: @textarea-indicator-text-font-size; + text-align: @textarea-indicator-text-align; + line-height: @textarea-indicator-text-line-height; + padding-top: @textarea-indicator-text-padding-top; + } + + &--border { + border-radius: @textarea-border-radius; + border: @textarea-border-width solid @textarea-border-color; } - &__count { - font-size: @textarea-count-font-size; - text-align: right; + .@{prefix}-is-disabled { + color: @textarea-disabled-text-color; } } diff --git a/src/textarea/textarea.ts b/src/textarea/textarea.ts index 07895da2f..fe37e28ae 100644 --- a/src/textarea/textarea.ts +++ b/src/textarea/textarea.ts @@ -22,7 +22,12 @@ export default class Textarea extends SuperComponent { behaviors = ['wx://form-field']; - externalClasses = [`${prefix}-class`, `${prefix}-class-textarea`, `${prefix}-class-label`]; + externalClasses = [ + `${prefix}-class`, + `${prefix}-class-textarea`, + `${prefix}-class-label`, + `${prefix}-class-indicator`, + ]; properties = props; diff --git a/src/textarea/textarea.wxml b/src/textarea/textarea.wxml index 0b0a3af19..d1ed6dfb5 100644 --- a/src/textarea/textarea.wxml +++ b/src/textarea/textarea.wxml @@ -1,16 +1,19 @@ - - + + {{ label }}