Przeglądaj źródła

feat: a11y transfer (#420)

* feat: a11y transfer

* feat: [Transfer] adjust a11y and add docs
Neptune 3 lat temu
rodzic
commit
9375fc6d6d

+ 7 - 0
content/input/transfer/index-en-US.md

@@ -905,6 +905,13 @@ import { Transfer } from '@douyinfe/semi-ui';
 };
 ```
 
+## Accessibility
+
+### ARIA
+
+- Add `role` `search` to the search box
+- Add `role` `list` to the selected list on the right, add `role` `listitem` to the selected item
+
 ## API Reference
 
 ### Trasnfer Props

+ 7 - 0
content/input/transfer/index.md

@@ -907,6 +907,13 @@ import { Transfer } from '@douyinfe/semi-ui';
 };
 ```
 
+## Accessibility
+
+### ARIA
+
+- 搜索框添加 `role` `search`
+- 右侧选中列表添加 `role` `list`,选中项添加 `role` `listitem`
+
 ## API 参考
 
 ### Trasnfer Props

+ 0 - 2
packages/semi-foundation/transfer/transfer.scss

@@ -93,8 +93,6 @@ $module: #{$prefix}-transfer;
         }
 
         .#{$module}-item-close-icon {
-            width: $width-transfer_item_close-icon;
-            height: $width-transfer_item_close-icon;
             font-size: $width-transfer_item_close-icon;
             cursor: pointer;
             visibility: hidden;

+ 30 - 26
packages/semi-ui/transfer/index.tsx

