Improve the Icon component (#6245)

GitOrigin-RevId: fbb23b32c47edbe5a22badc627318accbd09e82a
This commit is contained in:
Alf Eaton 2022-01-19 11:56:57 +00:00 committed by Copybot
parent ee00ff3c44
commit f065a7a909
37 changed files with 146 additions and 152 deletions

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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 }) {

View file

@ -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>

View file

@ -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>
)

View file

@ -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>
)

View file

@ -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>
)}

View file

@ -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>

View file

@ -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 />
&nbsp;
{label}
</Button>

View file

@ -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 (
<>
&nbsp;
<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

View file

@ -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 />
</>
)

View file

@ -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>

View file

@ -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 />
&nbsp;
<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 />
&nbsp;
<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 />
&nbsp;
<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 />
&nbsp;
<Trans
i18nKey="imported_from_the_output_of_another_project_at_date"

View file

@ -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}
/>
)
}

View file

@ -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 />
&nbsp;&nbsp;{t('loading')}
</span>
</div>

View file

@ -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}

View file

@ -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>

View file

@ -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')}

View file

@ -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>

View file

@ -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>

View file

@ -28,7 +28,7 @@ function PdfHybridDownloadButton() {
target="_blank"
style={{ pointerEvents: 'auto' }}
>
<Icon type="download" modifier="fw" />
<Icon type="download" fw />
</Button>
</OverlayTrigger>
)

View file

@ -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'}>

View file

@ -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 (

View file

@ -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>

View file

@ -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" />
&nbsp;
{hasErrors ? (
<Trans
i18nKey="log_entry_maximum_entries_message"

View file

@ -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')}

View file

@ -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 />

View file

@ -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 />
&nbsp;
{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>
)

View file

@ -22,7 +22,9 @@ export default function WordCountModalContent({ handleHide }) {
<Modal.Body>
{loading && !error && (
<div className="loading">
<Icon type="refresh" spin modifier="fw" /> &nbsp; {t('loading')}
<Icon type="refresh" spin fw />
&nbsp;
{t('loading')}
</div>
)}

View file

@ -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

View file

@ -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

View file

@ -24,7 +24,7 @@ function LoadingSpinner({ delay = 500 }) {
return (
<div className="loading">
<Icon type="fw" modifier="refresh" spin />
<Icon type="refresh" fw spin />
&nbsp;
{t('loading')}
</div>

View file

@ -7,7 +7,8 @@ function Processing({ isProcessing }) {
if (isProcessing) {
return (
<div aria-live="polite">
{t('processing')} <Icon type="fw" modifier="refresh" spin />
{t('processing')}&nbsp;
<Icon type="refresh" fw spin />
</div>
)
} else {

View file

@ -33,7 +33,7 @@ export const FixedWidth = args => {
}
FixedWidth.args = {
type: 'tasks',
modifier: 'fw',
fw: true,
}
export const AccessibilityLabel = args => {

View file

@ -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;

View file

@ -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
})
})