Skip to content

fix(Select): improved label filtering#3891

Open
RylanBot wants to merge 15 commits into
developfrom
rylan/feat/select/filterable
Open

fix(Select): improved label filtering#3891
RylanBot wants to merge 15 commits into
developfrom
rylan/feat/select/filterable

Conversation

@RylanBot
Copy link
Copy Markdown
Collaborator

@RylanBot RylanBot commented Oct 13, 2025

🤔 这个 PR 的性质是?

  • 日常 bug 修复
  • 新特性提交
  • 文档改进
  • 演示代码改进
  • 组件样式/交互改进
  • CI/CD 改进
  • 重构
  • 代码风格优化
  • 测试用例
  • 分支合并
  • 其他

🔗 相关 Issue

TreeSelect

复现代码
import React, { useEffect, useState } from 'react';
import { Select, Space, Switch, Tag } from 'tdesign-react';

export default function TreeSelectDemo() {
  const [autoWidth, setAutoWidth] = useState(false);
  const [data, setData] = useState([]);
  const [selectValue, setSelectValue] = useState('');

  const genFieldOption = ({ detail }) => {
    const value = `${detail.field_name}${detail.field_version ? ':' : ''}${detail.field_version ?? ''}`;
    const fieldNameNoVersion = `${detail.field_name}`;
    const showValue = `${fieldNameNoVersion}(${detail.field_name_ch})`;

    return {
      label: (
        <>
          <Tag size="small">{detail.meta_type}</Tag>
          {fieldNameNoVersion}
          <span className="t-input__comment">{detail.field_name_ch}</span>
        </>
      ),
      value,
      text: showValue,
      detail,
    };
  };

  const initList = async () => {
    const list = [
      {
        field_name: 'app_detail_service_getuserdata_request',
        field_name_ch: 'GetUserData Request',
        field_version: '1.0',
        meta_type: 'contract-sub',
      },
      {
        field_name: 'app_detail_service_getuserdata_reply',
        field_name_ch: 'GetUserData Reply',
        field_version: '1.0',
        meta_type: 'contract-sub',
      },
      {
        field_name: 'app_detail_service_getuserdata',
        field_name_ch: 'GetUserData',
        field_version: '1.0',
        meta_type: 'contract',
      },
      { field_name: 't_user_data', field_name_ch: '用户信息', field_version: '1.0', meta_type: 'storage' },
      {
        field_name: 't_midas_suborder_state',
        field_name_ch: '支付订单信息',
        field_version: '1.0',
        meta_type: 'storage',
      },
      { field_name: 'pay_channel', field_name_ch: '支付渠道', field_version: '1.0', meta_type: 'basic' },
      { field_name: 'pay_channel_sub_id', field_name_ch: '支付子渠道', field_version: '1.0', meta_type: 'basic' },
      { field_name: 'channel_order_id', field_name_ch: '渠道单号', field_version: '1.0', meta_type: 'basic' },
    ];
    setData(list.map((item) => genFieldOption({ detail: item })));
  };

  useEffect(() => {
    initList();
  }, []);

  const renderValueDisplay = (children) => {
    if (!children?.[1]) return '';
    return (
      <>
        {children[0]}
        {children[1]}
        <span className="t-input__comment">{children[2]?.props?.children}</span>
      </>
    );
  };

  const selectedOption = (data as any[]).find((item) => item.value === selectValue);
  const selectValueDisplay = selectedOption ? renderValueDisplay(selectedOption.label?.props?.children) : undefined;

  return (
    <Space direction="vertical">
      <div>
        <Switch<boolean> value={autoWidth} onChange={setAutoWidth} />
        Auto Width
      </div>

      <Select
        options={data}
        size="medium"
        value={selectValue || ''}
        onChange={(value) => {
          console.log(value);
          setSelectValue(value as string);
        }}
        clearable
        filterable
        valueDisplay={selectValueDisplay}
        autoWidth={autoWidth}
        {...(!autoWidth && { style: { width: 300 }, inputProps: { style: { width: 300 } } })}
      />
    </Space>
  );
}

💡 需求背景和解决方案

