1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | 230x 230x 230x 230x 230x 6x 2x 2x 1x 1x 2x 2x 1x 1x 230x 460x 460x 460x 230x 21x 230x 23x 223x 223x 2x 230x 6x 230x 23x 230x 230x 24x 1x 1x 23x 230x 230x 230x 229x 230x 230x 228x 186x 184x 183x 224x 230x 230x 230x 2x 230x 230x 230x 89x 89x 89x | /** * @category styles * @component icon * @variations collab-ui-react */ import React from 'react'; import PropTypes from 'prop-types'; import { chain, find, trimEnd, uniqueId } from 'lodash'; import iconPaths from '@collab-ui/icons/data/iconsData.json'; import colors from '@collab-ui/core/data/colors.json'; import { Button } from '@collab-ui/react'; class Icon extends React.PureComponent { render() { const { ariaLabel, buttonClassName, color, className, description, isAria, // TODO(pajeter): remove isAria code with next major release onClick, name, size, title, type, ...otherProps } = this.props; const iconCount = uniqueId(); const titleId = `icon-title-${iconCount}`; const descId = description ? `icon-desc-${iconCount}` : undefined; const consoleHandler = (message, data) => { /* eslint-disable no-console */ switch (message) { case 'isAria-warn': // TODO(pajeter): remove isAria code with next major release console.warn( `[@collab-ui/react] Icon: isAria prop is deprecated and will be removed. Title, description or ariaLabel props should be used to add accessibility.` ); break; case 'color-warn': console.warn( `[@collab-ui/react] Icon: ${data} may not exist in the design system,` + ` please use a color name from http://core.collab-ui.com/styles/colors` ); break; case 'color-error': console.warn( `[@collab-ui/react] Icon: ${data} does not exist in the design system,` + ` please use a color name from http://core.collab-ui.com/styles/colors` ); break; case 'name-error': console.warn( `[@collab-ui/react] Icon: Icon ${data} does not exist in the design system.` + ` Visit http://icons.collab-ui.com for a list of available icons or to request a new icon.` ); break; } /* eslint-enable no-console */ }; const getSize = () => { const defaultSize = 16; const sizeFromName = Number(name.split('_')[1]); return size || sizeFromName || defaultSize; }; const getColorSpec = colorObj => colorObj.hex ? colorObj.hex : colorObj.opacity && isolateRoot(colorObj.variable) === 'white' ? `rgba(255, 255, 255, ${colorObj.opacity / 100})` : `rgba(0, 0, 0, ${colorObj.opacity / 100})`; const getHexFromJSON = colorName => { for (let c of colors) { const variation = find(c.variations, ['variable', colorName]); if (variation) return getColorSpec(variation); } return consoleHandler('color-error', colorName); }; const isolateRoot = str => ( chain(str) .trimStart('$') .split('-') .value()[0] ); const formatColor = () => { return color.startsWith('$') ? color : color.endsWith('-base') ? trimEnd(color, '-base') : `$${color}`; }; const getColor = () => { if (!color) return 'inherit'; if (color.startsWith('#')) { consoleHandler('color-warn', color); return color; } return getHexFromJSON(formatColor()); }; const getPaths = () => { const iconName = name.startsWith('icon-') ? name.replace(/^(icon-)/,'') : name; return iconPaths[iconName] ? iconPaths[iconName].map((icoPath, index) => ( <path d={icoPath} key={index} /> )) : consoleHandler('name-error', iconName); }; const getAriaLabelledBy = () => { if (!isAria) return deprecationWarning(); // TODO(pajeter): remove isAria code with next major release if (!ariaLabel) { if (title && description) return (`${titleId} ${descId}`); if (title) return (`${titleId}`); if (description) return (`${descId}`); } return null; }; const getAriaLabel = () => ( (isAria // TODO(pajeter): remove isAria code with next major release && ariaLabel) ? ariaLabel : null ); const deprecationWarning = () => { // TODO(pajeter): remove isAria code with next major release consoleHandler('isAria-warn'); }; const getIcon = () => { return ( <svg className={ `cui-icon` + `${(className && ` ${className}`) || ''}` } name={name} width={getSize()} height={getSize()} aria-labelledby={!onClick ? getAriaLabelledBy() : null} aria-label={!onClick ? getAriaLabel() : null} {...!onClick && {...otherProps}} > {isAria // TODO(pajeter): remove isAria code with next major release && title && <title id={titleId}>{title}</title>} {isAria // TODO(pajeter): remove isAria code with next major release && description && <desc id={descId}>{description}</desc>} <g fill={getColor()} fillRule="evenodd"> {getPaths()} </g> </svg> ); }; return ( onClick ? <Button className={ 'cui-button--icon' + `${(type && ` cui-button--icon-${type}`) || ''}` + `${(buttonClassName && ` ${buttonClassName}`) || ''}` } ariaLabel={getAriaLabel()} ariaLabelledBy={ isAria // TODO(pajeter): remove isAria code with next major release ? getAriaLabelledBy() : deprecationWarning() // TODO(pajeter): remove isAria code with next major release } onClick={onClick} {...otherProps} > {getIcon()} </Button> : getIcon() ); } } Icon.propTypes = { /** @prop Text to display for blindness accessibility features | null */ ariaLabel: PropTypes.string, /** @prop Optional Button class name string | '' */ buttonClassName: PropTypes.string, /** @prop Optional color css styling | '' */ color: PropTypes.string, /** @prop Optional class name string | '' */ className: PropTypes.string, /** @prop Icon description text | '' */ description: PropTypes.string, /** @prop Depreciated prop that supports accessibility features | true */ isAria: PropTypes.bool, // TODO(pajeter): remove isAria code with next major release /** @prop Required Icon name */ name: PropTypes.string.isRequired, /** @prop Handler invoked by click of the user | null */ onClick: PropTypes.func, /** @prop Sets Icon size | null */ size: PropTypes.number, /** @prop Sets Icon Title prop | '' */ title: PropTypes.string, /** @prop Sets Icon Type | '' */ type: PropTypes.oneOf(['', 'white']) }; Icon.defaultProps = { ariaLabel: null, buttonClassName: '', color: '', className: '', description: '', isAria: true, // TODO(pajeter): remove isAria code with next major release onClick: null, size: null, title: '', type: '' }; Icon.displayName = 'Icon'; export default Icon; /** * @component icons * @section default * @react * import { Icon } from '@collab-ui/react'; export default class IconDefault extends React.PureComponent { render() { return( <div> <Icon name='accessories_16' /> <Icon name='accessories_20' /> <Icon name='accessories_36' /> <Icon name='accessories_56' /> </div> ); } } **/ /** * @component icons * @section color * @react * import { Icon } from '@collab-ui/react'; export default class IconColor extends React.PureComponent { render() { return( <div> <Icon name='accessories_16' color='blue' /> <Icon name='accessories_20' color='blue' /> <Icon name='accessories_36' color='blue' /> <Icon name='accessories_56' color='blue' /> </div> ); } } **/ /** * @component icons * @section white * @react * import { Icon } from '@collab-ui/react'; export default class Default extends React.PureComponent { render() { return( <div style={{ backgroundColor: 'black', padding: '5px', width: 'fit-content' }}> <Icon name='clear-active_24' ariaLabel='Clear' type='white' onClick={() => console.log('Icon 36 - clicked')} /> </div> ); } } **/ |