Skip to content

Commit

Permalink
fix(Cascader): optimize component interaction experience (#3027)
Browse files Browse the repository at this point in the history
* fix(Cascader): optimize component interaction experience

* docs: update md

* fix: update style

* fix: fix cr
  • Loading branch information
anlyyao authored Aug 2, 2024
1 parent 349da1f commit 0ae794e
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 39 deletions.
2 changes: 1 addition & 1 deletion script/generate-css-vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ if (combine[COMPONENT_NAME]) {
}

// 追加到文件
const cssVariableHeadContent = `\n\n### CSS 变量\n组件提供了下列 CSS 变量,可用于自定义样式。\n名称 | 默认值 | 描述 \n-- | -- | --\n`;
const cssVariableHeadContent = `\n\n### CSS Variables\n组件提供了下列 CSS 变量,可用于自定义样式。\n名称 | 默认值 | 描述 \n-- | -- | --\n`;
const cssVariableHeadContentEn = `\n\n### CSS Variables\nThe component provides the following CSS variables, which can be used to customize styles.\nName | Default Value | Description \n-- | -- | --\n`;

fs.appendFileSync(resolveCwd(`src/${COMPONENT_NAME}/README.md`), cssVariableHeadContent);
Expand Down
16 changes: 10 additions & 6 deletions src/cascader/README.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ The component provides the following CSS variables, which can be used to customi
Name | Default Value | Description
-- | -- | --
--td-cascader-active-color | @brand-color | -
--td-cascader-border-color | @border-color | -
--td-cascader-disabled-color | @font-gray-4 | -
--td-cascader-options-height | 640rpx | -
--td-cascader-options-title-color | @font-gray-3 | -
--td-cascader-step-arrow-color | @font-gray-3 | -
--td-cascader-bg-color | @bg-color-container | -
--td-cascader-border-color | @component-stroke | -
--td-cascader-content-height | 78vh | -
--td-cascader-disabled-color | @text-color-disabled | -
--td-cascader-options-height | calc(100% - @cascader-step-height) | -
--td-cascader-options-title-color | @text-color-placeholder | -
--td-cascader-step-arrow-color | @text-color-placeholder | -
--td-cascader-step-dot-size | 16rpx | -
--td-cascader-step-height | 88rpx | -
--td-cascader-title-color | @font-gray-1 | -
--td-cascader-title-color | @text-color-primary | -
--td-cascader-title-height | 26rpx | -
--td-cascader-title-padding | @spacer-2 | -
--td-cascder-title-font-size | 36rpx | -
18 changes: 11 additions & 7 deletions src/cascader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,21 @@ close | `(trigger: TriggerSource)` | `1.0.1`。关闭时触发。[详细类型
pick | `(value: string \| number, index: number)` | `1.0.1`。选择后触发


### CSS 变量
### CSS Variables
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-cascader-active-color | @brand-color | -
--td-cascader-border-color | @border-color | -
--td-cascader-disabled-color | @font-gray-4 | -
--td-cascader-options-height | 640rpx | -
--td-cascader-options-title-color | @font-gray-3 | -
--td-cascader-step-arrow-color | @font-gray-3 | -
--td-cascader-bg-color | @bg-color-container | -
--td-cascader-border-color | @component-stroke | -
--td-cascader-content-height | 78vh | -
--td-cascader-disabled-color | @text-color-disabled | -
--td-cascader-options-height | calc(100% - @cascader-step-height) | -
--td-cascader-options-title-color | @text-color-placeholder | -
--td-cascader-step-arrow-color | @text-color-placeholder | -
--td-cascader-step-dot-size | 16rpx | -
--td-cascader-step-height | 88rpx | -
--td-cascader-title-color | @font-gray-1 | -
--td-cascader-title-color | @text-color-primary | -
--td-cascader-title-height | 26rpx | -
--td-cascader-title-padding | @spacer-2 | -
--td-cascder-title-font-size | 36rpx | -
44 changes: 20 additions & 24 deletions src/cascader/cascader.less
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
@cascader-active-color: var(--td-cascader-active-color, @brand-color);
@cascader-disabled-color: var(--td-cascader-disabled-color, @text-color-disabled);
@cascader-title-color: var(--td-cascader-title-color, @text-color-primary);
@cascader-title-height: var(--td-cascader-title-height, 26rpx);
@cascader-title-padding: var(--td-cascader-title-padding, @spacer-2);
@cascder-title-font-size: var(--td-cascder-title-font-size, 36rpx);
@cascader-options-title-color: var(--td-cascader-options-title-color, @text-color-placeholder);
@cascader-border-color: var(--td-cascader-border-color, @component-stroke);

@cascader-options-height: var(--td-cascader-options-height, 640rpx);
@cascder-title-font-size: var(--td-cascder-title-font-size, 36rpx);

@cascader-content-height: var(--td-cascader-content-height, 78vh);
@cascader-options-height: var(--td-cascader-options-height, calc(100% - @cascader-step-height));
// steps
@cascader-step-height: var(--td-cascader-step-height, 88rpx);
@cascader-step-dot-size: var(--td-cascader-step-dot-size, 16rpx);
Expand All @@ -22,52 +23,47 @@
flex-direction: column;
background-color: @cascader-bg-color;
color: @cascader-title-color;
border-radius: 24rpx 24rpx 0 0;
border-radius: @radius-extra-large @radius-extra-large 0 0;
--td-radio-icon-checked-color: @cascader-active-color;
--td-tab-item-active-color: @cascader-active-color;
--td-tab-track-color: @cascader-active-color;

&__close-btn {
right: 16px;
top: 12px;
right: 32rpx;
top: 24rpx;
position: absolute;
}

&__title {
position: relative;
font-weight: 700;
text-align: center;
line-height: 48px;
line-height: @cascader-title-height;
padding: @cascader-title-padding;
font-size: @cascder-title-font-size;
}

&__content {
width: 100%;
flex: 1;
height: @cascader-content-height;
display: flex;
flex-direction: column;
}

&__options {
width: 100vw;
height: @cascader-options-height;

&-title {
margin-top: 40rpx;
color: @cascader-options-title-color;
font-size: 28rpx;
font-size: @font-size-base;
line-height: 44rpx;
padding-left: 16px;
}

&-content {
flex: 1;
height: 100%;
overflow: auto;
padding-left: 16px;
padding-top: 40rpx;
padding-left: @spacer-2;
box-sizing: border-box;
}

&-container {
flex: 1;
display: flex;
transition: all ease 0.3s;
}
Expand All @@ -88,7 +84,7 @@
width: @cascader-step-dot-size;
height: @cascader-step-dot-size;
border-radius: 50%;
border: 1px solid @cascader-active-color;
border: 2rpx solid @cascader-active-color;
box-sizing: border-box;

&:not(.@{cascader}__step-dot--last)::after {
Expand All @@ -98,7 +94,7 @@
left: 50%;
top: calc(@cascader-step-dot-size + 14rpx);
height: 36rpx;
width: 1px;
width: 2rpx;
background: @cascader-active-color;
transform: translateX(-50%);
}
Expand All @@ -110,8 +106,8 @@
}

&-label {
padding-left: 16px;
font-size: 16px;
padding-left: @spacer-2;
font-size: @font-size-m;

&--active {
color: @cascader-active-color;
Expand Down
62 changes: 61 additions & 1 deletion src/cascader/cascader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ function parseOptions(options: OptionsType, keys: KeysType) {
});
}

const defaultState = {
contentHeight: 0,
stepHeight: 0,
tabsHeight: 0,
subTitlesHeight: 0,
stepsInitHeight: 0,
};

@wxComponent()
export default class Cascader extends SuperComponent {
externalClasses = [`${prefix}-class`];
Expand All @@ -42,6 +50,10 @@ export default class Cascader extends SuperComponent {
},
];

state = {
...defaultState,
};

data = {
prefix,
name,
Expand All @@ -50,16 +62,22 @@ export default class Cascader extends SuperComponent {
selectedValue: [],
scrollTopList: [],
steps: [],
_optionsHeight: 0,
};

observers = {
visible(v) {
if (v) {
const $tabs = this.selectComponent('#tabs');

$tabs?.setTrack();
$tabs?.getTabHeight().then((res) => {
this.state.tabsHeight = res.height;
});
this.initOptionsHeight(this.data.steps.length);
this.updateScrollTop();
this.initWithValue();
} else {
this.state = { ...defaultState };
}
},

Expand All @@ -78,14 +96,20 @@ export default class Cascader extends SuperComponent {
});
},
selectedIndexes() {
const { visible, theme } = this.properties;
const { selectedValue, steps, items } = this.genItems();

this.setData({
steps,
selectedValue,
stepIndex: items.length - 1,
});

if (visible && theme === 'step') {
this.updateOptionsHeight(steps.length);
}
},

async stepIndex() {
const { visible } = this.data;

Expand All @@ -96,6 +120,42 @@ export default class Cascader extends SuperComponent {
};

methods = {
updateOptionsHeight(steps: number) {
const { contentHeight, stepsInitHeight, stepHeight, subTitlesHeight } = this.state;
this.setData({
_optionsHeight: contentHeight - stepsInitHeight - subTitlesHeight - (steps - 1) * stepHeight,
});
},

async initOptionsHeight(steps: number) {
const { theme, subTitles } = this.properties;

const { height } = await getRect(this, `.${name}__content`);
this.state.contentHeight = height;

if (theme === 'step') {
await Promise.all([getRect(this, `.${name}__steps`), getRect(this, `.${name}__step`)]).then(
([stepsRect, stepRect]) => {
this.state.stepsInitHeight = stepsRect.height - (steps - 1) * stepRect.height;
this.state.stepHeight = stepRect.height;
},
);
}

if (subTitles.length > 0) {
const { height } = await getRect(this, `.${name}__options-title`);
this.state.subTitlesHeight = height;
}

const optionsInitHeight = this.state.contentHeight - this.state.subTitlesHeight;
this.setData({
_optionsHeight:
theme === 'step'
? optionsInitHeight - this.state.stepsInitHeight - (steps - 1) * this.state.stepHeight
: optionsInitHeight - this.state.tabsHeight,
});
},

initWithValue() {
if (this.data.value != null && this.data.value !== '') {
const selectedIndexes = this.getIndexesByValue(this.data.options, this.data.value);
Expand Down
2 changes: 2 additions & 0 deletions src/cascader/cascader.wxml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
class="{{name}}__options"
scroll-y
scroll-top="{{scrollTopList[index]}}"
type="list"
style="height: {{_optionsHeight}}px"
>
<view class="cascader-radio-group-{{index}}">
<t-radio-group
Expand Down
5 changes: 5 additions & 0 deletions src/tabs/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ export default class Tabs extends SuperComponent {
return offset + targetLeft - (1 / 2) * containerWidth + targetWidth / 2;
},

// 外部无法获取虚拟组件节点位置信息
getTabHeight() {
return getRect(this, `.${name}`);
},

getTrackSize() {
return new Promise<number>((resolve, reject) => {
if (this.trackWidth) {
Expand Down

0 comments on commit 0ae794e

Please sign in to comment.