Select:(历史相关 PR:#973 (comment))

Cascader

image

(右边为当前效果... Input 框的撑开高度交给用户自己设置 inputClass 更加自由,下拉框的选项高度,通过组件库主动给高度设为 auto 比较合理)

📝 更新日志

  • fix(Select): 修复 label 为非 string 类型时,开启 filterable 搜索后报错的问题

  • fix(Select): 修复使用 label / content / children 自定义元素时,下拉框选项的高度没有撑开的问题

  • fix(SelectInput): 修复 inputProps.inputClass 无法生效的问题

  • fix(SelectInput): 修复单选且 valueDisplay 为自定义元素时,开启 filterable 无法显示输入内容的问题

  • feat(SelectInput): 支持 focus 时的内容为 valueDisplay 的对应值

  • 本条 PR 不需要纳入 Changelog

☑️ 请求合并前的自查清单

⚠️ 请自检并全部勾选全部选项⚠️

  • 文档已补充或无须补充
  • 代码演示已提供或无须提供
  • TypeScript 定义已补充或无须补充
  • Changelog 已提供或无须提供

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Oct 13, 2025

  • tdesign-react-demo

    npm i https://pkg.pr.new/Tencent/tdesign-react@3891
    
    npm i https://pkg.pr.new/Tencent/tdesign-react/@tdesign-react/chat@3891
    

commit: 7179cb0

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Oct 13, 2025

TDesign Component Site Preview Open

Component Preview
tdesign-react 完成
@tdesign-react/chat 完成

@RylanBot RylanBot added the WIP work in porgess label Oct 14, 2025
@RylanBot RylanBot force-pushed the rylan/feat/select/filterable branch from fc47b2a to 8ec8e7d Compare October 15, 2025 07:08
@RylanBot RylanBot removed the WIP work in porgess label Oct 15, 2025
@RylanBot RylanBot requested a review from Copilot October 15, 2025 10:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR improves label filtering functionality in the Select component and related components (SelectInput, Cascader, TreeSelect), fixing several issues with custom node rendering and input behavior.

Key Changes:

  • Fixed errors when filtering Select options with custom label nodes (ReactElements)
  • Fixed rendering issues for custom content in Select dropdown options
  • Improved single-selection input value display for SelectInput when labels are custom nodes
  • Fixed inputProps.inputClass not being applied correctly

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/components/select/base/Select.tsx Added extractTextFromTNode utility to enable filtering custom label nodes; fixed type annotations
packages/components/select/base/Option.tsx Added auto-height styling for custom element content; removed unreachable return statement
packages/components/select/_example/custom-options.tsx Refactored demo to show both slot-based and content attribute approaches for custom options
packages/components/select-input/useSingle.tsx Refactored single-select value display logic to properly render custom label nodes with absolute positioning
packages/components/_util/parseTNode.ts Added extractTextFromTNode utility function to recursively extract text from TNode structures
packages/components/tree-select/TreeSelect.tsx Simplified input value logic by removing redundant display handling code
test/snap/__snapshots__/ssr.test.jsx.snap Updated snapshots to reflect DOM structure changes
test/snap/__snapshots__/csr.test.jsx.snap Updated snapshots to reflect DOM structure changes

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread packages/components/select-input/useSingle.tsx Outdated
Comment thread packages/components/_util/parseTNode.ts
Comment thread packages/components/tree-select/TreeSelect.tsx
@RylanBot RylanBot force-pushed the rylan/feat/select/filterable branch from 9d1f8c9 to ba42885 Compare October 16, 2025 07:36
@RylanBot RylanBot added WIP work in porgess and removed WIP work in porgess labels Nov 27, 2025
@RylanBot RylanBot removed the WIP work in porgess label Nov 27, 2025
ref={setRefCurrent}
style={style}
style={{
...(isCustomElement ? { height: 'auto' } : {}),
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

使用 style 覆盖 css 里固定的 height

return normalizedValue.length ? displayNode : '';
}, [valueDisplay, multiple, normalizedValue]);

const internalInputValueDisplay: SelectInputProps['valueDisplay'] = useMemo(() => {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些逻辑全部交给 SelectInputuseSingle 内部处理

const labelNode = showLabelNode ? (
<div
style={{
position: 'absolute',
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这段新增的 div 以及样式...看是否要往 common 仓新增一个 class 统一管理 (?)

Vue 端在点击 Input 后,valueDisplay 会恢复为 value / label

React 端这次调整后采取保留原有的效果

value={singleValueDisplay ? ' ' : displayedValue}
label={
(props.label || singleValueDisplay) && (
suffix={
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原本的 displayValue 放在左侧 label
单选时光标位置在内容后面不太合理
现在移到 suffix,然后通过 style 绝对定位显示在左侧

或者为了减少 DOM 结构的变更
在不开启 filterable / allowInput 时,依旧使用 label 渲染 (?)
临时兼容的话我可以在这里补充对应逻辑...但未来为了方便管理,我还是偏向迟早有一个版本彻底使用 suffix

@RylanBot RylanBot added the breaking the changes involve a large amount of code label Jan 19, 2026
@RylanBot RylanBot force-pushed the rylan/feat/select/filterable branch from fc381b5 to d6e3e2a Compare May 20, 2026 06:57
@RylanBot RylanBot force-pushed the rylan/feat/select/filterable branch from d6e3e2a to 7179cb0 Compare May 20, 2026 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking the changes involve a large amount of code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants