Skip to content

Commit

Permalink
feat: make it possible to send in a "data:image" instead of a SVG - s…
Browse files Browse the repository at this point in the history
…izes are handles for dynamic usage as well
  • Loading branch information
tujoworker committed Jan 24, 2019
1 parent ff88149 commit c0e886f
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,8 @@ exports[`Button scss have to match snapshot 1`] = `
.dnb-icon--custom-size {
width: auto;
height: auto; }
.dnb-icon svg:not([width]):not([height]) {
.dnb-icon svg:not([width]):not([height]),
.dnb-icon img:not([width]):not([height]) {
width: inherit;
height: inherit; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import DefaultIcon, { DefaultIconSize, loadSVG } from '../icon/Icon'
import DefaultIcon, { DefaultIconSize, prepareIcon } from '../icon/Icon'
import * as primary_icons from '../../icons/primary_icons'
import * as primary_icons_medium from '../../icons/primary_icons_medium'

Expand Down Expand Up @@ -43,13 +43,13 @@ export default class IconPrimary extends PureComponent {
this.props
)

const Svg = loadSVG(icon, size, icons)
const IconContainer = prepareIcon({ icon, size, listOfIcons: icons })

if (!Svg) return <></>
if (!IconContainer) return <></>

return (
<span {...wrapperParams}>
<Svg {...svgParams} />
<IconContainer {...svgParams} />
</span>
)
}
Expand Down
48 changes: 34 additions & 14 deletions packages/dnb-ui-lib/src/components/icon/Icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,16 @@ export default class Icon extends PureComponent {
}

static getIconNameFromComponent(props) {
return typeof props.icon === 'string'
? props.icon
: props.icon &&
const name =
typeof props.icon === 'string'
? props.icon
: props.icon &&
typeof props.icon === 'object' &&
(props.icon.displayName || props.icon.name)
if (/^data:image\//.test(name)) {
return null
}
return name
}

static calcSize(props) {
Expand Down Expand Up @@ -224,7 +229,7 @@ export default class Icon extends PureComponent {
const {
color,
modifier,
alt,
alt: _alt,
title,
class: _className,
className,
Expand All @@ -237,18 +242,23 @@ export default class Icon extends PureComponent {
svgParams.color = color
}

// get the alt
let alt = _alt || title

if (!(alt && alt.length > 0)) {
alt = String(Icon.getIconNameFromComponent(props)).replace(/_/g, ' ')
}

// some wrapper params
// also used for code markup simulation
const wrapperParams = validateDOMAttributes(props, {
role: 'img',
// as we use aria-label, we do not provide an alt as well
// alt,
['aria-label']: alt,
title
})

// get the alt
wrapperParams['aria-label'] = String(
alt || title || Icon.getIconNameFromComponent(props)
).replace(/_/g, ' ')

if (area_hidden) {
// wrapperParams['role'] = 'presentation' // almost the same as aria-hidden
wrapperParams['aria-hidden'] = area_hidden
Expand All @@ -264,30 +274,40 @@ export default class Icon extends PureComponent {
return {
...props,
icon,
alt,
svgParams,
wrapperParams
}
}

render() {
const { icon, size, wrapperParams, svgParams } = Icon.prerender(
const { icon, size, wrapperParams, svgParams, alt } = Icon.prerender(
this.props
)

const Svg = loadSVG(icon, size)
const IconContainer = prepareIcon({ icon, size, alt })

// make sure we return an empty span if we dont could get the icon
if (!Svg) return <span />
if (!IconContainer) return <></>

return (
<span {...wrapperParams}>
<Svg {...svgParams} />
<IconContainer {...svgParams} />
</span>
)
}
}

export const loadSVG = (icon, size = null, listOfIcons = null) => {
export const prepareIcon = ({
icon,
size = null,
listOfIcons = null,
alt = null
} = {}) => {
if (typeof icon === 'string' && /^data:image\//.test(icon)) {
return () => <img src={icon} alt={alt || 'no-alt'} />
}

if (typeof icon === 'function') {
const elem = icon()
if (React.isValidElement(elem)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ exports[`Icon scss have to match snapshot 1`] = `
.dnb-icon--custom-size {
width: auto;
height: auto; }
.dnb-icon svg:not([width]):not([height]) {
.dnb-icon svg:not([width]):not([height]),
.dnb-icon img:not([width]):not([height]) {
width: inherit;
height: inherit; }
"
Expand Down
3 changes: 2 additions & 1 deletion packages/dnb-ui-lib/src/components/icon/style/_icon.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
height: auto; // only to feed the svg
}

svg:not([width]):not([height]) {
svg:not([width]):not([height]),
img:not([width]):not([height]) {
width: inherit;
height: inherit;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ exports[`InputMasked scss have to match snapshot 1`] = `
.dnb-icon--custom-size {
width: auto;
height: auto; }
.dnb-icon svg:not([width]):not([height]) {
.dnb-icon svg:not([width]):not([height]),
.dnb-icon img:not([width]):not([height]) {
width: inherit;
height: inherit; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,8 @@ exports[`Input scss have to match snapshot 1`] = `
.dnb-icon--custom-size {
width: auto;
height: auto; }
.dnb-icon svg:not([width]):not([height]) {
.dnb-icon svg:not([width]):not([height]),
.dnb-icon img:not([width]):not([height]) {
width: inherit;
height: inherit; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,8 @@ exports[`Modal scss have to match snapshot 1`] = `
.dnb-icon--custom-size {
width: auto;
height: auto; }
.dnb-icon svg:not([width]):not([height]) {
.dnb-icon svg:not([width]):not([height]),
.dnb-icon img:not([width]):not([height]) {
width: inherit;
height: inherit; }
Expand Down

0 comments on commit c0e886f

Please sign in to comment.