@@ -291,7 +291,7 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
             return null;
         }
         return (
-            <div className={`${prefixcls }-filter`}>
+            <div role="search" aria-label="Transfer filter" className={`${prefixcls}-filter`}>
                 <Input
                     prefix={<IconSearch />}
                     placeholder={locale.placeholder}
@@ -309,20 +309,20 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
         const { disabled } = this.props;
         const { totalContent, allContent, onAllClick, type, showButton } = headerConfig;
         const headerCls = cls({
-            [`${prefixcls }-header`]: true,
-            [`${prefixcls }-right-header`]: type === 'right',
-            [`${prefixcls }-left-header`]: type === 'left',
+            [`${prefixcls}-header`]: true,
+            [`${prefixcls}-right-header`]: type === 'right',
+            [`${prefixcls}-left-header`]: type === 'left',
         });
         return (
             <div className={headerCls}>
-                <span className={`${prefixcls }-header-total`}>{totalContent}</span>
+                <span className={`${prefixcls}-header-total`}>{totalContent}</span>
                 {showButton ? (
                     <Button
                         theme="borderless"
                         disabled={disabled}
                         type="tertiary"
                         size="small"
-                        className={`${prefixcls }-header-all`}
+                        className={`${prefixcls}-header-all`}
                         onClick={onAllClick}
                     >
                         {allContent}
@@ -340,8 +340,8 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
             return renderSourceItem({ ...item, checked, onChange: () => this.onSelectOrRemove(item) });
         }
         const leftItemCls = cls({
-            [`${prefixcls }-item`]: true,
-            [`${prefixcls }-item-disabled`]: item.disabled,
+            [`${prefixcls}-item`]: true,
+            [`${prefixcls}-item-disabled`]: item.disabled,
         });
         return (
             <Checkbox
@@ -349,6 +349,7 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
                 disabled={item.disabled || disabled}
                 className={leftItemCls}
                 checked={checked}
+                role="listitem"
                 onChange={() => this.onSelectOrRemove(item)}
             >
                 {item.label}
@@ -438,7 +439,7 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
         }
 
         return (
-            <section className={`${prefixcls }-left`}>
+            <section className={`${prefixcls}-left`}>
                 {inputCom}
                 {content}
             </section>
@@ -446,7 +447,7 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
     }
 
     renderGroupTitle(group: GroupItem) {
-        const groupCls = cls(`${prefixcls }-group-title`);
+        const groupCls = cls(`${prefixcls}-group-title`);
         return (
             <div className={groupCls} key={group.title}>
                 {group.title}
@@ -501,7 +502,7 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
                 content.push(optionContent);
             }
         });
-        return <div className={`${prefixcls }-left-list`}>{content}</div>;
+        return <div className={`${prefixcls}-left-list`} role="list" aria-label="Option list">{content}</div>;
     }
 
     renderRightItem(item: ResolvedDataItem): React.ReactNode {
@@ -513,9 +514,9 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
         }
         const onRemove = () => this.foundation.handleSelectOrRemove(newItem);
         const rightItemCls = cls({
-            [`${prefixcls }-item`]: true,
-            [`${prefixcls }-right-item`]: true,
-            [`${prefixcls }-right-item-draggable`]: draggable
+            [`${prefixcls}-item`]: true,
+            [`${prefixcls}-right-item`]: true,
+            [`${prefixcls}-right-item-draggable`]: draggable
         });
         const shouldShowPath = type === strings.TYPE_TREE_TO_LIST && showPath === true;
 
@@ -526,15 +527,18 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
         }
 
         const DragHandle = SortableHandle(() => (
-            <IconHandle className={`${prefixcls }-right-item-drag-handler`} />
+            <IconHandle role="button" aria-label="Drag and sort" className={`${prefixcls}-right-item-drag-handler`} />
         ));
 
         return (
-            <div className={rightItemCls} key={newItem.key}>
+            // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
+            <div role="listitem" className={rightItemCls} key={newItem.key}>
                 {draggable ? <DragHandle /> : null}
                 <div className={`${prefixcls}-right-item-text`}>{label}</div>
                 <IconClose
-                    onClick={onRemove} className={cls(`${prefixcls}-item-close-icon`, {
+                    onClick={onRemove}
+                    aria-disabled={item.disabled}
+                    className={cls(`${prefixcls}-item-close-icon`, {
                         [`${prefixcls}-item-close-icon-disabled`]: item.disabled
                     })}
                 />
@@ -544,11 +548,11 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
 
     renderEmpty(type: string, emptyText: React.ReactNode) {
         const emptyCls = cls({
-            [`${prefixcls }-empty`]: true,
-            [`${prefixcls }-right-empty`]: type === 'right',
-            [`${prefixcls }-left-empty`]: type === 'left',
+            [`${prefixcls}-empty`]: true,
+            [`${prefixcls}-right-empty`]: type === 'right',
+            [`${prefixcls}-left-empty`]: type === 'left',
         });
-        return <div className={emptyCls}>{emptyText}</div>;
+        return <div aria-label="empty" className={emptyCls}>{emptyText}</div>;
     }
 
     renderRightSortableList(selectedData: Array<ResolvedDataItem>) {
@@ -557,7 +561,7 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
             (item: ResolvedDataItem) => this.renderRightItem(item)) as React.SFC<ResolvedDataItem>
         );
         const SortableList = SortableContainer(({ items }: { items: Array<ResolvedDataItem> }) => (
-            <div className={`${prefixcls}-right-list`}>
+            <div className={`${prefixcls}-right-list`} role="list" aria-label="Selected list">
                 {items.map((item, index: number) => (
                     // sortableElement will take over the property 'key', so use another '_optionKey' to pass
                     <SortableItem key={item.label} index={index} {...item} _optionKey={item.key} />
@@ -597,7 +601,7 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
         };
         const headerCom = this.renderHeader(headerConfig);
         const emptyCom = this.renderEmpty('right', emptyContent.right ? emptyContent.right : locale.emptyRight);
-        const panelCls = `${prefixcls }-right`;
+        const panelCls = `${prefixcls}-right`;
 
         let content = null;
 
@@ -608,7 +612,7 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
                 break;
             case selectedData.length && !draggable:
                 const list = (
-                    <div className={`${prefixcls }-right-list`}>
+                    <div className={`${prefixcls}-right-list`} role="list" aria-label="Selected list">
                         {selectedData.map(item => this.renderRightItem({ ...item }))}
                     </div>
                 );
@@ -632,8 +636,8 @@ class Transfer extends BaseComponent<TransferProps, TransferState> {
     render() {
         const { className, style, disabled, renderSelectedPanel, renderSourcePanel } = this.props;
         const transferCls = cls(prefixcls, className, {
-            [`${prefixcls }-disabled`]: disabled,
-            [`${prefixcls }-custom-panel`]: renderSelectedPanel && renderSourcePanel,
+            [`${prefixcls}-disabled`]: disabled,
+            [`${prefixcls}-custom-panel`]: renderSelectedPanel && renderSourcePanel,
         });
 
         return (