Explorar o código

✨ ui: Add CSS ellipsis + Tooltip for SelectableButtonGroup; keep Tag intact

- Truncate long labels via pure CSS and always show full text in a Tooltip
- Ensure the right-side Tag is never truncated and remains fully visible
- Simplify implementation: remove overflow detection and ResizeObserver
- Use minimal markup with sbg-button/sbg-inner/sbg-label to enable shrinking
- Add global rules to allow `.semi-button-content` to shrink and ellipsize

Files:
- web/src/components/common/ui/SelectableButtonGroup.jsx
- web/src/index.css

No API changes; visuals improved and code complexity reduced.
t0ng7u hai 6 meses
pai
achega
e863be7ec3
Modificáronse 2 ficheiros con 44 adicións e 29 borrados
  1. 23 29
      web/src/components/common/ui/SelectableButtonGroup.jsx
  2. 21 0
      web/src/index.css

+ 23 - 29
web/src/components/common/ui/SelectableButtonGroup.jsx

@@ -17,10 +17,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
 For commercial licensing, please contact support@quantumnous.com
 */
 
-import React, { useState, useRef } from 'react';
+import React, { useState } from 'react';
 import { useIsMobile } from '../../../hooks/common/useIsMobile';
 import { useMinimumLoadingTime } from '../../../hooks/common/useMinimumLoadingTime';
-import { Divider, Button, Tag, Row, Col, Collapsible, Checkbox, Skeleton } from '@douyinfe/semi-ui';
+import { Divider, Button, Tag, Row, Col, Collapsible, Checkbox, Skeleton, Tooltip } from '@douyinfe/semi-ui';
 import { IconChevronDown, IconChevronUp } from '@douyinfe/semi-icons';
 
 /**
@@ -57,8 +57,6 @@ const SelectableButtonGroup = ({
   const needCollapse = collapsible && items.length > perRow * maxVisibleRows;
   const showSkeleton = useMinimumLoadingTime(loading);
 
-  const contentRef = useRef(null);
-
   const maskStyle = isOpen
     ? {}
     : {
@@ -131,7 +129,7 @@ const SelectableButtonGroup = ({
   };
 
   const contentElement = showSkeleton ? renderSkeletonButtons() : (
-    <Row gutter={[8, 8]} style={{ lineHeight: '32px', ...style }} ref={contentRef}>
+    <Row gutter={[8, 8]} style={{ lineHeight: '32px', ...style }}>
       {items.map((item) => {
         const isDisabled = item.disabled || (typeof item.tagCount === 'number' && item.tagCount === 0);
         const isActive = Array.isArray(activeValue)
@@ -152,6 +150,7 @@ const SelectableButtonGroup = ({
                 theme={isActive ? 'light' : 'outline'}
                 type={isActive ? 'primary' : 'tertiary'}
                 disabled={isDisabled}
+                className="sbg-button"
                 icon={
                   <Checkbox
                     checked={isActive}
@@ -162,19 +161,15 @@ const SelectableButtonGroup = ({
                 }
                 style={{ width: '100%', cursor: 'default' }}
               >
-                {item.icon && (
-                  <span style={{ marginRight: 4 }}>{item.icon}</span>
-                )}
-                <span style={{ marginRight: item.tagCount !== undefined ? 4 : 0 }}>{item.label}</span>
-                {item.tagCount !== undefined && (
-                  <Tag
-                    color='white'
-                    shape="circle"
-                    size="small"
-                  >
-                    {item.tagCount}
-                  </Tag>
-                )}
+                <div className="sbg-content">
+                  {item.icon && (<span className="sbg-icon">{item.icon}</span>)}
+                  <Tooltip content={item.label}>
+                    <span className="sbg-ellipsis">{item.label}</span>
+                  </Tooltip>
+                  {item.tagCount !== undefined && (
+                    <Tag className="sbg-tag" color='white' shape="circle" size="small">{item.tagCount}</Tag>
+                  )}
+                </div>
               </Button>
             </Col>
           );
@@ -192,20 +187,19 @@ const SelectableButtonGroup = ({
               onClick={() => onChange(item.value)}
               theme={isActive ? 'light' : 'outline'}
               type={isActive ? 'primary' : 'tertiary'}
-              icon={item.icon}
               disabled={isDisabled}
+              className="sbg-button"
               style={{ width: '100%' }}
             >
-              <span style={{ marginRight: item.tagCount !== undefined ? 4 : 0 }}>{item.label}</span>
-              {item.tagCount !== undefined && (
-                <Tag
-                  color='white'
-                  shape="circle"
-                  size="small"
-                >
-                  {item.tagCount}
-                </Tag>
-              )}
+              <div className="sbg-content">
+                {item.icon && (<span className="sbg-icon">{item.icon}</span>)}
+                <Tooltip content={item.label}>
+                  <span className="sbg-ellipsis">{item.label}</span>
+                </Tooltip>
+                {item.tagCount !== undefined && (
+                  <Tag className="sbg-tag" color='white' shape="circle" size="small">{item.tagCount}</Tag>
+                )}
+              </div>
             </Button>
           </Col>
         );

+ 21 - 0
web/src/index.css

@@ -289,6 +289,27 @@ code {
 }
 
 /* ==================== 组件特定样式 ==================== */
+/* SelectableButtonGroup */
+.sbg-button .semi-button-content {
+  min-width: 0 !important;
+}
+
+.sbg-content {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+  width: 100%;
+  min-width: 0;
+}
+
+.sbg-ellipsis {
+  flex: 1;
+  min-width: 0;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+
 /* Tabs组件样式 */
 .semi-tabs-content {
   padding: 0 !important;