1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-27 15:54:39 +00:00

Hover title (#7988)

* ['share' dialog] 'Share Link' panel: display full link when hover on the 'cut' link in the link list

* [user side panel] 'Files' sub nav items: added '.ellipsis' and display full text when hover on them

* ['library view' page] added title for the 'open/close the panel' icon

* ['library view' page] folder/file items: added title to the 'Star/Unstar' icon

* ['library view' page] improved the path bar(display full text when hover on the path items, and etc.)

* ['Properties' popover] added titles for the 'settings' icon & the 'close' icon

* [the top-right search] added title for the 'clear' icon

* [dialogs] added title for the 'search' & 'close' icons in dialogs/popovers
This commit is contained in:
llj
2025-06-27 21:02:25 +08:00
committed by GitHub
parent 1ae412f5d0
commit 67c6fbd5b7
18 changed files with 60 additions and 33 deletions

View File

@@ -4,7 +4,7 @@ import '../../css/seahub-modal-header.css';
const SeahubModalCloseIcon = (props) => { const SeahubModalCloseIcon = (props) => {
return ( return (
<button type="button" className={`close seahub-modal-btn ${props.className ? props.className : ''}`} data-dismiss="modal" aria-label={gettext('Close')} onClick={props.toggle}> <button type="button" className={`close seahub-modal-btn ${props.className ? props.className : ''}`} data-dismiss="modal" aria-label={gettext('Close')} title={gettext('Close')} onClick={props.toggle}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-x-01" aria-hidden="true"></i> <i className="sf3-font sf3-font-x-01" aria-hidden="true"></i>
</span> </span>

View File

@@ -5,7 +5,7 @@ import '../../css/seahub-modal-header.css';
const SeahubModalHeader = ({ children, ...props }) => { const SeahubModalHeader = ({ children, ...props }) => {
const customCloseBtn = ( const customCloseBtn = (
<button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Close')} onClick={props.toggle}> <button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Close')} title={gettext('Close')} onClick={props.toggle}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-x-01" aria-hidden="true"></i> <i className="sf3-font sf3-font-x-01" aria-hidden="true"></i>
</span> </span>

View File

@@ -21,6 +21,7 @@ const propTypes = {
pathPrefix: PropTypes.array, pathPrefix: PropTypes.array,
fileTags: PropTypes.array.isRequired, fileTags: PropTypes.array.isRequired,
toggleTreePanel: PropTypes.func.isRequired, toggleTreePanel: PropTypes.func.isRequired,
isTreePanelShown: PropTypes.bool.isRequired,
repoEncrypted: PropTypes.bool.isRequired, repoEncrypted: PropTypes.bool.isRequired,
enableDirPrivateShare: PropTypes.bool.isRequired, enableDirPrivateShare: PropTypes.bool.isRequired,
userPerm: PropTypes.string.isRequired, userPerm: PropTypes.string.isRequired,
@@ -201,7 +202,7 @@ class DirPath extends React.Component {
onUploadFolder={this.props.onUploadFolder} onUploadFolder={this.props.onUploadFolder}
loadDirentList={this.props.loadDirentList} loadDirentList={this.props.loadDirentList}
> >
<span className="path-file-name">{item}</span> <span className="last-path-item" title={item}>{item}</span>
</DirOperationToolbar> </DirOperationToolbar>
</Fragment> </Fragment>
); );
@@ -217,7 +218,9 @@ class DirPath extends React.Component {
onDragLeave={this.onDragLeave} onDragLeave={this.onDragLeave}
onDragOver={this.onDragOver} onDragOver={this.onDragOver}
onDrop={this.onDrop} onDrop={this.onDrop}
role="button"> role="button"
title={item}
>
{item} {item}
</span> </span>
</Fragment> </Fragment>
@@ -228,30 +231,34 @@ class DirPath extends React.Component {
}; };
render() { render() {
const { currentPath, repoName } = this.props; const { currentPath, repoName, isTreePanelShown } = this.props;
const pathElem = this.turnPathToLink(currentPath); const pathElem = this.turnPathToLink(currentPath);
return ( return (
<div className="path-container dir-view-path"> <div className="path-container dir-view-path">
<span className="cur-view-path-btn mr-1" onClick={this.props.toggleTreePanel}> <span
className="cur-view-path-btn mr-1"
title={isTreePanelShown ? gettext('Close the panel') : gettext('Open the panel')}
onClick={this.props.toggleTreePanel}
>
<span className="sf3-font-side-bar sf3-font"></span> <span className="sf3-font-side-bar sf3-font"></span>
</span> </span>
{this.props.pathPrefix && this.props.pathPrefix.map((item, index) => { {this.props.pathPrefix && this.props.pathPrefix.map((item, index) => {
return ( return (
<Fragment key={index}> <Fragment key={index}>
<Link to={item.url} className="path-item normal" onClick={(e) => this.onTabNavClick(e, item.name, item.id)}>{gettext(item.showName)}</Link> <Link to={item.url} className="path-item normal" onClick={(e) => this.onTabNavClick(e, item.name, item.id)} title={gettext(item.showName)}>{gettext(item.showName)}</Link>
<span className="path-split">/</span> <span className="path-split">/</span>
</Fragment> </Fragment>
); );
})} })}
{this.props.pathPrefix && this.props.pathPrefix.length === 0 && ( {this.props.pathPrefix && this.props.pathPrefix.length === 0 && (
<> <>
<Link to={siteRoot + 'libraries/'} className="path-item normal" onClick={(e) => this.onTabNavClick(e, 'libraries')}>{gettext('Files')}</Link> <Link to={siteRoot + 'libraries/'} className="flex-shrink-0 path-item normal" onClick={(e) => this.onTabNavClick(e, 'libraries')}>{gettext('Files')}</Link>
<span className="path-split">/</span> <span className="path-split">/</span>
</> </>
)} )}
{!this.props.pathPrefix && ( {!this.props.pathPrefix && (
<> <>
<Link to={siteRoot + 'libraries/'} className="path-item normal" onClick={(e) => this.onTabNavClick(e, 'libraries')}>{gettext('Files')}</Link> <Link to={siteRoot + 'libraries/'} className="flex-shrink-0 path-item normal" onClick={(e) => this.onTabNavClick(e, 'libraries')}>{gettext('Files')}</Link>
<span className="path-split">/</span> <span className="path-split">/</span>
</> </>
)} )}
@@ -271,9 +278,9 @@ class DirPath extends React.Component {
onUploadFolder={this.props.onUploadFolder} onUploadFolder={this.props.onUploadFolder}
loadDirentList={this.props.loadDirentList} loadDirentList={this.props.loadDirentList}
> >
<span className="path-repo-name">{repoName}</span> <span className="last-path-item" title={repoName}>{repoName}</span>
</DirOperationToolbar> : </DirOperationToolbar> :
<span className="path-item" data-path="/" onClick={this.onPathClick} role="button">{repoName}</span> <span className="path-item" data-path="/" onClick={this.onPathClick} role="button" title={repoName}>{repoName}</span>
} }
{pathElem} {pathElem}
</div> </div>

View File

@@ -14,6 +14,7 @@ const propTypes = {
pathPrefix: PropTypes.array, pathPrefix: PropTypes.array,
fileTags: PropTypes.array.isRequired, fileTags: PropTypes.array.isRequired,
toggleTreePanel: PropTypes.func.isRequired, toggleTreePanel: PropTypes.func.isRequired,
isTreePanelShown: PropTypes.bool.isRequired,
direntList: PropTypes.array, direntList: PropTypes.array,
sortBy: PropTypes.string, sortBy: PropTypes.string,
sortOrder: PropTypes.string, sortOrder: PropTypes.string,
@@ -63,6 +64,7 @@ class CurDirPath extends React.Component {
onTabNavClick={this.props.onTabNavClick} onTabNavClick={this.props.onTabNavClick}
fileTags={this.props.fileTags} fileTags={this.props.fileTags}
toggleTreePanel={this.props.toggleTreePanel} toggleTreePanel={this.props.toggleTreePanel}
isTreePanelShown={this.props.isTreePanelShown}
enableDirPrivateShare={this.props.enableDirPrivateShare} enableDirPrivateShare={this.props.enableDirPrivateShare}
showShareBtn={this.props.showShareBtn} showShareBtn={this.props.showShareBtn}
onUploadFile={this.props.onUploadFile} onUploadFile={this.props.onUploadFile}

View File

@@ -28,7 +28,7 @@ class AboutDialog extends React.Component {
return ( return (
<Modal isOpen={true} toggle={toggleDialog}> <Modal isOpen={true} toggle={toggleDialog}>
<ModalBody> <ModalBody>
<button type="button" className="close seahub-modal-btn p-0" aria-label={gettext('Close')} onClick={toggleDialog}> <button type="button" className="close seahub-modal-btn p-0" aria-label={gettext('Close')} title={gettext('Close')} onClick={toggleDialog}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-x-01" aria-hidden="true"></i> <i className="sf3-font sf3-font-x-01" aria-hidden="true"></i>
</span> </span>
@@ -41,7 +41,7 @@ class AboutDialog extends React.Component {
return ( return (
<Modal isOpen={true} toggle={toggleDialog}> <Modal isOpen={true} toggle={toggleDialog}>
<ModalBody> <ModalBody>
<button type="button" className="close seahub-modal-btn p-0" aria-label={gettext('Close')} onClick={toggleDialog}> <button type="button" className="close seahub-modal-btn p-0" aria-label={gettext('Close')} title={gettext('Close')} onClick={toggleDialog}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-x-01" aria-hidden="true"></i> <i className="sf3-font sf3-font-x-01" aria-hidden="true"></i>
</span> </span>

View File

@@ -322,13 +322,13 @@ class CopyDirent extends React.Component {
<ModalHeader toggle={this.toggle} <ModalHeader toggle={this.toggle}
close={ close={
<div className="header-buttons"> <div className="header-buttons">
<button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Close')} onClick={this.toggle}> <button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Close')} title={gettext('Close')} onClick={this.toggle}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-x-01" aria-hidden="true"></i> <i className="sf3-font sf3-font-x-01" aria-hidden="true"></i>
</span> </span>
</button> </button>
{(isPro && !showSearchBar) && {(isPro && !showSearchBar) &&
<button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Search')} onClick={this.onOpenSearchBar}> <button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Search')} title={gettext('Search')} onClick={this.onOpenSearchBar}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-search" aria-hidden="true"></i> <i className="sf3-font sf3-font-search" aria-hidden="true"></i>
</span> </span>

View File

@@ -18,7 +18,7 @@ class GuideForNewDialog extends React.Component {
return ( return (
<Modal isOpen={true} toggle={this.toggle}> <Modal isOpen={true} toggle={this.toggle}>
<ModalBody> <ModalBody>
<button type="button" className="close seahub-modal-btn p-0" aria-label={gettext('Close')} onClick={this.toggle}> <button type="button" className="close seahub-modal-btn p-0" aria-label={gettext('Close')} title={gettext('Close')} onClick={this.toggle}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-x-01" aria-hidden="true"></i> <i className="sf3-font sf3-font-x-01" aria-hidden="true"></i>
</span> </span>

View File

@@ -323,13 +323,13 @@ class MoveDirentDialog extends React.Component {
<ModalHeader toggle={this.toggle} <ModalHeader toggle={this.toggle}
close={ close={
<div className="header-buttons"> <div className="header-buttons">
<button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Close')} onClick={this.toggle}> <button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Close')} title={gettext('Close')} onClick={this.toggle}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-x-01" aria-hidden="true"></i> <i className="sf3-font sf3-font-x-01" aria-hidden="true"></i>
</span> </span>
</button> </button>
{(isPro && !showSearchBar) && {(isPro && !showSearchBar) &&
<button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Search')} onClick={this.onOpenSearchBar}> <button type="button" className="close seahub-modal-btn" data-dismiss="modal" aria-label={gettext('Search')} title={gettext('Search')} onClick={this.onOpenSearchBar}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-search" aria-hidden="true"></i> <i className="sf3-font sf3-font-search" aria-hidden="true"></i>
</span> </span>

View File

@@ -201,7 +201,7 @@ class TrashDialog extends React.Component {
<button className="btn btn-secondary clean flex-shrink-0 ml-4" onClick={this.cleanTrash}>{gettext('Clean')}</button> <button className="btn btn-secondary clean flex-shrink-0 ml-4" onClick={this.cleanTrash}>{gettext('Clean')}</button>
} }
{isDesktop && ( {isDesktop && (
<button type="button" className="close seahub-modal-btn" aria-label={gettext('Close')} onClick={toggleTrashDialog}> <button type="button" className="close seahub-modal-btn" aria-label={gettext('Close')} title={gettext('Close')}onClick={toggleTrashDialog}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-x-01" aria-hidden="true"></i> <i className="sf3-font sf3-font-x-01" aria-hidden="true"></i>
</span> </span>

View File

@@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { gettext } from '../../../../utils/constants';
import Icon from '../../../icon'; import Icon from '../../../icon';
import Title from './title'; import Title from './title';
@@ -14,7 +15,7 @@ const Header = ({ title, icon, iconSize = 32, onClose, children, component = {}
<div className="detail-control-container"> <div className="detail-control-container">
{children} {children}
{onClose && ( {onClose && (
<div className="detail-control" onClick={onClose}> <div className="detail-control" onClick={onClose} title={gettext('Close')}>
{closeIcon ? closeIcon : <Icon symbol="close" className="detail-control-icon" />} {closeIcon ? closeIcon : <Icon symbol="close" className="detail-control-icon" />}
</div> </div>
)} )}

View File

@@ -806,6 +806,7 @@ class DirentListItem extends React.Component {
<i <i
role="button" role="button"
aria-label={dirent.starred ? gettext('Unstar') : gettext('Star')} aria-label={dirent.starred ? gettext('Unstar') : gettext('Star')}
title={dirent.starred ? gettext('Unstar') : gettext('Star')}
onClick={this.onItemStarred} onClick={this.onItemStarred}
className={`sf3-font ${dirent.starred ? 'sf3-font-star' : 'sf3-font-star-empty'}`} className={`sf3-font ${dirent.starred ? 'sf3-font-star' : 'sf3-font-star-empty'}`}
> >

View File

@@ -34,11 +34,11 @@ class FilesSubNav extends React.Component {
<li key={item.id} className={`nav-item ${this.getActiveClass(item.name)}`}> <li key={item.id} className={`nav-item ${this.getActiveClass(item.name)}`}>
<Link <Link
to={siteRoot + 'group/' + item.id + '/'} to={siteRoot + 'group/' + item.id + '/'}
className={`nav-link ellipsis ${this.getActiveClass(item.name)}`} className={`nav-link ${this.getActiveClass(item.name)}`}
onClick={(e) => this.tabItemClick(e, item.name, item.id)} onClick={(e) => this.tabItemClick(e, item.name, item.id)}
> >
<span className={`${item.parent_group_id == 0 ? 'sf3-font-group' : 'sf3-font-department'} sf3-font nav-icon`} aria-hidden="true"></span> <span className={`${item.parent_group_id == 0 ? 'sf3-font-group' : 'sf3-font-department'} sf3-font nav-icon`} aria-hidden="true"></span>
<span className="nav-text">{item.name}</span> <span className="nav-text ellipsis" title={item.name}>{item.name}</span>
</Link> </Link>
</li> </li>
); );
@@ -52,23 +52,35 @@ class FilesSubNav extends React.Component {
<> <>
{canAddRepo && ( {canAddRepo && (
<li className={`nav-item ${this.getActiveClass('my-libs') || this.getActiveClass('deleted')}`}> <li className={`nav-item ${this.getActiveClass('my-libs') || this.getActiveClass('deleted')}`}>
<Link to={ siteRoot + 'my-libs/' } className={`nav-link ellipsis ${this.getActiveClass('my-libs') || this.getActiveClass('deleted') }`} title={gettext('My Libraries')} onClick={(e) => this.tabItemClick(e, 'my-libs')}> <Link
to={siteRoot + 'my-libs/'}
className={`nav-link ${this.getActiveClass('my-libs') || this.getActiveClass('deleted') }`}
onClick={(e) => this.tabItemClick(e, 'my-libs')}
>
<span className="sf3-font-mine sf3-font nav-icon" aria-hidden="true"></span> <span className="sf3-font-mine sf3-font nav-icon" aria-hidden="true"></span>
<span className="nav-text">{gettext('My Libraries')}</span> <span className="nav-text ellipsis" title={gettext('My Libraries')}>{gettext('My Libraries')}</span>
</Link> </Link>
</li> </li>
)} )}
<li className={`nav-item ${this.getActiveClass('shared-libs')}`}> <li className={`nav-item ${this.getActiveClass('shared-libs')}`}>
<Link to={siteRoot + 'shared-libs/'} className={`nav-link ellipsis ${this.getActiveClass('shared-libs')}`} title={gettext('Shared with me')} onClick={(e) => this.tabItemClick(e, 'shared-libs')}> <Link
to={siteRoot + 'shared-libs/'}
className={`nav-link ${this.getActiveClass('shared-libs')}`}
onClick={(e) => this.tabItemClick(e, 'shared-libs')}
>
<span className="sf3-font-share-with-me sf3-font nav-icon" aria-hidden="true"></span> <span className="sf3-font-share-with-me sf3-font nav-icon" aria-hidden="true"></span>
<span className="nav-text">{gettext('Shared with me')}</span> <span className="nav-text ellipsis" title={gettext('Shared with me')}>{gettext('Shared with me')}</span>
</Link> </Link>
</li> </li>
{canViewOrg && {canViewOrg &&
<li className={`nav-item ${this.getActiveClass('org')}`} onClick={(e) => this.tabItemClick(e, 'org')}> <li className={`nav-item ${this.getActiveClass('org')}`}>
<Link to={ siteRoot + 'org/' } className={`nav-link ellipsis ${this.getActiveClass('org')}`} title={gettext('Shared with all')}> <Link
to={siteRoot + 'org/'}
className={`nav-link ${this.getActiveClass('org')}`}
onClick={(e) => this.tabItemClick(e, 'org')}
>
<span className="sf3-font-share-with-all sf3-font nav-icon" aria-hidden="true"></span> <span className="sf3-font-share-with-all sf3-font nav-icon" aria-hidden="true"></span>
<span className="nav-text">{gettext('Shared with all')}</span> <span className="nav-text ellipsis" title={gettext('Shared with all')}>{gettext('Shared with all')}</span>
</Link> </Link>
</li> </li>
} }

View File

@@ -925,6 +925,7 @@ class Search extends Component {
className="search-icon-right sf3-font sf3-font-x-01" className="search-icon-right sf3-font sf3-font-x-01"
onClick={this.onClearSearch} onClick={this.onClearSearch}
aria-label={gettext('Clear search')} aria-label={gettext('Clear search')}
title={gettext('Clear search')}
> >
</button> </button>
} }
@@ -983,6 +984,7 @@ class Search extends Component {
className="search-icon-right input-icon-addon sf3-font sf3-font-x-01" className="search-icon-right input-icon-addon sf3-font sf3-font-x-01"
onClick={this.onClearSearch} onClick={this.onClearSearch}
aria-label={gettext('Clear search')} aria-label={gettext('Clear search')}
title={gettext('Clear search')}
> >
</button> </button>
} }

View File

@@ -155,7 +155,7 @@ class LinkItem extends React.Component {
onChange={this.toggleSelectLink} onChange={this.toggleSelectLink}
/> />
</td> </td>
<td> <td title={link}>
{this.cutLink(link)} {this.cutLink(link)}
</td> </td>
<td> <td>

View File

@@ -261,12 +261,12 @@
.dir-view-path .path-item, .dir-view-path .path-item,
.dir-view-path .last-path-item { .dir-view-path .last-path-item {
display: inline-block; display: inline-block;
min-width: 0; /* overwrite some styles */
padding: 0 6px; padding: 0 6px;
font-size: 1rem; font-size: 1rem;
color: inherit; color: inherit;
border-radius: 3px; border-radius: 3px;
text-decoration: none; text-decoration: none;
min-width: 28px;
max-width: 172px; max-width: 172px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;

View File

@@ -1,4 +1,5 @@
import React, { useMemo, useCallback, useState } from 'react'; import React, { useMemo, useCallback, useState } from 'react';
import { gettext } from '../../../utils/constants';
import Icon from '../../../components/icon'; import Icon from '../../../components/icon';
import HideColumnPopover from '../popover/hidden-column-popover'; import HideColumnPopover from '../popover/hidden-column-popover';
import { useMetadataDetails } from '../../hooks'; import { useMetadataDetails } from '../../hooks';
@@ -21,7 +22,7 @@ const SettingsIcon = () => {
return ( return (
<> <>
<div className="detail-control mr-2" id={target} onClick={onSetterToggle}> <div className="detail-control mr-2" id={target} onClick={onSetterToggle} title={gettext('Settings')}>
<Icon symbol="set-up" className="detail-control-icon" /> <Icon symbol="set-up" className="detail-control-icon" />
</div> </div>
{isShowSetter && ( {isShowSetter && (

View File

@@ -2442,6 +2442,7 @@ class LibContentView extends React.Component {
sortOrder={this.state.sortOrder} sortOrder={this.state.sortOrder}
sortItems={this.sortItems} sortItems={this.sortItems}
toggleTreePanel={this.toggleTreePanel} toggleTreePanel={this.toggleTreePanel}
isTreePanelShown={this.state.isTreePanelShown}
enableDirPrivateShare={enableDirPrivateShare} enableDirPrivateShare={enableDirPrivateShare}
showShareBtn={showShareBtn} showShareBtn={showShareBtn}
onUploadFile={this.onUploadFile} onUploadFile={this.onUploadFile}

View File

@@ -97,7 +97,7 @@ class WikiTrashDialog extends React.Component {
{(isAdmin && enableUserCleanTrash) && {(isAdmin && enableUserCleanTrash) &&
<button className="btn btn-secondary clean" onClick={this.cleanTrash}>{gettext('Clean')}</button> <button className="btn btn-secondary clean" onClick={this.cleanTrash}>{gettext('Clean')}</button>
} }
<button type="button" className="close seahub-modal-btn" aria-label={gettext('Close')} onClick={toggleTrashDialog}> <button type="button" className="close seahub-modal-btn" aria-label={gettext('Close')} title={gettext('Close')} onClick={toggleTrashDialog}>
<span className="seahub-modal-btn-inner"> <span className="seahub-modal-btn-inner">
<i className="sf3-font sf3-font-x-01" aria-hidden="true"></i> <i className="sf3-font sf3-font-x-01" aria-hidden="true"></i>
</span> </span>