mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Improve the Icon component (#6245)
GitOrigin-RevId: fbb23b32c47edbe5a22badc627318accbd09e82a
This commit is contained in:
parent
ee00ff3c44
commit
f065a7a909
37 changed files with 146 additions and 152 deletions
|
@ -6,8 +6,8 @@ function BackToProjectsButton() {
|
|||
return (
|
||||
<a className="toolbar-header-back-projects" href="/project">
|
||||
<Icon
|
||||
type="fw"
|
||||
modifier="level-up"
|
||||
type="level-up"
|
||||
fw
|
||||
accessibilityLabel={t('back_to_your_projects')}
|
||||
/>
|
||||
</a>
|
||||
|
|
|
@ -17,14 +17,10 @@ function ChatToggleButton({ chatIsOpen, unreadMessageCount, onClick }) {
|
|||
return (
|
||||
<div className="toolbar-item">
|
||||
<button className={classes} onClick={onClick}>
|
||||
<Icon
|
||||
type="fw"
|
||||
modifier="comment"
|
||||
classes={{ icon: hasUnreadMessages ? 'bounce' : undefined }}
|
||||
/>
|
||||
{hasUnreadMessages ? (
|
||||
<Icon type="comment" fw className={hasUnreadMessages ? 'bounce' : ''} />
|
||||
{hasUnreadMessages && (
|
||||
<span className="label label-info">{unreadMessageCount}</span>
|
||||
) : null}
|
||||
)}
|
||||
<p className="toolbar-label">{t('chat')}</p>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@ function HistoryToggleButton({ historyIsOpen, onClick }) {
|
|||
return (
|
||||
<div className="toolbar-item">
|
||||
<button className={classes} onClick={onClick}>
|
||||
<Icon type="fw" modifier="history" />
|
||||
<Icon type="history" fw />
|
||||
<p className="toolbar-label">{t('history')}</p>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -12,19 +12,19 @@ import { useLayoutContext } from '../../../shared/context/layout-context'
|
|||
import * as eventTracking from '../../../infrastructure/event-tracking'
|
||||
|
||||
function IconPlaceholder() {
|
||||
return <Icon type="" modifier="fw" />
|
||||
return <Icon type="" fw />
|
||||
}
|
||||
|
||||
function IconRefresh() {
|
||||
return <Icon type="refresh" modifier="fw" spin />
|
||||
return <Icon type="refresh" fw spin />
|
||||
}
|
||||
|
||||
function IconLayout() {
|
||||
return <Icon type="columns" modifier="fw" />
|
||||
return <Icon type="columns" fw />
|
||||
}
|
||||
|
||||
function IconDetach() {
|
||||
return <Icon type="window-restore" modifier="fw" />
|
||||
return <Icon type="window-restore" fw />
|
||||
}
|
||||
|
||||
function IconCheckmark({ iconFor, pdfLayout, view, detachRole }) {
|
||||
|
|
|
@ -8,11 +8,7 @@ function MenuButton({ onClick }) {
|
|||
return (
|
||||
<div className="toolbar-item">
|
||||
<button className="btn btn-full-height" onClick={onClick}>
|
||||
<Icon
|
||||
type="bars "
|
||||
modifier="fw"
|
||||
classes={{ icon: 'editor-menu-icon' }}
|
||||
/>
|
||||
<Icon type="bars" fw className="editor-menu-icon" />
|
||||
<p className="toolbar-label">{t('menu')}</p>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -105,7 +105,7 @@ const DropDownToggleButton = React.forwardRef((props, ref) => {
|
|||
onClick={props.onClick} // required by Bootstrap Dropdown to trigger an opening
|
||||
>
|
||||
<strong>{props.onlineUserCount}</strong>
|
||||
<Icon type="users" modifier="fw" />
|
||||
<Icon type="users" fw />
|
||||
</button>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
|
|
|
@ -21,7 +21,7 @@ function PdfToggleButton({ onClick, pdfViewIsOpen }) {
|
|||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid,jsx-a11y/click-events-have-key-events,jsx-a11y/interactive-supports-focus */}
|
||||
<a role="button" className={classes} onClick={onClick}>
|
||||
<Icon type="file-pdf-o" modifier="fw" accessibilityLabel="PDF" />
|
||||
<Icon type="file-pdf-o" fw accessibilityLabel="PDF" />
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
|
|
|
@ -82,7 +82,7 @@ function ProjectNameEditableLabel({
|
|||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid, jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus */}
|
||||
<a className="rename" role="button" onClick={startRenaming}>
|
||||
<Icon type="pencil" modifier="fw" />
|
||||
<Icon type="pencil" fw />
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
)}
|
||||
|
|
|
@ -8,7 +8,7 @@ function ShareProjectButton({ onClick }) {
|
|||
return (
|
||||
<div className="toolbar-item">
|
||||
<button className="btn btn-full-height" onClick={onClick}>
|
||||
<Icon type="fw" modifier="group" />
|
||||
<Icon type="group" fw />
|
||||
<p className="toolbar-label">{t('share')}</p>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -19,7 +19,7 @@ export default function FileTreeModalCreateFileMode({ mode, icon, label }) {
|
|||
onClick={handleClick}
|
||||
className="modal-new-file-mode"
|
||||
>
|
||||
<Icon modifier="fw" type={icon} />
|
||||
<Icon type={icon} fw />
|
||||
|
||||
{label}
|
||||
</Button>
|
||||
|
|
|
@ -1,36 +1,16 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import Icon from '../../../shared/components/icon'
|
||||
import iconTypeFromName from '../util/icon-type-from-name'
|
||||
|
||||
import { useSelectableEntity } from '../contexts/file-tree-selectable'
|
||||
|
||||
import FileTreeItemInner from './file-tree-item/file-tree-item-inner'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
import iconTypeFromName from '../util/icon-type-from-name'
|
||||
import classnames from 'classnames'
|
||||
|
||||
function FileTreeDoc({ name, id, isLinkedFile }) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { isSelected, props: selectableEntityProps } = useSelectableEntity(id)
|
||||
|
||||
const icons = (
|
||||
<>
|
||||
<Icon
|
||||
type={iconTypeFromName(name)}
|
||||
modifier="fw"
|
||||
classes={{ icon: 'spaced' }}
|
||||
>
|
||||
{isLinkedFile ? (
|
||||
<Icon
|
||||
type="external-link-square"
|
||||
modifier="rotate-180"
|
||||
classes={{ icon: 'linked-file-highlight' }}
|
||||
accessibilityLabel={t('linked_file')}
|
||||
/>
|
||||
) : null}
|
||||
</Icon>
|
||||
</>
|
||||
)
|
||||
return (
|
||||
<li
|
||||
role="treeitem"
|
||||
|
@ -42,7 +22,7 @@ function FileTreeDoc({ name, id, isLinkedFile }) {
|
|||
id={id}
|
||||
name={name}
|
||||
isSelected={isSelected}
|
||||
icons={icons}
|
||||
icons={<FileTreeIcon isLinkedFile={isLinkedFile} name={name} />}
|
||||
/>
|
||||
</li>
|
||||
)
|
||||
|
@ -54,4 +34,29 @@ FileTreeDoc.propTypes = {
|
|||
isLinkedFile: PropTypes.bool,
|
||||
}
|
||||
|
||||
export const FileTreeIcon = ({ isLinkedFile, name }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const className = classnames('spaced', { 'linked-file-icon': isLinkedFile })
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<Icon type={iconTypeFromName(name)} fw className={className} />
|
||||
{isLinkedFile && (
|
||||
<Icon
|
||||
type="external-link-square"
|
||||
modifier="rotate-180"
|
||||
className="linked-file-highlight"
|
||||
accessibilityLabel={t('linked_file')}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
FileTreeIcon.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
isLinkedFile: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default FileTreeDoc
|
||||
|
|
|
@ -45,9 +45,9 @@ function FileTreeFolder({ name, id, folders, docs, files }) {
|
|||
onClick={handleExpandCollapseClick}
|
||||
aria-label={expanded ? t('collapse') : t('expand')}
|
||||
>
|
||||
<Icon type={expanded ? 'angle-down' : 'angle-right'} modifier="fw" />
|
||||
<Icon type={expanded ? 'angle-down' : 'angle-right'} fw />
|
||||
</button>
|
||||
<Icon type={expanded ? 'folder-open' : 'folder'} modifier="fw" />
|
||||
<Icon type={expanded ? 'folder-open' : 'folder'} fw />
|
||||
</>
|
||||
)
|
||||
|
||||
|
|
|
@ -42,25 +42,21 @@ function FileTreeToolbarLeft() {
|
|||
description={t('new_file')}
|
||||
onClick={startCreatingDocOrFile}
|
||||
>
|
||||
<Icon type="file" modifier="fw" accessibilityLabel={t('new_file')} />
|
||||
<Icon type="file" fw accessibilityLabel={t('new_file')} />
|
||||
</TooltipButton>
|
||||
<TooltipButton
|
||||
id="new_folder"
|
||||
description={t('new_folder')}
|
||||
onClick={startCreatingFolder}
|
||||
>
|
||||
<Icon
|
||||
type="folder"
|
||||
modifier="fw"
|
||||
accessibilityLabel={t('new_folder')}
|
||||
/>
|
||||
<Icon type="folder" fw accessibilityLabel={t('new_folder')} />
|
||||
</TooltipButton>
|
||||
<TooltipButton
|
||||
id="upload"
|
||||
description={t('upload')}
|
||||
onClick={startUploadingDocOrFile}
|
||||
>
|
||||
<Icon type="upload" modifier="fw" accessibilityLabel={t('upload')} />
|
||||
<Icon type="upload" fw accessibilityLabel={t('upload')} />
|
||||
</TooltipButton>
|
||||
</div>
|
||||
)
|
||||
|
@ -83,7 +79,7 @@ function FileTreeToolbarRight() {
|
|||
description={t('rename')}
|
||||
onClick={startRenaming}
|
||||
>
|
||||
<Icon type="pencil" modifier="fw" accessibilityLabel={t('rename')} />
|
||||
<Icon type="pencil" fw accessibilityLabel={t('rename')} />
|
||||
</TooltipButton>
|
||||
) : null}
|
||||
{canDelete ? (
|
||||
|
@ -92,7 +88,7 @@ function FileTreeToolbarRight() {
|
|||
description={t('delete')}
|
||||
onClick={startDeleting}
|
||||
>
|
||||
<Icon type="trash-o" modifier="fw" accessibilityLabel={t('delete')} />
|
||||
<Icon type="trash-o" fw accessibilityLabel={t('delete')} />
|
||||
</TooltipButton>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
@ -10,6 +10,7 @@ import { useProjectContext } from '../../../shared/context/project-context'
|
|||
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
import useAbortController from '../../../shared/hooks/use-abort-controller'
|
||||
import { LinkedFileIcon } from './file-view-icons'
|
||||
const tprLinkedFileInfo = importOverleafModules('tprLinkedFileInfo')
|
||||
const tprLinkedFileRefreshError = importOverleafModules(
|
||||
'tprLinkedFileRefreshError'
|
||||
|
@ -120,7 +121,7 @@ export default function FileViewHeader({ file, storeReferencesKeys }) {
|
|||
onClick={refreshFile}
|
||||
disabled={refreshing}
|
||||
>
|
||||
<Icon type="refresh" spin={refreshing} modifier="fw" />
|
||||
<Icon type="refresh" spin={refreshing} fw />
|
||||
<span>{refreshing ? t('refreshing') + '...' : t('refresh')}</span>
|
||||
</button>
|
||||
)}
|
||||
|
@ -129,7 +130,7 @@ export default function FileViewHeader({ file, storeReferencesKeys }) {
|
|||
href={`/project/${projectId}/file/${file.id}`}
|
||||
className="btn btn-info"
|
||||
>
|
||||
<Icon type="download" modifier="fw" />
|
||||
<Icon type="download" fw />
|
||||
|
||||
<span>{t('download')}</span>
|
||||
</a>
|
||||
|
@ -162,11 +163,7 @@ FileViewHeader.propTypes = {
|
|||
function UrlProvider({ file }) {
|
||||
return (
|
||||
<p>
|
||||
<Icon
|
||||
type="external-link-square"
|
||||
modifier="rotate-180"
|
||||
classes={{ icon: 'linked-file-icon' }}
|
||||
/>
|
||||
<LinkedFileIcon />
|
||||
|
||||
<Trans
|
||||
i18nKey="imported_from_external_provider_at_date"
|
||||
|
@ -195,11 +192,7 @@ function ProjectFilePathProvider({ file }) {
|
|||
/* eslint-disable jsx-a11y/anchor-has-content, react/jsx-key */
|
||||
return (
|
||||
<p>
|
||||
<Icon
|
||||
type="external-link-square"
|
||||
modifier="rotate-180"
|
||||
classes={{ icon: 'linked-file-icon' }}
|
||||
/>
|
||||
<LinkedFileIcon />
|
||||
|
||||
<Trans
|
||||
i18nKey="imported_from_another_project_at_date"
|
||||
|
@ -235,11 +228,7 @@ ProjectFilePathProvider.propTypes = {
|
|||
function ProjectOutputFileProvider({ file }) {
|
||||
return (
|
||||
<p>
|
||||
<Icon
|
||||
type="external-link-square"
|
||||
modifier="rotate-180"
|
||||
classes={{ icon: 'linked-file-icon' }}
|
||||
/>
|
||||
<LinkedFileIcon />
|
||||
|
||||
<Trans
|
||||
i18nKey="imported_from_the_output_of_another_project_at_date"
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import Icon from '../../../shared/components/icon'
|
||||
|
||||
export const LinkedFileIcon = props => {
|
||||
return (
|
||||
<Icon
|
||||
type="external-link-square"
|
||||
modifier="rotate-180"
|
||||
className="linked-file-icon"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
|
@ -65,7 +65,7 @@ function FileViewLoadingIndicator() {
|
|||
return (
|
||||
<div className="loading-panel loading-panel-file-view">
|
||||
<span>
|
||||
<Icon type="refresh" modifier="spin" />
|
||||
<Icon type="refresh" spin />
|
||||
{t('loading')}…
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -80,7 +80,7 @@ function OutlineItem({ outlineItem, jumpToLine, highlightedLine }) {
|
|||
>
|
||||
<Icon
|
||||
type={expanded ? 'angle-down' : 'angle-right'}
|
||||
classes={{ icon: 'outline-caret-icon' }}
|
||||
className="outline-caret-icon"
|
||||
/>
|
||||
</button>
|
||||
) : null}
|
||||
|
|
|
@ -57,7 +57,7 @@ const OutlinePane = React.memo(function OutlinePane({
|
|||
>
|
||||
<Icon
|
||||
type={isOpen ? 'angle-down' : 'angle-right'}
|
||||
classes={{ icon: 'outline-caret-icon' }}
|
||||
className="outline-caret-icon"
|
||||
/>
|
||||
<h4 className="outline-header-name">{t('file_outline')}</h4>
|
||||
</button>
|
||||
|
|
|
@ -9,7 +9,7 @@ function PdfCodeCheckFailedNotice() {
|
|||
<div className="log-entry">
|
||||
<div className="log-entry-header log-entry-header-error">
|
||||
<div className="log-entry-header-icon-container">
|
||||
<Icon type="exclamation-triangle" modifier="fw" />
|
||||
<Icon type="exclamation-triangle" fw />
|
||||
</div>
|
||||
<h3 className="log-entry-header-title">
|
||||
{t('code_check_failed_explanation')}
|
||||
|
|
|
@ -48,36 +48,36 @@ function PdfCompileButton() {
|
|||
<MenuItem header>{t('auto_compile')}</MenuItem>
|
||||
|
||||
<MenuItem onSelect={() => setAutoCompile(true)}>
|
||||
<Icon type={autoCompile ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={autoCompile ? 'check' : ''} fw />
|
||||
{t('on')}
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem onSelect={() => setAutoCompile(false)}>
|
||||
<Icon type={!autoCompile ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={!autoCompile ? 'check' : ''} fw />
|
||||
{t('off')}
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem header>{t('compile_mode')}</MenuItem>
|
||||
|
||||
<MenuItem onSelect={() => setDraft(false)}>
|
||||
<Icon type={!draft ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={!draft ? 'check' : ''} fw />
|
||||
{t('normal')}
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem onSelect={() => setDraft(true)}>
|
||||
<Icon type={draft ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={draft ? 'check' : ''} fw />
|
||||
{t('fast')} <span className="subdued">[draft]</span>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem header>Syntax Checks</MenuItem>
|
||||
|
||||
<MenuItem onSelect={() => setStopOnValidationError(true)}>
|
||||
<Icon type={stopOnValidationError ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={stopOnValidationError ? 'check' : ''} fw />
|
||||
{t('stop_on_validation_error')}
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem onSelect={() => setStopOnValidationError(false)}>
|
||||
<Icon type={!stopOnValidationError ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={!stopOnValidationError ? 'check' : ''} fw />
|
||||
{t('ignore_validation_errors')}
|
||||
</MenuItem>
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ function PdfDownloadButton() {
|
|||
download
|
||||
href={pdfDownloadUrl || '#'}
|
||||
>
|
||||
<Icon type="download" modifier="fw" />
|
||||
<Icon type="download" fw />
|
||||
<span className="toolbar-text toolbar-hide-medium toolbar-hide-small">
|
||||
{t('download_pdf')}
|
||||
</span>
|
||||
|
|
|
@ -28,7 +28,7 @@ function PdfHybridDownloadButton() {
|
|||
target="_blank"
|
||||
style={{ pointerEvents: 'auto' }}
|
||||
>
|
||||
<Icon type="download" modifier="fw" />
|
||||
<Icon type="download" fw />
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
|
|
|
@ -40,7 +40,7 @@ function PdfHybridLogsButton() {
|
|||
style={{ position: 'relative' }}
|
||||
aria-label={showLogs ? t('view_pdf') : t('view_logs')}
|
||||
>
|
||||
<Icon type="file-text-o" modifier="fw" />
|
||||
<Icon type="file-text-o" fw />
|
||||
|
||||
{!showLogs && totalCount > 0 && (
|
||||
<Label bsStyle={errorCount === 0 ? 'warning' : 'danger'}>
|
||||
|
|
|
@ -30,13 +30,9 @@ function GoToCodeButton({
|
|||
|
||||
let buttonIcon = null
|
||||
if (syncToCodeInFlight) {
|
||||
buttonIcon = (
|
||||
<Icon type="refresh" spin classes={{ icon: 'synctex-spin-icon' }} />
|
||||
)
|
||||
buttonIcon = <Icon type="refresh" spin className="synctex-spin-icon" />
|
||||
} else if (!isDetachLayout) {
|
||||
buttonIcon = (
|
||||
<Icon type="arrow-left" classes={{ icon: 'synctex-control-icon' }} />
|
||||
)
|
||||
buttonIcon = <Icon type="arrow-left" className="synctex-control-icon" />
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -77,13 +73,9 @@ function GoToPdfButton({
|
|||
|
||||
let buttonIcon = null
|
||||
if (syncToPdfInFlight) {
|
||||
buttonIcon = (
|
||||
<Icon type="refresh" spin classes={{ icon: 'synctex-spin-icon' }} />
|
||||
)
|
||||
buttonIcon = <Icon type="refresh" spin className="synctex-spin-icon" />
|
||||
} else if (!isDetachLayout) {
|
||||
buttonIcon = (
|
||||
<Icon type="arrow-right" classes={{ icon: 'synctex-control-icon' }} />
|
||||
)
|
||||
buttonIcon = <Icon type="arrow-right" className="synctex-control-icon" />
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -30,7 +30,7 @@ function PreviewDownloadButton({
|
|||
href={pdfDownloadUrl || '#'}
|
||||
style={{ pointerEvents: 'auto' }}
|
||||
>
|
||||
<Icon type="download" modifier="fw" />
|
||||
<Icon type="download" fw />
|
||||
<span className="toolbar-text" style={textStyle}>
|
||||
{t('download_pdf')}
|
||||
</span>
|
||||
|
|
|
@ -15,7 +15,8 @@ function PreviewLogsPaneMaxEntries({ totalEntries, entriesShown, hasErrors }) {
|
|||
<div className="log-entry" aria-label={t('log_entry_maximum_entries')}>
|
||||
<PreviewLogEntryHeader level="raw" headerTitle={title} />
|
||||
<div className="log-entry-content">
|
||||
<Icon type="lightbulb-o" />{' '}
|
||||
<Icon type="lightbulb-o" />
|
||||
|
||||
{hasErrors ? (
|
||||
<Trans
|
||||
i18nKey="log_entry_maximum_entries_message"
|
||||
|
|
|
@ -172,7 +172,7 @@ function AutoCompileLintingErrorEntry() {
|
|||
<div className="log-entry">
|
||||
<div className="log-entry-header log-entry-header-error">
|
||||
<div className="log-entry-header-icon-container">
|
||||
<Icon type="exclamation-triangle" modifier="fw" />
|
||||
<Icon type="exclamation-triangle" fw />
|
||||
</div>
|
||||
<h3 className="log-entry-header-title">
|
||||
{t('code_check_failed_explanation')}
|
||||
|
|
|
@ -104,33 +104,33 @@ function PreviewRecompileButton({
|
|||
<Dropdown.Menu>
|
||||
<MenuItem header>{t('auto_compile')}</MenuItem>
|
||||
<MenuItem onSelect={handleSelectAutoCompileOn}>
|
||||
<Icon type={isAutoCompileOn ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={isAutoCompileOn ? 'check' : ''} fw />
|
||||
{t('on')}
|
||||
</MenuItem>
|
||||
<MenuItem onSelect={handleSelectAutoCompileOff}>
|
||||
<Icon type={!isAutoCompileOn ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={!isAutoCompileOn ? 'check' : ''} fw />
|
||||
{t('off')}
|
||||
</MenuItem>
|
||||
<MenuItem header>{t('compile_mode')}</MenuItem>
|
||||
<MenuItem onSelect={handleSelectDraftModeOff}>
|
||||
<Icon type={!isDraftModeOn ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={!isDraftModeOn ? 'check' : ''} fw />
|
||||
{t('normal')}
|
||||
</MenuItem>
|
||||
<MenuItem onSelect={handleSelectDraftModeOn}>
|
||||
<Icon type={isDraftModeOn ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={isDraftModeOn ? 'check' : ''} fw />
|
||||
{t('fast')} <span className="subdued">[draft]</span>
|
||||
</MenuItem>
|
||||
<MenuItem header>Syntax Checks</MenuItem>
|
||||
<MenuItem onSelect={handleSelectSyntaxCheckOn}>
|
||||
<Icon type={isSyntaxCheckOn ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={isSyntaxCheckOn ? 'check' : ''} fw />
|
||||
{t('stop_on_validation_error')}
|
||||
</MenuItem>
|
||||
<MenuItem onSelect={handleSelectSyntaxCheckOff}>
|
||||
<Icon type={!isSyntaxCheckOn ? 'check' : ''} modifier="fw" />
|
||||
<Icon type={!isSyntaxCheckOn ? 'check' : ''} fw />
|
||||
{t('ignore_validation_errors')}
|
||||
</MenuItem>
|
||||
<MenuItem onSelect={onRunSyntaxCheckNow}>
|
||||
<Icon type="" modifier="fw" />
|
||||
<Icon type="" fw />
|
||||
{t('run_syntax_check_now')}
|
||||
</MenuItem>
|
||||
<MenuItem className={!isCompiling ? 'hidden' : ''} divider />
|
||||
|
|
|
@ -270,7 +270,7 @@ function Option({ selected, item, getItemProps, index }) {
|
|||
className={classnames('suggestion-item', { selected })}
|
||||
{...getItemProps({ item, index })}
|
||||
>
|
||||
<Icon type="user" modifier="fw" />
|
||||
<Icon type="user" fw />
|
||||
|
||||
{item.display}
|
||||
</li>
|
||||
|
@ -309,7 +309,7 @@ function SelectedItem({
|
|||
className="tag-item"
|
||||
{...getSelectedItemProps({ selectedItem, index })}
|
||||
>
|
||||
<Icon type="user" modifier="fw" />
|
||||
<Icon type="user" fw />
|
||||
<span>{selectedItem.display}</span>
|
||||
<button
|
||||
type="button"
|
||||
|
@ -317,7 +317,7 @@ function SelectedItem({
|
|||
aria-label={t('remove')}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<Icon type="close" modifier="fw" />
|
||||
<Icon type="close" fw />
|
||||
</button>
|
||||
</span>
|
||||
)
|
||||
|
|
|
@ -22,7 +22,9 @@ export default function WordCountModalContent({ handleHide }) {
|
|||
<Modal.Body>
|
||||
{loading && !error && (
|
||||
<div className="loading">
|
||||
<Icon type="refresh" spin modifier="fw" /> {t('loading')}…
|
||||
<Icon type="refresh" spin fw />
|
||||
|
||||
{t('loading')}…
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import Icon from './icon'
|
|||
|
||||
function IconChecked() {
|
||||
const { t } = useTranslation()
|
||||
return <Icon type="check" modifier="fw" accessibilityLabel={t('selected')} />
|
||||
return <Icon type="check" fw accessibilityLabel={t('selected')} />
|
||||
}
|
||||
|
||||
export default IconChecked
|
||||
|
|
|
@ -1,32 +1,40 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import classNames from 'classnames'
|
||||
|
||||
/**
|
||||
* @param {string} type
|
||||
* @param {boolean} [spin]
|
||||
* @param {boolean} [fw]
|
||||
* @param {string} [modifier]
|
||||
* @param {string} [className]
|
||||
* @param {string} [accessibilityLabel]
|
||||
* @return {JSX.Element}
|
||||
*/
|
||||
function Icon({
|
||||
type,
|
||||
spin,
|
||||
fw,
|
||||
modifier,
|
||||
classes = {},
|
||||
className = '',
|
||||
accessibilityLabel,
|
||||
children,
|
||||
}) {
|
||||
const iconClassName = classNames(
|
||||
'fa',
|
||||
`fa-${type}`,
|
||||
{
|
||||
'fa-spin': spin,
|
||||
'fa-fw': fw,
|
||||
[`fa-${modifier}`]: modifier,
|
||||
},
|
||||
classes.icon
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<i className={iconClassName} aria-hidden="true">
|
||||
{children}
|
||||
</i>
|
||||
{accessibilityLabel ? (
|
||||
<i className={iconClassName} aria-hidden="true" />
|
||||
{accessibilityLabel && (
|
||||
<span className="sr-only">{accessibilityLabel}</span>
|
||||
) : null}
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -34,15 +42,10 @@ function Icon({
|
|||
Icon.propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
spin: PropTypes.bool,
|
||||
fw: PropTypes.bool,
|
||||
modifier: PropTypes.string,
|
||||
classes: PropTypes.exact({
|
||||
icon: PropTypes.string,
|
||||
}),
|
||||
className: PropTypes.string,
|
||||
accessibilityLabel: PropTypes.string,
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
PropTypes.node,
|
||||
]),
|
||||
}
|
||||
|
||||
export default Icon
|
||||
|
|
|
@ -24,7 +24,7 @@ function LoadingSpinner({ delay = 500 }) {
|
|||
|
||||
return (
|
||||
<div className="loading">
|
||||
<Icon type="fw" modifier="refresh" spin />
|
||||
<Icon type="refresh" fw spin />
|
||||
|
||||
{t('loading')}…
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,8 @@ function Processing({ isProcessing }) {
|
|||
if (isProcessing) {
|
||||
return (
|
||||
<div aria-live="polite">
|
||||
{t('processing')}… <Icon type="fw" modifier="refresh" spin />
|
||||
{t('processing')}…
|
||||
<Icon type="refresh" fw spin />
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
|
|
|
@ -33,7 +33,7 @@ export const FixedWidth = args => {
|
|||
}
|
||||
FixedWidth.args = {
|
||||
type: 'tasks',
|
||||
modifier: 'fw',
|
||||
fw: true,
|
||||
}
|
||||
|
||||
export const AccessibilityLabel = args => {
|
||||
|
|
|
@ -171,13 +171,20 @@
|
|||
i.fa {
|
||||
color: @file-tree-item-icon-color;
|
||||
font-size: 14px;
|
||||
&.linked-file-highlight {
|
||||
}
|
||||
|
||||
i.fa.linked-file-icon {
|
||||
position: relative;
|
||||
left: -2px;
|
||||
|
||||
+ .linked-file-highlight {
|
||||
& {
|
||||
color: white;
|
||||
}
|
||||
position: relative;
|
||||
top: 4px;
|
||||
left: -8px;
|
||||
width: 0;
|
||||
left: -2px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +234,7 @@
|
|||
.entity-menu-toggle i.fa {
|
||||
color: #fff;
|
||||
}
|
||||
> i.fa i.linked-file-highlight {
|
||||
> i.linked-file-highlight {
|
||||
color: @blue;
|
||||
}
|
||||
color: #fff;
|
||||
|
@ -296,7 +303,7 @@
|
|||
.entity-menu-toggle i.fa {
|
||||
color: @file-tree-item-selected-color;
|
||||
}
|
||||
> i.fa i.linked-file-highlight {
|
||||
> i.linked-file-highlight {
|
||||
color: @blue;
|
||||
}
|
||||
background-color: @file-tree-item-selected-bg;
|
||||
|
|
|
@ -27,6 +27,12 @@ describe('<Icon />', function () {
|
|||
expect(element).to.exist
|
||||
})
|
||||
|
||||
it('renders with fw', function () {
|
||||
const { container } = render(<Icon type="angle-down" fw />)
|
||||
const element = container.querySelector('i.fa.fa-angle-down.fa-fw')
|
||||
expect(element).to.exist
|
||||
})
|
||||
|
||||
it('renders with modifier', function () {
|
||||
const { container } = render(<Icon type="angle-down" modifier="2x" />)
|
||||
const element = container.querySelector('i.fa.fa-angle-down.fa-2x')
|
||||
|
@ -35,23 +41,11 @@ describe('<Icon />', function () {
|
|||
|
||||
it('renders with custom clases', function () {
|
||||
const { container } = render(
|
||||
<Icon type="angle-down" classes={{ icon: 'custom-icon-class' }} />
|
||||
<Icon type="angle-down" className="custom-icon-class" />
|
||||
)
|
||||
const element = container.querySelector(
|
||||
'i.fa.fa-angle-down.custom-icon-class'
|
||||
)
|
||||
expect(element).to.exist
|
||||
})
|
||||
|
||||
it('renders children', function () {
|
||||
const { container } = render(
|
||||
<Icon type="angle-down">
|
||||
<Icon type="angle-up" />
|
||||
</Icon>
|
||||
)
|
||||
const element = container.querySelector(
|
||||
'i.fa.fa-angle-down > i.fa.fa-angle-up'
|
||||
)
|
||||
expect(element).to.exist
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue